read events in the main loop

Related #445
This commit is contained in:
Gokcehan 2020-09-07 13:19:19 +03:00
parent f248ce77a1
commit ec512dfe31
2 changed files with 56 additions and 42 deletions

25
app.go
View File

@ -157,9 +157,10 @@ func (app *app) writeHistory() error {
// for evaluation. Similarly directories and regular files are also read in // for evaluation. Similarly directories and regular files are also read in
// separate goroutines and sent here for update. // separate goroutines and sent here for update.
func (app *app) loop() { func (app *app) loop() {
clientChan := app.ui.readExpr()
serverChan := readExpr() serverChan := readExpr()
app.ui.readExpr()
if gSelect != "" { if gSelect != "" {
go func() { go func() {
lstat, err := os.Lstat(gSelect) lstat, err := os.Lstat(gSelect)
@ -318,7 +319,27 @@ func (app *app) loop() {
} }
app.ui.draw(app.nav) app.ui.draw(app.nav)
case e := <-clientChan: case ev := <-app.ui.evChan:
e := app.ui.readEvent(ev)
if e == nil {
continue
}
e.eval(app, nil)
loop:
for {
select {
case ev := <-app.ui.evChan:
e = app.ui.readEvent(ev)
if e == nil {
continue
}
e.eval(app, nil)
default:
break loop
}
}
app.ui.draw(app.nav)
case e := <-app.ui.exprChan:
e.eval(app, nil) e.eval(app, nil)
app.ui.draw(app.nav) app.ui.draw(app.nav)
case e := <-serverChan: case e := <-serverChan:

73
ui.go
View File

@ -449,6 +449,7 @@ type ui struct {
dirPrev *dir dirPrev *dir
exprChan chan expr exprChan chan expr
keyChan chan string keyChan chan string
tevChan chan tcell.Event
evChan chan tcell.Event evChan chan tcell.Event
menuBuf *bytes.Buffer menuBuf *bytes.Buffer
cmdPrefix string cmdPrefix string
@ -514,8 +515,10 @@ func newUI(screen tcell.Screen) *ui {
promptWin: newWin(wtot, 1, 0, 0), promptWin: 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),
exprChan: make(chan expr, 1000),
keyChan: make(chan string, 1000), keyChan: make(chan string, 1000),
evChan: make(chan tcell.Event), tevChan: make(chan tcell.Event, 1000),
evChan: make(chan tcell.Event, 1000),
styles: parseStyles(), styles: parseStyles(),
icons: parseIcons(), icons: parseIcons(),
} }
@ -532,7 +535,7 @@ func (ui *ui) pollEvents() {
if ev == nil { if ev == nil {
return return
} }
ui.evChan <- ev ui.tevChan <- ev
} }
} }
@ -906,7 +909,7 @@ func (ui *ui) pollEvent() tcell.Event {
} }
return tcell.NewEventKey(k, ch, mod) return tcell.NewEventKey(k, ch, mod)
case ev := <-ui.evChan: case ev := <-ui.tevChan:
return ev return ev
} }
} }
@ -914,11 +917,7 @@ func (ui *ui) pollEvent() tcell.Event {
// This function is used to read a normal event on the client side. For keys, // This function is used to read a normal event on the client side. For keys,
// digits are interpreted as command counts but this is only done for digits // digits are interpreted as command counts but this is only done for digits
// preceding any non-digit characters (e.g. "42y2k" as 42 times "y2k"). // preceding any non-digit characters (e.g. "42y2k" as 42 times "y2k").
func (ui *ui) readEvent(ch chan<- expr, ev tcell.Event) { func (ui *ui) readNormalEvent(ev tcell.Event) expr {
if ev == nil {
return
}
draw := &callExpr{"draw", nil, 1} draw := &callExpr{"draw", nil, 1}
count := 1 count := 1
@ -943,18 +942,16 @@ func (ui *ui) readEvent(ch chan<- expr, ev tcell.Event) {
} else { } else {
val := gKeyVal[tev.Key()] val := gKeyVal[tev.Key()]
if val == "<esc>" { if val == "<esc>" {
ch <- draw
ui.keyAcc = nil ui.keyAcc = nil
ui.keyCount = nil ui.keyCount = nil
ui.menuBuf = nil ui.menuBuf = nil
return return draw
} }
ui.keyAcc = append(ui.keyAcc, []rune(val)...) ui.keyAcc = append(ui.keyAcc, []rune(val)...)
} }
if len(ui.keyAcc) == 0 { if len(ui.keyAcc) == 0 {
ch <- draw return draw
break
} }
binds, ok := findBinds(gOpts.keys, string(ui.keyAcc)) binds, ok := findBinds(gOpts.keys, string(ui.keyAcc))
@ -962,10 +959,10 @@ func (ui *ui) readEvent(ch chan<- expr, ev tcell.Event) {
switch len(binds) { switch len(binds) {
case 0: case 0:
ui.echoerrf("unknown mapping: %s", string(ui.keyAcc)) ui.echoerrf("unknown mapping: %s", string(ui.keyAcc))
ch <- draw
ui.keyAcc = nil ui.keyAcc = nil
ui.keyCount = nil ui.keyCount = nil
ui.menuBuf = nil ui.menuBuf = nil
return draw
default: default:
if ok { if ok {
if len(ui.keyCount) > 0 { if len(ui.keyCount) > 0 {
@ -981,71 +978,67 @@ func (ui *ui) readEvent(ch chan<- expr, ev tcell.Event) {
} else if e, ok := expr.(*listExpr); ok { } else if e, ok := expr.(*listExpr); ok {
e.count = count e.count = count
} }
ch <- expr
ui.keyAcc = nil ui.keyAcc = nil
ui.keyCount = nil ui.keyCount = nil
ui.menuBuf = nil ui.menuBuf = nil
return expr
} else { } else {
ui.menuBuf = listBinds(binds) ui.menuBuf = listBinds(binds)
ch <- draw return draw
} }
} }
case *tcell.EventResize: case *tcell.EventResize:
ch <- &callExpr{"redraw", nil, 1} return &callExpr{"redraw", nil, 1}
case *tcell.EventError: case *tcell.EventError:
log.Printf("Got EventError: '%s' at %s", tev.Error(), tev.When()) log.Printf("Got EventError: '%s' at %s", tev.Error(), tev.When())
return return nil
case *tcell.EventInterrupt: case *tcell.EventInterrupt:
log.Printf("Got EventInterrupt: at %s", tev.When()) log.Printf("Got EventInterrupt: at %s", tev.When())
return return nil
} }
return nil
} }
func readCmdEvent(ch chan<- expr, ev tcell.Event) { func readCmdEvent(ev tcell.Event) expr {
switch tev := ev.(type) { switch tev := ev.(type) {
case *tcell.EventKey: case *tcell.EventKey:
if tev.Key() == tcell.KeyRune { if tev.Key() == tcell.KeyRune {
if tev.Modifiers() == tcell.ModMask(tcell.ModAlt) { if tev.Modifiers() == tcell.ModMask(tcell.ModAlt) {
val := string([]rune{'<', 'a', '-', tev.Rune(), '>'}) val := string([]rune{'<', 'a', '-', tev.Rune(), '>'})
if expr, ok := gOpts.cmdkeys[val]; ok { if expr, ok := gOpts.cmdkeys[val]; ok {
ch <- expr return expr
} }
} else { } else {
ch <- &callExpr{"cmd-insert", []string{string(tev.Rune())}, 1} return &callExpr{"cmd-insert", []string{string(tev.Rune())}, 1}
} }
} else { } else {
val := gKeyVal[tev.Key()] val := gKeyVal[tev.Key()]
if expr, ok := gOpts.cmdkeys[val]; ok { if expr, ok := gOpts.cmdkeys[val]; ok {
ch <- expr return expr
} }
} }
} }
return nil
} }
func (ui *ui) readExpr() <-chan expr { func (ui *ui) readEvent(ev tcell.Event) expr {
ch := make(chan expr) if ev == nil {
return nil
}
ui.exprChan = ch if _, ok := ev.(*tcell.EventKey); ok && ui.cmdPrefix != "" {
return readCmdEvent(ev)
}
return ui.readNormalEvent(ev)
}
func (ui *ui) readExpr() {
go func() { go func() {
ch <- &callExpr{"draw", nil, 1}
for { for {
ev := ui.pollEvent() ui.evChan <- ui.pollEvent()
switch ev.(type) {
case *tcell.EventKey:
if ui.cmdPrefix != "" {
readCmdEvent(ch, ev)
continue
}
}
ui.readEvent(ch, ev)
} }
}() }()
return ch
} }
func (ui *ui) pause() { func (ui *ui) pause() {