From cdc90afbaa1a6ff7d0900b6ce904a1e51e31bcd1 Mon Sep 17 00:00:00 2001 From: Tim Culverhouse Date: Mon, 12 Feb 2024 06:26:19 -0600 Subject: aerc: replace tcell keys with vaxis keys Replace all instances of tcell key usage with vaxis keys Signed-off-by: Tim Culverhouse Acked-by: Robin Jarry --- app/account-wizard.go | 22 +++++++++------------ app/aerc.go | 54 +++++++++++++++++++++++++++++++++------------------ app/exline.go | 14 ++++++------- app/getpasswd.go | 10 ++++------ app/listbox.go | 44 +++++++++++++++++++++++++++++------------ app/selector.go | 23 +++++++++++----------- app/terminal.go | 1 + 7 files changed, 98 insertions(+), 70 deletions(-) (limited to 'app') diff --git a/app/account-wizard.go b/app/account-wizard.go index 0fd426ca..36bc0392 100644 --- a/app/account-wizard.go +++ b/app/account-wizard.go @@ -13,7 +13,6 @@ import ( "sync" "github.com/emersion/go-message/mail" - "github.com/gdamore/tcell/v2" "github.com/go-ini/ini" "golang.org/x/sys/unix" @@ -750,13 +749,11 @@ func (wizard *AccountWizard) Focus(focus bool) { func (wizard *AccountWizard) Event(event vaxis.Event) bool { interactive := wizard.getInteractive() - if event, ok := event.(*tcell.EventKey); ok { - switch event.Key() { - case tcell.KeyUp: - fallthrough - case tcell.KeyBacktab: - fallthrough - case tcell.KeyCtrlK: + if key, ok := event.(vaxis.Key); ok { + switch { + case key.Matches('k', vaxis.ModCtrl), + key.Matches(vaxis.KeyTab, vaxis.ModShift), + key.Matches(vaxis.KeyUp): if interactive != nil { interactive[wizard.focus].Focus(false) wizard.focus-- @@ -767,11 +764,10 @@ func (wizard *AccountWizard) Event(event vaxis.Event) bool { } wizard.Invalidate() return true - case tcell.KeyDown: - fallthrough - case tcell.KeyTab: - fallthrough - case tcell.KeyCtrlJ: + case key.Matches('j', vaxis.ModCtrl), + key.Matches(vaxis.KeyTab), + key.Matches(vaxis.KeyDown): + if interactive != nil { interactive[wizard.focus].Focus(false) wizard.focus++ diff --git a/app/aerc.go b/app/aerc.go index 0efaab30..8b5564a3 100644 --- a/app/aerc.go +++ b/app/aerc.go @@ -9,6 +9,7 @@ import ( "sort" "strings" "time" + "unicode" "git.sr.ht/~rjarry/go-opt" "git.sr.ht/~rockorager/vaxis" @@ -230,7 +231,7 @@ func (aerc *Aerc) HumanReadableBindings() []string { } result = append(result, fmt.Sprintf(fmtStr, "$ex", - fmt.Sprintf("'%c'", binds.ExKey.Rune), "", + fmt.Sprintf("'%c'", binds.ExKey.Key), "", )) result = append(result, fmt.Sprintf(fmtStr, "Globals", @@ -288,8 +289,23 @@ func (aerc *Aerc) simulate(strokes []config.KeyStroke) { aerc.simulating += 1 for _, stroke := range strokes { - simulated := tcell.NewEventKey( - stroke.Key, stroke.Rune, stroke.Modifiers) + simulated := vaxis.Key{ + Keycode: stroke.Key, + Modifiers: stroke.Modifiers, + } + if unicode.IsUpper(stroke.Key) { + simulated.Keycode = unicode.ToLower(stroke.Key) + simulated.Modifiers |= vaxis.ModShift + } + // If none of these mods are present, set the text field to + // enable matching keys like ":" + if stroke.Modifiers&vaxis.ModCtrl == 0 && + stroke.Modifiers&vaxis.ModAlt == 0 && + stroke.Modifiers&vaxis.ModSuper == 0 && + stroke.Modifiers&vaxis.ModHyper == 0 { + + simulated.Text = string(stroke.Key) + } aerc.Event(simulated) complete = stroke == bindings.CompleteKey } @@ -301,10 +317,7 @@ func (aerc *Aerc) simulate(strokes []config.KeyStroke) { }) if complete { // force completion now - exline.Event(tcell.NewEventKey( - bindings.CompleteKey.Key, - bindings.CompleteKey.Rune, - bindings.CompleteKey.Modifiers)) + exline.Event(vaxis.Key{Keycode: vaxis.KeyTab}) } } } @@ -319,7 +332,8 @@ func (aerc *Aerc) Event(event vaxis.Event) bool { } switch event := event.(type) { - case *tcell.EventKey: + // TODO: more vaxis events handling + case vaxis.Key: // If we are in a bracketed paste, don't process the keys for // bindings if aerc.pasting { @@ -330,11 +344,17 @@ func (aerc *Aerc) Event(event vaxis.Event) bool { return false } aerc.statusline.Expire() - aerc.pendingKeys = append(aerc.pendingKeys, config.KeyStroke{ - Modifiers: event.Modifiers(), - Key: event.Key(), - Rune: event.Rune(), - }) + stroke := config.KeyStroke{ + Modifiers: event.Modifiers, + } + switch { + case event.ShiftedCode != 0: + stroke.Key = event.ShiftedCode + stroke.Modifiers &^= vaxis.ModShift + default: + stroke.Key = event.Keycode + } + aerc.pendingKeys = append(aerc.pendingKeys, stroke) ui.Invalidate() bindings := aerc.getBindings() incomplete := false @@ -887,12 +907,8 @@ func errorScreen(s string) ui.Drawable { return grid } -func (aerc *Aerc) isExKey(event *tcell.EventKey, exKey config.KeyStroke) bool { - if event.Key() == tcell.KeyRune { - // Compare runes if it's a KeyRune - return event.Modifiers() == exKey.Modifiers && event.Rune() == exKey.Rune - } - return event.Modifiers() == exKey.Modifiers && event.Key() == exKey.Key +func (aerc *Aerc) isExKey(key vaxis.Key, exKey config.KeyStroke) bool { + return key.Matches(exKey.Key, exKey.Modifiers) } // CmdFallbackSearch checks cmds for the first executable availabe in PATH. An error is diff --git a/app/exline.go b/app/exline.go index 7eb6fde3..e8b0069e 100644 --- a/app/exline.go +++ b/app/exline.go @@ -1,8 +1,6 @@ package app import ( - "github.com/gdamore/tcell/v2" - "git.sr.ht/~rjarry/aerc/config" "git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib/ui" @@ -83,20 +81,20 @@ func (ex *ExLine) Focus(focus bool) { } func (ex *ExLine) Event(event vaxis.Event) bool { - if event, ok := event.(*tcell.EventKey); ok { - switch event.Key() { - case tcell.KeyEnter, tcell.KeyCtrlJ: + if key, ok := event.(vaxis.Key); ok { + switch { + case key.Matches(vaxis.KeyEnter), key.Matches('j', vaxis.ModCtrl): cmd := ex.input.String() ex.input.Focus(false) ex.commit(cmd) ex.finish() - case tcell.KeyUp: + case key.Matches(vaxis.KeyUp): ex.input.Set(ex.cmdHistory.Prev()) ex.Invalidate() - case tcell.KeyDown: + case key.Matches(vaxis.KeyDown): ex.input.Set(ex.cmdHistory.Next()) ex.Invalidate() - case tcell.KeyEsc, tcell.KeyCtrlC: + case key.Matches(vaxis.KeyEsc), key.Matches('c', vaxis.ModCtrl): ex.input.Focus(false) ex.cmdHistory.Reset() ex.finish() diff --git a/app/getpasswd.go b/app/getpasswd.go index 8781bce7..e5726d91 100644 --- a/app/getpasswd.go +++ b/app/getpasswd.go @@ -3,8 +3,6 @@ package app import ( "fmt" - "github.com/gdamore/tcell/v2" - "git.sr.ht/~rjarry/aerc/config" "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rockorager/vaxis" @@ -47,12 +45,12 @@ func (gp *GetPasswd) Invalidate() { func (gp *GetPasswd) Event(event vaxis.Event) bool { switch event := event.(type) { - case *tcell.EventKey: - switch event.Key() { - case tcell.KeyEnter: + case vaxis.Key: + switch { + case event.Matches(vaxis.KeyEnter): gp.input.Focus(false) gp.callback(gp.input.String(), nil) - case tcell.KeyEsc: + case event.Matches(vaxis.KeyEsc): gp.input.Focus(false) gp.callback("", fmt.Errorf("no password provided")) default: diff --git a/app/listbox.go b/app/listbox.go index d22eea1b..f5250700 100644 --- a/app/listbox.go +++ b/app/listbox.go @@ -231,59 +231,79 @@ func (lb *ListBox) Invalidate() { func (lb *ListBox) Event(event vaxis.Event) bool { showFilter := lb.showFilterField() - if event, ok := event.(*tcell.EventKey); ok { - switch event.Key() { - case tcell.KeyLeft: + if key, ok := event.(vaxis.Key); ok { + switch { + case key.Matches(vaxis.KeyLeft): if showFilter { break } lb.moveHorizontal(-1) lb.Invalidate() return true - case tcell.KeyRight: + case key.Matches(vaxis.KeyRight): if showFilter { break } lb.moveHorizontal(+1) lb.Invalidate() return true - case tcell.KeyCtrlA, tcell.KeyHome: + case key.Matches('b', vaxis.ModCtrl): + line := lb.selected[:lb.horizPos] + fds := strings.Fields(line) + if len(fds) > 1 { + lb.moveHorizontal( + strings.LastIndex(line, + fds[len(fds)-1]) - lb.horizPos - 1) + } else { + lb.horizPos = 0 + } + lb.Invalidate() + return true + case key.Matches('w', vaxis.ModCtrl): + line := lb.selected[lb.horizPos+1:] + fds := strings.Fields(line) + if len(fds) > 1 { + lb.moveHorizontal(strings.Index(line, fds[1])) + } + lb.Invalidate() + return true + case key.Matches('a', vaxis.ModCtrl), key.Matches(vaxis.KeyHome): if showFilter { break } lb.horizPos = 0 lb.Invalidate() return true - case tcell.KeyCtrlE, tcell.KeyEnd: + case key.Matches('e', vaxis.ModCtrl), key.Matches(vaxis.KeyEnd): if showFilter { break } lb.horizPos = len(lb.selected) lb.Invalidate() return true - case tcell.KeyCtrlP, tcell.KeyUp, tcell.KeyBacktab: + case key.Matches('p', vaxis.ModCtrl), key.Matches(vaxis.KeyUp): lb.moveCursor(-1) lb.Invalidate() return true - case tcell.KeyCtrlN, tcell.KeyDown, tcell.KeyTab: + case key.Matches('n', vaxis.ModCtrl), key.Matches(vaxis.KeyDown): lb.moveCursor(+1) lb.Invalidate() return true - case tcell.KeyPgUp: + case key.Matches(vaxis.KeyPgUp): if lb.jump >= 0 { lb.moveCursor(-lb.jump) lb.Invalidate() } return true - case tcell.KeyPgDn: + case key.Matches(vaxis.KeyPgDown): if lb.jump >= 0 { lb.moveCursor(+lb.jump) lb.Invalidate() } return true - case tcell.KeyEnter: + case key.Matches(vaxis.KeyEnter): return lb.quit(lb.selected) - case tcell.KeyEsc: + case key.Matches(vaxis.KeyEsc): return lb.quit("") } } diff --git a/app/selector.go b/app/selector.go index fe8c4d96..252616f0 100644 --- a/app/selector.go +++ b/app/selector.go @@ -4,7 +4,6 @@ import ( "fmt" "strings" - "github.com/gdamore/tcell/v2" "github.com/mattn/go-runewidth" "git.sr.ht/~rjarry/aerc/config" @@ -145,11 +144,11 @@ func (sel *Selector) Focus(focus bool) { } func (sel *Selector) Event(event vaxis.Event) bool { - if event, ok := event.(*tcell.EventKey); ok { - switch event.Key() { - case tcell.KeyCtrlH: + if key, ok := event.(vaxis.Key); ok { + switch { + case key.Matches('h', vaxis.ModCtrl): fallthrough - case tcell.KeyLeft: + case key.Matches(vaxis.KeyLeft): if sel.focus > 0 { sel.focus-- sel.Invalidate() @@ -157,9 +156,9 @@ func (sel *Selector) Event(event vaxis.Event) bool { if sel.onSelect != nil { sel.onSelect(sel.Selected()) } - case tcell.KeyCtrlL: + case key.Matches('l', vaxis.ModCtrl): fallthrough - case tcell.KeyRight: + case key.Matches(vaxis.KeyRight): if sel.focus < len(sel.options)-1 { sel.focus++ sel.Invalidate() @@ -167,7 +166,7 @@ func (sel *Selector) Event(event vaxis.Event) bool { if sel.onSelect != nil { sel.onSelect(sel.Selected()) } - case tcell.KeyEnter: + case key.Matches(vaxis.KeyEnter): if sel.onChoose != nil { sel.onChoose(sel.Selected()) } @@ -242,12 +241,12 @@ func (gp *SelectorDialog) Invalidate() { func (gp *SelectorDialog) Event(event vaxis.Event) bool { switch event := event.(type) { - case *tcell.EventKey: - switch event.Key() { - case tcell.KeyEnter: + case vaxis.Key: + switch { + case event.Matches(vaxis.KeyEnter): gp.selector.Focus(false) gp.callback(gp.selector.Selected(), nil) - case tcell.KeyEsc: + case event.Matches(vaxis.KeyEsc): gp.selector.Focus(false) gp.callback("", ErrNoOptionSelected) default: diff --git a/app/terminal.go b/app/terminal.go index 33478206..97cd4410 100644 --- a/app/terminal.go +++ b/app/terminal.go @@ -176,6 +176,7 @@ func (term *Terminal) HandleEvent(ev tcell.Event) { } func (term *Terminal) Event(event vaxis.Event) bool { + event = tcell.TcellEvent(event) if term.OnEvent != nil { if term.OnEvent(event) { return true -- cgit