mirror of
https://github.com/junegunn/fzf.git
synced 2025-12-10 14:41:55 +08:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a24d274a3c | ||
|
|
dac81432d6 | ||
|
|
309b5081ef | ||
|
|
91bc4f2671 | ||
|
|
4c9d37d919 | ||
|
|
7e9566f66a | ||
|
|
3f7e8a475d | ||
|
|
1cf7c0f334 | ||
|
|
ff8ee9ee4e | ||
|
|
cbbd939a94 | ||
|
|
f232df2887 | ||
|
|
16bfb2c80c | ||
|
|
0ba066123e | ||
|
|
81c51c26cc | ||
|
|
6fa8295ac5 | ||
|
|
f975b40236 | ||
|
|
01d9d9c8c8 | ||
|
|
1eafc4e5d9 | ||
|
|
38e4020aa8 | ||
|
|
ac32fbb3b2 | ||
|
|
7d26eca5cc |
@@ -1,6 +1,13 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
0.60.1
|
||||||
|
------
|
||||||
|
- Bug fixes and minor improvements
|
||||||
|
- Built-in walker now prints directory entries with a trailing slash
|
||||||
|
- Fixed a bug causing unexpected behavior with [fzf-tab](https://github.com/Aloxaf/fzf-tab). Please upgrade if you use it.
|
||||||
|
- Thanks to @alexeisersun, @bitraid, @Lompik, and @fsc0 for the contributions
|
||||||
|
|
||||||
0.60.0
|
0.60.0
|
||||||
------
|
------
|
||||||
_Release highlights: https://junegunn.github.io/fzf/releases/0.60.0/_
|
_Release highlights: https://junegunn.github.io/fzf/releases/0.60.0/_
|
||||||
|
|||||||
2
install
2
install
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
set -u
|
set -u
|
||||||
|
|
||||||
version=0.60.0
|
version=0.60.1
|
||||||
auto_completion=
|
auto_completion=
|
||||||
key_bindings=
|
key_bindings=
|
||||||
update_config=2
|
update_config=2
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
$version="0.60.0"
|
$version="0.60.1"
|
||||||
|
|
||||||
$fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition
|
$fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
..
|
..
|
||||||
.TH fzf\-tmux 1 "Feb 2025" "fzf 0.60.0" "fzf\-tmux - open fzf in tmux split pane"
|
.TH fzf\-tmux 1 "Feb 2025" "fzf 0.60.1" "fzf\-tmux - open fzf in tmux split pane"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
fzf\-tmux - open fzf in tmux split pane
|
fzf\-tmux - open fzf in tmux split pane
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
..
|
..
|
||||||
.TH fzf 1 "Feb 2025" "fzf 0.60.0" "fzf - a command-line fuzzy finder"
|
.TH fzf 1 "Feb 2025" "fzf 0.60.1" "fzf - a command-line fuzzy finder"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
fzf - a command-line fuzzy finder
|
fzf - a command-line fuzzy finder
|
||||||
@@ -56,7 +56,9 @@ Case-insensitive match (default: smart-case match)
|
|||||||
Case-sensitive match
|
Case-sensitive match
|
||||||
.TP
|
.TP
|
||||||
.B "\-\-smart\-case"
|
.B "\-\-smart\-case"
|
||||||
Smart-case match (default)
|
Smart-case match (default). In this mode, the search is case-insensitive by
|
||||||
|
default, but it becomes case-sensitive if the query contains any uppercase
|
||||||
|
letters.
|
||||||
.TP
|
.TP
|
||||||
.B "\-\-literal"
|
.B "\-\-literal"
|
||||||
Do not normalize latin script letters for matching.
|
Do not normalize latin script letters for matching.
|
||||||
|
|||||||
@@ -99,9 +99,9 @@ if [[ -o interactive ]]; then
|
|||||||
__fzf_defaults() {
|
__fzf_defaults() {
|
||||||
# $1: Prepend to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
|
# $1: Prepend to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
|
||||||
# $2: Append to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
|
# $2: Append to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
|
||||||
echo "--height ${FZF_TMUX_HEIGHT:-40%} --min-height 20+ --bind=ctrl-z:ignore $1"
|
echo -E "--height ${FZF_TMUX_HEIGHT:-40%} --min-height 20+ --bind=ctrl-z:ignore $1"
|
||||||
command cat "${FZF_DEFAULT_OPTS_FILE-}" 2> /dev/null
|
command cat "${FZF_DEFAULT_OPTS_FILE-}" 2> /dev/null
|
||||||
echo "${FZF_DEFAULT_OPTS-} $2"
|
echo -E "${FZF_DEFAULT_OPTS-} $2"
|
||||||
}
|
}
|
||||||
|
|
||||||
__fzf_comprun() {
|
__fzf_comprun() {
|
||||||
|
|||||||
@@ -14,102 +14,24 @@
|
|||||||
|
|
||||||
# Key bindings
|
# Key bindings
|
||||||
# ------------
|
# ------------
|
||||||
|
# For compatibility with fish versions down to 3.1.2, the script does not use:
|
||||||
|
# - The -f/--function switch of command: set
|
||||||
|
# - The process substitution syntax: $(cmd)
|
||||||
|
# - Ranges that omit start/end indexes: $var[$start..] $var[..$end] $var[..]
|
||||||
function fzf_key_bindings
|
function fzf_key_bindings
|
||||||
|
|
||||||
function __fzf_defaults
|
function __fzf_defaults
|
||||||
# $1: Prepend to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
|
# $argv[1]: Prepend to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
|
||||||
# $2: Append to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
|
# $argv[2..]: Append to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
|
||||||
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
|
test -n "$FZF_TMUX_HEIGHT"; or set -l FZF_TMUX_HEIGHT 40%
|
||||||
echo "--height $FZF_TMUX_HEIGHT --min-height 20+ --bind=ctrl-z:ignore" $argv[1]
|
string join ' ' -- \
|
||||||
test -r "$FZF_DEFAULT_OPTS_FILE"; and string collect -N -- <$FZF_DEFAULT_OPTS_FILE
|
"--height $FZF_TMUX_HEIGHT --min-height=20+ --bind=ctrl-z:ignore" $argv[1] \
|
||||||
echo $FZF_DEFAULT_OPTS $argv[2]
|
(test -r "$FZF_DEFAULT_OPTS_FILE"; and string join -- ' ' <$FZF_DEFAULT_OPTS_FILE) \
|
||||||
end
|
$FZF_DEFAULT_OPTS $argv[2..-1]
|
||||||
|
|
||||||
# Store current token in $dir as root for the 'find' command
|
|
||||||
function fzf-file-widget -d "List files and folders"
|
|
||||||
set -l commandline (__fzf_parse_commandline)
|
|
||||||
set -lx dir $commandline[1]
|
|
||||||
set -l fzf_query $commandline[2]
|
|
||||||
set -l prefix $commandline[3]
|
|
||||||
set -l result
|
|
||||||
|
|
||||||
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
|
|
||||||
begin
|
|
||||||
set -lx FZF_DEFAULT_OPTS (__fzf_defaults "--reverse --walker=file,dir,follow,hidden --scheme=path --walker-root=$dir" "$FZF_CTRL_T_OPTS")
|
|
||||||
set -lx FZF_DEFAULT_COMMAND "$FZF_CTRL_T_COMMAND"
|
|
||||||
set -lx FZF_DEFAULT_OPTS_FILE ''
|
|
||||||
set result (eval (__fzfcmd) -m --query=$fzf_query)
|
|
||||||
end
|
|
||||||
if test -z "$result"
|
|
||||||
commandline -f repaint
|
|
||||||
return
|
|
||||||
else
|
|
||||||
# Remove last token from commandline.
|
|
||||||
commandline -t ""
|
|
||||||
end
|
|
||||||
for i in $result
|
|
||||||
commandline -it -- $prefix
|
|
||||||
commandline -it -- (string escape -- $i)
|
|
||||||
commandline -it -- ' '
|
|
||||||
end
|
|
||||||
commandline -f repaint
|
|
||||||
end
|
|
||||||
|
|
||||||
function fzf-history-widget -d "Show command history"
|
|
||||||
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
|
|
||||||
begin
|
|
||||||
# merge history from other sessions before searching
|
|
||||||
test -z "$fish_private_mode"; and builtin history merge
|
|
||||||
|
|
||||||
set -lx FZF_DEFAULT_OPTS (__fzf_defaults "" "-n2..,.. --scheme=history --bind=ctrl-r:toggle-sort --wrap-sign '"\t"↳ ' --highlight-line +m $FZF_CTRL_R_OPTS")
|
|
||||||
set -lx FZF_DEFAULT_OPTS_FILE ''
|
|
||||||
set -lx FZF_DEFAULT_COMMAND
|
|
||||||
set -a -- FZF_DEFAULT_OPTS --with-shell=(status fish-path)\\ -c
|
|
||||||
|
|
||||||
if type -q perl
|
|
||||||
set -a FZF_DEFAULT_OPTS '--tac'
|
|
||||||
set FZF_DEFAULT_COMMAND 'builtin history -z --reverse | command perl -0 -pe \'s/^/$.\t/g; s/\n/\n\t/gm\''
|
|
||||||
else
|
|
||||||
set FZF_DEFAULT_COMMAND \
|
|
||||||
'set -l h (builtin history -z --reverse | string split0);' \
|
|
||||||
'for i in (seq (count $h) -1 1);' \
|
|
||||||
'string join0 -- $i\t(string replace -a -- \n \n\t $h[$i] | string collect);' \
|
|
||||||
'end'
|
|
||||||
end
|
|
||||||
set -l result (eval $FZF_DEFAULT_COMMAND \| (__fzfcmd) --read0 --print0 -q (commandline | string escape) "--bind=enter:become:'string replace -a -- \n\t \n {2..} | string collect'")
|
|
||||||
and commandline -- $result
|
|
||||||
end
|
|
||||||
commandline -f repaint
|
|
||||||
end
|
|
||||||
|
|
||||||
function fzf-cd-widget -d "Change directory"
|
|
||||||
set -l commandline (__fzf_parse_commandline)
|
|
||||||
set -lx dir $commandline[1]
|
|
||||||
set -l fzf_query $commandline[2]
|
|
||||||
set -l prefix $commandline[3]
|
|
||||||
|
|
||||||
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
|
|
||||||
begin
|
|
||||||
set -lx FZF_DEFAULT_OPTS (__fzf_defaults "--reverse --walker=dir,follow,hidden --scheme=path --walker-root=$dir" "$FZF_ALT_C_OPTS")
|
|
||||||
set -lx FZF_DEFAULT_OPTS_FILE ''
|
|
||||||
set -lx FZF_DEFAULT_COMMAND "$FZF_ALT_C_COMMAND"
|
|
||||||
set -l result (eval (__fzfcmd) +m --query=$fzf_query)
|
|
||||||
|
|
||||||
if test -n "$result"
|
|
||||||
cd -- $result
|
|
||||||
|
|
||||||
# Remove last token from commandline.
|
|
||||||
commandline -t ""
|
|
||||||
commandline -it -- $prefix
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
commandline -f repaint
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function __fzfcmd
|
function __fzfcmd
|
||||||
test -n "$FZF_TMUX"; or set FZF_TMUX 0
|
test -n "$FZF_TMUX_HEIGHT"; or set -l FZF_TMUX_HEIGHT 40%
|
||||||
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
|
|
||||||
if test -n "$FZF_TMUX_OPTS"
|
if test -n "$FZF_TMUX_OPTS"
|
||||||
echo "fzf-tmux $FZF_TMUX_OPTS -- "
|
echo "fzf-tmux $FZF_TMUX_OPTS -- "
|
||||||
else if test "$FZF_TMUX" = "1"
|
else if test "$FZF_TMUX" = "1"
|
||||||
@@ -119,56 +41,42 @@ function fzf_key_bindings
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
bind \cr fzf-history-widget
|
|
||||||
if not set -q FZF_CTRL_T_COMMAND; or test -n "$FZF_CTRL_T_COMMAND"
|
|
||||||
bind \ct fzf-file-widget
|
|
||||||
end
|
|
||||||
if not set -q FZF_ALT_C_COMMAND; or test -n "$FZF_ALT_C_COMMAND"
|
|
||||||
bind \ec fzf-cd-widget
|
|
||||||
end
|
|
||||||
|
|
||||||
bind -M insert \cr fzf-history-widget
|
|
||||||
if not set -q FZF_CTRL_T_COMMAND; or test -n "$FZF_CTRL_T_COMMAND"
|
|
||||||
bind -M insert \ct fzf-file-widget
|
|
||||||
end
|
|
||||||
if not set -q FZF_ALT_C_COMMAND; or test -n "$FZF_ALT_C_COMMAND"
|
|
||||||
bind -M insert \ec fzf-cd-widget
|
|
||||||
end
|
|
||||||
|
|
||||||
function __fzf_parse_commandline -d 'Parse the current command line token and return split of existing filepath, fzf query, and optional -option= prefix'
|
function __fzf_parse_commandline -d 'Parse the current command line token and return split of existing filepath, fzf query, and optional -option= prefix'
|
||||||
set -l commandline (commandline -t)
|
set -l dir '.'
|
||||||
|
set -l query
|
||||||
|
set -l commandline (commandline -t | string unescape -n)
|
||||||
|
|
||||||
# strip -option= from token if present
|
# Strip -option= from token if present
|
||||||
set -l prefix (string match -r -- '^-[^\s=]+=' $commandline)
|
set -l prefix (string match -r -- '^-[^\s=]+=' $commandline)
|
||||||
set commandline (string replace -- "$prefix" '' $commandline)
|
set commandline (string replace -- "$prefix" '' $commandline)
|
||||||
|
|
||||||
# Enable home directory expansion of leading ~/
|
# Enable home directory expansion of leading ~/
|
||||||
set commandline (string replace -r -- '^~/' '\$HOME/' $commandline)
|
set commandline (string replace -r -- '^~/' '\$HOME/' $commandline)
|
||||||
|
|
||||||
# escape special characters, except for the $ sign of valid variable names,
|
# Escape special characters, except for the $ sign of valid variable names,
|
||||||
# so that after eval, the original string is returned, but with the
|
# so that the original string with expanded variables is returned after eval.
|
||||||
# variable names replaced by their values.
|
|
||||||
set commandline (string escape -n -- $commandline)
|
set commandline (string escape -n -- $commandline)
|
||||||
set commandline (string replace -r -a -- '\x5c\$(?=[\w])' '\$' $commandline)
|
set commandline (string replace -r -a -- '\\\\\$(?=[\w])' '\$' $commandline)
|
||||||
|
|
||||||
# eval is used to do shell expansion on paths
|
# eval is used to do shell expansion on paths
|
||||||
eval set commandline $commandline
|
eval set commandline $commandline
|
||||||
|
|
||||||
# Combine multiple consecutive slashes into one, and unescape.
|
# Combine multiple consecutive slashes into one.
|
||||||
set commandline (string replace -r -a -- '/+' '/' $commandline | string unescape -n)
|
set commandline (string replace -r -a -- '/+' '/' $commandline)
|
||||||
|
|
||||||
if test -z "$commandline"
|
if test -n "$commandline"
|
||||||
# Default to current directory with no --query
|
# Strip trailing slash, unless $dir is root dir (/)
|
||||||
set dir '.'
|
set dir (string replace -r -- '(?<!^)/$' '' $commandline)
|
||||||
set fzf_query ''
|
|
||||||
else
|
|
||||||
set dir (__fzf_get_dir $commandline)
|
|
||||||
|
|
||||||
# BUG: on combined expressions, if a left argument is a single `!`, the
|
# Set $dir to the longest existing filepath
|
||||||
# builtin test command of fish will treat it as the ! operator. To
|
while not test -d "$dir"
|
||||||
# overcome this, have the variable parts on the right.
|
# If path is absolute, this can keep going until ends up at /
|
||||||
if test "." = "$dir" -a "./" != (string sub -l 2 -- $commandline)
|
# If path is relative, this can keep going until entire input is consumed, dirname returns "."
|
||||||
# if $dir is "." but commandline is not a relative path, this means no file path found
|
set dir (dirname -- $dir)
|
||||||
|
end
|
||||||
|
|
||||||
|
if test "$dir" = '.'; and test (string sub -l 2 -- $commandline) != './'
|
||||||
|
# If $dir is "." but commandline is not a relative path, this means no file path found
|
||||||
set fzf_query $commandline
|
set fzf_query $commandline
|
||||||
else
|
else
|
||||||
# Also remove trailing slash after dir, to "split" input properly
|
# Also remove trailing slash after dir, to "split" input properly
|
||||||
@@ -176,25 +84,98 @@ function fzf_key_bindings
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
echo -- $dir
|
string escape -n -- "$dir" "$fzf_query" "$prefix"
|
||||||
string escape -- $fzf_query
|
|
||||||
echo -- $prefix
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function __fzf_get_dir -d 'Find the longest existing filepath from input string'
|
# Store current token in $dir as root for the 'find' command
|
||||||
set dir $argv
|
function fzf-file-widget -d "List files and folders"
|
||||||
|
set -l commandline (__fzf_parse_commandline)
|
||||||
|
set -lx dir $commandline[1]
|
||||||
|
set -l fzf_query $commandline[2]
|
||||||
|
set -l prefix $commandline[3]
|
||||||
|
|
||||||
# Strip trailing slash, unless $dir is root dir (/)
|
set -lx FZF_DEFAULT_OPTS (__fzf_defaults \
|
||||||
set dir (string replace -r -- '(?<!^)/$' '' $dir)
|
"--reverse --walker=file,dir,follow,hidden --scheme=path --walker-root=$dir" \
|
||||||
|
"$FZF_CTRL_T_OPTS --multi")
|
||||||
|
|
||||||
# Iteratively check if dir exists and strip tail end of path
|
set -lx FZF_DEFAULT_COMMAND "$FZF_CTRL_T_COMMAND"
|
||||||
while test ! -d "$dir"
|
set -lx FZF_DEFAULT_OPTS_FILE
|
||||||
# If path is absolute, this can keep going until ends up at /
|
|
||||||
# If path is relative, this can keep going until entire input is consumed, dirname returns "."
|
if set -l result (eval (__fzfcmd) --query=$fzf_query)
|
||||||
set dir (dirname -- "$dir")
|
# Remove last token from commandline.
|
||||||
|
commandline -t ''
|
||||||
|
for i in $result
|
||||||
|
commandline -it -- $prefix(string escape -- $i)' '
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
string escape -n -- $dir
|
commandline -f repaint
|
||||||
|
end
|
||||||
|
|
||||||
|
function fzf-history-widget -d "Show command history"
|
||||||
|
set -l fzf_query (commandline | string escape)
|
||||||
|
|
||||||
|
set -lx FZF_DEFAULT_OPTS (__fzf_defaults '' \
|
||||||
|
'--nth=2..,.. --scheme=history --bind=ctrl-r:toggle-sort --wrap-sign="\t↳ "' \
|
||||||
|
"--highlight-line --no-multi $FZF_CTRL_R_OPTS --read0 --print0" \
|
||||||
|
"--bind='enter:become:string replace -a -- \n\t \n {2..} | string collect'" \
|
||||||
|
'--with-shell='(status fish-path)\\ -c)
|
||||||
|
|
||||||
|
set -lx FZF_DEFAULT_OPTS_FILE
|
||||||
|
set -lx FZF_DEFAULT_COMMAND
|
||||||
|
|
||||||
|
if type -q perl
|
||||||
|
set -a FZF_DEFAULT_OPTS '--tac'
|
||||||
|
set FZF_DEFAULT_COMMAND 'builtin history -z --reverse | command perl -0 -pe \'s/^/$.\t/g; s/\n/\n\t/gm\''
|
||||||
|
else
|
||||||
|
set FZF_DEFAULT_COMMAND \
|
||||||
|
'set -l h (builtin history -z --reverse | string split0);' \
|
||||||
|
'for i in (seq (count $h) -1 1);' \
|
||||||
|
'string join0 -- $i\t(string replace -a -- \n \n\t $h[$i] | string collect);' \
|
||||||
|
'end'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Merge history from other sessions before searching
|
||||||
|
test -z "$fish_private_mode"; and builtin history merge
|
||||||
|
|
||||||
|
set -l result (eval $FZF_DEFAULT_COMMAND \| (__fzfcmd) --query=$fzf_query)
|
||||||
|
and commandline -- $result
|
||||||
|
|
||||||
|
commandline -f repaint
|
||||||
|
end
|
||||||
|
|
||||||
|
function fzf-cd-widget -d "Change directory"
|
||||||
|
set -l commandline (__fzf_parse_commandline)
|
||||||
|
set -lx dir $commandline[1]
|
||||||
|
set -l fzf_query $commandline[2]
|
||||||
|
set -l prefix $commandline[3]
|
||||||
|
|
||||||
|
set -lx FZF_DEFAULT_OPTS (__fzf_defaults \
|
||||||
|
"--reverse --walker=dir,follow,hidden --scheme=path --walker-root=$dir" \
|
||||||
|
"$FZF_ALT_C_OPTS --no-multi")
|
||||||
|
|
||||||
|
set -lx FZF_DEFAULT_OPTS_FILE
|
||||||
|
set -lx FZF_DEFAULT_COMMAND "$FZF_ALT_C_COMMAND"
|
||||||
|
|
||||||
|
if set -l result (eval (__fzfcmd) --query=$fzf_query)
|
||||||
|
cd -- $result
|
||||||
|
commandline -rt -- $prefix
|
||||||
|
end
|
||||||
|
|
||||||
|
commandline -f repaint
|
||||||
|
end
|
||||||
|
|
||||||
|
bind \cr fzf-history-widget
|
||||||
|
bind -M insert \cr fzf-history-widget
|
||||||
|
|
||||||
|
if not set -q FZF_CTRL_T_COMMAND; or test -n "$FZF_CTRL_T_COMMAND"
|
||||||
|
bind \ct fzf-file-widget
|
||||||
|
bind -M insert \ct fzf-file-widget
|
||||||
|
end
|
||||||
|
|
||||||
|
if not set -q FZF_ALT_C_COMMAND; or test -n "$FZF_ALT_C_COMMAND"
|
||||||
|
bind \ec fzf-cd-widget
|
||||||
|
bind -M insert \ec fzf-cd-widget
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ if [[ -o interactive ]]; then
|
|||||||
__fzf_defaults() {
|
__fzf_defaults() {
|
||||||
# $1: Prepend to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
|
# $1: Prepend to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
|
||||||
# $2: Append to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
|
# $2: Append to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
|
||||||
echo "--height ${FZF_TMUX_HEIGHT:-40%} --min-height 20+ --bind=ctrl-z:ignore $1"
|
echo -E "--height ${FZF_TMUX_HEIGHT:-40%} --min-height 20+ --bind=ctrl-z:ignore $1"
|
||||||
command cat "${FZF_DEFAULT_OPTS_FILE-}" 2> /dev/null
|
command cat "${FZF_DEFAULT_OPTS_FILE-}" 2> /dev/null
|
||||||
echo "${FZF_DEFAULT_OPTS-} $2"
|
echo -E "${FZF_DEFAULT_OPTS-} $2"
|
||||||
}
|
}
|
||||||
|
|
||||||
# CTRL-T - Paste the selected file path(s) into the command line
|
# CTRL-T - Paste the selected file path(s) into the command line
|
||||||
|
|||||||
@@ -767,6 +767,9 @@ func FuzzyMatchV1(caseSensitive bool, normalize bool, forward bool, text *util.C
|
|||||||
char = unicode.To(unicode.LowerCase, char)
|
char = unicode.To(unicode.LowerCase, char)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if normalize {
|
||||||
|
char = normalizeRune(char)
|
||||||
|
}
|
||||||
|
|
||||||
pidx_ := indexAt(pidx, lenPattern, forward)
|
pidx_ := indexAt(pidx, lenPattern, forward)
|
||||||
pchar := pattern[pidx_]
|
pchar := pattern[pidx_]
|
||||||
|
|||||||
@@ -200,3 +200,12 @@ func TestLongString(t *testing.T) {
|
|||||||
bytes[math.MaxUint16] = 'z'
|
bytes[math.MaxUint16] = 'z'
|
||||||
assertMatch(t, FuzzyMatchV2, true, true, string(bytes), "zx", math.MaxUint16, math.MaxUint16+2, scoreMatch*2+bonusConsecutive)
|
assertMatch(t, FuzzyMatchV2, true, true, string(bytes), "zx", math.MaxUint16, math.MaxUint16+2, scoreMatch*2+bonusConsecutive)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLongStringWithNormalize(t *testing.T) {
|
||||||
|
bytes := make([]byte, 30000)
|
||||||
|
for i := range bytes {
|
||||||
|
bytes[i] = 'x'
|
||||||
|
}
|
||||||
|
unicodeString := string(bytes) + " Minímal example"
|
||||||
|
assertMatch2(t, FuzzyMatchV1, false, true, false, unicodeString, "minim", 30001, 30006, 140)
|
||||||
|
}
|
||||||
|
|||||||
@@ -320,6 +320,7 @@ func (r *Reader) readFiles(roots []string, opts walkerOpts, ignores []string) bo
|
|||||||
return filepath.SkipDir
|
return filepath.SkipDir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
path += sep
|
||||||
}
|
}
|
||||||
if ((opts.file && !isDir) || (opts.dir && isDir)) && r.pusher(stringBytes(path)) {
|
if ((opts.file && !isDir) || (opts.dir && isDir)) && r.pusher(stringBytes(path)) {
|
||||||
atomic.StoreInt32(&r.event, int32(EvtReadNew))
|
atomic.StoreInt32(&r.event, int32(EvtReadNew))
|
||||||
|
|||||||
@@ -638,6 +638,7 @@ type previewRequest struct {
|
|||||||
scrollOffset int
|
scrollOffset int
|
||||||
list []*Item
|
list []*Item
|
||||||
env []string
|
env []string
|
||||||
|
query string
|
||||||
}
|
}
|
||||||
|
|
||||||
type previewResult struct {
|
type previewResult struct {
|
||||||
@@ -3099,8 +3100,15 @@ func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMat
|
|||||||
maxWidth := t.window.Width() - (indentSize + 1)
|
maxWidth := t.window.Width() - (indentSize + 1)
|
||||||
wasWrapped := false
|
wasWrapped := false
|
||||||
if wrapped {
|
if wrapped {
|
||||||
maxWidth -= t.wrapSignWidth
|
wrapSign := t.wrapSign
|
||||||
t.window.CPrint(colBase.WithAttr(tui.Dim), t.wrapSign)
|
if maxWidth < t.wrapSignWidth {
|
||||||
|
runes, _ := util.Truncate(wrapSign, maxWidth)
|
||||||
|
wrapSign = string(runes)
|
||||||
|
maxWidth = 0
|
||||||
|
} else {
|
||||||
|
maxWidth -= t.wrapSignWidth
|
||||||
|
}
|
||||||
|
t.window.CPrint(colBase.WithAttr(tui.Dim), wrapSign)
|
||||||
wrapped = false
|
wrapped = false
|
||||||
wasWrapped = true
|
wasWrapped = true
|
||||||
}
|
}
|
||||||
@@ -3165,7 +3173,9 @@ func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMat
|
|||||||
displayWidth = t.displayWidthWithLimit(line, 0, displayWidth)
|
displayWidth = t.displayWidthWithLimit(line, 0, displayWidth)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.printColoredString(t.window, line, offsets, colBase)
|
if maxWidth > 0 {
|
||||||
|
t.printColoredString(t.window, line, offsets, colBase)
|
||||||
|
}
|
||||||
if postTask != nil {
|
if postTask != nil {
|
||||||
postTask(actualLineNum, displayWidth, wasWrapped, forceRedraw)
|
postTask(actualLineNum, displayWidth, wasWrapped, forceRedraw)
|
||||||
} else {
|
} else {
|
||||||
@@ -3374,8 +3384,10 @@ func (t *Terminal) renderPreviewText(height int, lines []string, lineNo int, unc
|
|||||||
wiped := false
|
wiped := false
|
||||||
image := false
|
image := false
|
||||||
wireframe := false
|
wireframe := false
|
||||||
|
var index int
|
||||||
|
var line string
|
||||||
Loop:
|
Loop:
|
||||||
for _, line := range lines {
|
for index, line = range lines {
|
||||||
var lbg tui.Color = -1
|
var lbg tui.Color = -1
|
||||||
if ansi != nil {
|
if ansi != nil {
|
||||||
ansi.lbg = -1
|
ansi.lbg = -1
|
||||||
@@ -3518,6 +3530,7 @@ Loop:
|
|||||||
}
|
}
|
||||||
lineNo++
|
lineNo++
|
||||||
}
|
}
|
||||||
|
t.previewer.scrollable = t.previewer.scrollable || index < len(lines)-1
|
||||||
t.previewed.image = image
|
t.previewed.image = image
|
||||||
t.previewed.wireframe = wireframe
|
t.previewed.wireframe = wireframe
|
||||||
}
|
}
|
||||||
@@ -4376,6 +4389,7 @@ func (t *Terminal) Loop() error {
|
|||||||
var items []*Item
|
var items []*Item
|
||||||
var commandTemplate string
|
var commandTemplate string
|
||||||
var env []string
|
var env []string
|
||||||
|
var query string
|
||||||
initialOffset := 0
|
initialOffset := 0
|
||||||
t.previewBox.Wait(func(events *util.Events) {
|
t.previewBox.Wait(func(events *util.Events) {
|
||||||
for req, value := range *events {
|
for req, value := range *events {
|
||||||
@@ -4389,6 +4403,7 @@ func (t *Terminal) Loop() error {
|
|||||||
initialOffset = request.scrollOffset
|
initialOffset = request.scrollOffset
|
||||||
items = request.list
|
items = request.list
|
||||||
env = request.env
|
env = request.env
|
||||||
|
query = request.query
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
events.Clear()
|
events.Clear()
|
||||||
@@ -4402,8 +4417,7 @@ func (t *Terminal) Loop() error {
|
|||||||
version++
|
version++
|
||||||
// We don't display preview window if no match
|
// We don't display preview window if no match
|
||||||
if items[0] != nil {
|
if items[0] != nil {
|
||||||
_, query := t.Input()
|
command, tempFiles := t.replacePlaceholder(commandTemplate, false, query, items)
|
||||||
command, tempFiles := t.replacePlaceholder(commandTemplate, false, string(query), items)
|
|
||||||
cmd := t.executor.ExecCommand(command, true)
|
cmd := t.executor.ExecCommand(command, true)
|
||||||
cmd.Env = env
|
cmd.Env = env
|
||||||
|
|
||||||
@@ -4531,7 +4545,7 @@ func (t *Terminal) Loop() error {
|
|||||||
if len(command) > 0 && t.canPreview() {
|
if len(command) > 0 && t.canPreview() {
|
||||||
_, list := t.buildPlusList(command, false)
|
_, list := t.buildPlusList(command, false)
|
||||||
t.cancelPreview()
|
t.cancelPreview()
|
||||||
t.previewBox.Set(reqPreviewEnqueue, previewRequest{command, t.evaluateScrollOffset(), list, t.environForPreview()})
|
t.previewBox.Set(reqPreviewEnqueue, previewRequest{command, t.evaluateScrollOffset(), list, t.environForPreview(), string(t.input)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4963,7 +4977,7 @@ func (t *Terminal) Loop() error {
|
|||||||
if valid {
|
if valid {
|
||||||
t.cancelPreview()
|
t.cancelPreview()
|
||||||
t.previewBox.Set(reqPreviewEnqueue,
|
t.previewBox.Set(reqPreviewEnqueue,
|
||||||
previewRequest{t.previewOpts.command, t.evaluateScrollOffset(), list, t.environForPreview()})
|
previewRequest{t.previewOpts.command, t.evaluateScrollOffset(), list, t.environForPreview(), string(t.input)})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Discard the preview content so that it won't accidentally appear
|
// Discard the preview content so that it won't accidentally appear
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const (
|
|||||||
|
|
||||||
const consoleDevice string = "/dev/tty"
|
const consoleDevice string = "/dev/tty"
|
||||||
|
|
||||||
var offsetRegexp = regexp.MustCompile("(.*)\x1b\\[([0-9]+);([0-9]+)R")
|
var offsetRegexp = regexp.MustCompile("(.*?)\x00?\x1b\\[([0-9]+);([0-9]+)R")
|
||||||
var offsetRegexpBegin = regexp.MustCompile("^\x1b\\[[0-9]+;[0-9]+R")
|
var offsetRegexpBegin = regexp.MustCompile("^\x1b\\[[0-9]+;[0-9]+R")
|
||||||
|
|
||||||
func (r *LightRenderer) Bell() {
|
func (r *LightRenderer) Bell() {
|
||||||
|
|||||||
@@ -544,4 +544,18 @@ class TestPreview < TestInteractive
|
|||||||
tmux.send_keys :Up
|
tmux.send_keys :Up
|
||||||
tmux.until { |lines| assert_includes lines, '> 2' }
|
tmux.until { |lines| assert_includes lines, '> 2' }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_preview_query_should_not_be_affected_by_search
|
||||||
|
tmux.send_keys "seq 1 | #{FZF} --bind 'change:transform-search(echo {q:1})' --preview 'echo [{q}/{}]'", :Enter
|
||||||
|
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||||
|
tmux.send_keys '1'
|
||||||
|
tmux.until { |lines| assert lines.any_include?('[1/1]') }
|
||||||
|
tmux.send_keys :Space
|
||||||
|
tmux.until { |lines| assert lines.any_include?('[1 /1]') }
|
||||||
|
tmux.send_keys '2'
|
||||||
|
tmux.until do |lines|
|
||||||
|
assert lines.any_include?('[1 2/1]')
|
||||||
|
assert_equal 1, lines.match_count
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ module TestShell
|
|||||||
tmux.prepare
|
tmux.prepare
|
||||||
tmux.send_keys :Escape, :c
|
tmux.send_keys :Escape, :c
|
||||||
lines = tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
lines = tmux.until { |lines| assert_operator lines.match_count, :>, 0 }
|
||||||
expected = lines.reverse.find { |l| l.start_with?('> ') }[2..]
|
expected = lines.reverse.find { |l| l.start_with?('> ') }[2..].chomp('/')
|
||||||
tmux.send_keys :Enter
|
tmux.send_keys :Enter
|
||||||
tmux.prepare
|
tmux.prepare
|
||||||
tmux.send_keys :pwd, :Enter
|
tmux.send_keys :pwd, :Enter
|
||||||
@@ -241,7 +241,7 @@ module CompletionTest
|
|||||||
tmux.until do |lines|
|
tmux.until do |lines|
|
||||||
assert_equal 1, lines.match_count
|
assert_equal 1, lines.match_count
|
||||||
assert_includes lines, '> 55'
|
assert_includes lines, '> 55'
|
||||||
assert_includes lines, '> /tmp/fzf-test/d55'
|
assert_includes lines, '> /tmp/fzf-test/d55/'
|
||||||
end
|
end
|
||||||
tmux.send_keys :Enter
|
tmux.send_keys :Enter
|
||||||
tmux.until(true) { |lines| assert_equal 'cd /tmp/fzf-test/d55/', lines[-1] }
|
tmux.until(true) { |lines| assert_equal 'cd /tmp/fzf-test/d55/', lines[-1] }
|
||||||
|
|||||||
Reference in New Issue
Block a user