diff --git a/app.go b/app.go index ea4ba6b..ceeaac2 100644 --- a/app.go +++ b/app.go @@ -32,24 +32,6 @@ type app struct { cmdHistoryInd int } -var gInvalidate struct { - sort bool - pos bool - dir bool - navSize bool - mouse bool - period bool -} - -func init() { - gInvalidate.sort = true - gInvalidate.pos = true - gInvalidate.dir = true - gInvalidate.navSize = true - gInvalidate.mouse = true - gInvalidate.period = true -} - func newApp(ui *ui, nav *nav) *app { quitChan := make(chan struct{}, 1) @@ -263,6 +245,19 @@ func (app *app) loop() { app.ui.readExpr() + if gSelect != "" { + go func() { + lstat, err := os.Lstat(gSelect) + if err != nil { + app.ui.exprChan <- &callExpr{"echoerr", []string{err.Error()}, 1} + } else if lstat.IsDir() { + app.ui.exprChan <- &callExpr{"cd", []string{gSelect}, 1} + } else { + app.ui.exprChan <- &callExpr{"select", []string{gSelect}, 1} + } + }() + } + if gConfigPath != "" { if _, err := os.Stat(gConfigPath); !os.IsNotExist(err) { app.readFile(gConfigPath) @@ -277,30 +272,6 @@ func (app *app) loop() { } } - // config has been read, now initialize nav with the wd - wd, err := os.Getwd() - if err != nil { - log.Printf("getting current directory: %s", err) - } - if gSelect != "" { - _, err := os.Lstat(gSelect) - if err != nil { - app.ui.exprChan <- &callExpr{"echoerr", []string{err.Error()}, 1} - } else if abs, err := filepath.Abs(gSelect); err == nil { - // if gSelect contains the /. suffix, the directory itself - // should be selected - if len(gSelect) > 2 && gSelect[len(gSelect)-2:] == "/." { - wd = abs - } else { - wd = filepath.Dir(abs) - app.ui.exprChan <- &callExpr{"select", []string{abs}, 1} - } - } - } - app.nav.getDirs(wd) - app.nav.addJumpList() - - // execute commands from args for _, cmd := range gCommands { p := newParser(strings.NewReader(cmd)) @@ -314,49 +285,6 @@ func (app *app) loop() { } for { - - // process invalidate flags - if gInvalidate.sort { - app.nav.sort() - app.ui.sort() - gInvalidate.sort = false - } - if gInvalidate.pos { - app.nav.position() - gInvalidate.pos = false - } - if gInvalidate.dir { - app.ui.loadFile(app.nav, true) - app.ui.loadFileInfo(app.nav) - app.ui.draw(app.nav) - gInvalidate.dir = false - } - if gInvalidate.navSize { - app.ui.renew() - if app.nav.height != app.ui.wins[0].h { - app.nav.height = app.ui.wins[0].h - app.nav.regCache = make(map[string]*reg) - } - gInvalidate.navSize = false - } - if gInvalidate.mouse { - if gOpts.mouse { - app.ui.screen.EnableMouse() - } else { - app.ui.screen.DisableMouse() - } - gInvalidate.mouse = false - } - if gInvalidate.period { - if gOpts.period == 0 { - app.ticker.Stop() - } else { - app.ticker.Stop() - app.ticker = time.NewTicker(time.Duration(gOpts.period) * time.Second) - } - gInvalidate.period = false - } - select { case <-app.quitChan: if app.nav.copyTotal > 0 { @@ -445,12 +373,7 @@ func (app *app) loop() { } app.ui.draw(app.nav) case d := <-app.nav.dirChan: - - if !app.nav.checkDir(d) { - log.Printf("debug: dirChan skip/reload %s", d.path) - continue - } - log.Printf("debug: dirChan %s %t", d.path, d.loading) + app.nav.checkDir(d) if gOpts.dircache { prev, ok := app.nav.dirCache[d.path] diff --git a/eval.go b/eval.go index c98bcd5..bb9fe62 100644 --- a/eval.go +++ b/eval.go @@ -7,12 +7,12 @@ import ( "path/filepath" "strconv" "strings" + "time" "unicode" "unicode/utf8" ) func (e *setExpr) eval(app *app, args []string) { - // from app only app.ui.echo*() may be used inside this function switch e.opt { case "anchorfind": gOpts.anchorfind = true @@ -40,70 +40,91 @@ func (e *setExpr) eval(app *app, args []string) { gOpts.dircounts = !gOpts.dircounts case "dironly": gOpts.dironly = true - gInvalidate.sort = true - gInvalidate.pos = true - gInvalidate.dir = true + app.nav.sort() + app.nav.position() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "nodironly": gOpts.dironly = false - gInvalidate.sort = true - gInvalidate.pos = true - gInvalidate.dir = true + app.nav.sort() + app.nav.position() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "dironly!": gOpts.dironly = !gOpts.dironly - gInvalidate.sort = true - gInvalidate.pos = true - gInvalidate.dir = true + app.nav.sort() + app.nav.position() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "dirfirst": gOpts.sortType.option |= dirfirstSort - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() case "nodirfirst": gOpts.sortType.option &= ^dirfirstSort - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() case "dirfirst!": gOpts.sortType.option ^= dirfirstSort - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() case "drawbox": gOpts.drawbox = true - gInvalidate.navSize = true - gInvalidate.dir = true + app.ui.renew() + if app.nav.height != app.ui.wins[0].h { + app.nav.height = app.ui.wins[0].h + app.nav.regCache = make(map[string]*reg) + } + app.ui.loadFile(app.nav, true) case "nodrawbox": gOpts.drawbox = false - gInvalidate.navSize = true - gInvalidate.dir = true + app.ui.renew() + if app.nav.height != app.ui.wins[0].h { + app.nav.height = app.ui.wins[0].h + app.nav.regCache = make(map[string]*reg) + } + app.ui.loadFile(app.nav, true) case "drawbox!": gOpts.drawbox = !gOpts.drawbox - gInvalidate.navSize = true - gInvalidate.dir = true + app.ui.renew() + if app.nav.height != app.ui.wins[0].h { + app.nav.height = app.ui.wins[0].h + app.nav.regCache = make(map[string]*reg) + } + app.ui.loadFile(app.nav, true) case "globsearch": gOpts.globsearch = true - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "noglobsearch": gOpts.globsearch = false - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "globsearch!": gOpts.globsearch = !gOpts.globsearch - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "hidden": gOpts.sortType.option |= hiddenSort - gInvalidate.sort = true - gInvalidate.pos = true - gInvalidate.dir = true + app.nav.sort() + app.nav.position() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "nohidden": gOpts.sortType.option &= ^hiddenSort - gInvalidate.sort = true - gInvalidate.pos = true - gInvalidate.dir = true + app.nav.sort() + app.nav.position() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "hidden!": gOpts.sortType.option ^= hiddenSort - gInvalidate.sort = true - gInvalidate.pos = true - gInvalidate.dir = true + app.nav.sort() + app.nav.position() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "icons": gOpts.icons = true case "noicons": @@ -112,28 +133,31 @@ func (e *setExpr) eval(app *app, args []string) { gOpts.icons = !gOpts.icons case "ignorecase": gOpts.ignorecase = true - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "noignorecase": gOpts.ignorecase = false - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "ignorecase!": gOpts.ignorecase = !gOpts.ignorecase - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "ignoredia": gOpts.ignoredia = true - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() case "noignoredia": gOpts.ignoredia = false - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() case "ignoredia!": gOpts.ignoredia = !gOpts.ignoredia - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() case "incfilter": gOpts.incfilter = true case "noincfilter": @@ -149,20 +173,21 @@ func (e *setExpr) eval(app *app, args []string) { case "mouse": if !gOpts.mouse { gOpts.mouse = true - gInvalidate.mouse = true + app.ui.screen.EnableMouse() } case "nomouse": if gOpts.mouse { gOpts.mouse = false - gInvalidate.mouse = true + app.ui.screen.DisableMouse() } case "mouse!": if gOpts.mouse { gOpts.mouse = false + app.ui.screen.DisableMouse() } else { gOpts.mouse = true + app.ui.screen.EnableMouse() } - gInvalidate.mouse = true case "number": gOpts.number = true case "nonumber": @@ -191,28 +216,31 @@ func (e *setExpr) eval(app *app, args []string) { gOpts.relativenumber = !gOpts.relativenumber case "reverse": gOpts.sortType.option |= reverseSort - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() case "noreverse": gOpts.sortType.option &= ^reverseSort - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() case "reverse!": gOpts.sortType.option ^= reverseSort - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() case "smartcase": gOpts.smartcase = true - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "nosmartcase": gOpts.smartcase = false - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "smartcase!": gOpts.smartcase = !gOpts.smartcase - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "smartdia": gOpts.smartdia = true case "nosmartdia": @@ -255,7 +283,12 @@ func (e *setExpr) eval(app *app, args []string) { return } gOpts.period = n - gInvalidate.period = true + if n == 0 { + app.ticker.Stop() + } else { + app.ticker.Stop() + app.ticker = time.NewTicker(time.Duration(gOpts.period) * time.Second) + } case "scrolloff": n, err := strconv.Atoi(e.val) if err != nil { @@ -296,9 +329,10 @@ func (e *setExpr) eval(app *app, args []string) { } } gOpts.hiddenfiles = toks - gInvalidate.sort = true - gInvalidate.pos = true - gInvalidate.dir = true + app.nav.sort() + app.nav.position() + app.ui.sort() + app.ui.loadFile(app.nav, true) case "ifs": gOpts.ifs = e.val case "info": @@ -343,7 +377,7 @@ func (e *setExpr) eval(app *app, args []string) { } gOpts.ratios = rats app.ui.wins = getWins(app.ui.screen) - gInvalidate.dir = true + app.ui.loadFile(app.nav, true) case "shell": gOpts.shell = e.val case "shellflag": @@ -374,8 +408,8 @@ func (e *setExpr) eval(app *app, args []string) { app.ui.echoerr("sortby: value should either be 'natural', 'name', 'size', 'time', 'atime', 'ctime' or 'ext'") return } - gInvalidate.sort = true - gInvalidate.dir = true + app.nav.sort() + app.ui.sort() case "tempmarks": if e.val != "" { gOpts.tempmarks = "'" + e.val @@ -399,6 +433,7 @@ func (e *setExpr) eval(app *app, args []string) { app.ui.echoerrf("unknown option: %s", e.opt) return } + app.ui.loadFileInfo(app.nav) } func (e *mapExpr) eval(app *app, args []string) { @@ -407,6 +442,7 @@ func (e *mapExpr) eval(app *app, args []string) { } else { gOpts.keys[e.keys] = e.expr } + app.ui.loadFileInfo(app.nav) } func (e *cmapExpr) eval(app *app, args []string) { @@ -415,6 +451,7 @@ func (e *cmapExpr) eval(app *app, args []string) { } else { gOpts.cmdkeys[e.key] = e.expr } + app.ui.loadFileInfo(app.nav) } func (e *cmdExpr) eval(app *app, args []string) { @@ -423,6 +460,7 @@ func (e *cmdExpr) eval(app *app, args []string) { } else { gOpts.cmds[e.name] = e.expr } + app.ui.loadFileInfo(app.nav) } func preChdir(app *app) { @@ -1256,7 +1294,6 @@ func (e *callExpr) eval(app *app, args []string) { if err != nil { log.Printf("getting current directory: %s", err) } - log.Printf("todo-cd-eval %s", wd) path = replaceTilde(path) if !filepath.IsAbs(path) { diff --git a/nav.go b/nav.go index 6d1c294..12c7568 100644 --- a/nav.go +++ b/nav.go @@ -163,10 +163,6 @@ func normalize(s1, s2 string, ignorecase, ignoredia bool) (string, string) { } func (dir *dir) sort() { - if dir.loading { - log.Printf("debug: sort/dir still loading: %s", dir.path) - return - } dir.sortType = gOpts.sortType dir.dironly = gOpts.dironly dir.hiddenfiles = gOpts.hiddenfiles @@ -310,10 +306,6 @@ func (dir *dir) name() string { } func (dir *dir) sel(name string, height int) { - if dir.loading { - //log.Printf("debug: sel/dir still loading: %s", dir.path) - return - } if len(dir.files) == 0 { dir.ind, dir.pos = 0, 0 return @@ -399,13 +391,11 @@ func (nav *nav) loadDir(path string) *dir { if gOpts.dircache { d, ok := nav.dirCache[path] if !ok { - log.Printf("debug: dirCache-new: %s", path) d = nav.loadDirInternal(path) nav.dirCache[path] = d return d } - log.Printf("debug: dirCache-found: %s", path) nav.checkDir(d) return d @@ -414,16 +404,11 @@ func (nav *nav) loadDir(path string) *dir { } } -func (nav *nav) checkDir(dir *dir) bool { - if dir.loading { - log.Printf("debug: skip loading: %s", dir.path) - return false - } - +func (nav *nav) checkDir(dir *dir) { s, err := os.Stat(dir.path) if err != nil { log.Printf("getting directory info: %s", err) - return true + return } switch { @@ -433,10 +418,9 @@ func (nav *nav) checkDir(dir *dir) bool { // XXX: Linux builtin exFAT drivers are able to predict modifications in the future // https://bugs.launchpad.net/ubuntu/+source/ubuntu-meta/+bug/1872504 if s.ModTime().After(now) { - return true + return } - log.Printf("debug: checkDir-reload: %s time", dir.path) dir.loading = true dir.loadTime = now go func() { @@ -445,23 +429,18 @@ func (nav *nav) checkDir(dir *dir) bool { nd.sort() nav.dirChan <- nd }() - return false case dir.sortType != gOpts.sortType || dir.dironly != gOpts.dironly || !reflect.DeepEqual(dir.hiddenfiles, gOpts.hiddenfiles) || dir.ignorecase != gOpts.ignorecase || dir.ignoredia != gOpts.ignoredia: - log.Printf("debug: checkDir-reload: %s opt", dir.path) - sd := dir dir.loading = true - dir.loadTime = time.Now() go func() { - sd.sort() - nav.dirChan <- sd + dir.sort() + dir.loading = false + nav.dirChan <- dir }() - return false } - return true } func (nav *nav) getDirs(wd string) { @@ -481,6 +460,10 @@ func (nav *nav) getDirs(wd string) { } func newNav(height int) *nav { + wd, err := os.Getwd() + if err != nil { + log.Printf("getting current directory: %s", err) + } nav := &nav{ copyBytesChan: make(chan int64, 1024), @@ -503,7 +486,8 @@ func newNav(height int) *nav { jumpListInd: -1, } - // do not call nav.getDirs() as our configuration isn't set up yet + nav.getDirs(wd) + nav.addJumpList() return nav } @@ -589,14 +573,7 @@ func (nav *nav) exportFiles() { currSelections := nav.currSelections() - var wd string - if currDir := nav.currDir(); currDir != nil { - wd = currDir.path - } else { - wd, _ = os.Getwd() - } - - exportFiles(currFile, currSelections, wd) + exportFiles(currFile, currSelections, nav.currDir().path) } func (nav *nav) previewLoop(ui *ui) { @@ -1275,26 +1252,19 @@ func (nav *nav) sync() error { } func (nav *nav) cd(wd string) error { - - currDir := nav.currDir() - wd = replaceTilde(wd) wd = filepath.Clean(wd) - if !filepath.IsAbs(wd) && currDir != nil { - wd = filepath.Join(currDir.path, wd) + if !filepath.IsAbs(wd) { + wd = filepath.Join(nav.currDir().path, wd) } if err := os.Chdir(wd); err != nil { return fmt.Errorf("cd: %s", err) } - if currDir == nil || wd != currDir.path { - nav.getDirs(wd) - nav.addJumpList() - } else { - log.Printf("debug: skip cd: %s", wd) - } + nav.getDirs(wd) + nav.addJumpList() return nil } @@ -1572,16 +1542,13 @@ func (nav *nav) writeMarks() error { } func (nav *nav) currDir() *dir { - if len(nav.dirs) == 0 { - return nil - } return nav.dirs[len(nav.dirs)-1] } func (nav *nav) currFile() (*file, error) { - dir := nav.currDir() + dir := nav.dirs[len(nav.dirs)-1] - if dir == nil || len(dir.files) == 0 { + if len(dir.files) == 0 { return nil, fmt.Errorf("empty directory") }