diff --git a/app.go b/app.go index 1762470..b6619c5 100644 --- a/app.go +++ b/app.go @@ -99,7 +99,7 @@ func (app *app) loop() { curr, err := app.nav.currFile() if err == nil { if d.path == app.nav.currDir().path { - app.nav.load(curr.path) + app.ui.loadFile(app.nav) } if d.path == curr.path { app.ui.dirPrev = d @@ -107,11 +107,13 @@ func (app *app) loop() { } app.ui.draw(app.nav) - case p := <-app.ui.prevChan: + case r := <-app.nav.regChan: + app.nav.regCache[r.path] = r + curr, err := app.nav.currFile() if err == nil { - if p.path == curr.path { - app.ui.regPrev = p.lines + if r.path == curr.path { + app.ui.regPrev = r } } diff --git a/nav.go b/nav.go index 2d17402..d48b717 100644 --- a/nav.go +++ b/nav.go @@ -1,12 +1,16 @@ package main import ( + "bufio" "errors" "fmt" + "io" "log" "os" + "os/exec" "path/filepath" "sort" + "strconv" "strings" "time" ) @@ -210,8 +214,10 @@ func (dir *dir) find(name string, height int) { type nav struct { dirs []*dir - dirCache map[string]*dir dirChan chan *dir + regChan chan *reg + dirCache map[string]*dir + regCache map[string]*reg saves map[string]bool marks map[string]int markInd int @@ -226,8 +232,10 @@ func newNav(height int) *nav { } nav := &nav{ - dirCache: make(map[string]*dir), dirChan: make(chan *dir), + regChan: make(chan *reg), + dirCache: make(map[string]*dir), + regCache: make(map[string]*reg), marks: make(map[string]int), saves: make(map[string]bool), markInd: 0, @@ -256,7 +264,7 @@ func (nav *nav) getDirs(wd string) { var dirs []*dir for curr, base := wd, ""; !isRoot(base); curr, base = filepath.Dir(curr), filepath.Base(curr) { - dir := nav.load(curr) + dir := nav.loadDir(curr) dirs = append(dirs, dir) } @@ -302,6 +310,7 @@ func (nav *nav) renew(height int) { func (nav *nav) reload() { nav.dirCache = make(map[string]*dir) + nav.regCache = make(map[string]*reg) wd, err := os.Getwd() if err != nil { @@ -311,7 +320,7 @@ func (nav *nav) reload() { nav.getDirs(wd) } -func (nav *nav) load(path string) *dir { +func (nav *nav) loadDir(path string) *dir { d, ok := nav.dirCache[path] if !ok { go func() { @@ -327,6 +336,72 @@ func (nav *nav) load(path string) *dir { return d } +func (nav *nav) preview() { + curr, err := nav.currFile() + if err != nil { + return + } + + var reader io.Reader + + if len(gOpts.previewer) != 0 { + cmd := exec.Command(gOpts.previewer, curr.path, strconv.Itoa(nav.height)) + + out, err := cmd.StdoutPipe() + if err != nil { + log.Printf("previewing file: %s", err) + } + + if err := cmd.Start(); err != nil { + log.Printf("previewing file: %s", err) + } + + defer cmd.Wait() + defer out.Close() + reader = out + } else { + f, err := os.Open(curr.path) + if err != nil { + log.Printf("opening file: %s", err) + } + + defer f.Close() + reader = f + } + + reg := ®{path: curr.path} + + buf := bufio.NewScanner(reader) + + for i := 0; i < nav.height && buf.Scan(); i++ { + for _, r := range buf.Text() { + if r == 0 { + reg.lines = []string{"\033[1mbinary\033[0m"} + nav.regChan <- reg + return + } + } + reg.lines = append(reg.lines, buf.Text()) + } + + if buf.Err() != nil { + log.Printf("loading file: %s", buf.Err()) + } + + nav.regChan <- reg +} + +func (nav *nav) loadReg(ui *ui, path string) *reg { + r, ok := nav.regCache[path] + if !ok { + go nav.preview() + r := ®{path: path, lines: []string{"\033[1mloading...\033[0m"}} + nav.regCache[path] = r + return r + } + return r +} + func (nav *nav) sort() { for _, d := range nav.dirs { name := d.name() @@ -397,7 +472,7 @@ func (nav *nav) open() error { path := curr.path - dir := nav.load(path) + dir := nav.loadDir(path) nav.dirs = append(nav.dirs, dir) diff --git a/ui.go b/ui.go index fd7f3ce..44aa5e3 100644 --- a/ui.go +++ b/ui.go @@ -1,13 +1,10 @@ package main import ( - "bufio" "bytes" "fmt" - "io" "log" "os" - "os/exec" "path/filepath" "sort" "strconv" @@ -229,10 +226,14 @@ func (win *win) printRight(y int, fg, bg termbox.Attribute, s string) { win.print(win.w-len(s), y, fg, bg, s) } -func (win *win) printReg(reg []string) { +func (win *win) printReg(reg *reg) { + if reg == nil { + return + } + fg, bg := termbox.ColorDefault, termbox.ColorDefault - for i, l := range reg { + for i, l := range reg.lines { fg, bg = win.print(2, i, fg, bg, l) } @@ -379,9 +380,8 @@ type ui struct { msgWin *win menuWin *win msg string - regPrev []string + regPrev *reg dirPrev *dir - prevChan chan preview keyChan chan string evChan chan termbox.Event menuBuf *bytes.Buffer @@ -441,13 +441,12 @@ func newUI() *ui { }() return &ui{ - wins: getWins(), - pwdWin: newWin(wtot, 1, 0, 0), - msgWin: newWin(wtot, 1, 0, htot-1), - menuWin: newWin(wtot, 1, 0, htot-2), - prevChan: make(chan preview), - keyChan: make(chan string, 1000), - evChan: evChan, + wins: getWins(), + pwdWin: newWin(wtot, 1, 0, 0), + msgWin: newWin(wtot, 1, 0, htot-1), + menuWin: newWin(wtot, 1, 0, htot-2), + keyChan: make(chan string, 1000), + evChan: evChan, } } @@ -475,68 +474,11 @@ func (ui *ui) printf(format string, a ...interface{}) { ui.print(fmt.Sprintf(format, a...)) } -type preview struct { +type reg struct { path string lines []string } -func (ui *ui) preview(nav *nav) { - curr, err := nav.currFile() - if err != nil { - return - } - - var reader io.Reader - - if len(gOpts.previewer) != 0 { - cmd := exec.Command(gOpts.previewer, curr.path, strconv.Itoa(nav.height)) - - out, err := cmd.StdoutPipe() - if err != nil { - ui.printf("previewing file: %s", err) - } - - if err := cmd.Start(); err != nil { - ui.printf("previewing file: %s", err) - } - - defer cmd.Wait() - defer out.Close() - reader = out - } else { - f, err := os.Open(curr.path) - if err != nil { - ui.printf("opening file: %s", err) - } - - defer f.Close() - reader = f - } - - var prev preview - - prev.path = curr.path - - buf := bufio.NewScanner(reader) - - for i := 0; i < nav.height && buf.Scan(); i++ { - for _, r := range buf.Text() { - if r == 0 { - prev.lines = []string{"\033[1mbinary\033[0m"} - ui.prevChan <- prev - return - } - } - prev.lines = append(prev.lines, buf.Text()) - } - - if buf.Err() != nil { - ui.printf("loading file: %s", buf.Err()) - } - - ui.prevChan <- prev -} - func (ui *ui) loadFile(nav *nav) { curr, err := nav.currFile() if err != nil { @@ -548,10 +490,9 @@ func (ui *ui) loadFile(nav *nav) { } if curr.IsDir() { - ui.dirPrev = nav.load(curr.path) + ui.dirPrev = nav.loadDir(curr.path) } else if curr.Mode().IsRegular() { - ui.regPrev = []string{"\033[1mloading...\033[0m"} - go ui.preview(nav) + ui.regPrev = nav.loadReg(ui, curr.path) } }