Skip to content

Commit

Permalink
Implement sort options as separate variables (#1577)
Browse files Browse the repository at this point in the history
  • Loading branch information
joelim-work authored Jan 18, 2024
1 parent 6af2556 commit b401318
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 117 deletions.
37 changes: 17 additions & 20 deletions eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -151,15 +151,15 @@ 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!":
if e.val != "" {
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":
Expand Down Expand Up @@ -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
Expand All @@ -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()
Expand All @@ -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()
Expand Down Expand Up @@ -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
Expand All @@ -722,15 +722,15 @@ 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!":
if e.val != "" {
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":
Expand Down Expand Up @@ -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":
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand All @@ -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:
Expand Down
7 changes: 1 addition & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
71 changes: 41 additions & 30 deletions nav.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -234,39 +238,39 @@ 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
}
})
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()
}
})
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())
}
})
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)
}
})
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)
Expand All @@ -289,15 +293,15 @@ 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
}
})
}

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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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:
Expand Down
Loading

0 comments on commit b401318

Please sign in to comment.