summaryrefslogtreecommitdiffstats
path: root/src/tui
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2024-04-13 14:00:16 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2024-04-13 14:00:16 +0900
commitfd1ba46f77532b4bc9b6af00db9dc8ecdf6e2b3f (patch)
treec284b39e0b6948e0ce12d2cacf830d586582d201 /src/tui
parenta4745626dd5c5f697dbbc5e3aa1796d5016c1faf (diff)
Export $FZF_KEY environment variable to child processes
It's the name of the last key pressed. Related #3412
Diffstat (limited to 'src/tui')
-rw-r--r--src/tui/eventtype_string.go120
-rw-r--r--src/tui/light.go65
-rw-r--r--src/tui/tui.go112
3 files changed, 230 insertions, 67 deletions
diff --git a/src/tui/eventtype_string.go b/src/tui/eventtype_string.go
new file mode 100644
index 00000000..ce34d36e
--- /dev/null
+++ b/src/tui/eventtype_string.go
@@ -0,0 +1,120 @@
+// Code generated by "stringer -type=EventType"; DO NOT EDIT.
+
+package tui
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[Rune-0]
+ _ = x[CtrlA-1]
+ _ = x[CtrlB-2]
+ _ = x[CtrlC-3]
+ _ = x[CtrlD-4]
+ _ = x[CtrlE-5]
+ _ = x[CtrlF-6]
+ _ = x[CtrlG-7]
+ _ = x[CtrlH-8]
+ _ = x[Tab-9]
+ _ = x[CtrlJ-10]
+ _ = x[CtrlK-11]
+ _ = x[CtrlL-12]
+ _ = x[CtrlM-13]
+ _ = x[CtrlN-14]
+ _ = x[CtrlO-15]
+ _ = x[CtrlP-16]
+ _ = x[CtrlQ-17]
+ _ = x[CtrlR-18]
+ _ = x[CtrlS-19]
+ _ = x[CtrlT-20]
+ _ = x[CtrlU-21]
+ _ = x[CtrlV-22]
+ _ = x[CtrlW-23]
+ _ = x[CtrlX-24]
+ _ = x[CtrlY-25]
+ _ = x[CtrlZ-26]
+ _ = x[Esc-27]
+ _ = x[CtrlSpace-28]
+ _ = x[CtrlDelete-29]
+ _ = x[CtrlBackSlash-30]
+ _ = x[CtrlRightBracket-31]
+ _ = x[CtrlCaret-32]
+ _ = x[CtrlSlash-33]
+ _ = x[ShiftTab-34]
+ _ = x[Backspace-35]
+ _ = x[Delete-36]
+ _ = x[PageUp-37]
+ _ = x[PageDown-38]
+ _ = x[Up-39]
+ _ = x[Down-40]
+ _ = x[Left-41]
+ _ = x[Right-42]
+ _ = x[Home-43]
+ _ = x[End-44]
+ _ = x[Insert-45]
+ _ = x[ShiftUp-46]
+ _ = x[ShiftDown-47]
+ _ = x[ShiftLeft-48]
+ _ = x[ShiftRight-49]
+ _ = x[ShiftDelete-50]
+ _ = x[F1-51]
+ _ = x[F2-52]
+ _ = x[F3-53]
+ _ = x[F4-54]
+ _ = x[F5-55]
+ _ = x[F6-56]
+ _ = x[F7-57]
+ _ = x[F8-58]
+ _ = x[F9-59]
+ _ = x[F10-60]
+ _ = x[F11-61]
+ _ = x[F12-62]
+ _ = x[AltBackspace-63]
+ _ = x[AltUp-64]
+ _ = x[AltDown-65]
+ _ = x[AltLeft-66]
+ _ = x[AltRight-67]
+ _ = x[AltShiftUp-68]
+ _ = x[AltShiftDown-69]
+ _ = x[AltShiftLeft-70]
+ _ = x[AltShiftRight-71]
+ _ = x[Alt-72]
+ _ = x[CtrlAlt-73]
+ _ = x[Invalid-74]
+ _ = x[Mouse-75]
+ _ = x[DoubleClick-76]
+ _ = x[LeftClick-77]
+ _ = x[RightClick-78]
+ _ = x[SLeftClick-79]
+ _ = x[SRightClick-80]
+ _ = x[ScrollUp-81]
+ _ = x[ScrollDown-82]
+ _ = x[SScrollUp-83]
+ _ = x[SScrollDown-84]
+ _ = x[PreviewScrollUp-85]
+ _ = x[PreviewScrollDown-86]
+ _ = x[Resize-87]
+ _ = x[Change-88]
+ _ = x[BackwardEOF-89]
+ _ = x[Start-90]
+ _ = x[Load-91]
+ _ = x[Focus-92]
+ _ = x[One-93]
+ _ = x[Zero-94]
+ _ = x[Result-95]
+ _ = x[Jump-96]
+ _ = x[JumpCancel-97]
+}
+
+const _EventType_name = "RuneCtrlACtrlBCtrlCCtrlDCtrlECtrlFCtrlGCtrlHTabCtrlJCtrlKCtrlLCtrlMCtrlNCtrlOCtrlPCtrlQCtrlRCtrlSCtrlTCtrlUCtrlVCtrlWCtrlXCtrlYCtrlZEscCtrlSpaceCtrlDeleteCtrlBackSlashCtrlRightBracketCtrlCaretCtrlSlashShiftTabBackspaceDeletePageUpPageDownUpDownLeftRightHomeEndInsertShiftUpShiftDownShiftLeftShiftRightShiftDeleteF1F2F3F4F5F6F7F8F9F10F11F12AltBackspaceAltUpAltDownAltLeftAltRightAltShiftUpAltShiftDownAltShiftLeftAltShiftRightAltCtrlAltInvalidMouseDoubleClickLeftClickRightClickSLeftClickSRightClickScrollUpScrollDownSScrollUpSScrollDownPreviewScrollUpPreviewScrollDownResizeChangeBackwardEOFStartLoadFocusOneZeroResultJumpJumpCancel"
+
+var _EventType_index = [...]uint16{0, 4, 9, 14, 19, 24, 29, 34, 39, 44, 47, 52, 57, 62, 67, 72, 77, 82, 87, 92, 97, 102, 107, 112, 117, 122, 127, 132, 135, 144, 154, 167, 183, 192, 201, 209, 218, 224, 230, 238, 240, 244, 248, 253, 257, 260, 266, 273, 282, 291, 301, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 333, 336, 339, 351, 356, 363, 370, 378, 388, 400, 412, 425, 428, 435, 442, 447, 458, 467, 477, 487, 498, 506, 516, 525, 536, 551, 568, 574, 580, 591, 596, 600, 605, 608, 612, 618, 622, 632}
+
+func (i EventType) String() string {
+ if i < 0 || i >= EventType(len(_EventType_index)-1) {
+ return "EventType(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _EventType_name[_EventType_index[i]:_EventType_index[i+1]]
+}
diff --git a/src/tui/light.go b/src/tui/light.go
index e42d398b..244891a9 100644
--- a/src/tui/light.go
+++ b/src/tui/light.go
@@ -245,7 +245,7 @@ func (r *LightRenderer) getBytesInternal(buffer []byte, nonblock bool) []byte {
}
retries := 0
- if c == ESC.Int() || nonblock {
+ if c == Esc.Int() || nonblock {
retries = r.escDelay / escPollInterval
}
buffer = append(buffer, byte(c))
@@ -260,7 +260,7 @@ func (r *LightRenderer) getBytesInternal(buffer []byte, nonblock bool) []byte {
continue
}
break
- } else if c == ESC.Int() && pc != c {
+ } else if c == Esc.Int() && pc != c {
retries = r.escDelay / escPollInterval
} else {
retries = 0
@@ -300,7 +300,7 @@ func (r *LightRenderer) GetChar() Event {
case CtrlQ.Byte():
return Event{CtrlQ, 0, nil}
case 127:
- return Event{BSpace, 0, nil}
+ return Event{Backspace, 0, nil}
case 0:
return Event{CtrlSpace, 0, nil}
case 28:
@@ -311,7 +311,7 @@ func (r *LightRenderer) GetChar() Event {
return Event{CtrlCaret, 0, nil}
case 31:
return Event{CtrlSlash, 0, nil}
- case ESC.Byte():
+ case Esc.Byte():
ev := r.escSequence(&sz)
// Second chance
if ev.Type == Invalid {
@@ -327,7 +327,7 @@ func (r *LightRenderer) GetChar() Event {
}
char, rsz := utf8.DecodeRune(r.buffer)
if char == utf8.RuneError {
- return Event{ESC, 0, nil}
+ return Event{Esc, 0, nil}
}
sz = rsz
return Event{Rune, char, nil}
@@ -335,7 +335,7 @@ func (r *LightRenderer) GetChar() Event {
func (r *LightRenderer) escSequence(sz *int) Event {
if len(r.buffer) < 2 {
- return Event{ESC, 0, nil}
+ return Event{Esc, 0, nil}
}
loc := offsetRegexpBegin.FindIndex(r.buffer)
@@ -349,15 +349,15 @@ func (r *LightRenderer) escSequence(sz *int) Event {
return CtrlAltKey(rune(r.buffer[1] + 'a' - 1))
}
alt := false
- if len(r.buffer) > 2 && r.buffer[1] == ESC.Byte() {
+ if len(r.buffer) > 2 && r.buffer[1] == Esc.Byte() {
r.buffer = r.buffer[1:]
alt = true
}
switch r.buffer[1] {
- case ESC.Byte():
- return Event{ESC, 0, nil}
+ case Esc.Byte():
+ return Event{Esc, 0, nil}
case 127:
- return Event{AltBS, 0, nil}
+ return Event{AltBackspace, 0, nil}
case '[', 'O':
if len(r.buffer) < 3 {
return Event{Invalid, 0, nil}
@@ -386,7 +386,7 @@ func (r *LightRenderer) escSequence(sz *int) Event {
}
return Event{Up, 0, nil}
case 'Z':
- return Event{BTab, 0, nil}
+ return Event{ShiftTab, 0, nil}
case 'H':
return Event{Home, 0, nil}
case 'F':
@@ -434,7 +434,7 @@ func (r *LightRenderer) escSequence(sz *int) Event {
return Event{Invalid, 0, nil} // INS
case '3':
if r.buffer[3] == '~' {
- return Event{Del, 0, nil}
+ return Event{Delete, 0, nil}
}
if len(r.buffer) == 6 && r.buffer[5] == '~' {
*sz = 6
@@ -442,16 +442,16 @@ func (r *LightRenderer) escSequence(sz *int) Event {
case '5':
return Event{CtrlDelete, 0, nil}
case '2':
- return Event{SDelete, 0, nil}
+ return Event{ShiftDelete, 0, nil}
}
}
return Event{Invalid, 0, nil}
case '4':
return Event{End, 0, nil}
case '5':
- return Event{PgUp, 0, nil}
+ return Event{PageUp, 0, nil}
case '6':
- return Event{PgDn, 0, nil}
+ return Event{PageDown, 0, nil}
case '7':
return Event{Home, 0, nil}
case '8':
@@ -489,16 +489,29 @@ func (r *LightRenderer) escSequence(sz *int) Event {
}
*sz = 6
switch r.buffer[4] {
- case '1', '2', '3', '5':
+ case '1', '2', '3', '4', '5':
+ // Kitty iTerm2 WezTerm
+ // SHIFT-ARROW "\e[1;2D"
+ // ALT-SHIFT-ARROW "\e[1;4D" "\e[1;10D" "\e[1;4D"
+ // CTRL-SHIFT-ARROW "\e[1;6D" N/A
+ // CMD-SHIFT-ARROW "\e[1;10D" N/A N/A ("\e[1;2D")
alt := r.buffer[4] == '3'
- altShift := r.buffer[4] == '1' && r.buffer[5] == '0'
char := r.buffer[5]
- if altShift {
+ altShift := false
+ if r.buffer[4] == '1' && r.buffer[5] == '0' {
+ altShift = true
if len(r.buffer) < 7 {
return Event{Invalid, 0, nil}
}
*sz = 7
char = r.buffer[6]
+ } else if r.buffer[4] == '4' {
+ altShift = true
+ if len(r.buffer) < 6 {
+ return Event{Invalid, 0, nil}
+ }
+ *sz = 6
+ char = r.buffer[5]
}
switch char {
case 'A':
@@ -506,33 +519,33 @@ func (r *LightRenderer) escSequence(sz *int) Event {
return Event{AltUp, 0, nil}
}
if altShift {
- return Event{AltSUp, 0, nil}
+ return Event{AltShiftUp, 0, nil}
}
- return Event{SUp, 0, nil}
+ return Event{ShiftUp, 0, nil}
case 'B':
if alt {
return Event{AltDown, 0, nil}
}
if altShift {
- return Event{AltSDown, 0, nil}
+ return Event{AltShiftDown, 0, nil}
}
- return Event{SDown, 0, nil}
+ return Event{ShiftDown, 0, nil}
case 'C':
if alt {
return Event{AltRight, 0, nil}
}
if altShift {
- return Event{AltSRight, 0, nil}
+ return Event{AltShiftRight, 0, nil}
}
- return Event{SRight, 0, nil}
+ return Event{ShiftRight, 0, nil}
case 'D':
if alt {
return Event{AltLeft, 0, nil}
}
if altShift {
- return Event{AltSLeft, 0, nil}
+ return Event{AltShiftLeft, 0, nil}
}
- return Event{SLeft, 0, nil}
+ return Event{ShiftLeft, 0, nil}
}
} // r.buffer[4]
} // r.buffer[3]
diff --git a/src/tui/tui.go b/src/tui/tui.go
index 729146cc..ad65e92f 100644
--- a/src/tui/tui.go
+++ b/src/tui/tui.go
@@ -6,10 +6,13 @@ import (
"strconv"
"time"
+ "github.com/junegunn/fzf/src/util"
"github.com/rivo/uniseg"
)
// Types of user action
+//
+//go:generate stringer -type=EventType
type EventType int
const (
@@ -41,7 +44,7 @@ const (
CtrlX
CtrlY
CtrlZ
- ESC
+ Esc
CtrlSpace
CtrlDelete
@@ -51,27 +54,12 @@ const (
CtrlCaret
CtrlSlash
- Invalid
- Resize
- Mouse
- DoubleClick
- LeftClick
- RightClick
- SLeftClick
- SRightClick
- ScrollUp
- ScrollDown
- SScrollUp
- SScrollDown
- PreviewScrollUp
- PreviewScrollDown
-
- BTab
- BSpace
+ ShiftTab
+ Backspace
- Del
- PgUp
- PgDn
+ Delete
+ PageUp
+ PageDown
Up
Down
@@ -81,11 +69,11 @@ const (
End
Insert
- SUp
- SDown
- SLeft
- SRight
- SDelete
+ ShiftUp
+ ShiftDown
+ ShiftLeft
+ ShiftRight
+ ShiftDelete
F1
F2
@@ -100,6 +88,38 @@ const (
F11
F12
+ AltBackspace
+
+ AltUp
+ AltDown
+ AltLeft
+ AltRight
+
+ AltShiftUp
+ AltShiftDown
+ AltShiftLeft
+ AltShiftRight
+
+ Alt
+ CtrlAlt
+
+ Invalid
+
+ Mouse
+ DoubleClick
+ LeftClick
+ RightClick
+ SLeftClick
+ SRightClick
+ ScrollUp
+ ScrollDown
+ SScrollUp
+ SScrollDown
+ PreviewScrollUp
+ PreviewScrollDown
+
+ // Events
+ Resize
Change
BackwardEOF
Start
@@ -110,21 +130,6 @@ const (
Result
Jump
JumpCancel
-
- AltBS
-
- AltUp
- AltDown
- AltLeft
- AltRight
-
- AltSUp
- AltSDown
- AltSLeft
- AltSRight
-
- Alt
- CtrlAlt
)
func (t EventType) AsEvent() Event {
@@ -144,6 +149,31 @@ func (e Event) Comparable() Event {
return Event{e.Type, e.Char, nil}
}
+func (e Event) KeyName() string {
+ if e.Type >= Invalid {
+ return ""
+ }
+
+ switch e.Type {
+ case Rune:
+ return string(e.Char)
+ case Alt:
+ return "alt-" + string(e.Char)
+ case CtrlAlt:
+ return "ctrl-alt-" + string(e.Char)
+ case CtrlBackSlash:
+ return "ctrl-\\"
+ case CtrlRightBracket:
+ return "ctrl-]"
+ case CtrlCaret:
+ return "ctrl-^"
+ case CtrlSlash:
+ return "ctrl-/"
+ }
+
+ return util.ToKebabCase(e.Type.String())
+}
+
func Key(r rune) Event {
return Event{Rune, r, nil}
}