Nikola Milenkovic 2025-06-16 10:17:25 -05:00 committed by GitHub
commit 8eec1e8d40
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 98 additions and 0 deletions

View File

@ -3,6 +3,9 @@
| `:quit`, `:q` | Close the current view. | | `:quit`, `:q` | Close the current view. |
| `:quit!`, `:q!` | Force close the current view, ignoring unsaved changes. | | `:quit!`, `:q!` | Force close the current view, ignoring unsaved changes. |
| `:open`, `:o`, `:edit`, `:e` | Open a file from disk into the current view. | | `:open`, `:o`, `:edit`, `:e` | Open a file from disk into the current view. |
| `:jump-to-buffer`, `:j` | Switch to a document buffer using its index in the buffer jumplist. |
| `:add-buffer-to-jumplist`, `:ab` | Add the current document buffer to the buffer jumplist. |
| `:remove-buffer-from-jumplist`, `:rb` | Remove the current document buffer from the buffer jumplist. |
| `: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. |

View File

@ -3145,6 +3145,7 @@ fn buffer_picker(cx: &mut Context) {
is_modified: bool, is_modified: bool,
is_current: bool, is_current: bool,
focused_at: std::time::Instant, focused_at: std::time::Instant,
index_in_buffer_jumplist: Option<usize>,
} }
let new_meta = |doc: &Document| BufferMeta { let new_meta = |doc: &Document| BufferMeta {
@ -3153,6 +3154,11 @@ fn buffer_picker(cx: &mut Context) {
is_modified: doc.is_modified(), is_modified: doc.is_modified(),
is_current: doc.id() == current, is_current: doc.id() == current,
focused_at: doc.focused_at, focused_at: doc.focused_at,
index_in_buffer_jumplist: cx
.editor
.buffer_jumplist
.iter()
.position(|id| id == &doc.id()),
}; };
let mut items = cx let mut items = cx
@ -3175,6 +3181,10 @@ fn buffer_picker(cx: &mut Context) {
if meta.is_current { if meta.is_current {
flags.push('*'); flags.push('*');
} }
if let Some(index) = meta.index_in_buffer_jumplist {
flags.push_str(&index.to_string());
}
flags.into() flags.into()
}), }),
PickerColumn::new("path", |meta: &BufferMeta, _| { PickerColumn::new("path", |meta: &BufferMeta, _| {

View File

@ -99,6 +99,51 @@ fn force_quit(cx: &mut compositor::Context, _args: Args, event: PromptEvent) ->
Ok(()) Ok(())
} }
fn buffer_jump(cx: &mut compositor::Context, args: Args, event: PromptEvent) -> anyhow::Result<()> {
if event != PromptEvent::Validate {
return Ok(());
}
let pos: usize = args.first().unwrap_or("0").parse().unwrap_or(0);
if let Some(doc_id) = cx.editor.buffer_jumplist.get(pos) {
cx.editor.switch(*doc_id, Action::Replace);
}
return Ok(());
}
fn add_buffer_to_jumplist(
cx: &mut compositor::Context,
_args: Args,
event: PromptEvent,
) -> anyhow::Result<()> {
if event != PromptEvent::Validate {
return Ok(());
}
let current = view!(cx.editor).doc;
cx.editor.buffer_jumplist.push(current);
return Ok(());
}
fn remove_buffer_from_jumplist(
cx: &mut compositor::Context,
_args: Args,
event: PromptEvent,
) -> anyhow::Result<()> {
if event != PromptEvent::Validate {
return Ok(());
}
let current = view!(cx.editor).doc;
cx.editor
.buffer_jumplist
.retain(|doc_id| *doc_id != current);
return Ok(());
}
fn open(cx: &mut compositor::Context, args: Args, event: PromptEvent) -> anyhow::Result<()> { fn open(cx: &mut compositor::Context, args: Args, event: PromptEvent) -> anyhow::Result<()> {
if event != PromptEvent::Validate { if event != PromptEvent::Validate {
return Ok(()); return Ok(());
@ -2615,6 +2660,39 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
..Signature::DEFAULT ..Signature::DEFAULT
}, },
}, },
TypableCommand {
name: "jump-to-buffer",
aliases: &["j"],
doc: "Switch to a document buffer using its index in the buffer jumplist.",
fun: buffer_jump,
completer: CommandCompleter::all(completers::filename),
signature: Signature {
positionals: (1, None),
..Signature::DEFAULT
},
},
TypableCommand {
name: "add-buffer-to-jumplist",
aliases: &["ab"],
doc: "Add the current document buffer to the buffer jumplist.",
fun: add_buffer_to_jumplist,
completer: CommandCompleter::all(completers::filename),
signature: Signature {
positionals: (0, None),
..Signature::DEFAULT
},
},
TypableCommand {
name: "remove-buffer-from-jumplist",
aliases: &["rb"],
doc: "Remove the current document buffer from the buffer jumplist.",
fun: remove_buffer_from_jumplist,
completer: CommandCompleter::all(completers::filename),
signature: Signature {
positionals: (0, None),
..Signature::DEFAULT
},
},
TypableCommand { TypableCommand {
name: "buffer-close", name: "buffer-close",
aliases: &["bc", "bclose"], aliases: &["bc", "bclose"],

View File

@ -1133,6 +1133,9 @@ pub struct Editor {
pub mouse_down_range: Option<Range>, pub mouse_down_range: Option<Range>,
pub cursor_cache: CursorCache, pub cursor_cache: CursorCache,
/// Stores a manually curated list of document IDs for navigation.
pub buffer_jumplist: Vec<DocumentId>,
} }
pub type Motion = Box<dyn Fn(&mut Editor)>; pub type Motion = Box<dyn Fn(&mut Editor)>;
@ -1255,6 +1258,7 @@ impl Editor {
handlers, handlers,
mouse_down_range: None, mouse_down_range: None,
cursor_cache: CursorCache::default(), cursor_cache: CursorCache::default(),
buffer_jumplist: Vec::new(),
} }
} }
@ -1843,6 +1847,9 @@ impl Editor {
// This will also disallow any follow-up writes // This will also disallow any follow-up writes
self.saves.remove(&doc_id); self.saves.remove(&doc_id);
// Removes the document from the buffer jumplist when closed.
self.buffer_jumplist.retain(|doc| *doc != doc_id);
enum Action { enum Action {
Close(ViewId), Close(ViewId),
ReplaceDoc(ViewId, DocumentId), ReplaceDoc(ViewId, DocumentId),