summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
Diffstat (limited to 'shell')
-rw-r--r--shell/key-bindings.fish104
1 files changed, 66 insertions, 38 deletions
diff --git a/shell/key-bindings.fish b/shell/key-bindings.fish
index 658addbb..72b42079 100644
--- a/shell/key-bindings.fish
+++ b/shell/key-bindings.fish
@@ -42,45 +42,73 @@ function fzf_key_bindings
end
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 fzf_query ''
+ set -l prefix ''
set -l dir '.'
- set -l query
- set -l commandline (commandline -t | string unescape -n)
- # Strip -option= from token if present
- set -l prefix (string match -r -- '^-[^\s=]+=' $commandline)
- set commandline (string replace -- "$prefix" '' $commandline)
-
- # Enable home directory expansion of leading ~/
- set commandline (string replace -r -- '^~/' '\$HOME/' $commandline)
-
- # Escape special characters, except for the $ sign of valid variable names,
- # so that the original string with expanded variables is returned after eval.
- set commandline (string escape -n -- $commandline)
- set commandline (string replace -r -a -- '\\\\\$(?=[\w])' '\$' $commandline)
-
- # eval is used to do shell expansion on paths
- eval set commandline $commandline
-
- # Combine multiple consecutive slashes into one.
- set commandline (string replace -r -a -- '/+' '/' $commandline)
-
- if test -n "$commandline"
- # Strip trailing slash, unless $dir is root dir (/)
- set dir (string replace -r -- '(?<!^)/$' '' $commandline)
+ # Set variables containing the major and minor fish version numbers, using
+ # a method compatible with all supported fish versions.
+ set -l -- fish_major (string match -r -- '^\d+' $version)
+ set -l -- fish_minor (string match -r -- '^\d+\.(\d+)' $version)[2]
+
+ # Set $prefix and expanded $fzf_query with preserved trailing newlines.
+ if test "$fish_major" -ge 4
+ # fish v4.0.0 and newer
+ string match -q -r -- '(?<prefix>^-[^\s=]+=)?(?<fzf_query>[\s\S]*?(?=\n?$)$)' \
+ (commandline --current-token --tokens-expanded | string collect -N)
+ else if test "$fish_major" -eq 3 -a "$fish_minor" -ge 2
+ # fish v3.2.0 - v3.7.1 (last v3)
+ string match -q -r -- '(?<prefix>^-[^\s=]+=)?(?<fzf_query>[\s\S]*?(?=\n?$)$)' \
+ (commandline --current-token --tokenize | string collect -N)
+ eval set -- fzf_query (string escape -n -- $fzf_query | string replace -r -a '^\\\(?=~)|\\\(?=\$\w)' '')
+ else
+ # fish older than v3.2.0 (v3.1b1 - v3.1.2)
+ set -l -- cl_token (commandline --current-token --tokenize | string collect -N)
+ set -- prefix (string match -r -- '^-[^\s=]+=' $cl_token)
+ set -- fzf_query (string replace -- "$prefix" '' $cl_token | string collect -N)
+ eval set -- fzf_query (string escape -n -- $fzf_query | string replace -r -a '^\\\(?=~)|\\\(?=\$\w)|\\\n\\\n$' '')
+ end
- # Set $dir to the longest existing filepath
- while not test -d "$dir"
- # 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 "."
- set dir (dirname -- $dir)
+ if test -n "$fzf_query"
+ # Normalize path in $fzf_query, set $dir to the longest existing directory.
+ if test \( "$fish_major" -ge 4 \) -o \( "$fish_major" -eq 3 -a "$fish_minor" -ge 5 \)
+ # fish v3.5.0 and newer
+ set -- fzf_query (path normalize -- $fzf_query)
+ set -- dir $fzf_query
+ while not path is -d $dir
+ set -- dir (path dirname $dir)
+ end
+ else
+ # fish older than v3.5.0 (v3.1b1 - v3.4.1)
+ if test "$fish_major" -eq 3 -a "$fish_minor" -ge 2
+ # fish v3.2.0 - v3.4.1
+ string match -q -r -- '(?<fzf_query>^[\s\S]*?(?=\n?$)$)' \
+ (string replace -r -a -- '(?<=/)/|(?<!^)/+(?!\n)$' '' $fzf_query | string collect -N)
+ else
+ # fish v3.1b1 - v3.1.2
+ set -- fzf_query (string replace -r -a -- '(?<=/)/|(?<!^)/+(?!\n)$' '' $fzf_query | string collect -N)
+ eval set -- fzf_query (string escape -n -- $fzf_query | string replace -r '\\\n$' '')
+ end
+ set -- dir $fzf_query
+ while not test -d "$dir"
+ set -- dir (dirname -z -- "$dir" | string split0)
+ end
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
- else
- # Also remove trailing slash after dir, to "split" input properly
- set fzf_query (string replace -r -- "^$dir/?" '' $commandline)
+ if not string match -q -- '.' $dir; or string match -q -r -- '^\./|^\.$' $fzf_query
+ # Strip $dir from $fzf_query - preserve trailing newlines.
+ if test "$fish_major" -ge 4
+ # fish v4.0.0 and newer
+ string match -q -r -- '^'(string escape --style=regex -- $dir)'/?(?<fzf_query>[\s\S]*)' $fzf_query
+ else if test "$fish_major" -eq 3 -a "$fish_minor" -ge 2
+ # fish v3.2.0 - v3.7.1 (last v3)
+ string match -q -r -- '^/?(?<fzf_query>[\s\S]*?(?=\n?$)$)' \
+ (string replace -- "$dir" '' $fzf_query | string collect -N)
+ else
+ # fish older than v3.2.0 (v3.1b1 - v3.1.2)
+ set -- fzf_query (string replace -- "$dir" '' $fzf_query | string collect -N)
+ eval set -- fzf_query (string escape -n -- $fzf_query | string replace -r -a '^/?|\\\n$' '')
+ end
end
end
@@ -95,13 +123,13 @@ function fzf_key_bindings
set -l prefix $commandline[3]
set -lx FZF_DEFAULT_OPTS (__fzf_defaults \
- "--reverse --walker=file,dir,follow,hidden --scheme=path --walker-root=$dir" \
+ "--reverse --walker=file,dir,follow,hidden --scheme=path" \
"$FZF_CTRL_T_OPTS --multi --print0")
set -lx FZF_DEFAULT_COMMAND "$FZF_CTRL_T_COMMAND"
set -lx FZF_DEFAULT_OPTS_FILE
- if set -l result (eval (__fzfcmd) --query=$fzf_query | string split0)
+ if set -l result (eval (__fzfcmd) --walker-root=$dir --query=$fzf_query | string split0)
# Remove last token from commandline.
commandline -t ''
for i in $result
@@ -154,13 +182,13 @@ function fzf_key_bindings
set -l prefix $commandline[3]
set -lx FZF_DEFAULT_OPTS (__fzf_defaults \
- "--reverse --walker=dir,follow,hidden --scheme=path --walker-root=$dir" \
+ "--reverse --walker=dir,follow,hidden --scheme=path" \
"$FZF_ALT_C_OPTS --no-multi --print0")
set -lx FZF_DEFAULT_OPTS_FILE
set -lx FZF_DEFAULT_COMMAND "$FZF_ALT_C_COMMAND"
- if set -l result (eval (__fzfcmd) --query=$fzf_query | string split0)
+ if set -l result (eval (__fzfcmd) --query=$fzf_query --walker-root=$dir | string split0)
cd -- $result
commandline -rt -- $prefix
end