cache file previews in memory

Related #5 and #92
This commit is contained in:
Gokcehan 2018-02-10 18:59:19 +03:00
parent 288561a9ba
commit 55ef28b4c7
3 changed files with 102 additions and 84 deletions

10
app.go
View File

@ -99,7 +99,7 @@ func (app *app) loop() {
curr, err := app.nav.currFile() curr, err := app.nav.currFile()
if err == nil { if err == nil {
if d.path == app.nav.currDir().path { if d.path == app.nav.currDir().path {
app.nav.load(curr.path) app.ui.loadFile(app.nav)
} }
if d.path == curr.path { if d.path == curr.path {
app.ui.dirPrev = d app.ui.dirPrev = d
@ -107,11 +107,13 @@ func (app *app) loop() {
} }
app.ui.draw(app.nav) 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() curr, err := app.nav.currFile()
if err == nil { if err == nil {
if p.path == curr.path { if r.path == curr.path {
app.ui.regPrev = p.lines app.ui.regPrev = r
} }
} }

85
nav.go
View File

@ -1,12 +1,16 @@
package main package main
import ( import (
"bufio"
"errors" "errors"
"fmt" "fmt"
"io"
"log" "log"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"sort" "sort"
"strconv"
"strings" "strings"
"time" "time"
) )
@ -210,8 +214,10 @@ func (dir *dir) find(name string, height int) {
type nav struct { type nav struct {
dirs []*dir dirs []*dir
dirCache map[string]*dir
dirChan chan *dir dirChan chan *dir
regChan chan *reg
dirCache map[string]*dir
regCache map[string]*reg
saves map[string]bool saves map[string]bool
marks map[string]int marks map[string]int
markInd int markInd int
@ -226,8 +232,10 @@ func newNav(height int) *nav {
} }
nav := &nav{ nav := &nav{
dirCache: make(map[string]*dir),
dirChan: make(chan *dir), dirChan: make(chan *dir),
regChan: make(chan *reg),
dirCache: make(map[string]*dir),
regCache: make(map[string]*reg),
marks: make(map[string]int), marks: make(map[string]int),
saves: make(map[string]bool), saves: make(map[string]bool),
markInd: 0, markInd: 0,
@ -256,7 +264,7 @@ func (nav *nav) getDirs(wd string) {
var dirs []*dir var dirs []*dir
for curr, base := wd, ""; !isRoot(base); curr, base = filepath.Dir(curr), filepath.Base(curr) { 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) dirs = append(dirs, dir)
} }
@ -302,6 +310,7 @@ func (nav *nav) renew(height int) {
func (nav *nav) reload() { func (nav *nav) reload() {
nav.dirCache = make(map[string]*dir) nav.dirCache = make(map[string]*dir)
nav.regCache = make(map[string]*reg)
wd, err := os.Getwd() wd, err := os.Getwd()
if err != nil { if err != nil {
@ -311,7 +320,7 @@ func (nav *nav) reload() {
nav.getDirs(wd) nav.getDirs(wd)
} }
func (nav *nav) load(path string) *dir { func (nav *nav) loadDir(path string) *dir {
d, ok := nav.dirCache[path] d, ok := nav.dirCache[path]
if !ok { if !ok {
go func() { go func() {
@ -327,6 +336,72 @@ func (nav *nav) load(path string) *dir {
return d 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 := &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 := &reg{path: path, lines: []string{"\033[1mloading...\033[0m"}}
nav.regCache[path] = r
return r
}
return r
}
func (nav *nav) sort() { func (nav *nav) sort() {
for _, d := range nav.dirs { for _, d := range nav.dirs {
name := d.name() name := d.name()
@ -397,7 +472,7 @@ func (nav *nav) open() error {
path := curr.path path := curr.path
dir := nav.load(path) dir := nav.loadDir(path)
nav.dirs = append(nav.dirs, dir) nav.dirs = append(nav.dirs, dir)

79
ui.go
View File

@ -1,13 +1,10 @@
package main package main
import ( import (
"bufio"
"bytes" "bytes"
"fmt" "fmt"
"io"
"log" "log"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"sort" "sort"
"strconv" "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) 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 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) fg, bg = win.print(2, i, fg, bg, l)
} }
@ -379,9 +380,8 @@ type ui struct {
msgWin *win msgWin *win
menuWin *win menuWin *win
msg string msg string
regPrev []string regPrev *reg
dirPrev *dir dirPrev *dir
prevChan chan preview
keyChan chan string keyChan chan string
evChan chan termbox.Event evChan chan termbox.Event
menuBuf *bytes.Buffer menuBuf *bytes.Buffer
@ -445,7 +445,6 @@ func newUI() *ui {
pwdWin: newWin(wtot, 1, 0, 0), pwdWin: newWin(wtot, 1, 0, 0),
msgWin: newWin(wtot, 1, 0, htot-1), msgWin: newWin(wtot, 1, 0, htot-1),
menuWin: newWin(wtot, 1, 0, htot-2), menuWin: newWin(wtot, 1, 0, htot-2),
prevChan: make(chan preview),
keyChan: make(chan string, 1000), keyChan: make(chan string, 1000),
evChan: evChan, evChan: evChan,
} }
@ -475,68 +474,11 @@ func (ui *ui) printf(format string, a ...interface{}) {
ui.print(fmt.Sprintf(format, a...)) ui.print(fmt.Sprintf(format, a...))
} }
type preview struct { type reg struct {
path string path string
lines []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) { func (ui *ui) loadFile(nav *nav) {
curr, err := nav.currFile() curr, err := nav.currFile()
if err != nil { if err != nil {
@ -548,10 +490,9 @@ func (ui *ui) loadFile(nav *nav) {
} }
if curr.IsDir() { if curr.IsDir() {
ui.dirPrev = nav.load(curr.path) ui.dirPrev = nav.loadDir(curr.path)
} else if curr.Mode().IsRegular() { } else if curr.Mode().IsRegular() {
ui.regPrev = []string{"\033[1mloading...\033[0m"} ui.regPrev = nav.loadReg(ui, curr.path)
go ui.preview(nav)
} }
} }