on master help sign in
Add last modified file (gm) (#1093)
e2b428cIvan Tham
book/src/keymap.md+2−1
@@ -165,13 +165,14 @@ Jumps to various locations.
165| `l` | Go to the end of the line | `goto_line_end` |
165| `l` | Go to the end of the line | `goto_line_end` |
166| `s` | Go to first non-whitespace character of the line | `goto_first_nonwhitespace` |
166| `s` | Go to first non-whitespace character of the line | `goto_first_nonwhitespace` |
167| `t` | Go to the top of the screen | `goto_window_top` |
167| `t` | Go to the top of the screen | `goto_window_top` |
168−| `m` | Go to the middle of the screen | `goto_window_middle` |
168+| `c` | Go to the middle of the screen | `goto_window_center` |
169| `b` | Go to the bottom of the screen | `goto_window_bottom` |
169| `b` | Go to the bottom of the screen | `goto_window_bottom` |
170| `d` | Go to definition (**LSP**) | `goto_definition` |
170| `d` | Go to definition (**LSP**) | `goto_definition` |
171| `y` | Go to type definition (**LSP**) | `goto_type_definition` |
171| `y` | Go to type definition (**LSP**) | `goto_type_definition` |
172| `r` | Go to references (**LSP**) | `goto_reference` |
172| `r` | Go to references (**LSP**) | `goto_reference` |
173| `i` | Go to implementation (**LSP**) | `goto_implementation` |
173| `i` | Go to implementation (**LSP**) | `goto_implementation` |
174| `a` | Go to the last accessed/alternate file | `goto_last_accessed_file` |
174| `a` | Go to the last accessed/alternate file | `goto_last_accessed_file` |
175+| `m` | Go to the last modified/alternate file | `goto_last_modified_file` |
175| `n` | Go to next buffer | `goto_next_buffer` |
176| `n` | Go to next buffer | `goto_next_buffer` |
176| `p` | Go to previous buffer | `goto_previous_buffer` |
177| `p` | Go to previous buffer | `goto_previous_buffer` |
177| `.` | Go to last modification in current file | `goto_last_modification` |
178| `.` | Go to last modification in current file | `goto_last_modification` |
helix-term/src/commands.rs+17−2
@@ -264,9 +264,10 @@ impl Command {
264 goto_file_vsplit, "Goto files in the selection in vertical splits",
264 goto_file_vsplit, "Goto files in the selection in vertical splits",
265 goto_reference, "Goto references",
265 goto_reference, "Goto references",
266 goto_window_top, "Goto window top",
266 goto_window_top, "Goto window top",
267− goto_window_middle, "Goto window middle",
267+ goto_window_center, "Goto window center",
268 goto_window_bottom, "Goto window bottom",
268 goto_window_bottom, "Goto window bottom",
269 goto_last_accessed_file, "Goto last accessed file",
269 goto_last_accessed_file, "Goto last accessed file",
270+ goto_last_modified_file, "Goto last modified file",
270 goto_last_modification, "Goto last modification",
271 goto_last_modification, "Goto last modification",
271 goto_line, "Goto line",
272 goto_line, "Goto line",
272 goto_last_line, "Goto last line",
273 goto_last_line, "Goto last line",
@@ -763,7 +764,7 @@ fn goto_window_top(cx: &mut Context) {
763 goto_window(cx, Align::Top)
764 goto_window(cx, Align::Top)
764}
765}
765
766
766−fn goto_window_middle(cx: &mut Context) {
767+fn goto_window_center(cx: &mut Context) {
767 goto_window(cx, Align::Center)
768 goto_window(cx, Align::Center)
768}
769}
769
770
@@ -3610,6 +3611,20 @@ fn goto_last_modification(cx: &mut Context) {
3610 }
3611 }
3611}
3612}
3612
3613
3614+fn goto_last_modified_file(cx: &mut Context) {
3615+ let view = view!(cx.editor);
3616+ let alternate_file = view
3617+ .last_modified_docs
3618+ .into_iter()
3619+ .flatten()
3620+ .find(|&id| id != view.doc);
3621+ if let Some(alt) = alternate_file {
3622+ cx.editor.switch(alt, Action::Replace);
3623+ } else {
3624+ cx.editor.set_error("no last modified buffer".to_owned())
3625+ }
3626+}
3627+
3613fn select_mode(cx: &mut Context) {
3628fn select_mode(cx: &mut Context) {
3614 let (view, doc) = current!(cx.editor);
3629 let (view, doc) = current!(cx.editor);
3615 let text = doc.text().slice(..);
3630 let text = doc.text().slice(..);
helix-term/src/keymap.rs+2−1
@@ -521,9 +521,10 @@ impl Default for Keymaps {
521 "r" => goto_reference,
521 "r" => goto_reference,
522 "i" => goto_implementation,
522 "i" => goto_implementation,
523 "t" => goto_window_top,
523 "t" => goto_window_top,
524− "m" => goto_window_middle,
524+ "c" => goto_window_center,
525 "b" => goto_window_bottom,
525 "b" => goto_window_bottom,
526 "a" => goto_last_accessed_file,
526 "a" => goto_last_accessed_file,
527+ "m" => goto_last_modified_file,
527 "n" => goto_next_buffer,
528 "n" => goto_next_buffer,
528 "p" => goto_previous_buffer,
529 "p" => goto_previous_buffer,
529 "." => goto_last_modification,
530 "." => goto_last_modification,
helix-view/src/document.rs+6
@@ -104,6 +104,7 @@ pub struct Document {
104
104
105 last_saved_revision: usize,
105 last_saved_revision: usize,
106 version: i32, // should be usize?
106 version: i32, // should be usize?
107+ pub(crate) modified_since_accessed: bool,
107
108
108 diagnostics: Vec<Diagnostic>,
109 diagnostics: Vec<Diagnostic>,
109 language_server: Option<Arc<helix_lsp::Client>>,
110 language_server: Option<Arc<helix_lsp::Client>>,
@@ -127,6 +128,7 @@ impl fmt::Debug for Document {
127 // .field("history", &self.history)
128 // .field("history", &self.history)
128 .field("last_saved_revision", &self.last_saved_revision)
129 .field("last_saved_revision", &self.last_saved_revision)
129 .field("version", &self.version)
130 .field("version", &self.version)
131+ .field("modified_since_accessed", &self.modified_since_accessed)
130 .field("diagnostics", &self.diagnostics)
132 .field("diagnostics", &self.diagnostics)
131 // .field("language_server", &self.language_server)
133 // .field("language_server", &self.language_server)
132 .finish()
134 .finish()
@@ -344,6 +346,7 @@ impl Document {
344 history: Cell::new(History::default()),
346 history: Cell::new(History::default()),
345 savepoint: None,
347 savepoint: None,
346 last_saved_revision: 0,
348 last_saved_revision: 0,
349+ modified_since_accessed: false,
347 language_server: None,
350 language_server: None,
348 }
351 }
349 }
352 }
@@ -639,6 +642,9 @@ impl Document {
639 selection.clone().ensure_invariants(self.text.slice(..)),
642 selection.clone().ensure_invariants(self.text.slice(..)),
640 );
643 );
641 }
644 }
645+
646+ // set modified since accessed
647+ self.modified_since_accessed = true;
642 }
648 }
643
649
644 if !transaction.changes().is_empty() {
650 if !transaction.changes().is_empty() {
helix-view/src/editor.rs+12−2
@@ -369,7 +369,8 @@ impl Editor {
369 .tree
369 .tree
370 .traverse()
370 .traverse()
371 .any(|(_, v)| v.doc == doc.id && v.id != view.id);
371 .any(|(_, v)| v.doc == doc.id && v.id != view.id);
372+
372− let view = view_mut!(self);
373+ let (view, doc) = current!(self);
373 if remove_empty_scratch {
374 if remove_empty_scratch {
374 // Copy `doc.id` into a variable before calling `self.documents.remove`, which requires a mutable
375 // Copy `doc.id` into a variable before calling `self.documents.remove`, which requires a mutable
375 // borrow, invalidating direct access to `doc.id`.
376 // borrow, invalidating direct access to `doc.id`.
@@ -378,7 +379,16 @@ impl Editor {
378 } else {
379 } else {
379 let jump = (view.doc, doc.selection(view.id).clone());
380 let jump = (view.doc, doc.selection(view.id).clone());
380 view.jumps.push(jump);
381 view.jumps.push(jump);
382+ // Set last accessed doc if it is a different document
383+ if doc.id != id {
381− view.last_accessed_doc = Some(view.doc);
384+ view.last_accessed_doc = Some(view.doc);
385+ // Set last modified doc if modified and last modified doc is different
386+ if std::mem::take(&mut doc.modified_since_accessed)
387+ && view.last_modified_docs[0] != Some(id)
388+ {
389+ view.last_modified_docs = [Some(view.doc), view.last_modified_docs[0]];
390+ }
391+ }
382 }
392 }
383
393
384 let view_id = view.id;
394 let view_id = view.id;
helix-view/src/view.rs+6
@@ -75,6 +75,11 @@ pub struct View {
75 pub jumps: JumpList,
75 pub jumps: JumpList,
76 /// the last accessed file before the current one
76 /// the last accessed file before the current one
77 pub last_accessed_doc: Option<DocumentId>,
77 pub last_accessed_doc: Option<DocumentId>,
78+ /// the last modified files before the current one
79+ /// ordered from most frequent to least frequent
80+ // uses two docs because we want to be able to swap between the
81+ // two last modified docs which we need to manually keep track of
82+ pub last_modified_docs: [Option<DocumentId>; 2],
78}
83}
79
84
80impl View {
85impl View {
@@ -86,6 +91,7 @@ impl View {
86 area: Rect::default(), // will get calculated upon inserting into tree
91 area: Rect::default(), // will get calculated upon inserting into tree
87 jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel
92 jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel
88 last_accessed_doc: None,
93 last_accessed_doc: None,
94+ last_modified_docs: [None, None],
89 }
95 }
90 }
96 }
91
97