textredux icon indicating copy to clipboard operation
textredux copied to clipboard

preserve files order in search

Open basiliscos opened this issue 7 years ago • 8 comments

There files (sorted) :

$ ls -1 core
buffer.lua
filteredlist.lua
indicator.lua
init.lua
list.lua
style.lua
ui.lua

when I type lua, I'd like to have all that files, keeping the original.

With the proposed patch:

diff --git a/util/matcher.lua b/util/matcher.lua
index ddb2fbf..ebcd36b 100644
--- a/util/matcher.lua
+++ b/util/matcher.lua
@@ -161,6 +161,17 @@ end
 -- @return A table of matcher functions, each taking a line as parameter and
 -- returning a score (or nil for no match).
 function M:_matchers_for_search(search_string)
+  print(search_string);
+  return {
+    function(line)
+      local start_pos, end_pos = string.find(line, search_string, 1, true)
+      if start_pos then
+        return 1, start_pos, end_pos, search_string
+      end
+    end
+  }
+
+--[[
   local fuzzy = self.search_fuzzy
   local fuzzy_penalty = self.fuzzy_score_penalty
   local groups = {}
@@ -184,6 +195,7 @@ function M:_matchers_for_search(search_string)
     end
   end
   return matchers
+]]
 end

I can achive the same.

The default behaviour is a bit crazy: it sorts files by filename length.

ui.lua
list.lua
init.lua
style.lua
buffer.lua
indicator.lua
filteredlist.lua

it's very confusing. I'm also not sure how the current patch can be integrated...

basiliscos avatar Sep 13 '17 19:09 basiliscos

Cool, I'll have a look!

rgieseke avatar Sep 13 '17 19:09 rgieseke

I think the reason for this behaviour is that a match with a large overlap is considered to be better (thus the sorting by length). One give less weight to matches in the extension etc. but I don't see an easy solution here. I agree that simply filtering out non-matches would be better for lists of files ... Maybe there is a way to apply this in the fs sub-module.

rgieseke avatar Sep 13 '17 19:09 rgieseke

I think would be nice to have some switcheable matching policy. The one I proposed can be named "simple_matcher", and the original one "score_match" (or "fuzzy_matcher").

If it is OK for you, I can refactor fs.lua to let it have some variable with default policy, and make it tuneable.

basiliscos avatar Sep 13 '17 19:09 basiliscos

I wouldn't mind if a open dialog always kept the order (so no need for both options).

Maybe it needs to be an option in list - which is then checked in the matching function or somewhere else.

So one creates a list and can define whether it should keep order or not.

So like in list.lua:

--- Whether searches are case insensitive or not.
-- It's possible to override this for a specific list by assigning another
-- value to the instance itself. The default value is `true`.
list.search_case_insensitive = true

--- Whether fuzzy searching should be in addition to explicit matches.
-- It's possible to override this for a specific list by assigning another
-- value to the instance itself. The default value is `true`.
list.search_fuzzy = true

something like list.keep_order?

rgieseke avatar Sep 13 '17 20:09 rgieseke

I got an impression that keep order is exclusive to scores, which lead to the result above; and it seems by scores the shorter names pop up...

basiliscos avatar Sep 13 '17 20:09 basiliscos

Maybe something like this might work:

diff --git a/core/list.lua b/core/list.lua
index 798a114..f65dff0 100644
--- a/core/list.lua
+++ b/core/list.lua
@@ -73,6 +73,8 @@ list.search_case_insensitive = true
 -- value to the instance itself. The default value is `true`.
 list.search_fuzzy = true
 
+list.keep_order = true
+
 --- List instance fields.
 -- These can be set only for a list instance, and not globally for the module.
 -- @section instance
@@ -151,7 +153,8 @@ function list:show()
     matcher = util_matcher.new(
                 self.items,
                 self.search_case_insensitive,
-                self.search_fuzzy
+                self.search_fuzzy,
+                self.keep_order
               ),
    list = self
   }
diff --git a/util/matcher.lua b/util/matcher.lua
index ddb2fbf..fe53bcb 100644
--- a/util/matcher.lua
+++ b/util/matcher.lua
@@ -20,10 +20,11 @@ Defaults to `true`.
 @param search_fuzzy Whether fuzzy searching should be used in addition to
 explicit matching. Defaults to `true`.
 ]]
-function M.new(candidates, search_case_insensitive, search_fuzzy)
+function M.new(candidates, search_case_insensitive, search_fuzzy, keep_order)
   local m = {
     search_case_insensitive = search_case_insensitive,
-    search_fuzzy = search_fuzzy
+    search_fuzzy = search_fuzzy,
+    keep_order = keep_order
   }
   setmetatable(m, { __index = M })
   m:_set_candidates(candidates)
@@ -105,13 +106,17 @@ function M:match(search)
   for i, line in ipairs(lines) do
     local score = match_score(line.text, matchers)
     if score then
-      matches[#matches + 1] = { index = line.index, score = score }
+      matches[#matches + 1] = { index = line.index, score = score, text = line.text }
       matching_lines[#matching_lines + 1] = line
     end
   end
   cache.lines[search] = matching_lines
 
-  table.sort(matches, function(a ,b) return a.score < b.score end)
+  if self.keep_order then
+    table.sort(matches, function(a ,b) return a.text < b.text end)
+  else
+    table.sort(matches, function(a ,b) return a.score < b.score end)
+  end
   local matching_candidates = {}
   for _, match in ipairs(matches) do
     matching_candidates[#matching_candidates + 1] = self.candidates[match.index]

rgieseke avatar Sep 14 '17 04:09 rgieseke

Seems fine for me! Thanks!

basiliscos avatar Sep 14 '17 11:09 basiliscos

Great, let me know if you discover any issues. Also not sure yet where and whether this should be default ...

rgieseke avatar Sep 14 '17 11:09 rgieseke