Skip to content

[Draft] Add simple goto buffer command like Harpoon2 for Helix #13448

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions book/src/generated/typable-cmd.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
| `:quit`, `:q` | Close the current view. |
| `:quit!`, `:q!` | Force close the current view, ignoring unsaved changes. |
| `: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 forcefully, ignoring unsaved changes. |
| `:buffer-close-others`, `:bco`, `:bcloseother` | Close all buffers but the currently focused one. |
Expand Down
10 changes: 10 additions & 0 deletions helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3143,6 +3143,7 @@ fn buffer_picker(cx: &mut Context) {
is_modified: bool,
is_current: bool,
focused_at: std::time::Instant,
index_in_buffer_jumplist: Option<usize>,
}

let new_meta = |doc: &Document| BufferMeta {
Expand All @@ -3151,6 +3152,11 @@ fn buffer_picker(cx: &mut Context) {
is_modified: doc.is_modified(),
is_current: doc.id() == current,
focused_at: doc.focused_at,
index_in_buffer_jumplist: cx
.editor
.buffer_jumplist
.iter()
.position(|id| id == &doc.id()),
};

let mut items = cx
Expand All @@ -3173,6 +3179,10 @@ fn buffer_picker(cx: &mut Context) {
if meta.is_current {
flags.push('*');
}
if let Some(index) = meta.index_in_buffer_jumplist {
flags.push_str(&index.to_string());
}

flags.into()
}),
PickerColumn::new("path", |meta: &BufferMeta, _| {
Expand Down
78 changes: 78 additions & 0 deletions helix-term/src/commands/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,51 @@ fn force_quit(cx: &mut compositor::Context, _args: Args, event: PromptEvent) ->
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<()> {
if event != PromptEvent::Validate {
return Ok(());
Expand Down Expand Up @@ -2615,6 +2660,39 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
..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 {
name: "buffer-close",
aliases: &["bc", "bclose"],
Expand Down
7 changes: 7 additions & 0 deletions helix-view/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,9 @@ pub struct Editor {

pub mouse_down_range: Option<Range>,
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)>;
Expand Down Expand Up @@ -1248,6 +1251,7 @@ impl Editor {
handlers,
mouse_down_range: None,
cursor_cache: CursorCache::default(),
buffer_jumplist: Vec::new(),
}
}

Expand Down Expand Up @@ -1832,6 +1836,9 @@ impl Editor {
// This will also disallow any follow-up writes
self.saves.remove(&doc_id);

// Removes the document from the buffer jumplist when closed.
self.buffer_jumplist.retain(|doc| *doc != doc_id);

enum Action {
Close(ViewId),
ReplaceDoc(ViewId, DocumentId),
Expand Down