on master help sign in
Implement "Goto last modification" command (#1067)
commit35c974c9c49f9127da3798c9a8e49795b3c4aadc authorath3 <45574139+ath3@users.noreply.github.com> dateSun 14 Nov 2021, 16:11 (5 years ago) parent0949a0d
6 files changed+47−3
book/src/keymap.md+1 helix-core/src/history.rs+29−1 helix-term/src/commands.rs+14 helix-term/src/keymap.rs+1 helix-term/src/ui/editor.rs+1−1 helix-view/src/document.rs+1−1
book/src/keymap.md+1
@@ -165,6 +165,7 @@ Jumps to various locations.
165165| `a` | Go to the last accessed/alternate file | `goto_last_accessed_file` |
166166| `n` | Go to next buffer | `goto_next_buffer` |
167167| `p` | Go to previous buffer | `goto_previous_buffer` |
168+| `.` | Go to last modification in current file | `goto_last_modification` |
168169
169170#### Match mode
170171
helix-core/src/history.rs+29−1
@@ -1,4 +1,4 @@
1−use crate::{ChangeSet, Rope, State, Transaction};
1+use crate::{Assoc, ChangeSet, Rope, State, Transaction};
22use once_cell::sync::Lazy;
33use regex::Regex;
44use std::num::NonZeroUsize;
@@ -133,6 +133,34 @@ impl History {
133133 Some(&self.revisions[last_child.get()].transaction)
134134 }
135135
136+ // Get the position of last change
137+ pub fn last_edit_pos(&self) -> Option<usize> {
138+ if self.current == 0 {
139+ return None;
140+ }
141+ let current_revision = &self.revisions[self.current];
142+ let primary_selection = current_revision
143+ .inversion
144+ .selection()
145+ .expect("inversion always contains a selection")
146+ .primary();
147+ let (_from, to, _fragment) = current_revision
148+ .transaction
149+ .changes_iter()
150+ // find a change that matches the primary selection
151+ .find(|(from, to, _fragment)| {
152+ crate::Range::new(*from, *to).overlaps(&primary_selection)
153+ })
154+ // or use the first change
155+ .or_else(|| current_revision.transaction.changes_iter().next())
156+ .unwrap();
157+ let pos = current_revision
158+ .transaction
159+ .changes()
160+ .map_pos(to, Assoc::After);
161+ Some(pos)
162+ }
163+
136164 fn lowest_common_ancestor(&self, mut a: usize, mut b: usize) -> usize {
137165 use std::collections::HashSet;
138166 let mut a_path_set = HashSet::new();
helix-term/src/commands.rs+14
@@ -257,6 +257,7 @@ impl Command {
257257 goto_window_middle, "Goto window middle",
258258 goto_window_bottom, "Goto window bottom",
259259 goto_last_accessed_file, "Goto last accessed file",
260+ goto_last_modification, "Goto last modification",
260261 goto_line, "Goto line",
261262 goto_last_line, "Goto last line",
262263 goto_first_diag, "Goto first diagnostic",
@@ -3195,6 +3196,19 @@ fn goto_last_accessed_file(cx: &mut Context) {
31953196 }
31963197}
31973198
3199+fn goto_last_modification(cx: &mut Context) {
3200+ let (view, doc) = current!(cx.editor);
3201+ let pos = doc.history.get_mut().last_edit_pos();
3202+ let text = doc.text().slice(..);
3203+ if let Some(pos) = pos {
3204+ let selection = doc
3205+ .selection(view.id)
3206+ .clone()
3207+ .transform(|range| range.put_cursor(text, pos, doc.mode == Mode::Select));
3208+ doc.set_selection(view.id, selection);
3209+ }
3210+}
3211+
31983212fn select_mode(cx: &mut Context) {
31993213 let (view, doc) = current!(cx.editor);
32003214 let text = doc.text().slice(..);
helix-term/src/keymap.rs+1
@@ -525,6 +525,7 @@ impl Default for Keymaps {
525525 "a" => goto_last_accessed_file,
526526 "n" => goto_next_buffer,
527527 "p" => goto_previous_buffer,
528+ "." => goto_last_modification,
528529 },
529530 ":" => command_mode,
530531
helix-term/src/ui/editor.rs+1−1
@@ -743,7 +743,7 @@ impl EditorView {
743743 std::num::NonZeroUsize::new(cxt.editor.count.map_or(i, |c| c.get() * 10 + i));
744744 }
745745 // special handling for repeat operator
746− key!('.') => {
746+ key!('.') if self.keymaps.pending().is_empty() => {
747747 // first execute whatever put us into insert mode
748748 self.last_insert.0.execute(cxt);
749749 // then replay the inputs
helix-view/src/document.rs+1−1
@@ -98,7 +98,7 @@ pub struct Document {
9898 // It can be used as a cell where we will take it out to get some parts of the history and put
9999 // it back as it separated from the edits. We could split out the parts manually but that will
100100 // be more troublesome.
101− history: Cell<History>,
101+ pub history: Cell<History>,
102102
103103 pub savepoint: Option<Transaction>,
104104