Skip to content

Commit 7c447bb

Browse files
jablkojunegunn
andauthored
[bash] Start C-r search with current command line (junegunn#1886)
Restore the original line when search is aborted. Add --query "$READLINE_LINE" and fall back to the current behavior pre Bash 4. Co-authored-by: Junegunn Choi <junegunn.c@gmail.com>
1 parent 7bf1f2c commit 7c447bb

File tree

3 files changed

+64
-54
lines changed

3 files changed

+64
-54
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ script:
1919
# LC_ALL=C to avoid escape codes in
2020
# printf %q $'\355\205\214\354\212\244\355\212\270' on macOS. Bash on
2121
# macOS is built without HANDLE_MULTIBYTE?
22-
- make install && ./install --all && LC_ALL=C tmux new-session -d && ruby test/test_go.rb
22+
- make install && ./install --all && LC_ALL=C tmux new-session -d && ruby test/test_go.rb --verbose

shell/key-bindings.bash

+38-29
Original file line numberDiff line numberDiff line change
@@ -51,47 +51,56 @@ __fzf_cd__() {
5151
dir=$(eval "$cmd" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse $FZF_DEFAULT_OPTS $FZF_ALT_C_OPTS" $(__fzfcmd) +m) && printf 'cd %q' "$dir"
5252
}
5353

54-
__fzf_history__() (
55-
local line
56-
line=$(
54+
__fzf_history__() {
55+
local output
56+
output=$(
5757
builtin fc -lnr -2147483648 |
58-
perl -p -l0 -e 'BEGIN { getc; $/ = "\n\t" } s/^[ *]//; $_ = '"$1"' - $. . "\t$_"' |
59-
FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS +m --read0" $(__fzfcmd)
60-
)
61-
echo "${line#*$'\t'}"
62-
)
58+
last_hist=$(HISTTIMEFORMAT='' builtin history 1) perl -p -l0 -e 'BEGIN { getc; $/ = "\n\t"; $HISTCMD = $ENV{last_hist} + 1 } s/^[ *]//; $_ = $HISTCMD - $. . "\t$_"' |
59+
FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS +m --query $(printf %q "$READLINE_LINE") --read0" $(__fzfcmd)
60+
) || return
61+
READLINE_LINE=${output#*$'\t'}
62+
if [ -z "$READLINE_POINT" ]; then
63+
echo "$READLINE_LINE"
64+
else
65+
READLINE_POINT=0x7fffffff
66+
fi
67+
}
6368

6469
# Required to refresh the prompt after fzf
6570
bind -m emacs-standard '"\er": redraw-current-line'
6671

67-
# CTRL-T - Paste the selected file path into the command line
68-
if [ $BASH_VERSINFO -gt 3 ]; then
69-
bind -m emacs-standard -x '"\C-t": "fzf-file-widget"'
70-
elif __fzf_use_tmux__; then
71-
bind -m emacs-standard '"\C-t": " \C-b\C-k \C-u`__fzf_select_tmux__`\e\C-e\C-a\C-y\C-h\C-e\e \C-y\ey\C-x\C-x\C-f"'
72-
else
73-
bind -m emacs-standard '"\C-t": " \C-b\C-k \C-u`__fzf_select__`\e\C-e\er\C-a\C-y\C-h\C-e\e \C-y\ey\C-x\C-x\C-f"'
74-
fi
75-
76-
# CTRL-R - Paste the selected command from history into the command line
77-
bind -m emacs-standard '"\C-r": "\C-e \C-u\C-y\ey\C-u__fzf_history__ $HISTCMD\e\C-e`"\C-a"`\C-e\e\C-e\er"'
78-
79-
# ALT-C - cd into the selected directory
80-
bind -m emacs-standard '"\ec": " \C-b\C-k \C-u`__fzf_cd__`\e\C-e\er\C-m\C-y\C-h\e \C-y\ey\C-x\C-x\C-d"'
81-
8272
bind -m vi-command '"\C-z": emacs-editing-mode'
8373
bind -m vi-insert '"\C-z": emacs-editing-mode'
8474
bind -m emacs-standard '"\C-z": vi-editing-mode'
8575

86-
# CTRL-T - Paste the selected file path into the command line
87-
bind -m vi-command '"\C-t": "\C-z\C-t\C-z"'
88-
bind -m vi-insert '"\C-t": "\C-z\C-t\C-z"'
76+
if [ "${BASH_VERSINFO[0]}" -lt 4 ]; then
77+
# CTRL-T - Paste the selected file path into the command line
78+
if __fzf_use_tmux__; then
79+
bind -m emacs-standard '"\C-t": " \C-b\C-k \C-u`__fzf_select_tmux__`\e\C-e\C-a\C-y\C-h\C-e\e \C-y\ey\C-x\C-x\C-f"'
80+
else
81+
bind -m emacs-standard '"\C-t": " \C-b\C-k \C-u`__fzf_select__`\e\C-e\er\C-a\C-y\C-h\C-e\e \C-y\ey\C-x\C-x\C-f"'
82+
fi
83+
bind -m vi-command '"\C-t": "\C-z\C-t\C-z"'
84+
bind -m vi-insert '"\C-t": "\C-z\C-t\C-z"'
8985

90-
# CTRL-R - Paste the selected command from history into the command line
91-
bind -m vi-command '"\C-r": "\C-z\C-r\C-z"'
92-
bind -m vi-insert '"\C-r": "\C-z\C-r\C-z"'
86+
# CTRL-R - Paste the selected command from history into the command line
87+
bind -m emacs-standard '"\C-r": "\C-e \C-u\C-y\ey\C-u"$(__fzf_history__)"\e\C-e\er"'
88+
bind -m vi-command '"\C-r": "\C-z\C-r\C-z"'
89+
bind -m vi-insert '"\C-r": "\C-z\C-r\C-z"'
90+
else
91+
# CTRL-T - Paste the selected file path into the command line
92+
bind -m emacs-standard -x '"\C-t": fzf-file-widget'
93+
bind -m vi-command -x '"\C-t": fzf-file-widget'
94+
bind -m vi-insert -x '"\C-t": fzf-file-widget'
95+
96+
# CTRL-R - Paste the selected command from history into the command line
97+
bind -m emacs-standard -x '"\C-r": __fzf_history__'
98+
bind -m vi-command -x '"\C-r": __fzf_history__'
99+
bind -m vi-insert -x '"\C-r": __fzf_history__'
100+
fi
93101

94102
# ALT-C - cd into the selected directory
103+
bind -m emacs-standard '"\ec": " \C-b\C-k \C-u`__fzf_cd__`\e\C-e\er\C-m\C-y\C-h\e \C-y\ey\C-x\C-x\C-d"'
95104
bind -m vi-command '"\ec": "\C-z\ec\C-z"'
96105
bind -m vi-insert '"\ec": "\C-z\ec\C-z"'
97106

test/test_go.rb

+25-24
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,6 @@ def fish
8484
end
8585

8686
class Tmux
87-
TEMPNAME = '/tmp/fzf-test.txt'
88-
8987
attr_reader :win
9088

9189
def initialize(shell = :bash)
@@ -129,12 +127,7 @@ def paste(str)
129127
end
130128

131129
def capture(pane = 0)
132-
File.unlink TEMPNAME while File.exist? TEMPNAME
133-
wait do
134-
go("capture-pane -t #{win}.#{pane} \\; save-buffer #{TEMPNAME} 2> /dev/null")
135-
$CHILD_STATUS.exitstatus.zero?
136-
end
137-
File.read(TEMPNAME).split($INPUT_RECORD_SEPARATOR).reverse.drop_while(&:empty?).reverse
130+
go("capture-pane -p -t #{win}.#{pane}")
138131
end
139132

140133
def until(refresh = false, pane = 0)
@@ -1738,7 +1731,8 @@ def test_backward_delete_char_eof
17381731

17391732
module TestShell
17401733
def setup
1741-
super
1734+
@tmux = Tmux.new shell
1735+
tmux.prepare
17421736
end
17431737

17441738
def teardown
@@ -1855,6 +1849,16 @@ def test_ctrl_r
18551849
tmux.until { |lines| lines[-1] == '3rd' }
18561850
end
18571851

1852+
def test_ctrl_r_abort
1853+
skip "doesn't restore the original line when search is aborted pre Bash 4" if shell == :bash && /(?<= version )\d+/.match(`#{Shell.bash} --version`).to_s.to_i < 4
1854+
tmux.send_keys 'foo'
1855+
tmux.until { |lines| lines[-1].start_with? 'foo' }
1856+
tmux.send_keys 'C-r'
1857+
tmux.until { |lines| lines[-1].start_with? '>' }
1858+
tmux.send_keys 'C-g'
1859+
tmux.until { |lines| lines[-1].start_with? 'foo' }
1860+
end
1861+
18581862
def retries(times = 3)
18591863
(times - 1).times do
18601864
begin
@@ -2044,17 +2048,16 @@ class TestBash < TestBase
20442048
include TestShell
20452049
include CompletionTest
20462050

2051+
def shell
2052+
:bash
2053+
end
2054+
20472055
def new_shell
20482056
tmux.prepare
20492057
tmux.send_keys "FZF_TMUX=1 #{Shell.bash}", :Enter
20502058
tmux.prepare
20512059
end
20522060

2053-
def setup
2054-
super
2055-
@tmux = Tmux.new :bash
2056-
end
2057-
20582061
def test_dynamic_completion_loader
20592062
tmux.paste 'touch /tmp/foo; _fzf_completion_loader=1'
20602063
tmux.paste '_completion_loader() { complete -o default fake; }'
@@ -2077,20 +2080,23 @@ class TestZsh < TestBase
20772080
include TestShell
20782081
include CompletionTest
20792082

2083+
def shell
2084+
:zsh
2085+
end
2086+
20802087
def new_shell
20812088
tmux.send_keys "FZF_TMUX=1 #{Shell.zsh}", :Enter
20822089
tmux.prepare
20832090
end
2084-
2085-
def setup
2086-
super
2087-
@tmux = Tmux.new :zsh
2088-
end
20892091
end
20902092

20912093
class TestFish < TestBase
20922094
include TestShell
20932095

2096+
def shell
2097+
:fish
2098+
end
2099+
20942100
def new_shell
20952101
tmux.send_keys 'env FZF_TMUX=1 fish', :Enter
20962102
tmux.send_keys 'function fish_prompt; end; clear', :Enter
@@ -2102,11 +2108,6 @@ def set_var(name, val)
21022108
tmux.send_keys "set -g #{name} '#{val}'", :Enter
21032109
tmux.prepare
21042110
end
2105-
2106-
def setup
2107-
super
2108-
@tmux = Tmux.new :fish
2109-
end
21102111
end
21112112

21122113
__END__

0 commit comments

Comments
 (0)