diff options
| author | Junegunn Choi <junegunn.c@gmail.com> | 2020-12-30 01:59:18 +0900 |
|---|---|---|
| committer | Junegunn Choi <junegunn.c@gmail.com> | 2020-12-30 18:39:17 +0900 |
| commit | 7f8e0dbc408eff786865d0e2d9e3c62ec3ed4776 (patch) | |
| tree | deeac2dc561a2ccd5bf444f4180abb43bff060be /src/tui | |
| parent | 0de7ab18f64db7838c8ca06d08188f976cbfdbb4 (diff) | |
| download | fzf-7f8e0dbc408eff786865d0e2d9e3c62ec3ed4776.tar.gz | |
Extend support for alt key chords
"alt-" with any case-sensitive character is allowed
Diffstat (limited to 'src/tui')
| -rw-r--r-- | src/tui/light.go | 43 | ||||
| -rw-r--r-- | src/tui/tcell.go | 71 | ||||
| -rw-r--r-- | src/tui/tui.go | 50 |
3 files changed, 81 insertions, 83 deletions
diff --git a/src/tui/light.go b/src/tui/light.go index 4f50d687..9c48b465 100644 --- a/src/tui/light.go +++ b/src/tui/light.go @@ -1,6 +1,7 @@ package tui import ( + "bytes" "fmt" "os" "regexp" @@ -230,7 +231,7 @@ func (r *LightRenderer) getBytesInternal(buffer []byte, nonblock bool) []byte { } retries := 0 - if c == ESC || nonblock { + if c == ESC.Int() || nonblock { retries = r.escDelay / escPollInterval } buffer = append(buffer, byte(c)) @@ -245,7 +246,7 @@ func (r *LightRenderer) getBytesInternal(buffer []byte, nonblock bool) []byte { continue } break - } else if c == ESC && pc != c { + } else if c == ESC.Int() && pc != c { retries = r.escDelay / escPollInterval } else { retries = 0 @@ -278,11 +279,11 @@ func (r *LightRenderer) GetChar() Event { }() switch r.buffer[0] { - case CtrlC: + case CtrlC.Byte(): return Event{CtrlC, 0, nil} - case CtrlG: + case CtrlG.Byte(): return Event{CtrlG, 0, nil} - case CtrlQ: + case CtrlQ.Byte(): return Event{CtrlQ, 0, nil} case 127: return Event{BSpace, 0, nil} @@ -296,7 +297,7 @@ func (r *LightRenderer) GetChar() Event { return Event{CtrlCaret, 0, nil} case 31: return Event{CtrlSlash, 0, nil} - case ESC: + case ESC.Byte(): ev := r.escSequence(&sz) // Second chance if ev.Type == Invalid { @@ -307,8 +308,8 @@ func (r *LightRenderer) GetChar() Event { } // CTRL-A ~ CTRL-Z - if r.buffer[0] <= CtrlZ { - return Event{int(r.buffer[0]), 0, nil} + if r.buffer[0] <= CtrlZ.Byte() { + return Event{EventType(r.buffer[0]), 0, nil} } char, rsz := utf8.DecodeRune(r.buffer) if char == utf8.RuneError { @@ -331,26 +332,16 @@ func (r *LightRenderer) escSequence(sz *int) Event { *sz = 2 if r.buffer[1] >= 1 && r.buffer[1] <= 'z'-'a'+1 { - return Event{int(CtrlAltA + r.buffer[1] - 1), 0, nil} + return CtrlAltKey(rune(r.buffer[1] + 'a' - 1)) } alt := false - if len(r.buffer) > 2 && r.buffer[1] == ESC { + if len(r.buffer) > 2 && r.buffer[1] == ESC.Byte() { r.buffer = r.buffer[1:] alt = true } switch r.buffer[1] { - case ESC: + case ESC.Byte(): return Event{ESC, 0, nil} - case ' ': - return Event{AltSpace, 0, nil} - case '/': - return Event{AltSlash, 0, nil} - case 'b': - return Event{AltB, 0, nil} - case 'd': - return Event{AltD, 0, nil} - case 'f': - return Event{AltF, 0, nil} case 127: return Event{AltBS, 0, nil} case '[', 'O': @@ -518,11 +509,11 @@ func (r *LightRenderer) escSequence(sz *int) Event { } // r.buffer[2] } // r.buffer[2] } // r.buffer[1] - if r.buffer[1] >= 'a' && r.buffer[1] <= 'z' { - return Event{AltA + int(r.buffer[1]) - 'a', 0, nil} - } - if r.buffer[1] >= '0' && r.buffer[1] <= '9' { - return Event{Alt0 + int(r.buffer[1]) - '0', 0, nil} + rest := bytes.NewBuffer(r.buffer[1:]) + c, size, err := rest.ReadRune() + if err == nil { + *sz = 1 + size + return AltKey(c) } return Event{Invalid, 0, nil} } diff --git a/src/tui/tcell.go b/src/tui/tcell.go index 16d3151a..938c1ba0 100644 --- a/src/tui/tcell.go +++ b/src/tui/tcell.go @@ -226,65 +226,65 @@ func (r *FullscreenRenderer) GetChar() Event { alt := (mods & tcell.ModAlt) > 0 shift := (mods & tcell.ModShift) > 0 altShift := alt && shift - keyfn := func(r rune) int { + keyfn := func(r rune) Event { if alt { - return CtrlAltA - 'a' + int(r) + return CtrlAltKey(r) } - return CtrlA - 'a' + int(r) + return EventType(CtrlA.Int() - 'a' + int(r)).AsEvent() } switch ev.Key() { case tcell.KeyCtrlA: - return Event{keyfn('a'), 0, nil} + return keyfn('a') case tcell.KeyCtrlB: - return Event{keyfn('b'), 0, nil} + return keyfn('b') case tcell.KeyCtrlC: - return Event{keyfn('c'), 0, nil} + return keyfn('c') case tcell.KeyCtrlD: - return Event{keyfn('d'), 0, nil} + return keyfn('d') case tcell.KeyCtrlE: - return Event{keyfn('e'), 0, nil} + return keyfn('e') case tcell.KeyCtrlF: - return Event{keyfn('f'), 0, nil} + return keyfn('f') case tcell.KeyCtrlG: - return Event{keyfn('g'), 0, nil} + return keyfn('g') case tcell.KeyCtrlH: - return Event{keyfn('h'), 0, nil} + return keyfn('h') case tcell.KeyCtrlI: - return Event{keyfn('i'), 0, nil} + return keyfn('i') case tcell.KeyCtrlJ: - return Event{keyfn('j'), 0, nil} + return keyfn('j') case tcell.KeyCtrlK: - return Event{keyfn('k'), 0, nil} + return keyfn('k') case tcell.KeyCtrlL: - return Event{keyfn('l'), 0, nil} + return keyfn('l') case tcell.KeyCtrlM: - return Event{keyfn('m'), 0, nil} + return keyfn('m') case tcell.KeyCtrlN: - return Event{keyfn('n'), 0, nil} + return keyfn('n') case tcell.KeyCtrlO: - return Event{keyfn('o'), 0, nil} + return keyfn('o') case tcell.KeyCtrlP: - return Event{keyfn('p'), 0, nil} + return keyfn('p') case tcell.KeyCtrlQ: - return Event{keyfn('q'), 0, nil} + return keyfn('q') case tcell.KeyCtrlR: - return Event{keyfn('r'), 0, nil} + return keyfn('r') case tcell.KeyCtrlS: - return Event{keyfn('s'), 0, nil} + return keyfn('s') case tcell.KeyCtrlT: - return Event{keyfn('t'), 0, nil} + return keyfn('t') case tcell.KeyCtrlU: - return Event{keyfn('u'), 0, nil} + return keyfn('u') case tcell.KeyCtrlV: - return Event{keyfn('v'), 0, nil} + return keyfn('v') case tcell.KeyCtrlW: - return Event{keyfn('w'), 0, nil} + return keyfn('w') case tcell.KeyCtrlX: - return Event{keyfn('x'), 0, nil} + return keyfn('x') case tcell.KeyCtrlY: - return Event{keyfn('y'), 0, nil} + return keyfn('y') case tcell.KeyCtrlZ: - return Event{keyfn('z'), 0, nil} + return keyfn('z') case tcell.KeyCtrlSpace: return Event{CtrlSpace, 0, nil} case tcell.KeyCtrlBackslash: @@ -389,18 +389,7 @@ func (r *FullscreenRenderer) GetChar() Event { case tcell.KeyRune: r := ev.Rune() if alt { - switch r { - case ' ': - return Event{AltSpace, 0, nil} - case '/': - return Event{AltSlash, 0, nil} - } - if r >= 'a' && r <= 'z' { - return Event{AltA + int(r) - 'a', 0, nil} - } - if r >= '0' && r <= '9' { - return Event{Alt0 + int(r) - '0', 0, nil} - } + return AltKey(r) } return Event{Rune, r, nil} diff --git a/src/tui/tui.go b/src/tui/tui.go index edbc9a14..cc9c7f67 100644 --- a/src/tui/tui.go +++ b/src/tui/tui.go @@ -8,8 +8,10 @@ import ( ) // Types of user action +type EventType int + const ( - Rune = iota + Rune EventType = iota CtrlA CtrlB @@ -89,8 +91,6 @@ const ( Change BackwardEOF - AltSpace - AltSlash AltBS AltUp @@ -103,20 +103,38 @@ const ( AltSLeft AltSRight - Alt0 + Alt + CtrlAlt ) -const ( // Reset iota - AltA = Alt0 + 'a' - '0' + iota - AltB - AltC - AltD - AltE - AltF - AltZ = AltA + 'z' - 'a' - CtrlAltA = AltZ + 1 - CtrlAltM = CtrlAltA + 'm' - 'a' -) +func (t EventType) AsEvent() Event { + return Event{t, 0, nil} +} + +func (t EventType) Int() int { + return int(t) +} + +func (t EventType) Byte() byte { + return byte(t) +} + +func (e Event) Comparable() Event { + // Ignore MouseEvent pointer + return Event{e.Type, e.Char, nil} +} + +func Key(r rune) Event { + return Event{Rune, r, nil} +} + +func AltKey(r rune) Event { + return Event{Alt, r, nil} +} + +func CtrlAltKey(r rune) Event { + return Event{CtrlAlt, r, nil} +} const ( doubleClickDuration = 500 * time.Millisecond @@ -251,7 +269,7 @@ type ColorTheme struct { } type Event struct { - Type int + Type EventType Char rune MouseEvent *MouseEvent } |
