lotabout / skim

Fuzzy Finder in rust!
MIT License
5.13k stars 184 forks source link

Multi-select should output items in order in which they were selected #464

Open otto-dev opened 2 years ago

otto-dev commented 2 years ago

In multi-select, items are currently returned according to some internal order, rather than in the order in which they were selected.

For applications where the item order matters, it would be useful to return the items in order of selection. If algorithmic sorting of any kind is desired, it is always possible to do so in a post-processing step. But it is not possible, on the other hand, to recover the order of manual selections, unless skim provides this information.

My use-case involves selecting multiple files for processing where order matters and cannot be inferred from the file names or their contents.

Thanks!

otto-dev commented 2 years ago

For now I have locally patched it like this:

diff --git a/Cargo.toml b/Cargo.toml
index c9254a1..a6bddb2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -42,6 +42,10 @@ crossbeam = "0.8.0"
 beef = "0.5.0" # compact cow
 defer-drop = "1.0.1"

+[dependencies.linked_hash_map]
+package = "linked-hash-map"
+version = "=0.5.6"
+
 [features]
 default = []

diff --git a/src/selection.rs b/src/selection.rs
index 5b55891..e6388b6 100644
--- a/src/selection.rs
+++ b/src/selection.rs
@@ -1,6 +1,5 @@
 use std::cmp::max;
 use std::cmp::min;
-use std::collections::BTreeMap;
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::Arc;

@@ -17,13 +16,14 @@ use crate::{DisplayContext, MatchRange, Matches, Selector, SkimItem, SkimOptions
 use regex::Regex;
 use std::rc::Rc;
 use unicode_width::UnicodeWidthStr;
+use linked_hash_map::LinkedHashMap;

 type ItemIndex = (u32, u32);

 pub struct Selection {
     // all items
     items: OrderedVec<MatchedItem>,
-    selected: BTreeMap<ItemIndex, Arc<dyn SkimItem>>,
+    selected: LinkedHashMap<ItemIndex, Arc<dyn SkimItem>>,

     //
     // |>------ items[items.len()-1]
@@ -63,7 +63,7 @@ impl Selection {
     pub fn new() -> Self {
         Selection {
             items: OrderedVec::new(),
-            selected: BTreeMap::new(),
+            selected: LinkedHashMap::new(),
             item_cursor: 0,
             line_cursor: 0,
             hscroll_offset: 0,