aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--book/src/generated/typable-cmd.md4
-rw-r--r--helix-term/src/commands.rs120
2 files changed, 107 insertions, 17 deletions
diff --git a/book/src/generated/typable-cmd.md b/book/src/generated/typable-cmd.md
index 5881716d..370da21a 100644
--- a/book/src/generated/typable-cmd.md
+++ b/book/src/generated/typable-cmd.md
@@ -5,6 +5,10 @@
| `: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 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) |
| `:new`, `:n` | Create a new scratch buffer. |
| `:format`, `:fmt` | Format the file using the LSP formatter. |
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)",