add globsearch option for wildcard searching

Mentioned in #69.
This commit is contained in:
Gokcehan 2017-07-15 17:06:18 +03:00
parent fe05105c88
commit 9e69ce94ca
6 changed files with 128 additions and 69 deletions

View File

@ -53,6 +53,9 @@ var (
"dirfirst", "dirfirst",
"nodirfirst", "nodirfirst",
"dirfirst!", "dirfirst!",
"globsearch",
"noglobsearch",
"globsearch!",
"hidden", "hidden",
"nohidden", "nohidden",
"hidden!", "hidden!",

33
doc.go
View File

@ -68,22 +68,23 @@ keybindings:
The following options can be used to customize the behavior of lf: The following options can be used to customize the behavior of lf:
dircounts boolean (default off) dircounts boolean (default off)
dirfirst boolean (default on) dirfirst boolean (default on)
hidden boolean (default off) globsearch boolean (default off)
preview boolean (default on) hidden boolean (default off)
reverse boolean (default off) preview boolean (default on)
wrapscan boolean (default on) reverse boolean (default off)
scrolloff integer (default 0) wrapscan boolean (default on)
tabstop integer (default 8) scrolloff integer (default 0)
filesep string (default ":") tabstop integer (default 8)
ifs string (default "") (not exported if empty) filesep string (default ":")
previewer string (default "") (not filtered if empty) ifs string (default "") (not exported if empty)
shell string (default "/bin/sh") previewer string (default "") (not filtered if empty)
sortby string (default "natural") shell string (default "/bin/sh")
timefmt string (default "Mon Jan _2 15:04:05 2006") sortby string (default "natural")
ratios string (default "1:2:3") timefmt string (default "Mon Jan _2 15:04:05 2006")
info string (default "") ratios string (default "1:2:3")
info string (default "")
The following variables are exported for shell commands: The following variables are exported for shell commands:

View File

@ -72,22 +72,23 @@ keybindings:
The following options can be used to customize the behavior of lf: The following options can be used to customize the behavior of lf:
dircounts boolean (default off) dircounts boolean (default off)
dirfirst boolean (default on) dirfirst boolean (default on)
hidden boolean (default off) globsearch boolean (default off)
preview boolean (default on) hidden boolean (default off)
reverse boolean (default off) preview boolean (default on)
wrapscan boolean (default on) reverse boolean (default off)
scrolloff integer (default 0) wrapscan boolean (default on)
tabstop integer (default 8) scrolloff integer (default 0)
filesep string (default ":") tabstop integer (default 8)
ifs string (default "") (not exported if empty) filesep string (default ":")
previewer string (default "") (not filtered if empty) ifs string (default "") (not exported if empty)
shell string (default "/bin/sh") previewer string (default "") (not filtered if empty)
sortby string (default "natural") shell string (default "/bin/sh")
timefmt string (default "Mon Jan _2 15:04:05 2006") sortby string (default "natural")
ratios string (default "1:2:3") timefmt string (default "Mon Jan _2 15:04:05 2006")
info string (default "") ratios string (default "1:2:3")
info string (default "")
The following variables are exported for shell commands: The following variables are exported for shell commands:

42
eval.go
View File

@ -26,6 +26,12 @@ func (e *setExpr) eval(app *app, args []string) {
case "dirfirst!": case "dirfirst!":
gOpts.dirfirst = !gOpts.dirfirst gOpts.dirfirst = !gOpts.dirfirst
app.nav.renew(app.nav.height) app.nav.renew(app.nav.height)
case "globsearch":
gOpts.globsearch = true
case "noglobsearch":
gOpts.globsearch = false
case "globsearch!":
gOpts.globsearch = !gOpts.globsearch
case "hidden": case "hidden":
gOpts.hidden = true gOpts.hidden = true
app.nav.renew(app.nav.height) app.nav.renew(app.nav.height)
@ -297,11 +303,21 @@ func (e *callExpr) eval(app *app, args []string) {
case "search-back": case "search-back":
app.ui.cmdpref = "?" app.ui.cmdpref = "?"
case "search-next": case "search-next":
app.nav.searchNext() if err := app.nav.searchNext(); err != nil {
msg := fmt.Sprintf("search: %s: %s", err, app.nav.search)
app.ui.message = msg
log.Printf(msg)
return
}
app.ui.loadFile(app.nav) app.ui.loadFile(app.nav)
app.ui.loadFileInfo(app.nav) app.ui.loadFileInfo(app.nav)
case "search-prev": case "search-prev":
app.nav.searchPrev() if err := app.nav.searchPrev(); err != nil {
msg := fmt.Sprintf("search: %s: %s", err, app.nav.search)
app.ui.message = msg
log.Printf(msg)
return
}
app.ui.loadFile(app.nav) app.ui.loadFile(app.nav)
app.ui.loadFileInfo(app.nav) app.ui.loadFileInfo(app.nav)
case "toggle": case "toggle":
@ -448,15 +464,25 @@ func (e *callExpr) eval(app *app, args []string) {
case "/": case "/":
log.Printf("search: %s", s) log.Printf("search: %s", s)
app.nav.search = s app.nav.search = s
app.nav.searchNext() if err := app.nav.searchNext(); err != nil {
app.ui.loadFile(app.nav) msg := fmt.Sprintf("search: %s: %s", err, app.nav.search)
app.ui.loadFileInfo(app.nav) app.ui.message = msg
log.Printf(msg)
} else {
app.ui.loadFile(app.nav)
app.ui.loadFileInfo(app.nav)
}
case "?": case "?":
log.Printf("search-back: %s", s) log.Printf("search-back: %s", s)
app.nav.search = s app.nav.search = s
app.nav.searchPrev() if err := app.nav.searchPrev(); err != nil {
app.ui.loadFile(app.nav) msg := fmt.Sprintf("search: %s: %s", err, app.nav.search)
app.ui.loadFileInfo(app.nav) app.ui.message = msg
log.Printf(msg)
} else {
app.ui.loadFile(app.nav)
app.ui.loadFileInfo(app.nav)
}
default: default:
log.Printf("entering unknown execution prefix: %q", app.ui.cmdpref) log.Printf("entering unknown execution prefix: %q", app.ui.cmdpref)
} }

46
nav.go
View File

@ -368,40 +368,66 @@ func (nav *nav) cd(wd string) error {
return nil return nil
} }
func (nav *nav) searchNext() { func match(pattern, name string) (matched bool, err error) {
if gOpts.globsearch {
return filepath.Match(pattern, name)
} else {
return strings.Contains(name, pattern), nil
}
}
func (nav *nav) searchNext() error {
last := nav.currDir() last := nav.currDir()
for i := last.ind + 1; i < len(last.fi); i++ { for i := last.ind + 1; i < len(last.fi); i++ {
if strings.Contains(last.fi[i].Name(), nav.search) { matched, err := match(nav.search, last.fi[i].Name())
if err != nil {
return err
}
if matched {
nav.down(i - last.ind) nav.down(i - last.ind)
return return nil
} }
} }
if gOpts.wrapscan { if gOpts.wrapscan {
for i := 0; i < last.ind; i++ { for i := 0; i < last.ind; i++ {
if strings.Contains(last.fi[i].Name(), nav.search) { matched, err := match(nav.search, last.fi[i].Name())
if err != nil {
return err
}
if matched {
nav.up(last.ind - i) nav.up(last.ind - i)
return return nil
} }
} }
} }
return nil
} }
func (nav *nav) searchPrev() { func (nav *nav) searchPrev() error {
last := nav.currDir() last := nav.currDir()
for i := last.ind - 1; i >= 0; i-- { for i := last.ind - 1; i >= 0; i-- {
if strings.Contains(last.fi[i].Name(), nav.search) { matched, err := match(nav.search, last.fi[i].Name())
if err != nil {
return err
}
if matched {
nav.up(last.ind - i) nav.up(last.ind - i)
return return nil
} }
} }
if gOpts.wrapscan { if gOpts.wrapscan {
for i := len(last.fi) - 1; i > last.ind; i-- { for i := len(last.fi) - 1; i > last.ind; i-- {
if strings.Contains(last.fi[i].Name(), nav.search) { matched, err := match(nav.search, last.fi[i].Name())
if err != nil {
return err
}
if matched {
nav.down(i - last.ind) nav.down(i - last.ind)
return return nil
} }
} }
} }
return nil
} }
func (nav *nav) toggleMark(path string) { func (nav *nav) toggleMark(path string) {

40
opts.go
View File

@ -3,30 +3,32 @@ package main
import "time" import "time"
var gOpts struct { var gOpts struct {
dircounts bool dircounts bool
dirfirst bool dirfirst bool
hidden bool globsearch bool
preview bool hidden bool
reverse bool preview bool
wrapscan bool reverse bool
scrolloff int wrapscan bool
tabstop int scrolloff int
filesep string tabstop int
ifs string filesep string
previewer string ifs string
shell string previewer string
sortby string shell string
timefmt string sortby string
ratios []int timefmt string
info []string ratios []int
keys map[string]expr info []string
cmdkeys map[string]expr keys map[string]expr
cmds map[string]expr cmdkeys map[string]expr
cmds map[string]expr
} }
func init() { func init() {
gOpts.dircounts = false gOpts.dircounts = false
gOpts.dirfirst = true gOpts.dirfirst = true
gOpts.globsearch = false
gOpts.hidden = false gOpts.hidden = false
gOpts.preview = true gOpts.preview = true
gOpts.reverse = false gOpts.reverse = false