diff --git a/eval.go b/eval.go index e54dabf..603444b 100644 --- a/eval.go +++ b/eval.go @@ -18,15 +18,15 @@ func (e *setExpr) eval(app *app, args []string) { case "dircounts!": gOpts.dircounts = !gOpts.dircounts case "dirfirst": - gOpts.dirfirst = true + gOpts.sortType.option |= dirfirstSort app.nav.sort() app.ui.sort() case "nodirfirst": - gOpts.dirfirst = false + gOpts.sortType.option &= ^dirfirstSort app.nav.sort() app.ui.sort() case "dirfirst!": - gOpts.dirfirst = !gOpts.dirfirst + gOpts.sortType.option ^= dirfirstSort app.nav.sort() app.ui.sort() case "drawbox": @@ -48,15 +48,15 @@ func (e *setExpr) eval(app *app, args []string) { case "globsearch!": gOpts.globsearch = !gOpts.globsearch case "hidden": - gOpts.hidden = true + gOpts.sortType.option |= hiddenSort app.nav.sort() app.ui.sort() case "nohidden": - gOpts.hidden = false + gOpts.sortType.option &= ^hiddenSort app.nav.sort() app.ui.sort() case "hidden!": - gOpts.hidden = !gOpts.hidden + gOpts.sortType.option ^= hiddenSort app.nav.sort() app.ui.sort() case "ignorecase": @@ -72,15 +72,15 @@ func (e *setExpr) eval(app *app, args []string) { case "preview!": gOpts.preview = !gOpts.preview case "reverse": - gOpts.reverse = true + gOpts.sortType.option |= reverseSort app.nav.sort() app.ui.sort() case "noreverse": - gOpts.reverse = false + gOpts.sortType.option &= ^reverseSort app.nav.sort() app.ui.sort() case "reverse!": - gOpts.reverse = !gOpts.reverse + gOpts.sortType.option ^= reverseSort app.nav.sort() app.ui.sort() case "smartcase": @@ -132,7 +132,16 @@ func (e *setExpr) eval(app *app, args []string) { app.ui.print("sortby: value should either be 'natural', 'name', 'size' or 'time'") return } - gOpts.sortby = e.val + switch e.val { + case "natural": + gOpts.sortType.method = naturalSort + case "name": + gOpts.sortType.method = nameSort + case "size": + gOpts.sortType.method = sizeSort + case "time": + gOpts.sortType.method = timeSort + } app.nav.sort() app.ui.sort() case "timefmt": diff --git a/nav.go b/nav.go index 650da57..4aad832 100644 --- a/nav.go +++ b/nav.go @@ -97,6 +97,7 @@ type dir struct { path string // full path of directory fi []*file // displayed files in directory including or excluding hidden ones all []*file // all files in directory including hidden ones (same array as fi) + sortType sortType // sort method and options from last sort } func newDir(path string) *dir { @@ -126,36 +127,36 @@ func (dir *dir) renew() { } func (dir *dir) sort() { + dir.sortType = gOpts.sortType + dir.fi = dir.all - switch gOpts.sortby { - case "natural": + switch gOpts.sortType.method { + case naturalSort: sortFilesStable(dir.fi, func(i, j int) bool { return naturalLess(strings.ToLower(dir.fi[i].Name()), strings.ToLower(dir.fi[j].Name())) }) - case "name": + case nameSort: sortFilesStable(dir.fi, func(i, j int) bool { return strings.ToLower(dir.fi[i].Name()) < strings.ToLower(dir.fi[j].Name()) }) - case "size": + case sizeSort: sortFilesStable(dir.fi, func(i, j int) bool { return dir.fi[i].Size() < dir.fi[j].Size() }) - case "time": + case timeSort: sortFilesStable(dir.fi, func(i, j int) bool { return dir.fi[i].ModTime().Before(dir.fi[j].ModTime()) }) - default: - log.Printf("unknown sorting type: %s", gOpts.sortby) } - if gOpts.reverse { + if gOpts.sortType.option&reverseSort != 0 { for i, j := 0, len(dir.fi)-1; i < j; i, j = i+1, j-1 { dir.fi[i], dir.fi[j] = dir.fi[j], dir.fi[i] } } - if gOpts.dirfirst { + if gOpts.sortType.option&dirfirstSort != 0 { sortFilesStable(dir.fi, func(i, j int) bool { if dir.fi[i].IsDir() == dir.fi[j].IsDir() { return i < j @@ -167,7 +168,7 @@ func (dir *dir) sort() { // when hidden option is disabled, we move hidden files to the // beginning of our file list and then set the beginning of displayed // files to the first non-hidden file in the list - if !gOpts.hidden { + if gOpts.sortType.option&hiddenSort == 0 { sortFilesStable(dir.fi, func(i, j int) bool { if dir.fi[i].Name()[0] == '.' && dir.fi[j].Name()[0] == '.' { return i < j @@ -333,6 +334,11 @@ func (nav *nav) loadDir(path string) *dir { nav.dirCache[path] = d return d } + if d.sortType != gOpts.sortType { + name := d.name() + d.sort() + d.find(name, nav.height) + } return d } diff --git a/opts.go b/opts.go index d6cbbc2..707c76b 100644 --- a/opts.go +++ b/opts.go @@ -2,15 +2,34 @@ package main import "time" +type sortMethod byte + +const ( + naturalSort sortMethod = iota + nameSort + sizeSort + timeSort +) + +type sortOption byte + +const ( + dirfirstSort sortOption = 1 << iota + hiddenSort + reverseSort +) + +type sortType struct { + method sortMethod + option sortOption +} + var gOpts struct { dircounts bool - dirfirst bool drawbox bool globsearch bool - hidden bool ignorecase bool preview bool - reverse bool smartcase bool wrapscan bool scrolloff int @@ -20,24 +39,21 @@ var gOpts struct { previewer string promptfmt string shell string - sortby string timefmt string ratios []int info []string keys map[string]expr cmdkeys map[string]expr cmds map[string]expr + sortType sortType } func init() { gOpts.dircounts = false - gOpts.dirfirst = true gOpts.drawbox = false gOpts.globsearch = false - gOpts.hidden = false gOpts.ignorecase = true gOpts.preview = true - gOpts.reverse = false gOpts.smartcase = true gOpts.wrapscan = true gOpts.scrolloff = 0 @@ -45,10 +61,10 @@ func init() { gOpts.filesep = "\n" gOpts.promptfmt = "\033[32;1m%u@%h\033[0m:\033[34;1m%w/\033[0m\033[1m%f\033[0m" gOpts.shell = gDefaultShell - gOpts.sortby = "natural" gOpts.timefmt = time.ANSIC gOpts.ratios = []int{1, 2, 3} gOpts.info = nil + gOpts.sortType = sortType{naturalSort, dirfirstSort} gOpts.keys = make(map[string]expr)