[fish] Improve commandline parsing

- Enable using unescaped quotes for exact-match, exact-boundary-match.
- Enable suffix-exact-match.
- Enable inverse-exact-match, inverse-prefix/suffix-exact-match.
- Allow searching for double quotes and backslashes.
- Combine multiple consecutive slashes into one.
- Workaround for test command bug, allowing $dir or $commandline be a
  single `!`.
This commit is contained in:
bitraid 2024-11-08 09:44:34 +02:00 committed by Junegunn Choi
parent 961ae1541c
commit 4d357d1063

View File

@ -36,10 +36,10 @@ function fzf_key_bindings
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40% test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
begin 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_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_COMMAND "$FZF_CTRL_T_COMMAND"
set -lx FZF_DEFAULT_OPTS_FILE '' set -lx FZF_DEFAULT_OPTS_FILE ''
eval (__fzfcmd)' -m --query "'$fzf_query'"' | while read -l r; set result $result $r; end eval (__fzfcmd) -m --query=$fzf_query | while read -l r; set -a result $r; end
end end
if [ -z "$result" ] if [ -z "$result" ]
commandline -f repaint commandline -f repaint
@ -98,10 +98,10 @@ function fzf_key_bindings
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40% test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
begin 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 (__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_OPTS_FILE ''
set -lx FZF_DEFAULT_COMMAND "$FZF_ALT_C_COMMAND" set -lx FZF_DEFAULT_COMMAND "$FZF_ALT_C_COMMAND"
eval (__fzfcmd)' +m --query "'$fzf_query'"' | read -l result eval (__fzfcmd) +m --query=$fzf_query | read -l result
if [ -n "$result" ] if [ -n "$result" ]
cd -- $result cd -- $result
@ -152,9 +152,18 @@ function fzf_key_bindings
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)
# escape special characters, except for the $ sign of valid variable names,
# so that after eval, the original string is returned, but with the
# variable names replaced by their values.
set commandline (string escape -n -- $commandline)
set commandline (string replace -r -a '\x5c\$(?=[\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
set commandline (string replace -r -a '/+' '/' -- $commandline)
if [ -z $commandline ] if [ -z $commandline ]
# Default to current directory with no --query # Default to current directory with no --query
set dir '.' set dir '.'
@ -162,27 +171,28 @@ function fzf_key_bindings
else else
set dir (__fzf_get_dir $commandline) set dir (__fzf_get_dir $commandline)
if [ "$dir" = "." -a (string sub -l 1 -- $commandline) != '.' ] # BUG: on combined expressions, if a left argument is a single `!`, the
# builtin test command of fish will treat it as the ! operator. To
# overcome this, have the variable parts on the right.
if test "." = "$dir" -a "." != (string sub -l 1 -- $commandline)
# if $dir is "." but commandline is not a relative path, this means no file path found # 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
set fzf_query (string replace -r "^$dir/?" -- '' "$commandline") set fzf_query (string replace -r "^$dir/?" '' -- $commandline)
end end
end end
echo $dir echo (string escape -- $dir)
echo $fzf_query echo (string escape -- $fzf_query)
echo $prefix echo $prefix
end end
function __fzf_get_dir -d 'Find the longest existing filepath from input string' function __fzf_get_dir -d 'Find the longest existing filepath from input string'
set dir $argv set dir $argv
# Strip all trailing slashes. Ignore if $dir is root dir (/) # Strip trailing slash, unless $dir is root dir (/)
if [ (string length -- $dir) -gt 1 ] set dir (string replace -r '(?<!^)/$' '' -- $dir)
set dir (string replace -r '/*$' -- '' $dir)
end
# Iteratively check if dir exists and strip tail end of path # Iteratively check if dir exists and strip tail end of path
while [ ! -d "$dir" ] while [ ! -d "$dir" ]