77 "path/filepath"
88 "regexp"
99 "slices"
10+ "sort"
1011 "strings"
1112 "sync"
1213
@@ -33,7 +34,7 @@ type ScanCache struct {
3334 mutex sync.Mutex
3435 root_dir , search_text string
3536 in_progress bool
36- matches []ResultItem
37+ matches []* ResultItem
3738}
3839
3940func (sc * ScanCache ) get_cached_entries (root_dir string ) (ans []ResultItem , found bool ) {
@@ -93,48 +94,72 @@ func (sc *ScanCache) fs_scan(root_dir, current_dir string, max_depth int, exclud
9394 return
9495}
9596
96- func (sc * ScanCache ) scan (root_dir , search_text string , max_depth int , exclude_patterns []* regexp.Regexp ) (ans []ResultItem ) {
97- seen := make (map [string ]bool , 1024 )
98- ans = sc .fs_scan (root_dir , root_dir , max_depth , exclude_patterns , seen )
99- if search_text == "" {
100- slices .SortFunc (ans , func (a , b ResultItem ) int {
101- switch a .dir_entry .IsDir () {
102- case true :
103- switch b .dir_entry .IsDir () {
104- case true :
105- return strings .Compare (strings .ToLower (a .text ), strings .ToLower (b .text ))
106- case false :
107- return - 1
108- }
109- case false :
110- switch b .dir_entry .IsDir () {
111- case true :
112- return 1
113- case false :
114- return strings .Compare (strings .ToLower (a .text ), strings .ToLower (b .text ))
97+ func sort_items_without_search_text (items []ResultItem ) (ans []* ResultItem ) {
98+ type s struct {
99+ ltext string
100+ num_of_slashes int
101+ is_dir bool
102+ is_hidden bool
103+ r * ResultItem
104+ }
105+ hidden_pat := regexp .MustCompile (`(^|/)\.[^/]+(/|$)` )
106+ d := utils .Map (func (x ResultItem ) s {
107+ return s {strings .ToLower (x .text ), strings .Count (x .text , "/" ), x .dir_entry .IsDir (), hidden_pat .MatchString (x .abspath ), & x }
108+ }, items )
109+ sort .Slice (d , func (i , j int ) bool {
110+ a , b := d [i ], d [j ]
111+ if a .num_of_slashes == b .num_of_slashes {
112+ if a .is_dir == b .is_dir {
113+ if a .is_hidden == b .is_hidden {
114+ return a .ltext < b .ltext
115115 }
116+ return b .is_hidden
116117 }
117- return 0
118- })
119- } else {
120- pm := make (map [string ]ResultItem , len (ans ))
121- for _ , x := range ans {
122- pm [x .text ] = x
118+ return a .is_dir
119+ }
120+ return a .num_of_slashes < b .num_of_slashes
121+ })
122+ return utils .Map (func (s s ) * ResultItem { return s .r }, d )
123+ }
124+
125+ func get_modified_score (r * ResultItem , score float64 , score_patterns []ScorePattern ) float64 {
126+ for _ , sp := range score_patterns {
127+ if sp .pat .MatchString (r .abspath ) {
128+ score = sp .op (score , sp .val )
123129 }
124- matches := utils .Filter (subseq .ScoreItems (search_text , utils .Keys (pm ), subseq.Options {}), func (x * subseq.Match ) bool {
125- return x .Score > 0
126- })
127- slices .SortFunc (matches , func (a , b * subseq.Match ) int { return cmp .Compare (b .Score , a .Score ) })
128- ans = utils .Map (func (m * subseq.Match ) ResultItem {
129- x := pm [m .Text ]
130- x .positions = m .Positions
131- return x
132- }, matches )
133130 }
134- return ans
131+ return score
132+ }
133+
134+ func (sc * ScanCache ) scan (root_dir , search_text string , max_depth int , exclude_patterns []* regexp.Regexp , score_patterns []ScorePattern ) (ans []* ResultItem ) {
135+ seen := make (map [string ]bool , 1024 )
136+ matches := sc .fs_scan (root_dir , root_dir , max_depth , exclude_patterns , seen )
137+ if search_text == "" {
138+ ans = sort_items_without_search_text (matches )
139+ return
140+ }
141+ pm := make (map [string ]* ResultItem , len (ans ))
142+ for _ , x := range matches {
143+ nx := x
144+ pm [x .text ] = & nx
145+ }
146+ matches2 := utils .Filter (subseq .ScoreItems (search_text , utils .Keys (pm ), subseq.Options {}), func (x * subseq.Match ) bool {
147+ return x .Score > 0
148+ })
149+ type s struct {
150+ r * ResultItem
151+ score float64
152+ }
153+ ss := utils .Map (func (m * subseq.Match ) s {
154+ x := pm [m .Text ]
155+ x .positions = m .Positions
156+ return s {x , get_modified_score (x , m .Score , score_patterns )}
157+ }, matches2 )
158+ slices .SortFunc (ss , func (a , b s ) int { return cmp .Compare (b .score , a .score ) })
159+ return utils .Map (func (s s ) * ResultItem { return s .r }, ss )
135160}
136161
137- func (h * Handler ) get_results () (ans []ResultItem , in_progress bool ) {
162+ func (h * Handler ) get_results () (ans []* ResultItem , in_progress bool ) {
138163 sc := & h .scan_cache
139164 sc .mutex .Lock ()
140165 defer sc .mutex .Unlock ()
@@ -150,8 +175,9 @@ func (h *Handler) get_results() (ans []ResultItem, in_progress bool) {
150175 search_text := h .state .SearchText ()
151176 sc .root_dir = root_dir
152177 sc .search_text = search_text
178+ md , ep , sp := h .state .MaxDepth (), h .state .ExcludePatterns (), h .state .ScorePatterns ()
153179 go func () {
154- results := sc .scan (root_dir , search_text , h . state . MaxDepth (), h . state . ExcludePatterns () )
180+ results := sc .scan (root_dir , search_text , md , ep , sp )
155181 sc .mutex .Lock ()
156182 defer sc .mutex .Unlock ()
157183 if root_dir == sc .root_dir && search_text == sc .search_text {
0 commit comments