From d4e14550cd80cf8eb59b795378cfa99767ccbc2d Mon Sep 17 00:00:00 2001 From: Noah Pederson Date: Wed, 8 Jul 2026 20:08:45 -0500 Subject: [PATCH] Add autocomplete script for mk --- fish/completions/mk.fish | 139 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 fish/completions/mk.fish diff --git a/fish/completions/mk.fish b/fish/completions/mk.fish new file mode 100644 index 0000000..a7988a5 --- /dev/null +++ b/fish/completions/mk.fish @@ -0,0 +1,139 @@ +function __fish_mk_arg_is_option_value + set -l tokens (commandline -opc) + set -l previous $tokens[-1] + + test "$previous" = -f +end + +function __fish_mk_current_mkfile + set -l tokens (commandline -opc) + set -e tokens[1] + + set -l mkfile mkfile + set -l previous + for token in $tokens + if test "$previous" = -f + set mkfile $token + end + set previous $token + end + + printf '%s\n' $mkfile +end + +function __fish_mk_complete_targets + set -l mkfile (__fish_mk_current_mkfile) + + if not test -r "$mkfile" + return + end + + command awk ' + function strip_comment(s, i, c, out, quote) { + quote = 0 + out = "" + for (i = 1; i <= length(s); i++) { + c = substr(s, i, 1) + if (c == "'"'"'") { + quote = !quote + } + if (c == "#" && !quote) { + break + } + out = out c + } + return out + } + + function first_unquoted(s, chars, i, c, quote) { + quote = 0 + for (i = 1; i <= length(s); i++) { + c = substr(s, i, 1) + if (c == "'"'"'") { + quote = !quote + } + if (index(chars, c) && !quote) { + return i + } + } + return 0 + } + + function split_targets(s, i, c, word, quote) { + quote = 0 + word = "" + for (i = 1; i <= length(s); i++) { + c = substr(s, i, 1) + if (c == "'"'"'") { + quote = !quote + continue + } + if (c ~ /[[:space:]]/ && !quote) { + print_target(word) + word = "" + continue + } + word = word c + } + print_target(word) + } + + function print_target(target) { + if (target == "" || target ~ /[%&]/ || target ~ /^\$/) { + return + } + if (!seen[target]++) { + print target + } + } + + { + line = pending $0 + pending = "" + while (line ~ /\\$/) { + sub(/\\$/, "", line) + if ((getline nextline) <= 0) { + break + } + line = line nextline + } + + if (line ~ /^[[:space:]]/ || line ~ /^[[:space:]]*($|<)/) { + next + } + + line = strip_comment(line) + sub(/^[[:space:]]+/, "", line) + sub(/[[:space:]]+$/, "", line) + if (line == "") { + next + } + + sep = first_unquoted(line, ":=") + if (!sep || substr(line, sep, 1) != ":") { + next + } + + targets = substr(line, 1, sep - 1) + tail = substr(line, sep + 1) + if (tail ~ /^[^:]*R:/) { + next + } + + split_targets(targets) + } + ' "$mkfile" | string escape +end + +complete -c mk -f +complete -c mk -s a -d 'Assume all targets are out of date' +complete -c mk -s d -x -a 'e g p eg ep gp egp' -d 'Produce debugging output' +complete -c mk -s e -d 'Explain why each target is made' +complete -c mk -s f -r -F -d 'Read mkfile' +complete -c mk -s i -d 'Force missing intermediate targets to be made' +complete -c mk -s k -d 'Do as much as possible after errors' +complete -c mk -s n -d 'Print commands without executing them' +complete -c mk -s s -d 'Make command line targets sequentially' +complete -c mk -s t -d 'Touch file targets without executing recipes' +complete -c mk -s w -x -a '(__fish_mk_complete_targets)' -d 'Pretend targets were modified' +complete -c mk -n 'not __fish_mk_arg_is_option_value' -a '(__fish_mk_complete_targets)' -d Target -- 2.51.2