From b6c540ded9a527f19b8bff7888e330ba2786f552 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sat, 1 Dec 2018 13:15:28 +1300 Subject: Use the positional parameter aliases for words The current word is available in $2, and the previous word in $3. That's easier (and maybe a bit less expensive) to dig out, so let's use it. --- bash/bash_completion.d/make.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bash/bash_completion.d/make.bash') diff --git a/bash/bash_completion.d/make.bash b/bash/bash_completion.d/make.bash index 0f39ef4b..8ca36529 100644 --- a/bash/bash_completion.d/make.bash +++ b/bash/bash_completion.d/make.bash @@ -40,7 +40,7 @@ _make() { *[^[:word:]./-]*) ;; # Add targets that match what we're completing - "${COMP_WORDS[COMP_CWORD]}"*) + "$2"*) COMPREPLY[${#COMPREPLY[@]}]=$target ;; esac -- cgit v1.2.3 From 7d6fe8b1886f902f8ffbec2a9985fae9f91121cb Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sun, 2 Dec 2018 17:59:29 +1300 Subject: Overhaul Bash completion scripts Some general changes: * Apply case sensitivity switching in more contexts, using a dynamically loaded helper function * Use array counters for appending to COMPREPLY where possible * Lots more short-circuiting to limit structural depth These changes are expansive and there will definitely be bugs. --- bash/bash_completion.d/make.bash | 93 +++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 40 deletions(-) (limited to 'bash/bash_completion.d/make.bash') diff --git a/bash/bash_completion.d/make.bash b/bash/bash_completion.d/make.bash index 8ca36529..2527d145 100644 --- a/bash/bash_completion.d/make.bash +++ b/bash/bash_completion.d/make.bash @@ -1,3 +1,8 @@ +# Load _completion_ignore_case helper function +if ! declare -F _completion_ignore_case >/dev/null ; then + source "$HOME"/.bash_completion.d/_completion_ignore_case.bash +fi + # Completion setup for Make, completing targets _make() { @@ -5,48 +10,56 @@ _make() { # first, then "Makefile"). You may want to add "GNU-makefile" after this. local mf for mf in makefile Makefile '' ; do - [[ -e $mf ]] || continue - break + ! [[ -e $mf ]] || break done [[ -n $mf ]] || return - # Iterate through the Makefile, line by line - local line - while IFS= read -r line ; do - case $line in - - # We're looking for targets but not variable assignments - \#*) ;; - $'\t'*) ;; - *:=*) ;; - *:*) - - # Break the target up with space delimiters - local -a targets - IFS=' ' read -rd '' -a targets < \ - <(printf '%s\0' "${line%%:*}") - - # Iterate through the targets and add suitable ones - local target - for target in "${targets[@]}" ; do - case $target in - - # Don't complete special targets beginning with a - # period - .*) ;; - - # Don't complete targets with names that have - # characters outside of the POSIX spec (plus slashes) - *[^[:word:]./-]*) ;; - - # Add targets that match what we're completing - "$2"*) - COMPREPLY[${#COMPREPLY[@]}]=$target - ;; - esac - done - ;; - esac - done < "$mf" + # Iterate through completions produced by subshell + local ci comp + while read -r comp ; do + COMPREPLY[ci++]=$comp + done < <( + while IFS= read -r line ; do + + # Match expected format + case $line in + # Has no equals sign anywhere + (*=*) continue ;; + # First char not a tab + ($'\t'*) continue ;; + # Has a colon on the line + (*:*) ;; + # Skip anything else + (*) continue ;; + esac + + # Break the target up with space delimiters + local -a targets + IFS=' ' read -a targets -r \ + < <(printf '%s\n' "${line%%:*}") + + # Short-circuit if there are no targets + ((${#targets[@]})) || exit + + # Make matches behave correctly + if _completion_ignore_case ; then + shopt -s nocasematch 2>/dev/null + fi + + # Examine each target for completion suitability + local target + for target in "${targets[@]}" ; do + case $target in + # Not .PHONY, .POSIX etc + (.*) ;; + # Nothing with metacharacters + (*[^[:word:]./-]*) ;; + # Match! + ("$2"*) printf '%s\n' "$target" ;; + esac + done + + done < "$mf" + ) } complete -F _make -o bashdefault -o default make -- cgit v1.2.3