mirror of
https://github.com/junegunn/fzf.git
synced 2026-08-12 19:07:00 +08:00
+3
-1
@@ -25,7 +25,9 @@ CHANGELOG
|
|||||||
```
|
```
|
||||||
- Improved the cache structure, reducing memory footprint per entry by 86x.
|
- Improved the cache structure, reducing memory footprint per entry by 86x.
|
||||||
- With the reduced per-entry cost, the cache now has broader coverage.
|
- With the reduced per-entry cost, the cache now has broader coverage.
|
||||||
- fish: Improved command history (CTRL-R) (#4703) (@bitraid)
|
- Shell integration improvements
|
||||||
|
- bash: Press `shift-delete` to delete history entries during CTRL-R search (#4715)
|
||||||
|
- fish: Improved command history (CTRL-R) (#4703) (@bitraid)
|
||||||
- `GET /` HTTP endpoint now includes `positions` field in each match entry, providing the indices of matched characters for external highlighting (#4726)
|
- `GET /` HTTP endpoint now includes `positions` field in each match entry, providing the indices of matched characters for external highlighting (#4726)
|
||||||
- Bug fixes
|
- Bug fixes
|
||||||
- `--walker=follow` no longer follows symlinks whose target is an ancestor of the walker root, avoiding severe resource exhaustion when a symlink points outside the tree (e.g. Wine's `z:` → `/`) (#4710)
|
- `--walker=follow` no longer follows symlinks whose target is an ancestor of the walker root, avoiding severe resource exhaustion when a symlink points outside the tree (e.g. Wine's `z:` → `/`) (#4710)
|
||||||
|
|||||||
+24
-6
@@ -77,17 +77,31 @@ __fzf_cd__() {
|
|||||||
) && printf 'builtin cd -- %q' "$(builtin unset CDPATH && builtin cd -- "$dir" && builtin pwd)"
|
) && printf 'builtin cd -- %q' "$(builtin unset CDPATH && builtin cd -- "$dir" && builtin pwd)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__fzf_history_delete() {
|
||||||
|
[[ -s $1 ]] || return
|
||||||
|
|
||||||
|
local offsets
|
||||||
|
offsets=($(sort -rnu "$1"))
|
||||||
|
for offset in "${offsets[@]}"; do
|
||||||
|
builtin history -d "$offset"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
if command -v perl > /dev/null; then
|
if command -v perl > /dev/null; then
|
||||||
__fzf_history__() {
|
__fzf_history__() {
|
||||||
local output script
|
local output script deletefile
|
||||||
|
deletefile=$(mktemp)
|
||||||
script='BEGIN { getc; $/ = "\n\t"; $HISTCOUNT = $ENV{last_hist} + 1 } s/^[ *]//; s/\n/\n\t/gm; print $HISTCOUNT - $. . "\t$_" if !$seen{$_}++'
|
script='BEGIN { getc; $/ = "\n\t"; $HISTCOUNT = $ENV{last_hist} + 1 } s/^[ *]//; s/\n/\n\t/gm; print $HISTCOUNT - $. . "\t$_" if !$seen{$_}++'
|
||||||
output=$(
|
output=$(
|
||||||
set +o pipefail
|
set +o pipefail
|
||||||
builtin fc -lnr -2147483648 |
|
builtin fc -lnr -2147483648 |
|
||||||
last_hist=$(HISTTIMEFORMAT='' builtin history 1) command perl -n -l0 -e "$script" |
|
last_hist=$(HISTTIMEFORMAT='' builtin history 1) command perl -n -l0 -e "$script" |
|
||||||
FZF_DEFAULT_OPTS=$(__fzf_defaults "" "-n2..,.. --scheme=history --bind=ctrl-r:toggle-sort,alt-r:toggle-raw --wrap-sign '"$'\t'"↳ ' --highlight-line ${FZF_CTRL_R_OPTS-} +m --read0") \
|
FZF_DEFAULT_OPTS=$(__fzf_defaults "" "-n2..,.. --scheme=history --bind=ctrl-r:toggle-sort,alt-r:toggle-raw --wrap-sign '"$'\t'"↳ ' --highlight-line --bind 'shift-delete:execute-silent(echo {1} >> \"$deletefile\")+exclude' ${FZF_CTRL_R_OPTS-} +m --read0") \
|
||||||
FZF_DEFAULT_OPTS_FILE='' $(__fzfcmd) --query "$READLINE_LINE"
|
FZF_DEFAULT_OPTS_FILE='' $(__fzfcmd) --query "$READLINE_LINE"
|
||||||
) || return
|
)
|
||||||
|
__fzf_history_delete "$deletefile"
|
||||||
|
command rm -f "$deletefile"
|
||||||
|
[[ -n $output ]] || return
|
||||||
READLINE_LINE=$(command perl -pe 's/^\d*\t//' <<< "$output")
|
READLINE_LINE=$(command perl -pe 's/^\d*\t//' <<< "$output")
|
||||||
if [[ -z $READLINE_POINT ]]; then
|
if [[ -z $READLINE_POINT ]]; then
|
||||||
echo "$READLINE_LINE"
|
echo "$READLINE_LINE"
|
||||||
@@ -97,7 +111,8 @@ if command -v perl > /dev/null; then
|
|||||||
}
|
}
|
||||||
else # awk - fallback for POSIX systems
|
else # awk - fallback for POSIX systems
|
||||||
__fzf_history__() {
|
__fzf_history__() {
|
||||||
local output script
|
local output script deletefile
|
||||||
|
deletefile=$(mktemp)
|
||||||
[[ $(HISTTIMEFORMAT='' builtin history 1) =~ [[:digit:]]+ ]] # how many history entries
|
[[ $(HISTTIMEFORMAT='' builtin history 1) =~ [[:digit:]]+ ]] # how many history entries
|
||||||
script='function P(b) { ++n; sub(/^[ *]/, "", b); if (!seen[b]++) { printf "%d\t%s%c", '$((BASH_REMATCH + 1))' - n, b, 0 } }
|
script='function P(b) { ++n; sub(/^[ *]/, "", b); if (!seen[b]++) { printf "%d\t%s%c", '$((BASH_REMATCH + 1))' - n, b, 0 } }
|
||||||
NR==1 { b = substr($0, 2); next }
|
NR==1 { b = substr($0, 2); next }
|
||||||
@@ -108,9 +123,12 @@ else # awk - fallback for POSIX systems
|
|||||||
set +o pipefail
|
set +o pipefail
|
||||||
builtin fc -lnr -2147483648 2> /dev/null | # ( $'\t '<lines>$'\n' )* ; <lines> ::= [^\n]* ( $'\n'<lines> )*
|
builtin fc -lnr -2147483648 2> /dev/null | # ( $'\t '<lines>$'\n' )* ; <lines> ::= [^\n]* ( $'\n'<lines> )*
|
||||||
__fzf_exec_awk "$script" | # ( <counter>$'\t'<lines>$'\000' )*
|
__fzf_exec_awk "$script" | # ( <counter>$'\t'<lines>$'\000' )*
|
||||||
FZF_DEFAULT_OPTS=$(__fzf_defaults "" "-n2..,.. --scheme=history --bind=ctrl-r:toggle-sort,alt-r:toggle-raw --wrap-sign '"$'\t'"↳ ' --highlight-line ${FZF_CTRL_R_OPTS-} +m --read0") \
|
FZF_DEFAULT_OPTS=$(__fzf_defaults "" "-n2..,.. --scheme=history --bind=ctrl-r:toggle-sort,alt-r:toggle-raw --wrap-sign '"$'\t'"↳ ' --highlight-line --bind 'shift-delete:execute-silent(echo {1} >> \"$deletefile\")+exclude' ${FZF_CTRL_R_OPTS-} +m --read0") \
|
||||||
FZF_DEFAULT_OPTS_FILE='' $(__fzfcmd) --query "$READLINE_LINE"
|
FZF_DEFAULT_OPTS_FILE='' $(__fzfcmd) --query "$READLINE_LINE"
|
||||||
) || return
|
)
|
||||||
|
__fzf_history_delete "$deletefile"
|
||||||
|
command rm -f "$deletefile"
|
||||||
|
[[ -n $output ]] || return
|
||||||
READLINE_LINE=${output#*$'\t'}
|
READLINE_LINE=${output#*$'\t'}
|
||||||
if [[ -z $READLINE_POINT ]]; then
|
if [[ -z $READLINE_POINT ]]; then
|
||||||
echo "$READLINE_LINE"
|
echo "$READLINE_LINE"
|
||||||
|
|||||||
@@ -832,6 +832,50 @@ class TestBash < TestBase
|
|||||||
tmux.prepare
|
tmux.prepare
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_ctrl_r_delete
|
||||||
|
tmux.prepare
|
||||||
|
tmux.send_keys 'echo to-keep', :Enter
|
||||||
|
tmux.prepare
|
||||||
|
tmux.send_keys 'echo to-delete-1', :Enter
|
||||||
|
tmux.prepare
|
||||||
|
tmux.send_keys 'echo to-delete-2', :Enter
|
||||||
|
tmux.prepare
|
||||||
|
tmux.send_keys 'echo another-keeper', :Enter
|
||||||
|
tmux.prepare
|
||||||
|
|
||||||
|
# Open Ctrl-R and delete two entries
|
||||||
|
tmux.send_keys 'C-r'
|
||||||
|
tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||||
|
tmux.send_keys 'to-delete'
|
||||||
|
tmux.until { |lines| assert_equal 2, lines.match_count }
|
||||||
|
# Delete the first match
|
||||||
|
tmux.send_keys 'S-Delete'
|
||||||
|
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||||
|
# Delete the second match
|
||||||
|
tmux.send_keys 'S-Delete'
|
||||||
|
tmux.until { |lines| assert_equal 0, lines.match_count }
|
||||||
|
# Exit without selecting
|
||||||
|
tmux.send_keys :Escape
|
||||||
|
tmux.prepare
|
||||||
|
|
||||||
|
# Verify deleted entries are gone from history
|
||||||
|
tmux.send_keys 'C-r'
|
||||||
|
tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||||
|
tmux.send_keys 'to-delete'
|
||||||
|
tmux.until { |lines| assert_equal 0, lines.match_count }
|
||||||
|
tmux.send_keys :Escape
|
||||||
|
tmux.prepare
|
||||||
|
|
||||||
|
# Verify kept entries are still there
|
||||||
|
tmux.send_keys 'C-r'
|
||||||
|
tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||||
|
tmux.send_keys 'to-keep'
|
||||||
|
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||||
|
tmux.send_keys :Enter
|
||||||
|
tmux.until { |lines| assert_equal 'echo to-keep', lines[-1] }
|
||||||
|
tmux.send_keys 'C-c'
|
||||||
|
end
|
||||||
|
|
||||||
def test_dynamic_completion_loader
|
def test_dynamic_completion_loader
|
||||||
tmux.paste 'touch /tmp/foo; _fzf_completion_loader=1'
|
tmux.paste 'touch /tmp/foo; _fzf_completion_loader=1'
|
||||||
tmux.paste '_completion_loader() { complete -o default fake; }'
|
tmux.paste '_completion_loader() { complete -o default fake; }'
|
||||||
|
|||||||
Reference in New Issue
Block a user