summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoe Lim <50560759+joelim-work@users.noreply.github.com>2024-01-18 11:15:06 +1100
committerGitHub <noreply@github.com>2024-01-18 11:15:06 +1100
commitb401318046c4d4260ab982e9a4ce1dabf5b5623f (patch)
tree34c6521cfc2d63407b46865f0a4290e46e21b190
parent6af25565d4d2c6a2914905b59ae5fa607b1472a5 (diff)
Implement sort options as separate variables (#1577)
-rw-r--r--eval.go37
-rw-r--r--main.go7
-rw-r--r--nav.go71
-rw-r--r--opts.go102
4 files changed, 100 insertions, 117 deletions
diff --git a/eval.go b/eval.go
index 59bfc62..25be197 100644
--- a/eval.go
+++ b/eval.go
@@ -137,9 +137,9 @@ func (e *setExpr) eval(app *app, args []string) {
gOpts.dircounts = !gOpts.dircounts
case "dirfirst":
if e.val == "" || e.val == "true" {
- gOpts.sortType.option |= dirfirstSort
+ gOpts.dirfirst = true
} else if e.val == "false" {
- gOpts.sortType.option &= ^dirfirstSort
+ gOpts.dirfirst = false
} else {
app.ui.echoerr("dirfirst: value should be empty, 'true', or 'false'")
return
@@ -151,7 +151,7 @@ func (e *setExpr) eval(app *app, args []string) {
app.ui.echoerrf("nodirfirst: unexpected value: %s", e.val)
return
}
- gOpts.sortType.option &= ^dirfirstSort
+ gOpts.dirfirst = false
app.nav.sort()
app.ui.sort()
case "dirfirst!":
@@ -159,7 +159,7 @@ func (e *setExpr) eval(app *app, args []string) {
app.ui.echoerrf("dirfirst!: unexpected value: %s", e.val)
return
}
- gOpts.sortType.option ^= dirfirstSort
+ gOpts.dirfirst = !gOpts.dirfirst
app.nav.sort()
app.ui.sort()
case "dironly":
@@ -304,9 +304,9 @@ func (e *setExpr) eval(app *app, args []string) {
app.ui.loadFile(app, true)
case "hidden":
if e.val == "" || e.val == "true" {
- gOpts.sortType.option |= hiddenSort
+ gOpts.hidden = true
} else if e.val == "false" {
- gOpts.sortType.option &= ^hiddenSort
+ gOpts.hidden = false
} else {
app.ui.echoerr("hidden: value should be empty, 'true', or 'false'")
return
@@ -320,7 +320,7 @@ func (e *setExpr) eval(app *app, args []string) {
app.ui.echoerrf("nohidden: unexpected value: %s", e.val)
return
}
- gOpts.sortType.option &= ^hiddenSort
+ gOpts.hidden = false
app.nav.sort()
app.nav.position()
app.ui.sort()
@@ -330,7 +330,7 @@ func (e *setExpr) eval(app *app, args []string) {
app.ui.echoerrf("hidden!: unexpected value: %s", e.val)
return
}
- gOpts.sortType.option ^= hiddenSort
+ gOpts.hidden = !gOpts.hidden
app.nav.sort()
app.nav.position()
app.ui.sort()
@@ -708,9 +708,9 @@ func (e *setExpr) eval(app *app, args []string) {
gOpts.relativenumber = !gOpts.relativenumber
case "reverse":
if e.val == "" || e.val == "true" {
- gOpts.sortType.option |= reverseSort
+ gOpts.reverse = true
} else if e.val == "false" {
- gOpts.sortType.option &= ^reverseSort
+ gOpts.reverse = false
} else {
app.ui.echoerr("reverse: value should be empty, 'true', or 'false'")
return
@@ -722,7 +722,7 @@ func (e *setExpr) eval(app *app, args []string) {
app.ui.echoerrf("noreverse: unexpected value: %s", e.val)
return
}
- gOpts.sortType.option &= ^reverseSort
+ gOpts.reverse = false
app.nav.sort()
app.ui.sort()
case "reverse!":
@@ -730,7 +730,7 @@ func (e *setExpr) eval(app *app, args []string) {
app.ui.echoerrf("reverse!: unexpected value: %s", e.val)
return
}
- gOpts.sortType.option ^= reverseSort
+ gOpts.reverse = !gOpts.reverse
app.nav.sort()
app.ui.sort()
case "scrolloff":
@@ -821,7 +821,7 @@ func (e *setExpr) eval(app *app, args []string) {
app.ui.echoerr(invalidSortErrorMessage)
return
}
- gOpts.sortType.method = method
+ gOpts.sortby = method
app.nav.sort()
app.ui.sort()
case "statfmt":
@@ -977,8 +977,7 @@ func (e *setLocalExpr) eval(app *app, args []string) {
if val, ok := gLocalOpts.dirfirsts[path]; ok {
gLocalOpts.dirfirsts[path] = !val
} else {
- val = gOpts.sortType.option&dirfirstSort != 0
- gLocalOpts.dirfirsts[path] = !val
+ gLocalOpts.dirfirsts[path] = !gOpts.dirfirst
}
app.nav.sort()
app.ui.sort()
@@ -1040,8 +1039,7 @@ func (e *setLocalExpr) eval(app *app, args []string) {
if val, ok := gLocalOpts.hiddens[path]; ok {
gLocalOpts.hiddens[path] = !val
} else {
- val = gOpts.sortType.option&hiddenSort != 0
- gLocalOpts.hiddens[path] = !val
+ gLocalOpts.hiddens[path] = !gOpts.hidden
}
app.nav.sort()
app.ui.sort()
@@ -1087,8 +1085,7 @@ func (e *setLocalExpr) eval(app *app, args []string) {
if val, ok := gLocalOpts.reverses[path]; ok {
gLocalOpts.reverses[path] = !val
} else {
- val = gOpts.sortType.option&reverseSort != 0
- gLocalOpts.reverses[path] = !val
+ gLocalOpts.reverses[path] = !gOpts.reverse
}
app.nav.sort()
app.ui.sort()
@@ -1098,7 +1095,7 @@ func (e *setLocalExpr) eval(app *app, args []string) {
app.ui.echoerr(invalidSortErrorMessage)
return
}
- gLocalOpts.sortMethods[path] = method
+ gLocalOpts.sortbys[path] = method
app.nav.sort()
app.ui.sort()
default:
diff --git a/main.go b/main.go
index 759f72f..985d842 100644
--- a/main.go
+++ b/main.go
@@ -137,12 +137,7 @@ func getOptsMap() map[string]string {
continue
}
- if name == "lf_sortType" {
- opts["lf_sortby"] = string(gOpts.sortType.method)
- opts["lf_reverse"] = strconv.FormatBool(gOpts.sortType.option&reverseSort != 0)
- opts["lf_hidden"] = strconv.FormatBool(gOpts.sortType.option&hiddenSort != 0)
- opts["lf_dirfirst"] = strconv.FormatBool(gOpts.sortType.option&dirfirstSort != 0)
- } else if name == "lf_user" {
+ if name == "lf_user" {
// set each user option
for key, value := range gOpts.user {
opts[name+"_"+key] = value
diff --git a/nav.go b/nav.go
index c63e829..8acedde 100644
--- a/nav.go
+++ b/nav.go
@@ -161,21 +161,24 @@ func readdir(path string) ([]*file, error) {
}
type dir struct {
- loading bool // directory is loading from disk
- loadTime time.Time // current loading or last load time
- ind int // index of current entry in files
- pos int // position of current entry in ui
- path string // full path of directory
- files []*file // displayed files in directory including or excluding hidden ones
- allFiles []*file // all files in directory including hidden ones (same array as files)
- sortType sortType // sort method and options from last sort
- dironly bool // dironly value from last sort
- hiddenfiles []string // hiddenfiles value from last sort
- filter []string // last filter for this directory
- ignorecase bool // ignorecase value from last sort
- ignoredia bool // ignoredia value from last sort
- noPerm bool // whether lf has no permission to open the directory
- lines []string // lines of text to display if directory previews are enabled
+ loading bool // directory is loading from disk
+ loadTime time.Time // current loading or last load time
+ ind int // index of current entry in files
+ pos int // position of current entry in ui
+ path string // full path of directory
+ files []*file // displayed files in directory including or excluding hidden ones
+ allFiles []*file // all files in directory including hidden ones (same array as files)
+ sortby sortMethod // sortby value from last sort
+ dirfirst bool // dirfirst value from last sort
+ dironly bool // dironly value from last sort
+ hidden bool // hidden value from last sort
+ reverse bool // reverse value from last sort
+ hiddenfiles []string // hiddenfiles value from last sort
+ filter []string // last filter for this directory
+ ignorecase bool // ignorecase value from last sort
+ ignoredia bool // ignoredia value from last sort
+ noPerm bool // whether lf has no permission to open the directory
+ lines []string // lines of text to display if directory previews are enabled
}
func newDir(path string) *dir {
@@ -209,8 +212,11 @@ func normalize(s1, s2 string, ignorecase, ignoredia bool) (string, string) {
}
func (dir *dir) sort() {
- dir.sortType = getSortType(dir.path)
+ dir.sortby = getSortBy(dir.path)
+ dir.dirfirst = getDirFirst(dir.path)
dir.dironly = getDirOnly(dir.path)
+ dir.hidden = getHidden(dir.path)
+ dir.reverse = getReverse(dir.path)
dir.hiddenfiles = gOpts.hiddenfiles
dir.ignorecase = gOpts.ignorecase
dir.ignoredia = gOpts.ignoredia
@@ -219,13 +225,11 @@ func (dir *dir) sort() {
// reverse order cannot be applied after stable sorting, otherwise the order
// of equivalent elements will be reversed
- reverse := dir.sortType.option&reverseSort != 0
-
- switch dir.sortType.method {
+ switch dir.sortby {
case naturalSort:
sort.SliceStable(dir.files, func(i, j int) bool {
s1, s2 := normalize(dir.files[i].Name(), dir.files[j].Name(), dir.ignorecase, dir.ignoredia)
- if !reverse {
+ if !dir.reverse {
return naturalLess(s1, s2)
} else {
return naturalLess(s2, s1)
@@ -234,7 +238,7 @@ func (dir *dir) sort() {
case nameSort:
sort.SliceStable(dir.files, func(i, j int) bool {
s1, s2 := normalize(dir.files[i].Name(), dir.files[j].Name(), dir.ignorecase, dir.ignoredia)
- if !reverse {
+ if !dir.reverse {
return s1 < s2
} else {
return s2 < s1
@@ -242,7 +246,7 @@ func (dir *dir) sort() {
})
case sizeSort:
sort.SliceStable(dir.files, func(i, j int) bool {
- if !reverse {
+ if !dir.reverse {
return dir.files[i].TotalSize() < dir.files[j].TotalSize()
} else {
return dir.files[j].TotalSize() < dir.files[i].TotalSize()
@@ -250,7 +254,7 @@ func (dir *dir) sort() {
})
case timeSort:
sort.SliceStable(dir.files, func(i, j int) bool {
- if !reverse {
+ if !dir.reverse {
return dir.files[i].ModTime().Before(dir.files[j].ModTime())
} else {
return dir.files[j].ModTime().Before(dir.files[i].ModTime())
@@ -258,7 +262,7 @@ func (dir *dir) sort() {
})
case atimeSort:
sort.SliceStable(dir.files, func(i, j int) bool {
- if !reverse {
+ if !dir.reverse {
return dir.files[i].accessTime.Before(dir.files[j].accessTime)
} else {
return dir.files[j].accessTime.Before(dir.files[i].accessTime)
@@ -266,7 +270,7 @@ func (dir *dir) sort() {
})
case ctimeSort:
sort.SliceStable(dir.files, func(i, j int) bool {
- if !reverse {
+ if !dir.reverse {
return dir.files[i].changeTime.Before(dir.files[j].changeTime)
} else {
return dir.files[j].changeTime.Before(dir.files[i].changeTime)
@@ -289,7 +293,7 @@ func (dir *dir) sort() {
// in order to also have natural sorting with the filenames
// combine the name with the ext but have the ext at the front
- if !reverse {
+ if !dir.reverse {
return ext1 < ext2 || ext1 == ext2 && name1 < name2
} else {
return ext2 < ext1 || ext2 == ext1 && name2 < name1
@@ -297,7 +301,7 @@ func (dir *dir) sort() {
})
}
- if dir.sortType.option&dirfirstSort != 0 {
+ if dir.dirfirst {
sort.SliceStable(dir.files, func(i, j int) bool {
if dir.files[i].IsDir() == dir.files[j].IsDir() {
return i < j
@@ -329,7 +333,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 dir.sortType.option&hiddenSort == 0 {
+ if !dir.hidden {
sort.SliceStable(dir.files, func(i, j int) bool {
if isHidden(dir.files[i], dir.path, dir.hiddenfiles) && isHidden(dir.files[j], dir.path, dir.hiddenfiles) {
return i < j
@@ -471,7 +475,11 @@ func (nav *nav) loadDirInternal(path string) *dir {
loading: true,
loadTime: time.Now(),
path: path,
- sortType: getSortType(path),
+ sortby: getSortBy(path),
+ dirfirst: getDirFirst(path),
+ dironly: getDirOnly(path),
+ hidden: getHidden(path),
+ reverse: getReverse(path),
hiddenfiles: gOpts.hiddenfiles,
ignorecase: gOpts.ignorecase,
ignoredia: gOpts.ignoredia,
@@ -534,8 +542,11 @@ func (nav *nav) checkDir(dir *dir) {
}
nav.dirChan <- nd
}()
- case dir.sortType != getSortType(dir.path) ||
+ case dir.sortby != getSortBy(dir.path) ||
+ dir.dirfirst != getDirFirst(dir.path) ||
dir.dironly != getDirOnly(dir.path) ||
+ dir.hidden != getHidden(dir.path) ||
+ dir.reverse != getReverse(dir.path) ||
!reflect.DeepEqual(dir.hiddenfiles, gOpts.hiddenfiles) ||
dir.ignorecase != gOpts.ignorecase ||
dir.ignoredia != gOpts.ignoredia:
diff --git a/opts.go b/opts.go
index 315943b..fc211e0 100644
--- a/opts.go
+++ b/opts.go
@@ -29,19 +29,6 @@ func isValidSortMethod(method sortMethod) bool {
const invalidSortErrorMessage = `sortby: value should either be 'natural', 'name', 'size', 'time', 'atime', 'ctime' or 'ext'`
-type sortOption byte
-
-const (
- dirfirstSort sortOption = 1 << iota
- hiddenSort
- reverseSort
-)
-
-type sortType struct {
- method sortMethod
- option sortOption
-}
-
var gOpts struct {
anchorfind bool
autoquit bool
@@ -54,11 +41,13 @@ var gOpts struct {
hidecursorinactive bool
dircache bool
dircounts bool
+ dirfirst bool
dironly bool
dirpreviews bool
drawbox bool
dupfilefmt string
globsearch bool
+ hidden bool
icons bool
ignorecase bool
ignoredia bool
@@ -67,9 +56,11 @@ var gOpts struct {
mouse bool
number bool
preview bool
+ relativenumber bool
+ reverse bool
selectfmt string
sixel bool
- relativenumber bool
+ sortby sortMethod
smartcase bool
smartdia bool
waitmsg string
@@ -106,19 +97,18 @@ var gOpts struct {
cmdkeys map[string]expr
cmds map[string]expr
user map[string]string
- sortType sortType
tempmarks string
numberfmt string
tagfmt string
}
var gLocalOpts struct {
- sortMethods map[string]sortMethod
- dirfirsts map[string]bool
- dironlys map[string]bool
- hiddens map[string]bool
- reverses map[string]bool
- infos map[string][]string
+ sortbys map[string]sortMethod
+ dirfirsts map[string]bool
+ dironlys map[string]bool
+ hiddens map[string]bool
+ reverses map[string]bool
+ infos map[string][]string
}
func localOptPaths(path string) []string {
@@ -130,71 +120,58 @@ func localOptPaths(path string) []string {
return list
}
-func getSortMethod(path string) sortMethod {
+func getDirFirst(path string) bool {
for _, key := range localOptPaths(path) {
- if val, ok := gLocalOpts.sortMethods[key]; ok {
+ if val, ok := gLocalOpts.dirfirsts[key]; ok {
return val
}
}
- return gOpts.sortType.method
+ return gOpts.dirfirst
}
-func getSortType(path string) sortType {
- method := getSortMethod(path)
- option := gOpts.sortType.option
+func getDirOnly(path string) bool {
for _, key := range localOptPaths(path) {
- if val, ok := gLocalOpts.dirfirsts[key]; ok {
- if val {
- option |= dirfirstSort
- } else {
- option &= ^dirfirstSort
- }
- break
+ if val, ok := gLocalOpts.dironlys[key]; ok {
+ return val
}
}
+ return gOpts.dironly
+}
+
+func getHidden(path string) bool {
for _, key := range localOptPaths(path) {
if val, ok := gLocalOpts.hiddens[key]; ok {
- if val {
- option |= hiddenSort
- } else {
- option &= ^hiddenSort
- }
- break
+ return val
}
}
+ return gOpts.hidden
+}
+
+func getInfo(path string) []string {
for _, key := range localOptPaths(path) {
- if val, ok := gLocalOpts.reverses[key]; ok {
- if val {
- option |= reverseSort
- } else {
- option &= ^reverseSort
- }
- break
+ if val, ok := gLocalOpts.infos[key]; ok {
+ return val
}
}
- val := sortType{
- method: method,
- option: option,
- }
- return val
+ return gOpts.info
}
-func getDirOnly(path string) bool {
+func getReverse(path string) bool {
for _, key := range localOptPaths(path) {
- if val, ok := gLocalOpts.dironlys[key]; ok {
+ if val, ok := gLocalOpts.reverses[key]; ok {
return val
}
}
- return gOpts.dironly
+ return gOpts.reverse
}
-func getInfo(path string) []string {
+func getSortBy(path string) sortMethod {
for _, key := range localOptPaths(path) {
- if val, ok := gLocalOpts.infos[key]; ok {
+ if val, ok := gLocalOpts.sortbys[key]; ok {
return val
}
}
- return gOpts.info
+ return gOpts.sortby
}
func init() {
@@ -202,6 +179,7 @@ func init() {
gOpts.autoquit = false
gOpts.dircache = true
gOpts.dircounts = false
+ gOpts.dirfirst = true
gOpts.dironly = false
gOpts.dirpreviews = false
gOpts.drawbox = false
@@ -214,6 +192,7 @@ func init() {
gOpts.cutfmt = "\033[7;31m"
gOpts.hidecursorinactive = false
gOpts.globsearch = false
+ gOpts.hidden = false
gOpts.icons = false
gOpts.ignorecase = true
gOpts.ignoredia = true
@@ -222,9 +201,11 @@ func init() {
gOpts.mouse = false
gOpts.number = false
gOpts.preview = true
+ gOpts.relativenumber = false
+ gOpts.reverse = false
gOpts.selectfmt = "\033[7;35m"
gOpts.sixel = false
- gOpts.relativenumber = false
+ gOpts.sortby = naturalSort
gOpts.smartcase = true
gOpts.smartdia = false
gOpts.waitmsg = "Press any key to continue"
@@ -257,7 +238,6 @@ func init() {
gOpts.rulerfmt = " %a| %p| \033[7;31m %m \033[0m| \033[7;33m %c \033[0m| \033[7;35m %s \033[0m| \033[7;34m %f \033[0m| %i/%t"
gOpts.preserve = []string{"mode"}
gOpts.shellopts = nil
- gOpts.sortType = sortType{naturalSort, dirfirstSort}
gOpts.tempmarks = "'"
gOpts.numberfmt = "\033[33m"
gOpts.tagfmt = "\033[31m"
@@ -380,7 +360,7 @@ func init() {
gOpts.cmds = make(map[string]expr)
gOpts.user = make(map[string]string)
- gLocalOpts.sortMethods = make(map[string]sortMethod)
+ gLocalOpts.sortbys = make(map[string]sortMethod)
gLocalOpts.dirfirsts = make(map[string]bool)
gLocalOpts.dironlys = make(map[string]bool)
gLocalOpts.hiddens = make(map[string]bool)