aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src
diff options
context:
space:
mode:
authorDaniel S Poulin2022-03-01 01:31:24 +0000
committerGitHub2022-03-01 01:31:24 +0000
commit78d37fd332ab98e867b8e74f08c4cf45295c167a (patch)
tree19e216bea4dd82553089f7d343dd03edcb7986e1 /helix-term/src
parent59c691d2dbdf14c02d0a4b8f9b014112ead6cda5 (diff)
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?
Diffstat (limited to 'helix-term/src')
-rw-r--r--helix-term/src/commands.rs120
1 files changed, 103 insertions, 17 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 2c5a2d90..74d4c8d7 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -2077,18 +2077,27 @@ pub mod cmd {
Ok(())
}
- fn buffer_close_impl(
+ fn buffer_close_by_ids_impl(
editor: &mut Editor,
- args: &[Cow<str>],
+ doc_ids: &[DocumentId],
force: bool,
) -> 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() {
let doc_id = view!(editor).doc;
- editor.close_document(doc_id, force)?;
- return Ok(());
+ return vec![doc_id];
}
let mut nonexistent_buffers = vec![];
+ let mut document_ids = vec![];
for arg in args {
let doc_id = editor.documents().find_map(|doc| {
let arg_path = Some(Path::new(arg.as_ref()));
@@ -2102,21 +2111,19 @@ pub mod cmd {
});
match doc_id {
- Some(doc_id) => editor.close_document(doc_id, force)?,
- None => nonexistent_buffers.push(arg),
+ Some(doc_id) => document_ids.push(doc_id),
+ None => nonexistent_buffers.push(format!("'{}'", arg)),
}
}
- let nonexistent_buffers: Vec<_> = nonexistent_buffers
- .into_iter()
- .map(|str| format!("'{}'", str))
- .collect();
- editor.set_error(format!(
- "couldn't close buffer(s) {}: does not exist",
- nonexistent_buffers.join(", ")
- ));
+ if !nonexistent_buffers.is_empty() {
+ editor.set_error(format!(
+ "cannot close non-existent buffers: {}",
+ nonexistent_buffers.join(", ")
+ ));
+ }
- Ok(())
+ document_ids
}
fn buffer_close(
@@ -2124,7 +2131,8 @@ pub mod cmd {
args: &[Cow<str>],
_event: PromptEvent,
) -> 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(
@@ -2132,7 +2140,57 @@ pub mod cmd {
args: &[Cow<str>],
_event: PromptEvent,
) -> 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<()> {
@@ -2971,6 +3029,34 @@ pub mod cmd {
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 {
name: "write",
aliases: &["w"],
doc: "Write changes to disk. Accepts an optional path (:write some/path.txt)",