mirror of
https://github.com/ilyakooo0/helix.git
synced 2024-12-01 11:23:10 +03:00
Implement bulk buffer closing commands (#1677)
* Implement buffer-close-all * Implement buffer-close-others * Refactor all buffer close variants to use shared logic * Fix clippy lint * Docgen for new commands * Shorten error message for attempting to close buffers that don't exist * Refactor shared buffer methods to pass only editor, not whole compositor * Switch signature of bulk buffer closing to use slice of DocumentIds Addresses feedback that accepting an IntoIterator implementor is too much for an internal. Also possibly saves some moving?
This commit is contained in:
parent
59c691d2db
commit
78d37fd332
@ -5,6 +5,10 @@
|
|||||||
| `:open`, `:o` | Open a file from disk into the current view. |
|
| `:open`, `:o` | Open a file from disk into the current view. |
|
||||||
| `:buffer-close`, `:bc`, `:bclose` | Close the current buffer. |
|
| `:buffer-close`, `:bc`, `:bclose` | Close the current buffer. |
|
||||||
| `:buffer-close!`, `:bc!`, `:bclose!` | Close the current buffer forcefully (ignoring unsaved changes). |
|
| `:buffer-close!`, `:bc!`, `:bclose!` | Close the current buffer forcefully (ignoring unsaved changes). |
|
||||||
|
| `:buffer-close-others`, `:bco`, `:bcloseother` | Close all buffers but the currently focused one. |
|
||||||
|
| `:buffer-close-others!`, `:bco!`, `:bcloseother!` | Close all buffers but the currently focused one. |
|
||||||
|
| `:buffer-close-all`, `:bca`, `:bcloseall` | Close all buffers, without quiting. |
|
||||||
|
| `:buffer-close-all!`, `:bca!`, `:bcloseall!` | Close all buffers forcefully (ignoring unsaved changes), without quiting. |
|
||||||
| `:write`, `:w` | Write changes to disk. Accepts an optional path (:write some/path.txt) |
|
| `:write`, `:w` | Write changes to disk. Accepts an optional path (:write some/path.txt) |
|
||||||
| `:new`, `:n` | Create a new scratch buffer. |
|
| `:new`, `:n` | Create a new scratch buffer. |
|
||||||
| `:format`, `:fmt` | Format the file using the LSP formatter. |
|
| `:format`, `:fmt` | Format the file using the LSP formatter. |
|
||||||
|
@ -2077,18 +2077,27 @@ pub mod cmd {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buffer_close_impl(
|
fn buffer_close_by_ids_impl(
|
||||||
editor: &mut Editor,
|
editor: &mut Editor,
|
||||||
args: &[Cow<str>],
|
doc_ids: &[DocumentId],
|
||||||
force: bool,
|
force: bool,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
for &doc_id in doc_ids {
|
||||||
|
editor.close_document(doc_id, force)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn buffer_gather_paths_impl(editor: &mut Editor, args: &[Cow<str>]) -> Vec<DocumentId> {
|
||||||
|
// No arguments implies current document
|
||||||
if args.is_empty() {
|
if args.is_empty() {
|
||||||
let doc_id = view!(editor).doc;
|
let doc_id = view!(editor).doc;
|
||||||
editor.close_document(doc_id, force)?;
|
return vec![doc_id];
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut nonexistent_buffers = vec![];
|
let mut nonexistent_buffers = vec![];
|
||||||
|
let mut document_ids = vec![];
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let doc_id = editor.documents().find_map(|doc| {
|
let doc_id = editor.documents().find_map(|doc| {
|
||||||
let arg_path = Some(Path::new(arg.as_ref()));
|
let arg_path = Some(Path::new(arg.as_ref()));
|
||||||
@ -2102,21 +2111,19 @@ pub mod cmd {
|
|||||||
});
|
});
|
||||||
|
|
||||||
match doc_id {
|
match doc_id {
|
||||||
Some(doc_id) => editor.close_document(doc_id, force)?,
|
Some(doc_id) => document_ids.push(doc_id),
|
||||||
None => nonexistent_buffers.push(arg),
|
None => nonexistent_buffers.push(format!("'{}'", arg)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let nonexistent_buffers: Vec<_> = nonexistent_buffers
|
if !nonexistent_buffers.is_empty() {
|
||||||
.into_iter()
|
|
||||||
.map(|str| format!("'{}'", str))
|
|
||||||
.collect();
|
|
||||||
editor.set_error(format!(
|
editor.set_error(format!(
|
||||||
"couldn't close buffer(s) {}: does not exist",
|
"cannot close non-existent buffers: {}",
|
||||||
nonexistent_buffers.join(", ")
|
nonexistent_buffers.join(", ")
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
document_ids
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buffer_close(
|
fn buffer_close(
|
||||||
@ -2124,7 +2131,8 @@ pub mod cmd {
|
|||||||
args: &[Cow<str>],
|
args: &[Cow<str>],
|
||||||
_event: PromptEvent,
|
_event: PromptEvent,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
buffer_close_impl(cx.editor, args, false)
|
let document_ids = buffer_gather_paths_impl(cx.editor, args);
|
||||||
|
buffer_close_by_ids_impl(cx.editor, &document_ids, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn force_buffer_close(
|
fn force_buffer_close(
|
||||||
@ -2132,7 +2140,57 @@ pub mod cmd {
|
|||||||
args: &[Cow<str>],
|
args: &[Cow<str>],
|
||||||
_event: PromptEvent,
|
_event: PromptEvent,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
buffer_close_impl(cx.editor, args, true)
|
let document_ids = buffer_gather_paths_impl(cx.editor, args);
|
||||||
|
buffer_close_by_ids_impl(cx.editor, &document_ids, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn buffer_gather_others_impl(editor: &mut Editor) -> Vec<DocumentId> {
|
||||||
|
let current_document = &doc!(editor).id();
|
||||||
|
editor
|
||||||
|
.documents()
|
||||||
|
.map(|doc| doc.id())
|
||||||
|
.filter(|doc_id| doc_id != current_document)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn buffer_close_others(
|
||||||
|
cx: &mut compositor::Context,
|
||||||
|
_args: &[Cow<str>],
|
||||||
|
_event: PromptEvent,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let document_ids = buffer_gather_others_impl(cx.editor);
|
||||||
|
buffer_close_by_ids_impl(cx.editor, &document_ids, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn force_buffer_close_others(
|
||||||
|
cx: &mut compositor::Context,
|
||||||
|
_args: &[Cow<str>],
|
||||||
|
_event: PromptEvent,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let document_ids = buffer_gather_others_impl(cx.editor);
|
||||||
|
buffer_close_by_ids_impl(cx.editor, &document_ids, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn buffer_gather_all_impl(editor: &mut Editor) -> Vec<DocumentId> {
|
||||||
|
editor.documents().map(|doc| doc.id()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn buffer_close_all(
|
||||||
|
cx: &mut compositor::Context,
|
||||||
|
_args: &[Cow<str>],
|
||||||
|
_event: PromptEvent,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let document_ids = buffer_gather_all_impl(cx.editor);
|
||||||
|
buffer_close_by_ids_impl(cx.editor, &document_ids, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn force_buffer_close_all(
|
||||||
|
cx: &mut compositor::Context,
|
||||||
|
_args: &[Cow<str>],
|
||||||
|
_event: PromptEvent,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let document_ids = buffer_gather_all_impl(cx.editor);
|
||||||
|
buffer_close_by_ids_impl(cx.editor, &document_ids, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_impl(cx: &mut compositor::Context, path: Option<&Cow<str>>) -> anyhow::Result<()> {
|
fn write_impl(cx: &mut compositor::Context, path: Option<&Cow<str>>) -> anyhow::Result<()> {
|
||||||
@ -2970,6 +3028,34 @@ pub mod cmd {
|
|||||||
fun: force_buffer_close,
|
fun: force_buffer_close,
|
||||||
completer: Some(completers::buffer),
|
completer: Some(completers::buffer),
|
||||||
},
|
},
|
||||||
|
TypableCommand {
|
||||||
|
name: "buffer-close-others",
|
||||||
|
aliases: &["bco", "bcloseother"],
|
||||||
|
doc: "Close all buffers but the currently focused one.",
|
||||||
|
fun: buffer_close_others,
|
||||||
|
completer: None,
|
||||||
|
},
|
||||||
|
TypableCommand {
|
||||||
|
name: "buffer-close-others!",
|
||||||
|
aliases: &["bco!", "bcloseother!"],
|
||||||
|
doc: "Close all buffers but the currently focused one.",
|
||||||
|
fun: force_buffer_close_others,
|
||||||
|
completer: None,
|
||||||
|
},
|
||||||
|
TypableCommand {
|
||||||
|
name: "buffer-close-all",
|
||||||
|
aliases: &["bca", "bcloseall"],
|
||||||
|
doc: "Close all buffers, without quiting.",
|
||||||
|
fun: buffer_close_all,
|
||||||
|
completer: None,
|
||||||
|
},
|
||||||
|
TypableCommand {
|
||||||
|
name: "buffer-close-all!",
|
||||||
|
aliases: &["bca!", "bcloseall!"],
|
||||||
|
doc: "Close all buffers forcefully (ignoring unsaved changes), without quiting.",
|
||||||
|
fun: force_buffer_close_all,
|
||||||
|
completer: None,
|
||||||
|
},
|
||||||
TypableCommand {
|
TypableCommand {
|
||||||
name: "write",
|
name: "write",
|
||||||
aliases: &["w"],
|
aliases: &["w"],
|
||||||
|
Loading…
Reference in New Issue
Block a user