From 26e9116eef56ed87a89c108783e3fa377c36a8ec Mon Sep 17 00:00:00 2001 From: FollieHiyuki Date: Sun, 15 May 2022 02:58:54 +0700 Subject: [PATCH] [fish] Decouple functions This commit makes setting up more flexible. The user can define keybindings for only the functions they need. --- shell/key-bindings.fish | 254 ++++++++++++++++++++-------------------- 1 file changed, 126 insertions(+), 128 deletions(-) diff --git a/shell/key-bindings.fish b/shell/key-bindings.fish index 36b3aa34aa1..72c2d9255ff 100644 --- a/shell/key-bindings.fish +++ b/shell/key-bindings.fish @@ -14,159 +14,157 @@ # Key bindings # ------------ function fzf_key_bindings + bind \ct fzf-file-widget + bind \cr fzf-history-widget + bind \ec fzf-cd-widget - # 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 -l dir $commandline[1] - set -l fzf_query $commandline[2] - set -l prefix $commandline[3] - - # "-path \$dir'*/\\.*'" matches hidden files/folders inside $dir but not - # $dir itself, even if hidden. - test -n "$FZF_CTRL_T_COMMAND"; or set -l FZF_CTRL_T_COMMAND " - command find -L \$dir -mindepth 1 \\( -path \$dir'*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' \\) -prune \ - -o -type f -print \ - -o -type d -print \ - -o -type l -print 2> /dev/null | sed 's@^\./@@'" - - test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40% - begin - set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_CTRL_T_OPTS" - eval "$FZF_CTRL_T_COMMAND | "(__fzfcmd)' -m --query "'$fzf_query'"' | while read -l r; set result $result $r; end - end - if [ -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 + if bind -M insert > /dev/null 2>&1 + bind -M insert \ct fzf-file-widget + bind -M insert \cr fzf-history-widget + bind -M insert \ec fzf-cd-widget end +end - function fzf-history-widget -d "Show command history" - test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40% - begin - set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT $FZF_DEFAULT_OPTS --tiebreak=index --bind=ctrl-r:toggle-sort,ctrl-z:ignore $FZF_CTRL_R_OPTS +m" - - set -l FISH_MAJOR (echo $version | cut -f1 -d.) - set -l FISH_MINOR (echo $version | cut -f2 -d.) - - # history's -z flag is needed for multi-line support. - # history's -z flag was added in fish 2.4.0, so don't use it for versions - # before 2.4.0. - if [ "$FISH_MAJOR" -gt 2 -o \( "$FISH_MAJOR" -eq 2 -a "$FISH_MINOR" -ge 4 \) ]; - history -z | eval (__fzfcmd) --read0 --print0 -q '(commandline)' | read -lz result - and commandline -- $result - else - history | eval (__fzfcmd) -q '(commandline)' | read -l result - and commandline -- $result - end - end +# 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 -l dir $commandline[1] + set -l fzf_query $commandline[2] + set -l prefix $commandline[3] + + # "-path \$dir'*/\\.*'" matches hidden files/folders inside $dir but not + # $dir itself, even if hidden. + test -n "$FZF_CTRL_T_COMMAND"; or set -l FZF_CTRL_T_COMMAND " + command find -L \$dir -mindepth 1 \\( -path \$dir'*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' \\) -prune \ + -o -type f -print \ + -o -type d -print \ + -o -type l -print 2> /dev/null | sed 's@^\./@@'" + + test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40% + begin + set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_CTRL_T_OPTS" + eval "$FZF_CTRL_T_COMMAND | "(__fzfcmd)' -m --query "'$fzf_query'"' | while read -l r; set result $result $r; end + end + if [ -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-cd-widget -d "Change directory" - set -l commandline (__fzf_parse_commandline) - set -l dir $commandline[1] - set -l fzf_query $commandline[2] - set -l prefix $commandline[3] - - test -n "$FZF_ALT_C_COMMAND"; or set -l FZF_ALT_C_COMMAND " - command find -L \$dir -mindepth 1 \\( -path \$dir'*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' \\) -prune \ - -o -type d -print 2> /dev/null | sed 's@^\./@@'" - test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40% - begin - set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_ALT_C_OPTS" - eval "$FZF_ALT_C_COMMAND | "(__fzfcmd)' +m --query "'$fzf_query'"' | read -l result - - if [ -n "$result" ] - builtin cd -- $result - - # Remove last token from commandline. - commandline -t "" - commandline -it -- $prefix - end - end +function fzf-history-widget -d "Show command history" + test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40% + begin + set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT $FZF_DEFAULT_OPTS --tiebreak=index --bind=ctrl-r:toggle-sort,ctrl-z:ignore $FZF_CTRL_R_OPTS +m" - commandline -f repaint - end + set -l FISH_MAJOR (echo $version | cut -f1 -d.) + set -l FISH_MINOR (echo $version | cut -f2 -d.) - function __fzfcmd - test -n "$FZF_TMUX"; or set FZF_TMUX 0 - test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40% - if [ -n "$FZF_TMUX_OPTS" ] - echo "fzf-tmux $FZF_TMUX_OPTS -- " - else if [ $FZF_TMUX -eq 1 ] - echo "fzf-tmux -d$FZF_TMUX_HEIGHT -- " + # history's -z flag is needed for multi-line support. + # history's -z flag was added in fish 2.4.0, so don't use it for versions + # before 2.4.0. + if [ "$FISH_MAJOR" -gt 2 -o \( "$FISH_MAJOR" -eq 2 -a "$FISH_MINOR" -ge 4 \) ]; + history -z | eval (__fzfcmd) --read0 --print0 -q '(commandline)' | read -lz result + and commandline -- $result else - echo "fzf" + history | eval (__fzfcmd) -q '(commandline)' | read -l result + and commandline -- $result + end + end + commandline -f repaint +end + +function fzf-cd-widget -d "Change directory" + set -l commandline (__fzf_parse_commandline) + set -l dir $commandline[1] + set -l fzf_query $commandline[2] + set -l prefix $commandline[3] + + test -n "$FZF_ALT_C_COMMAND"; or set -l FZF_ALT_C_COMMAND " + command find -L \$dir -mindepth 1 \\( -path \$dir'*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' \\) -prune \ + -o -type d -print 2> /dev/null | sed 's@^\./@@'" + test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40% + begin + set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_ALT_C_OPTS" + eval "$FZF_ALT_C_COMMAND | "(__fzfcmd)' +m --query "'$fzf_query'"' | read -l result + + if [ -n "$result" ] + builtin cd -- $result + + # Remove last token from commandline. + commandline -t "" + commandline -it -- $prefix end end - bind \ct fzf-file-widget - bind \cr fzf-history-widget - bind \ec fzf-cd-widget + commandline -f repaint +end - if bind -M insert > /dev/null 2>&1 - bind -M insert \ct fzf-file-widget - bind -M insert \cr fzf-history-widget - bind -M insert \ec fzf-cd-widget +function __fzfcmd + test -n "$FZF_TMUX"; or set FZF_TMUX 0 + test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40% + if [ -n "$FZF_TMUX_OPTS" ] + echo "fzf-tmux $FZF_TMUX_OPTS -- " + else if [ $FZF_TMUX -eq 1 ] + echo "fzf-tmux -d$FZF_TMUX_HEIGHT -- " + else + echo "fzf" end +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 commandline (commandline -t) +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) - # strip -option= from token if present - set -l prefix (string match -r -- '^-[^\s=]+=' $commandline) - set commandline (string replace -- "$prefix" '' $commandline) + # strip -option= from token if present + set -l prefix (string match -r -- '^-[^\s=]+=' $commandline) + set commandline (string replace -- "$prefix" '' $commandline) - # eval is used to do shell expansion on paths - eval set commandline $commandline + # eval is used to do shell expansion on paths + eval set commandline $commandline - if [ -z $commandline ] - # Default to current directory with no --query - set dir '.' - set fzf_query '' + if [ -z $commandline ] + # Default to current directory with no --query + set dir '.' + set fzf_query '' + else + set dir (__fzf_get_dir $commandline) + + if [ "$dir" = "." -a (string sub -l 1 -- $commandline) != '.' ] + # if $dir is "." but commandline is not a relative path, this means no file path found + set fzf_query $commandline else - set dir (__fzf_get_dir $commandline) - - if [ "$dir" = "." -a (string sub -l 1 -- $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") - end + # Also remove trailing slash after dir, to "split" input properly + set fzf_query (string replace -r "^$dir/?" -- '' "$commandline") end - - echo $dir - echo $fzf_query - echo $prefix end - function __fzf_get_dir -d 'Find the longest existing filepath from input string' - set dir $argv + echo $dir + echo $fzf_query + echo $prefix +end - # Strip all trailing slashes. Ignore if $dir is root dir (/) - if [ (string length -- $dir) -gt 1 ] - set dir (string replace -r '/*$' -- '' $dir) - end +function __fzf_get_dir -d 'Find the longest existing filepath from input string' + set dir $argv - # Iteratively check if dir exists and strip tail end of path - while [ ! -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") - end + # Strip all trailing slashes. Ignore if $dir is root dir (/) + if [ (string length -- $dir) -gt 1 ] + set dir (string replace -r '/*$' -- '' $dir) + end - echo $dir + # Iteratively check if dir exists and strip tail end of path + while [ ! -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") end + echo $dir end