@@ -2077,18 +2077,27 @@ pub mod cmd {
2080− fn buffer_close_impl(
2080+ fn buffer_close_by_ids_impl(
2081 editor: &mut Editor,
2081 editor: &mut Editor,
2082− args: &[Cow<str>],
2082+ doc_ids: &[DocumentId],
2083 force: bool,
2083 force: bool,
2084 ) -> anyhow::Result<()> {
2084 ) -> anyhow::Result<()> {
2085+ for &doc_id in doc_ids {
2086+ editor.close_document(doc_id, force)?;
2092+ fn buffer_gather_paths_impl(editor: &mut Editor, args: &[Cow<str>]) -> Vec<DocumentId> {
2093+ // No arguments implies current document
2085 if args.is_empty() {
2094 if args.is_empty() {
2086 let doc_id = view!(editor).doc;
2095 let doc_id = view!(editor).doc;
2087− editor.close_document(doc_id, force)?;
2088− return Ok(());
2096+ return vec![doc_id];
2091 let mut nonexistent_buffers = vec![];
2099 let mut nonexistent_buffers = vec![];
2100+ let mut document_ids = vec![];
2092 for arg in args {
2101 for arg in args {
2093 let doc_id = editor.documents().find_map(|doc| {
2102 let doc_id = editor.documents().find_map(|doc| {
2094 let arg_path = Some(Path::new(arg.as_ref()));
2103 let arg_path = Some(Path::new(arg.as_ref()));
@@ -2102,21 +2111,19 @@ pub mod cmd {
2104 match doc_id {
2113 match doc_id {
2105− Some(doc_id) => editor.close_document(doc_id, force)?,
2114+ Some(doc_id) => document_ids.push(doc_id),
2106− None => nonexistent_buffers.push(arg),
2115+ None => nonexistent_buffers.push(format!("'{}'", arg)),
2110− let nonexistent_buffers: Vec<_> = nonexistent_buffers
2119+ if !nonexistent_buffers.is_empty() {
2112− .map(|str| format!("'{}'", str))
2114− editor.set_error(format!(
2120+ editor.set_error(format!(
2115− "couldn't close buffer(s) {}: does not exist",
2121+ "cannot close non-existent buffers: {}",
2116− nonexistent_buffers.join(", ")
2122+ nonexistent_buffers.join(", ")
2119− Ok(())
2126+ document_ids
2122 fn buffer_close(
2129 fn buffer_close(
@@ -2124,7 +2131,8 @@ pub mod cmd {
2124 args: &[Cow<str>],
2131 args: &[Cow<str>],
2125 _event: PromptEvent,
2132 _event: PromptEvent,
2126 ) -> anyhow::Result<()> {
2133 ) -> anyhow::Result<()> {
2127− buffer_close_impl(cx.editor, args, false)
2134+ let document_ids = buffer_gather_paths_impl(cx.editor, args);
2135+ buffer_close_by_ids_impl(cx.editor, &document_ids, false)
2130 fn force_buffer_close(
2138 fn force_buffer_close(
@@ -2132,7 +2140,57 @@ pub mod cmd {
2132 args: &[Cow<str>],
2140 args: &[Cow<str>],
2133 _event: PromptEvent,
2141 _event: PromptEvent,
2134 ) -> anyhow::Result<()> {
2142 ) -> anyhow::Result<()> {
2135− buffer_close_impl(cx.editor, args, true)
2143+ let document_ids = buffer_gather_paths_impl(cx.editor, args);
2144+ buffer_close_by_ids_impl(cx.editor, &document_ids, true)
2147+ fn buffer_gather_others_impl(editor: &mut Editor) -> Vec<DocumentId> {
2148+ let current_document = &doc!(editor).id();
2151+ .map(|doc| doc.id())
2152+ .filter(|doc_id| doc_id != current_document)
2156+ fn buffer_close_others(
2157+ cx: &mut compositor::Context,
2158+ _args: &[Cow<str>],
2159+ _event: PromptEvent,
2160+ ) -> anyhow::Result<()> {
2161+ let document_ids = buffer_gather_others_impl(cx.editor);
2162+ buffer_close_by_ids_impl(cx.editor, &document_ids, false)
2165+ fn force_buffer_close_others(
2166+ cx: &mut compositor::Context,
2167+ _args: &[Cow<str>],
2168+ _event: PromptEvent,
2169+ ) -> anyhow::Result<()> {
2170+ let document_ids = buffer_gather_others_impl(cx.editor);
2171+ buffer_close_by_ids_impl(cx.editor, &document_ids, true)
2174+ fn buffer_gather_all_impl(editor: &mut Editor) -> Vec<DocumentId> {
2175+ editor.documents().map(|doc| doc.id()).collect()
2178+ fn buffer_close_all(
2179+ cx: &mut compositor::Context,
2180+ _args: &[Cow<str>],
2181+ _event: PromptEvent,
2182+ ) -> anyhow::Result<()> {
2183+ let document_ids = buffer_gather_all_impl(cx.editor);
2184+ buffer_close_by_ids_impl(cx.editor, &document_ids, false)
2187+ fn force_buffer_close_all(
2188+ cx: &mut compositor::Context,
2189+ _args: &[Cow<str>],
2190+ _event: PromptEvent,
2191+ ) -> anyhow::Result<()> {
2192+ let document_ids = buffer_gather_all_impl(cx.editor);
2193+ buffer_close_by_ids_impl(cx.editor, &document_ids, true)
2138 fn write_impl(cx: &mut compositor::Context, path: Option<&Cow<str>>) -> anyhow::Result<()> {
2196 fn write_impl(cx: &mut compositor::Context, path: Option<&Cow<str>>) -> anyhow::Result<()> {
@@ -2970,6 +3028,34 @@ pub mod cmd {
2970 fun: force_buffer_close,
3028 fun: force_buffer_close,
2971 completer: Some(completers::buffer),
3029 completer: Some(completers::buffer),
3032+ name: "buffer-close-others",
3033+ aliases: &["bco", "bcloseother"],
3034+ doc: "Close all buffers but the currently focused one.",
3035+ fun: buffer_close_others,
3039+ name: "buffer-close-others!",
3040+ aliases: &["bco!", "bcloseother!"],
3041+ doc: "Close all buffers but the currently focused one.",
3042+ fun: force_buffer_close_others,
3046+ name: "buffer-close-all",
3047+ aliases: &["bca", "bcloseall"],
3048+ doc: "Close all buffers, without quiting.",
3049+ fun: buffer_close_all,
3053+ name: "buffer-close-all!",
3054+ aliases: &["bca!", "bcloseall!"],
3055+ doc: "Close all buffers forcefully (ignoring unsaved changes), without quiting.",
3056+ fun: force_buffer_close_all,
2973 TypableCommand {
3059 TypableCommand {
2974 name: "write",
3060 name: "write",
2975 aliases: &["w"],
3061 aliases: &["w"],