Skip to content

Commit f138d49

Browse files
committed
sort: filter first and only once before sorting
Mostly authored by @joelim-work
1 parent 62103c9 commit f138d49

File tree

1 file changed

+50
-86
lines changed

1 file changed

+50
-86
lines changed

nav.go

Lines changed: 50 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,53 @@ func (dir *dir) sort() {
203203
dir.dironly = getDirOnly(dir.path)
204204
dir.hidden = getHidden(dir.path)
205205
dir.reverse = getReverse(dir.path)
206-
207206
dir.hiddenfiles = gOpts.hiddenfiles
208207
dir.ignorecase = gOpts.ignorecase
209208
dir.ignoredia = gOpts.ignoredia
210209

210+
dir.files = dir.allFiles
211+
212+
var filterFun func(*file) bool = nil
213+
addFilter := func(fun func(*file) bool) {
214+
if filterFun == nil {
215+
filterFun = fun
216+
} else {
217+
oldFilterFun := filterFun
218+
filterFun = func(f *file) bool {
219+
return oldFilterFun(f) && fun(f)
220+
}
221+
}
222+
}
223+
224+
if dir.dironly {
225+
addFilter(func(f *file) bool {
226+
return f.IsDir()
227+
})
228+
}
229+
230+
if !dir.hidden {
231+
addFilter(func(f *file) bool {
232+
return !isHidden(f, dir.path, dir.hiddenfiles)
233+
})
234+
}
235+
236+
if len(dir.filter) != 0 {
237+
addFilter(func(f *file) bool {
238+
return !isFiltered(f, dir.filter)
239+
})
240+
}
241+
242+
if filterFun != nil {
243+
var filtered []*file
244+
for _, file := range dir.files {
245+
if filterFun(file) {
246+
filtered = append(filtered, file)
247+
}
248+
}
249+
dir.files = filtered
250+
}
251+
252+
211253
collopts := []collate.Option{}
212254
if dir.ignorecase {
213255
collopts = append(collopts, collate.IgnoreCase)
@@ -218,18 +260,12 @@ func (dir *dir) sort() {
218260
if dir.sortby == naturalSort {
219261
collopts = append(collopts, collate.Numeric)
220262
}
221-
coll := collate.New(language.English, collopts...)
222-
223-
dir.files = dir.allFiles
263+
coll := collate.New(language.Und, collopts...)
224264

225265
var lessfun func(i, j int) bool
226266

227267
switch dir.sortby {
228-
case naturalSort:
229-
lessfun = func(i, j int) bool {
230-
return coll.CompareString(dir.files[i].Name(), dir.files[j].Name()) == -1
231-
}
232-
case nameSort:
268+
case nameSort, naturalSort:
233269
lessfun = func(i, j int) bool {
234270
return coll.CompareString(dir.files[i].Name(), dir.files[j].Name()) == -1
235271
}
@@ -251,100 +287,28 @@ func (dir *dir) sort() {
251287
}
252288
case extSort:
253289
lessfun = func(i, j int) bool {
254-
ext1, ext2 := dir.files[i].ext, dir.files[j].ext
255-
256-
// if the extension could not be determined (directories, files without)
257-
// use a zero byte so that these files can be ranked higher
258-
if ext1 == "" {
259-
ext1 = "\x00"
260-
}
261-
if ext2 == "" {
262-
ext2 = "\x00"
263-
}
264-
265-
// in order to also have natural sorting with the filenames
266-
// combine the name with the ext but have the ext at the front
267-
extcmp := coll.CompareString(ext1, ext2)
268-
return extcmp == -1 || extcmp == 0 &&
269-
coll.CompareString(dir.files[i].Name(), dir.files[j].Name()) == -1
290+
cmp := coll.CompareString(dir.files[i].ext, dir.files[j].ext)
291+
return cmp == -1 || cmp == 0 && coll.CompareString(dir.files[i].Name(), dir.files[j].Name()) == -1
270292
}
271293
}
272294

273295
if dir.reverse {
274-
oldlessfun := lessfun // In order to capture lessfun by value
296+
oldlessfun := lessfun
275297
lessfun = func(i, j int) bool {
276298
return oldlessfun(j, i)
277299
}
278300
}
279301

280-
// when dironly option is enabled, we move files to the beginning of our file
281-
// list and then set the beginning of displayed files to the first directory
282-
// in the list
283-
if dir.dironly {
284-
sort.SliceStable(dir.files, func(i, j int) bool {
285-
if !dir.files[i].IsDir() && !dir.files[j].IsDir() {
286-
return i < j
287-
}
288-
return !dir.files[i].IsDir()
289-
})
290-
dir.files = func() []*file {
291-
for i, f := range dir.files {
292-
if f.IsDir() {
293-
return dir.files[i:]
294-
}
295-
}
296-
return dir.files[len(dir.files):]
297-
}()
298-
} else if dir.dirfirst {
302+
if dir.dirfirst {
299303
oldlessfun := lessfun
300-
lessfun = func(i, j int) bool {
304+
lessfun = func(i, j int) bool {
301305
if dir.files[i].IsDir() == dir.files[j].IsDir() {
302306
return oldlessfun(i, j)
303307
}
304308
return dir.files[i].IsDir()
305309
}
306310
}
307311

308-
// when hidden option is disabled, we move hidden files to the
309-
// beginning of our file list and then set the beginning of displayed
310-
// files to the first non-hidden file in the list
311-
if !dir.hidden {
312-
sort.SliceStable(dir.files, func(i, j int) bool {
313-
if isHidden(dir.files[i], dir.path, dir.hiddenfiles) && isHidden(dir.files[j], dir.path, dir.hiddenfiles) {
314-
return i < j
315-
}
316-
return isHidden(dir.files[i], dir.path, dir.hiddenfiles)
317-
})
318-
for i, f := range dir.files {
319-
if !isHidden(f, dir.path, dir.hiddenfiles) {
320-
dir.files = dir.files[i:]
321-
break
322-
}
323-
}
324-
if len(dir.files) > 0 && isHidden(dir.files[len(dir.files)-1], dir.path, dir.hiddenfiles) {
325-
dir.files = dir.files[len(dir.files):]
326-
}
327-
}
328-
329-
if len(dir.filter) != 0 {
330-
sort.SliceStable(dir.files, func(i, j int) bool {
331-
if isFiltered(dir.files[i], dir.filter) && isFiltered(dir.files[j], dir.filter) {
332-
return i < j
333-
}
334-
return isFiltered(dir.files[i], dir.filter)
335-
})
336-
for i, f := range dir.files {
337-
if !isFiltered(f, dir.filter) {
338-
dir.files = dir.files[i:]
339-
break
340-
}
341-
}
342-
if len(dir.files) > 0 && isFiltered(dir.files[len(dir.files)-1], dir.filter) {
343-
dir.files = dir.files[len(dir.files):]
344-
}
345-
}
346-
347-
// Finally sort after filtering it all
348312
sort.SliceStable(dir.files, lessfun)
349313

350314
dir.ind = max(dir.ind, 0)

0 commit comments

Comments
 (0)