FZF_KEY enhancements

* 'enter' instead of 'ctrl-m'
* 'space' instead of ' '
This commit is contained in:
Junegunn Choi 2025-02-02 01:48:52 +09:00
parent 178b49832e
commit 32234be7a2
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627
8 changed files with 73 additions and 12 deletions

View File

@ -34,6 +34,19 @@ CHANGELOG
fzf --header '[src] [test]' --no-input --layout reverse \
--header-border bottom --input-border \
--bind 'click-header:transform-search:echo ${FZF_CLICK_HEADER_WORD:1:-1}'
# Vim-like mode switch
fzf --layout reverse-list --no-input \
--bind 'j:down,k:up,/:show-input+unbind(j,k)' \
--bind 'enter,esc,ctrl-c:transform:
if [[ $FZF_INPUT_STATE = enabled ]]; then
echo "rebind(j,k)+hide-input"
elif [[ $FZF_KEY = enter ]]; then
echo accept
else
echo abort
fi
'
```
- You can later show the input section using `show-input` or `toggle-input` action, and hide it again using `hide-input`, or `toggle-input`.
- Extended `{q}` placeholder to support ranges. e.g. `{q:1}`, `{q:2..}`, etc.

View File

@ -885,7 +885,7 @@ func parseKeyChordsImpl(str string, message string) (map[tui.Event]string, error
case "right":
add(tui.Right)
case "enter", "return":
add(tui.CtrlM)
add(tui.Enter)
case "space":
chords[tui.Key(' ')] = key
case "backspace", "bspace", "bs":
@ -3220,7 +3220,7 @@ func postProcessOptions(opts *Options) error {
// If 'double-click' is left unbound, bind it to the action bound to 'enter'
if _, prs := opts.Keymap[tui.DoubleClick.AsEvent()]; !prs {
opts.Keymap[tui.DoubleClick.AsEvent()] = opts.Keymap[tui.CtrlM.AsEvent()]
opts.Keymap[tui.DoubleClick.AsEvent()] = opts.Keymap[tui.Enter.AsEvent()]
}
// If we're not using extended search mode, --nth option becomes irrelevant

View File

@ -172,7 +172,7 @@ func TestParseKeys(t *testing.T) {
if len(pairs) != 9 {
t.Error(9)
}
check(tui.CtrlM, "Return")
check(tui.Enter, "Return")
checkEvent(tui.Key(' '), "space")
check(tui.Tab, "tab")
check(tui.ShiftTab, "btab")
@ -195,7 +195,7 @@ func TestParseKeys(t *testing.T) {
check(tui.ShiftLeft, "shift-left")
check(tui.ShiftRight, "shift-right")
check(tui.ShiftTab, "shift-tab")
check(tui.CtrlM, "Enter")
check(tui.Enter, "Enter")
check(tui.Backspace, "bspace")
}

View File

@ -671,7 +671,7 @@ func defaultKeymap() map[tui.Event][]*action {
add(tui.CtrlJ, actDown)
add(tui.CtrlK, actUp)
add(tui.CtrlL, actClearScreen)
add(tui.CtrlM, actAccept)
add(tui.Enter, actAccept)
add(tui.CtrlN, actDown)
add(tui.CtrlP, actUp)
add(tui.CtrlU, actUnixLineDiscard)

View File

@ -21,7 +21,7 @@ func _() {
_ = x[CtrlJ-10]
_ = x[CtrlK-11]
_ = x[CtrlL-12]
_ = x[CtrlM-13]
_ = x[Enter-13]
_ = x[CtrlN-14]
_ = x[CtrlO-15]
_ = x[CtrlP-16]
@ -110,7 +110,7 @@ func _() {
_ = x[ClickHeader-99]
}
const _EventType_name = "RuneCtrlACtrlBCtrlCCtrlDCtrlECtrlFCtrlGCtrlHTabCtrlJCtrlKCtrlLCtrlMCtrlNCtrlOCtrlPCtrlQCtrlRCtrlSCtrlTCtrlUCtrlVCtrlWCtrlXCtrlYCtrlZEscCtrlSpaceCtrlDeleteCtrlBackSlashCtrlRightBracketCtrlCaretCtrlSlashShiftTabBackspaceDeletePageUpPageDownUpDownLeftRightHomeEndInsertShiftUpShiftDownShiftLeftShiftRightShiftDeleteF1F2F3F4F5F6F7F8F9F10F11F12AltBackspaceAltUpAltDownAltLeftAltRightAltShiftUpAltShiftDownAltShiftLeftAltShiftRightAltCtrlAltInvalidFatalMouseDoubleClickLeftClickRightClickSLeftClickSRightClickScrollUpScrollDownSScrollUpSScrollDownPreviewScrollUpPreviewScrollDownResizeChangeBackwardEOFStartLoadFocusOneZeroResultJumpJumpCancelClickHeader"
const _EventType_name = "RuneCtrlACtrlBCtrlCCtrlDCtrlECtrlFCtrlGCtrlHTabCtrlJCtrlKCtrlLEnterCtrlNCtrlOCtrlPCtrlQCtrlRCtrlSCtrlTCtrlUCtrlVCtrlWCtrlXCtrlYCtrlZEscCtrlSpaceCtrlDeleteCtrlBackSlashCtrlRightBracketCtrlCaretCtrlSlashShiftTabBackspaceDeletePageUpPageDownUpDownLeftRightHomeEndInsertShiftUpShiftDownShiftLeftShiftRightShiftDeleteF1F2F3F4F5F6F7F8F9F10F11F12AltBackspaceAltUpAltDownAltLeftAltRightAltShiftUpAltShiftDownAltShiftLeftAltShiftRightAltCtrlAltInvalidFatalMouseDoubleClickLeftClickRightClickSLeftClickSRightClickScrollUpScrollDownSScrollUpSScrollDownPreviewScrollUpPreviewScrollDownResizeChangeBackwardEOFStartLoadFocusOneZeroResultJumpJumpCancelClickHeader"
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, 452, 463, 472, 482, 492, 503, 511, 521, 530, 541, 556, 573, 579, 585, 596, 601, 605, 610, 613, 617, 623, 627, 637, 648}

View File

@ -82,9 +82,9 @@ func TestGetCharEventKey(t *testing.T) {
{giveKey{tcell.KeyTab, rune(tcell.KeyTab), tcell.ModNone}, wantKey{Tab, 0, nil}}, // unhandled, actual "Tab" keystroke
{giveKey{tcell.KeyTAB, rune(tcell.KeyTAB), tcell.ModNone}, wantKey{Tab, 0, nil}}, // fabricated, unhandled
// KeyEnter is alias for KeyCR
{giveKey{tcell.KeyCtrlM, rune(tcell.KeyCtrlM), tcell.ModNone}, wantKey{CtrlM, 0, nil}}, // actual "Enter" keystroke
{giveKey{tcell.KeyCR, rune(tcell.KeyCR), tcell.ModNone}, wantKey{CtrlM, 0, nil}}, // fabricated, unhandled
{giveKey{tcell.KeyEnter, rune(tcell.KeyEnter), tcell.ModNone}, wantKey{CtrlM, 0, nil}}, // fabricated, unhandled
{giveKey{tcell.KeyCtrlM, rune(tcell.KeyCtrlM), tcell.ModNone}, wantKey{Enter, 0, nil}}, // actual "Enter" keystroke
{giveKey{tcell.KeyCR, rune(tcell.KeyCR), tcell.ModNone}, wantKey{Enter, 0, nil}}, // fabricated, unhandled
{giveKey{tcell.KeyEnter, rune(tcell.KeyEnter), tcell.ModNone}, wantKey{Enter, 0, nil}}, // fabricated, unhandled
// Ctrl+Alt keys
{giveKey{tcell.KeyCtrlA, rune(tcell.KeyCtrlA), tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAlt, 'a', nil}}, // fabricated
{giveKey{tcell.KeyCtrlA, rune(tcell.KeyCtrlA), tcell.ModCtrl | tcell.ModAlt | tcell.ModShift}, wantKey{CtrlAlt, 'a', nil}}, // fabricated
@ -233,7 +233,7 @@ Quick reference
10 1 KeyCtrlJ KeyLF = ^J CtrlJ
11 1 KeyCtrlK KeyVT = ^K CtrlK
12 1 KeyCtrlL KeyFF = ^L CtrlL
13 1 KeyCtrlM KeyCR = ^M KeyEnter CtrlM
13 1 KeyCtrlM KeyCR = ^M KeyEnter Enter
14 1 KeyCtrlN KeySO = ^N CtrlN
15 1 KeyCtrlO KeySI = ^O CtrlO
16 1 KeyCtrlP KeyDLE = ^P CtrlP

View File

@ -28,7 +28,7 @@ const (
CtrlJ
CtrlK
CtrlL
CtrlM
Enter
CtrlN
CtrlO
CtrlP
@ -160,6 +160,9 @@ func (e Event) KeyName() string {
switch e.Type {
case Rune:
if e.Char == ' ' {
return "space"
}
return string(e.Char)
case Alt:
return "alt-" + string(e.Char)

View File

@ -1607,4 +1607,49 @@ class TestCore < TestInteractive
assert_equal 4, lines.match_count
end
end
def test_env_vars
def to_vars(lines)
lines.select { it.start_with?('FZF_') }.to_h do
key, val = it.split('=', 2)
[key.to_sym, val]
end
end
tmux.send_keys %(seq 100 | #{FZF} --multi --reverse --preview-window up,noborder --preview 'env | grep ^FZF_ | sort' --no-input --bind enter:show-input+refresh-preview,space:disable-search+refresh-preview), :Enter
expected = {
FZF_TOTAL_COUNT: '100',
FZF_MATCH_COUNT: '100',
FZF_SELECT_COUNT: '0',
FZF_ACTION: 'start',
FZF_KEY: '',
FZF_POS: '1',
FZF_QUERY: '',
FZF_PROMPT: '>',
FZF_INPUT_STATE: 'hidden'
}
tmux.until do |lines|
assert_equal expected, to_vars(lines).slice(*expected.keys)
end
tmux.send_keys :Enter
tmux.until do |lines|
expected.merge!(FZF_INPUT_STATE: 'enabled', FZF_ACTION: 'show-input', FZF_KEY: 'enter')
assert_equal expected, to_vars(lines).slice(*expected.keys)
end
tmux.send_keys :Tab, :Tab
tmux.until do |lines|
expected.merge!(FZF_ACTION: 'toggle-down', FZF_KEY: 'tab', FZF_POS: '3', FZF_SELECT_COUNT: '2')
assert_equal expected, to_vars(lines).slice(*expected.keys)
end
tmux.send_keys '99'
tmux.until do |lines|
expected.merge!(FZF_ACTION: 'char', FZF_KEY: '9', FZF_QUERY: '99', FZF_MATCH_COUNT: '1', FZF_POS: '1')
assert_equal expected, to_vars(lines).slice(*expected.keys)
end
tmux.send_keys :Space
tmux.until do |lines|
expected.merge!(FZF_INPUT_STATE: 'disabled', FZF_ACTION: 'disable-search', FZF_KEY: 'space')
assert_equal expected, to_vars(lines).slice(*expected.keys)
end
end
end