From 3b28d5c2b9cb54cbe1e0266e60ce4cdc8d804be2 Mon Sep 17 00:00:00 2001 From: Jonathan Hodgson Date: Sat, 9 May 2020 20:44:18 +0100 Subject: [PATCH] Split completion overide scripts up and into seperate files --- shells/zsh/includes/currentwordcompletion.zsh | 88 ++++++++++++ shells/zsh/includes/fzf.zsh | 134 +++--------------- .../zsh/includes/overidepartialcompletion.zsh | 72 ++++++++++ 3 files changed, 179 insertions(+), 115 deletions(-) create mode 100644 shells/zsh/includes/currentwordcompletion.zsh create mode 100644 shells/zsh/includes/overidepartialcompletion.zsh diff --git a/shells/zsh/includes/currentwordcompletion.zsh b/shells/zsh/includes/currentwordcompletion.zsh new file mode 100644 index 00000000..dbda0358 --- /dev/null +++ b/shells/zsh/includes/currentwordcompletion.zsh @@ -0,0 +1,88 @@ +# This file provides my current word completion +# Unlike standard completion provided by zsh, this completion is based on the current word rather than the current command + + + + + +# Prompts the user to select a wordlist from the wordlists folder +wordlistSelect() { + fd -a --type f --hidden --follow --color=always --exclude .git --exclude \*.md --exclude \*.gif --exclude \*.jpg --exclude \*.png --exclude \*.lua --exclude \*.jar --exclude \*.pl '' /usr/share/wordlists/ | fzf --preview 'bat --color=always {}' +} + +word_replace(){ + local ret=1 + local word="$1" + local cmd="$2" + case "$word" in + wl) wordlistSelect; return 0 ;; + myip) ip route | grep -oE '(dev|src) [^ ]+' | sed 'N;s/\n/,/;s/src //;s/dev //' | awk -F',' '{print $2 " " $1}' | sort -u | fzf -1 --no-preview | cut -d' ' -f1; return 0 ;; + esac + return "$ret" +} + +currentwordcomplete(){ + local tokens cmd swap ret=1 lastWord + # http://zsh.sourceforge.net/FAQ/zshfaq03.html + # http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion-Flags + + # Use zsh's shell parsing to split lbuffer into items + # This takes into account quoting and escaping + tokens=(${(z)LBUFFER}) + + # If there isn't anythng typed, fall back to old tab binding + if [ ${#tokens} -lt 1 ]; then + zle ${currentword_default_completion:-expand-or-complete} + return + fi + + # Assume the first element + # TODO: make this work for multiple commands chained with | or > or && etc. + # TODO: make this work when command prepended with variables eg a=2 foo bar + # foo is the command name + cmd="${tokens[1]}" + lastWord="${tokens[-1]}" + + # Check we haven't pushed space + if [ "${LBUFFER[-1]}" != " " ]; then + swap="$(word_replace "$lastWord" "$cmd")" + ret="$?" + + # This part checks if the part after an = is completable + if [ "$ret" -ne "0" ]; then + local afterEqual="${lastWord##*=}" + local beforeEqual="${lastWord%=*}" + # If they are different, there is an equals in the word + if [ "$afterEqual" != "$lastWord" ]; then + swap="${beforeEqual}=$(word_replace "$afterEqual" "$cmd")" + ret="$?" + fi + fi + fi + + + if [ "$ret" -eq "0" ]; then + if [ -n "$swap" ]; then + tokens[-1]="$swap" + LBUFFER="${tokens[@]}" + fi + zle reset-prompt + return 0 + else + zle ${currentword_default_completion:-expand-or-complete} + return + fi +} + +# Record what ctrl+i is currently set to +# That way we can call it if jhcompletion doesn't result in anything +[ -z "$currentword_default_completion" ] && { + binding=$(bindkey '^I') + [[ $binding =~ 'undefined-key' ]] || currentword_default_completion=$binding[(s: :w)2] + unset binding +} +zle -N currentwordcomplete +bindkey '^I' currentwordcomplete + + + diff --git a/shells/zsh/includes/fzf.zsh b/shells/zsh/includes/fzf.zsh index acc0d803..5523a1ad 100644 --- a/shells/zsh/includes/fzf.zsh +++ b/shells/zsh/includes/fzf.zsh @@ -5,6 +5,7 @@ export FZF_CTRL_R_OPTS="" # this is the argument completeion optionm, use the same command export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" export FZF_CTRL_T_OPTS="$FZF_DEFAULT_OPTS --ansi --preview \"bat --style=numbers --color=always {}\"" +#export FZF_COMPLETION_TRIGGER='' sourced="False" @@ -20,49 +21,6 @@ fi if [ "$sourced" = "True" ]; then - # jhComplete(){ - # local comp=$(echo $1 | cut -d':' -f1) - # local prompt=$(echo $1 | cut -d':' -f2) - # local currentProject=$(project current --path) - # find "$HOME/.local/share/snippets/" -name \*.func | while read line; do - # source "$line" - # done - # case "${comp}" in - # ip) - # if [ -n "$currentProject" ]; then - # project hosts ip --fzf - # fi - # ;; - # myip) - # ip route | grep -oE '(dev|src) [^ ]+' | sed 'N;s/\n/,/;s/src //' | awk -F',' '{print $2 " " $1}' | sort -u | fzf --no-preview | cut -d' ' -f1 - # ;; - # pf) - # if [ -n "$currentProject" ]; then - # find "$currentProject" -type f | fzf - # fi - # ;; - # pd) - # if [ -n "$currentProject" ]; then - # find "$currentProject" -type d | fzf --no-preview - # fi - # ;; - # wl|wordlist) - # __fsel_wordlist - # ;; - # snip) - # snippets - # ;; - # network-interface|int) - # ip -o link show | cut -d' ' -f2- | sed -E 's/[^:]+(UP|DOWN).*/\1/' | tr ':' ' ' | fzf --preview="interface=\$(echo {} | cut -f1 -d' ');ip address show \$interface" | cut -d' ' -f1 - # ;; - # *) - # if command -v "jhcomplete::$comp" > /dev/null; then - # "jhcomplete::$comp" - # else - # echo "" - # fi - # esac - # } # on_word_replace(){ @@ -90,85 +48,31 @@ if [ "$sourced" = "True" ]; then # } - # Prompts the user to select a wordlist from the wordlists folder - wordlistSelect() { - fd -a --type f --hidden --follow --color=always --exclude .git --exclude \*.md --exclude \*.gif --exclude \*.jpg --exclude \*.png --exclude \*.lua --exclude \*.jar --exclude \*.pl '' /usr/share/wordlists/ | fzf --preview 'bat --color=always {}' + _fzf_complete_yay(){ + local tokens=(${(z)LBUFFER}) + if [ "${tokens[-1]}" = "-S" -a "${LBUFFER[-1]}" = " " ]; then + notify-send "complete" + fi + return 1 } - word_replace(){ - local ret=1 - local word="$1" - local cmd="$2" - case "$word" in - wl) wordlistSelect; return 0 ;; - myip) ip route | grep -oE '(dev|src) [^ ]+' | sed 'N;s/\n/,/;s/src //;s/dev //' | awk -F',' '{print $2 " " $1}' | sort -u | fzf -1 --no-preview | cut -d' ' -f1; return 0 ;; - esac - return "$ret" - } - jh_tabcomplete(){ - local tokens cmd swap ret=1 lastWord - # http://zsh.sourceforge.net/FAQ/zshfaq03.html - # http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion-Flags - # Use zsh's shell parsing to split lbuffer into items - # This takes into account quoting and escaping - tokens=(${(z)LBUFFER}) - # If there isn't anythng typed, fall back to old tab binding - if [ ${#tokens} -lt 1 ]; then - zle ${jhcomplete_default_completion:-expand-or-complete} - return - fi - # Assume the first element - # TODO: make this work for multiple commands chained with | or > or && etc. - # TODO: make this work when command prepended with variables eg a=2 foo bar - # foo is the command name - cmd="${tokens[1]}" - lastWord="${tokens[-1]}" - - # This part checks to see if the whole "word" is replaceable - if [ "${LBUFFER[-1]}" != " " ]; then - swap="$(word_replace "$lastWord" "$cmd")" - ret="$?" - fi - # This part checks if the part after an = is completable - if [ "$ret" -ne "0" ]; then - local afterEqual="${lastWord##*=}" - local beforeEqual="${lastWord%=*}" - # If they are different, there is an equals in the word - if [ "$afterEqual" != "$lastWord" ]; then - swap="${beforeEqual}=$(word_replace "$afterEqual" "$cmd")" - ret="$?" - fi - fi - if [ "$ret" -eq "0" ]; then - if [ -n "$swap" ]; then - tokens[-1]="$swap" - LBUFFER="${tokens[@]}" - fi - zle reset-prompt - return 0 - else - zle ${jhcomplete_default_completion:-expand-or-complete} - # Redrawing here means I can use fzf in my completion functions - # This is not ideal, I would preferably run this after fzf in the completion functions but can't because they are not widgets. - zle reset-prompt - return - fi - } - - # Record what ctrl+i is currently set to - # That way we can call it if jhcompletion doesn't result in anything - [ -z "$jhcomplete_default_completion" ] && { - binding=$(bindkey '^I') - [[ $binding =~ 'undefined-key' ]] || jhcomplete_default_completion=$binding[(s: :w)2] - unset binding - } - zle -N jh_tabcomplete - bindkey '^I' jh_tabcomplete + + + + + + + + + + + + fi diff --git a/shells/zsh/includes/overidepartialcompletion.zsh b/shells/zsh/includes/overidepartialcompletion.zsh new file mode 100644 index 00000000..2f8a2feb --- /dev/null +++ b/shells/zsh/includes/overidepartialcompletion.zsh @@ -0,0 +1,72 @@ +# This file will try to provide completion before the default completion system +# This allows me to overide parts of command completion. Normally, this is so I can use fzf. + +overidecomplete(){ + local tokens cmd toadd ret=1 lastWord + # http://zsh.sourceforge.net/FAQ/zshfaq03.html + # http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion-Flags + + # Use zsh's shell parsing to split lbuffer into items + # This takes into account quoting and escaping + tokens=(${(z)LBUFFER}) + + # If there isn't anythng typed, fall back to old tab binding + if [ ${#tokens} -lt 1 ]; then + zle ${overide_default_completion:-expand-or-complete} + return + fi + + # Assume the first element + # TODO: make this work for multiple commands chained with | or > or && etc. + # TODO: make this work when command prepended with variables eg a=2 foo bar + # foo is the command name + cmd="${tokens[1]}" + lastWord="${tokens[-1]}" + + # If using sudo, check the second word + [ "$cmd" = "sudo" ] && cmd="${tokens[2]}" + + # Check we have pushed space + # This means that we are not trying to complete a partial word - leave that to zsh's completion system + if [ "${LBUFFER[-1]}" = " " ]; then + case "$cmd" in + # Pacman and yay have almost the same syntac so for simplicities sake, treat them the same + pacman|yay) + case "$lastWord" in + # If I want to install something, give a list of things to install + -S) toadd="$($cmd -Slq | fzf -m --preview "$cmd -Si {1}" | tr '\n' ' ')"; ret=0 ;; + # If I want to uninstall something, give a list of things to uninstall + -R*) toadd="$($cmd -Qq | fzf -m --preview "$cmd -Qi {1}" | tr '\n' ' ')"; ret=0 ;; + esac ;; + esac + fi + + + if [ "$ret" -eq "0" ]; then + if [ -n "$toadd" ]; then + tokens+=("$toadd") + LBUFFER="${tokens[@]}" + fi + zle reset-prompt + return 0 + else + zle ${overide_default_completion:-expand-or-complete} + # Redrawing here means I can use fzf in my completion functions + # This is not ideal, I would preferably run this after fzf in the completion functions but can't because they are not widgets. + zle reset-prompt + return + fi +} + +# Record what ctrl+i is currently set to +# That way we can call it if jhcompletion doesn't result in anything +[ -z "$overide_default_completion" ] && { + binding=$(bindkey '^I') + [[ $binding =~ 'undefined-key' ]] || overide_default_completion=$binding[(s: :w)2] + unset binding +} +zle -N overidecomplete +bindkey '^I' overidecomplete + + +