summaryrefslogtreecommitdiff
path: root/completions/make
diff options
context:
space:
mode:
Diffstat (limited to 'completions/make')
-rw-r--r--completions/make101
1 files changed, 91 insertions, 10 deletions
diff --git a/completions/make b/completions/make
index 1aec3489..b4ad9e73 100644
--- a/completions/make
+++ b/completions/make
@@ -1,11 +1,81 @@
# bash completion for GNU make -*- shell-script -*-
+function _make_target_extract_script()
+{
+ local mode="$1"
+ shift
+
+ local prefix="$1"
+ local prefix_pat=$( printf "%s\n" "$prefix" | \
+ sed 's/[][\,.*^$(){}?+|/]/\\&/g' )
+ local basename=${prefix##*/}
+ local dirname_len=$(( ${#prefix} - ${#basename} ))
+
+ if [[ $mode == -d ]]; then
+ # display mode, only output current path component to the next slash
+ local output="\2"
+ else
+ # completion mode, output full path to the next slash
+ local output="\1\2"
+ fi
+
+ cat <<EOF
+ /^# Make data base/,/^# Files/d # skip until files section
+ /^# Not a target/,/^$/ d # skip not target blocks
+ /^${prefix_pat}/,/^$/! d # skip anything user dont want
+
+ # The stuff above here describes lines that are not
+ # explicit targets or not targets other than special ones
+ # The stuff below here decides whether an explicit target
+ # should be output.
+
+ /^# File is an intermediate prerequisite/ {
+ s/^.*$//;x # unhold target
+ d # delete line
+ }
+
+ /^$/ { # end of target block
+ x # unhold target
+ /^$/d # dont print blanks
+ s,^(.{${dirname_len}})(.{${#basename}}[^:/]*/?)[^:]*:.*$,${output},p
+ d # hide any bugs
+ }
+
+ /^[^#\t:%]+:/ { # found target block
+
+ /^\.PHONY:/ d # special target
+ /^\.SUFFIXES:/ d # special target
+ /^\.DEFAULT:/ d # special target
+ /^\.PRECIOUS:/ d # special target
+ /^\.INTERMEDIATE:/ d # special target
+ /^\.SECONDARY:/ d # special target
+ /^\.SECONDEXPANSION:/ d # special target
+ /^\.DELETE_ON_ERROR:/ d # special target
+ /^\.IGNORE:/ d # special target
+ /^\.LOW_RESOLUTION_TIME:/ d # special target
+ /^\.SILENT:/ d # special target
+ /^\.EXPORT_ALL_VARIABLES:/ d # special target
+ /^\.NOTPARALLEL:/ d # special target
+ /^\.ONESHELL:/ d # special target
+ /^\.POSIX:/ d # special target
+ /^\.NOEXPORT:/ d # special target
+ /^\.MAKE:/ d # special target
+
+ /^[^a-zA-Z0-9]/ d # convention for hidden tgt
+
+ h # hold target
+ d # delete line
+ }
+
+EOF
+}
+
_make()
{
local cur prev words cword split
_init_completion -s || return
- local file makef makef_dir="." makef_inc i
+ local file makef makef_dir=( "-C" "." ) makef_inc i
case $prev in
-f|--file|--makefile|-o|--old-file|--assume-old|-W|--what-if|\
@@ -49,7 +119,7 @@ _make()
for (( i=0; i < ${#words[@]}; i++ )); do
if [[ ${words[i]} == -@(C|-directory) ]]; then
# eval for tilde expansion
- eval makef_dir=${words[i+1]}
+ eval makef_dir=( -C "${words[i+1]}" )
break
fi
done
@@ -59,21 +129,32 @@ _make()
for (( i=0; i < ${#words[@]}; i++ )); do
if [[ ${words[i]} == -@(f|-?(make)file) ]]; then
# eval for tilde expansion
- eval makef=${words[i+1]}
+ eval makef=( -f "${words[i+1]}" )
break
fi
done
- [[ -n $makef ]] && makef="-f ${makef}"
- [[ -n $makef_dir ]] && makef_dir="-C ${makef_dir}"
+ # recognise that possible completions are only going to be displayed
+ # so only the base name is shown
+ local mode=--
+ if (( COMP_TYPE != 9 )); then
+ mode=-d # display-only mode
+ fi
+
+ local reset=$( set +o | grep -F posix ); set +o posix # for <(...)
+ COMPREPLY=( $( LC_ALL=C \
+ make -npq "${makef[@]}" "${makef_dir[@]}" .DEFAULT 2>/dev/null | \
+ sed -nrf <(_make_target_extract_script $mode "$cur") ) )
+ $reset
- COMPREPLY=( $( compgen -W "$( make -qp $makef $makef_dir 2>/dev/null | \
- awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
- {split($1,A,/ /);for(i in A)print A[i]}' )" \
- -- "$cur" ) )
+ if [[ $mode != -d ]]; then
+ # Completion will occur if there is only one suggestion
+ # so set options for completion based on the first one
+ [[ $COMPREPLY == */ ]] && compopt -o nospace
+ fi
fi
} &&
-complete -F _make make gmake gnumake pmake
+complete -F _make make gmake gnumake pmake colormake
# ex: ts=4 sw=4 et filetype=sh