diff options
author | Tom Ryder <tom@sanctum.geek.nz> | 2018-12-01 13:06:03 +1300 |
---|---|---|
committer | Tom Ryder <tom@sanctum.geek.nz> | 2018-12-01 13:07:48 +1300 |
commit | 2f59b3c6a7931de14e837ad3c8b969327fda89ff (patch) | |
tree | 0a21ba8fe0bca781dd927b388a7af6e649d5dee4 /bash | |
parent | Remove unneeded -q option to shopt -s commands (diff) | |
download | dotfiles-2f59b3c6a7931de14e837ad3c8b969327fda89ff.tar.gz dotfiles-2f59b3c6a7931de14e837ad3c8b969327fda89ff.zip |
Overhaul bd() completion again
I forgot that the second positional parameter $2 to these completion
functions is the word currently being completed. That's going to make
things a bit less verbose.
Diffstat (limited to 'bash')
-rw-r--r-- | bash/bash_completion.d/bd.bash | 59 |
1 files changed, 43 insertions, 16 deletions
diff --git a/bash/bash_completion.d/bd.bash b/bash/bash_completion.d/bd.bash index e67cdd09..59f4718f 100644 --- a/bash/bash_completion.d/bd.bash +++ b/bash/bash_completion.d/bd.bash @@ -1,25 +1,52 @@ # Completion setup for bd() _bd() { - # Only makes sense for the first argument + # The function accepts only one argument, so it doesn't make sense to + # complete anywhere else ((COMP_CWORD == 1)) || return - # Build a list of dirnames in $PWD - local -a dirnames - IFS=/ read -rd '' -a dirnames < <(printf '%s\0' "${PWD#/}") + # Iterate through slash-delimited matching parent path elements, as piped + # in by the subshell + local ci word + while IFS= read -rd/ word ; do + COMPREPLY[ci++]=$word + done < <( - # Remove the last element in the array (the current directory) - ((${#dirnames[@]})) || return - dirnames=("${dirnames[@]:0:${#dirnames[@]}-1}") + # Build an array of path nodes, leaf to root + path=$PWD + while [[ -n $path ]] ; do + node=${path##*/} + path=${path%/*} + [[ -n $node ]] || continue + nodes[ni++]=$node + done - # Add the matching dirnames to the reply - local dirname - for dirname in "${dirnames[@]}" ; do - case $dirname in - "${COMP_WORDS[COMP_CWORD]}"*) - COMPREPLY[${#COMPREPLY[@]}]=$(printf %q "$dirname") - ;; - esac - done + # Continue if we have at least two nodes, counting the leaf + ((${#nodes} > 1)) || return + + # Shift off the leaf, since it's not meaningful to go "back to" the + # current directory + nodes=("${nodes[@]:1}") + + # Turn on case-insensitive matching, if configured to do so + while read -r _ setting ; do + case $setting in + ('completion-ignore-case on') + shopt -s nocasematch 2>/dev/null + break + ;; + esac + done < <(bind -v) + + # Iterate through the nodes and print the ones that match the word + # being completed, with a trailing slash as terminator + for node in "${nodes[@]}" ; do + case $node in + ("$2"*) + printf '%s/' "$node" + ;; + esac + done + ) } complete -F _bd bd |