aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2018-12-01 13:06:03 +1300
committerTom Ryder <tom@sanctum.geek.nz>2018-12-01 13:07:48 +1300
commit2f59b3c6a7931de14e837ad3c8b969327fda89ff (patch)
tree0a21ba8fe0bca781dd927b388a7af6e649d5dee4
parentRemove unneeded -q option to shopt -s commands (diff)
downloaddotfiles-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.
-rw-r--r--bash/bash_completion.d/bd.bash59
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