1 | const script = `#!/usr/bin/env bash
|
2 |
|
3 | # This function joins an array using a character passed in
|
4 | # e.g. ARRAY=(one two three) -> join_by ":" \${ARRAY[@]} -> "one:two:three"
|
5 | function join_by { local IFS="$1"; shift; echo "$*"; }
|
6 |
|
7 | _<CLI_BIN>_autocomplete()
|
8 | {
|
9 |
|
10 | local cur="\${COMP_WORDS[COMP_CWORD]}" opts normalizedCommand colonPrefix IFS=$' \\t\\n'
|
11 | COMPREPLY=()
|
12 |
|
13 | local commands="
|
14 | <BASH_COMMANDS_WITH_FLAGS_LIST>
|
15 | "
|
16 |
|
17 | function __trim_colon_commands()
|
18 | {
|
19 | # Turn $commands into an array
|
20 | commands=("\${commands[@]}")
|
21 |
|
22 | if [[ -z "$colonPrefix" ]]; then
|
23 | colonPrefix="$normalizedCommand:"
|
24 | fi
|
25 |
|
26 | # Remove colon-word prefix from $commands
|
27 | commands=( "\${commands[@]/$colonPrefix}" )
|
28 |
|
29 | for i in "\${!commands[@]}"; do
|
30 | if [[ "\${commands[$i]}" == "$normalizedCommand" ]]; then
|
31 | # If the currently typed in command is a topic command we need to remove it to avoid suggesting it again
|
32 | unset "\${commands[$i]}"
|
33 | else
|
34 | # Trim subcommands from each command
|
35 | commands[$i]="\${commands[$i]%%:*}"
|
36 | fi
|
37 | done
|
38 | }
|
39 |
|
40 | if [[ "$cur" != "-"* ]]; then
|
41 | # Command
|
42 | __COMP_WORDS=( "\${COMP_WORDS[@]:1}" )
|
43 |
|
44 | # The command typed by the user but separated by colons (e.g. "mycli command subcom" -> "command:subcom")
|
45 | normalizedCommand="$( printf "%s" "$(join_by ":" "\${__COMP_WORDS[@]}")" )"
|
46 |
|
47 | # The command hirarchy, with colons, leading up to the last subcommand entered (e.g. "mycli com subcommand subsubcom" -> "com:subcommand:")
|
48 | colonPrefix="\${normalizedCommand%"\${normalizedCommand##*:}"}"
|
49 |
|
50 | if [[ -z "$normalizedCommand" ]]; then
|
51 | # If there is no normalizedCommand yet the user hasn't typed in a full command
|
52 | # So we should trim all subcommands & flags from $commands so we can suggest all top level commands
|
53 | opts=$(printf "%s " "\${commands[@]}" | grep -Eo '^[a-zA-Z0-9_-]+')
|
54 | else
|
55 | # Filter $commands to just the ones that match the $normalizedCommand and turn into an array
|
56 | commands=( $(compgen -W "$commands" -- "\${normalizedCommand}") )
|
57 | # Trim higher level and subcommands from the subcommands to suggest
|
58 | __trim_colon_commands "$colonPrefix"
|
59 |
|
60 | opts=$(printf "%s " "\${commands[@]}") # | grep -Eo '^[a-zA-Z0-9_-]+'
|
61 | fi
|
62 | else
|
63 | # Flag
|
64 |
|
65 | # The full CLI command separated by colons (e.g. "mycli command subcommand --fl" -> "command:subcommand")
|
66 | # This needs to be defined with $COMP_CWORD-1 as opposed to above because the current "word" on the command line is a flag and the command is everything before the flag
|
67 | normalizedCommand="$( printf "%s" "$(join_by ":" "\${COMP_WORDS[@]:1:($COMP_CWORD - 1)}")" )"
|
68 |
|
69 | # The line below finds the command in $commands using grep
|
70 | # Then, using sed, it removes everything from the found command before the --flags (e.g. "command:subcommand:subsubcom --flag1 --flag2" -> "--flag1 --flag2")
|
71 | opts=$(printf "%s " "\${commands[@]}" | grep "\${normalizedCommand}" | sed -n "s/^\${normalizedCommand} //p")
|
72 | fi
|
73 |
|
74 | COMPREPLY=($(compgen -W "$opts" -- "\${cur}"))
|
75 | }
|
76 |
|
77 | complete -F _<CLI_BIN>_autocomplete <CLI_BIN>
|
78 | `;
|
79 | export default script;
|