From 6a1bb81f1022533c226395aaa41439ab1ea41dd4 Mon Sep 17 00:00:00 2001
From: Evgeniy Tatarkin <tatarkin.evg@gmail.com>
Date: Fri, 28 Apr 2023 19:05:14 +0300
Subject: [PATCH] Sort the buffer picker by most recent access (#2980)

---
 helix-term/src/commands.rs | 18 +++++++++++++-----
 helix-view/src/document.rs |  9 +++++++++
 helix-view/src/editor.rs   |  8 ++++++++
 3 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 5a75553c..88393ff4 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -2473,6 +2473,7 @@ fn buffer_picker(cx: &mut Context) {
         path: Option<PathBuf>,
         is_modified: bool,
         is_current: bool,
+        focused_at: std::time::Instant,
     }
 
     impl ui::menu::Item for BufferMeta {
@@ -2505,14 +2506,21 @@ fn buffer_picker(cx: &mut Context) {
         path: doc.path().cloned(),
         is_modified: doc.is_modified(),
         is_current: doc.id() == current,
+        focused_at: doc.focused_at,
     };
 
+    let mut items = cx
+        .editor
+        .documents
+        .values()
+        .map(|doc| new_meta(doc))
+        .collect::<Vec<BufferMeta>>();
+
+    // mru
+    items.sort_unstable_by_key(|item| std::cmp::Reverse(item.focused_at));
+
     let picker = FilePicker::new(
-        cx.editor
-            .documents
-            .values()
-            .map(|doc| new_meta(doc))
-            .collect(),
+        items,
         (),
         |cx, meta, action| {
             cx.editor.switch(meta.id, action);
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index eca60026..5ede5bc6 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -169,6 +169,9 @@ pub struct Document {
 
     diff_handle: Option<DiffHandle>,
     version_control_head: Option<Arc<ArcSwap<Box<str>>>>,
+
+    // when document was used for most-recent-used buffer picker
+    pub focused_at: std::time::Instant,
 }
 
 /// Inlay hints for a single `(Document, View)` combo.
@@ -496,6 +499,7 @@ impl Document {
             diff_handle: None,
             config,
             version_control_head: None,
+            focused_at: std::time::Instant::now(),
         }
     }
     pub fn default(config: Arc<dyn DynAccess<Config>>) -> Self {
@@ -908,6 +912,11 @@ impl Document {
         }
     }
 
+    /// Mark document as recent used for MRU sorting
+    pub fn mark_as_focused(&mut self) {
+        self.focused_at = std::time::Instant::now();
+    }
+
     /// Remove a view's selection and inlay hints from this document.
     pub fn remove_view(&mut self, view_id: ViewId) {
         self.selections.remove(&view_id);
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index fd0abe91..005c6667 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -1176,6 +1176,7 @@ impl Editor {
         let doc = doc_mut!(self, &doc_id);
         doc.ensure_view_init(view.id);
         view.sync_changes(doc);
+        doc.mark_as_focused();
 
         align_view(doc, view, Align::Center);
     }
@@ -1246,6 +1247,7 @@ impl Editor {
                 let view_id = view!(self).id;
                 let doc = doc_mut!(self, &id);
                 doc.ensure_view_init(view_id);
+                doc.mark_as_focused();
                 return;
             }
             Action::HorizontalSplit | Action::VerticalSplit => {
@@ -1267,6 +1269,7 @@ impl Editor {
                 // initialize selection for view
                 let doc = doc_mut!(self, &id);
                 doc.ensure_view_init(view_id);
+                doc.mark_as_focused();
             }
         }
 
@@ -1417,6 +1420,7 @@ impl Editor {
             let view_id = self.tree.insert(view);
             let doc = doc_mut!(self, &doc_id);
             doc.ensure_view_init(view_id);
+            doc.mark_as_focused();
         }
 
         self._refresh();
@@ -1471,6 +1475,10 @@ impl Editor {
                 view.sync_changes(doc);
             }
         }
+
+        let view = view!(self, view_id);
+        let doc = doc_mut!(self, &view.doc);
+        doc.mark_as_focused();
     }
 
     pub fn focus_next(&mut self) {