diff --git a/README.md b/README.md index 622460d2..18110510 100755 --- a/README.md +++ b/README.md @@ -104,6 +104,12 @@ To uninstall mbed CLI, run: pip uninstall mbed-cli ``` +### Adding Bash tab completion + +To install mbed-cli bash tab completion navigate to the `tools/bash_completion` directory. Then copy the `mbed` script into your `/etc/bash_completion.d/` or `/usr/local/etc/bash_completion.d` directory and reload your terminal. + +[Full documentation here](tools/bash_completion/install.md) + ## Quickstart video [![Video tutorial](http://img.youtube.com/vi/PI1Kq9RSN_Y/0.jpg)](https://www.youtube.com/watch?v=PI1Kq9RSN_Y) diff --git a/tools/bash_completion/generator.py b/tools/bash_completion/generator.py new file mode 100644 index 00000000..98fc9e7c --- /dev/null +++ b/tools/bash_completion/generator.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python +# Michael Bartling (michael.bartling@arm.com) + +from collections import defaultdict +import pystache +import re +import subprocess + +# Top level --version is a pain to deal with so ignoring for now +# This one extracts single commands and the help txt +commandRegex = r"^\s+(?P\w+)\s+(?P[a-zA-Z ]*)$" + +# Why the hell do spaces get regexed in command1 ? +subcommandRegex = r"^\s+(?P-+[a-zA-Z_\-]+(?P\s+[A-Z_\-]+)?)"\ + r"(?P,\s+-+[a-zA-Z_-]+(?P\s+[A-Z_-]+)?)?"\ + r"\s+(?P.*)$" + + +def getHelpTxt(command=None): + if command: + p = subprocess.Popen(["mbed", command, "-h"], stdout=subprocess.PIPE) + else: + p = subprocess.Popen(["mbed", "-h"], stdout=subprocess.PIPE) + out, err = p.communicate() + return out + +def getTargetCode(): + txt = '' + with open("templates/target.tmplt") as fp: + txt = fp.read() + return txt + +def getToolchainCode(): + txt = '' + with open("templates/toolchain.tmplt") as fp: + txt = fp.read() + return txt + +def getSCMCode(): + txt = '' + with open("templates/scm.tmplt") as fp: + txt = fp.read() + return txt + +def getIDECode(): + txt = '' + with open("templates/ide.tmplt") as fp: + txt = fp.read() + return txt + +def getProtocolCode(): + txt = '' + with open("templates/protocol.tmplt") as fp: + txt = fp.read() + return txt + +def parseCommands(): + commands = defaultdict(defaultdict) + commands["COMMAND"] = [] + helpTxt = getHelpTxt() + # print helpTxt + for line in helpTxt.split('\n'): + match = re.search(commandRegex, line) + if match: + g = match.groupdict() + commands[g["command"]]["helptxt"] = g["helptxt"] + commands[g["command"]]["subcommands"] = [] + + # Subcommand mustache generation + commands[g["command"]]["DDASH_COMMANDS"] = [] + commands[g["command"]]["DASH_COMMANDS"] = [] + commands[g["command"]]["COMMAND"] = g["command"] + + commands[g["command"]]["HAVE_PREV"] = {"PREV_CASE": []} + + # Main function generation + commands["COMMAND"].append({"name": g["command"]}) + + for commandKey in commands: + # Skip + if commandKey == "COMMAND": + continue + + helpTxt = getHelpTxt(commandKey) + for line in helpTxt.split('\n'): + match = re.search(subcommandRegex, line) + if match: + commandMatch = match.groupdict() + + # Clean up the subcommands + command1 = commandMatch["command1"] + command2 = commandMatch["command2"] + + if command1: + command1 = re.sub(",", "", command1) + command1.strip() + command1 = command1.split()[0] + if command2: + command2 = re.sub(",", "", command2) + command2.strip() + command2 = command2.split()[0] + + # Not sure why the cleaning is even necessary, + # the regex looks correct + commandMatch["command1"] = command1 + commandMatch["command2"] = command2 + + commands[commandKey]["subcommands"].append(commandMatch) + + # Push format for mustache + if command1 and '--' in command1: + commands[commandKey]["DDASH_COMMANDS"].append( + {"name": command1}) + if command2 and '--' in command2: + commands[commandKey]["DDASH_COMMANDS"].append( + {"name": command2}) + + if command1: + m = re.match("^-[a-zA-Z]{1,2}", command1) + if m: + commands[commandKey]["DASH_COMMANDS"].append( + {"name": command1}) + else: + command1 = "" + + if command2: + m = re.match("^-[a-zA-Z]{1,2}", command2) + if m: + commands[commandKey]["DASH_COMMANDS"].append( + {"name": command2}) + else: + command2 = "" + + # Adding the dependent command handlers + if "target" in command1 or "target" in command2: + commands[commandKey]["HAVE_PREV"]["PREV_CASE"].append({"case": "|".join(filter(None, [command1, command2])), "code": getTargetCode()}) + + if "toolchain" in command1 or "toolchain" in command2: + commands[commandKey]["HAVE_PREV"]["PREV_CASE"].append({"case": "|".join(filter(None, [command1, command2])), "code": getToolchainCode()}) + + + if "--ide" in command1 or "--ide" in command2: + commands[commandKey]["HAVE_PREV"]["PREV_CASE"].append({"case": "|".join(filter(None, [command1, command2])), "code": getIDECode()}) + + if "scm" in command1 or "scm" in command2: + commands[commandKey]["HAVE_PREV"]["PREV_CASE"].append({"case": "|".join(filter(None, [command1, command2])), "code": getSCMCode()}) + + if "protocol" in command1 or "protocol" in command2: + commands[commandKey]["HAVE_PREV"]["PREV_CASE"].append({"case": "|".join(filter(None, [command1, command2])), "code": getProtocolCode()}) + + # Adding the dependent command handlers for target and toolchain + if "target" in commandKey: + commands[commandKey]["HAVE_PREV"]["PREV_CASE"].append({"case": commandKey, "code": getTargetCode()}) + + if "toolchain" in commandKey: + commands[commandKey]["HAVE_PREV"]["PREV_CASE"].append({"case": commandKey, "code": getToolchainCode()}) + + return commands + + +def generateMain(commands): + tmplt = "" + + txt = [] + + with open("templates/mbed.tmplt") as fp: + tmplt = fp.read() + + txt.append(pystache.render(tmplt, commands)) + + return txt + + +def generateCompleters(commands): + tmplt = "" + txt = [] + + renderer = pystache.Renderer(escape=lambda u: u) + + with open("templates/command.tmplt") as fp: + tmplt = fp.read() + + for commandKey in commands: + txt.append(renderer.render(tmplt, commands[commandKey])) + + # if need to add hacks add them here + + return txt + + +def generateBoilerPlate(commands): + txt = [] + + with open("templates/boilerplate.tmplt") as fp: + txt.append(fp.read()) + + return txt + + +def generateScript(commands): + txt = [] + + txt.extend(generateBoilerPlate(commands)) + txt.extend(generateCompleters(commands)) + txt.extend(generateMain(commands)) + + with open("mbed-completion", "w") as fp: + for x in txt: + fp.write("%s\n" % x) + + +if __name__ == '__main__': + commands = parseCommands() + + # At this point we have a list of all the commands and sub commands + # for each command create a Bash function + # register each subcommand + generateScript(commands) diff --git a/tools/bash_completion/install.md b/tools/bash_completion/install.md new file mode 100644 index 00000000..15e01324 --- /dev/null +++ b/tools/bash_completion/install.md @@ -0,0 +1,13 @@ +# Install Guide + +## System-wide Installation (root) + +- Copy or link the bash completion script, `mbed`, into your `/etc/bash_completion.d` or `/usr/local/etc/bash_completion.d` directory. +- Reopen terminal + +## Local Installation + +- `mkdir ~/.bash_completion.d && cp mbed ~/.bash_completion.d/` +- `echo "source ~/.bash_completion.d/mbed" >> ~/.bash_profile` +- logout and login + diff --git a/tools/bash_completion/mbed b/tools/bash_completion/mbed new file mode 100644 index 00000000..e2561f16 --- /dev/null +++ b/tools/bash_completion/mbed @@ -0,0 +1,750 @@ +# Based on mbed auto complete scripts + +__mbedcomp_words_include() { + local i=1 + while [[ "$i" -lt "$COMP_CWORD" ]] + do + if [[ "${COMP_WORDS[i]}" = "$1" ]] + then + return 0 + fi + i="$((++i))" + done + return 1 +} + +# Find the previous non-switch word +__mbedcomp_prev() { + local idx="$((COMP_CWORD - 1))" + local prv="${COMP_WORDS[idx]}" + while [[ "$prv" = -* ]] + do + idx="$((--idx))" + prv="${COMP_WORDS[idx]}" + done + echo "$prv" +} + +__mbedcomp() { +# break $1 on space, tab, and newline characters, +# and turn it into a newline separated list of words + local list s sep=$'\n' IFS=$' '$'\t'$'\n' + local cur="${COMP_WORDS[COMP_CWORD]}" + + for s in $1 + do + __mbedcomp_words_include "$s" && continue + list="$list$s$sep" + done + + IFS="$sep" + COMPREPLY=($(compgen -W "$list" -- "$cur")) +} + +__mbed_complete_new() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --scm + --program + --library + --mbedlib + --create-only + --depth + --protocol + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -v + -vv + " + return + ;; + esac + case "$prev" in + --scm) + __mbedcomp "bld git hg" + return + ;; + --protocol) + __mbedcomp "https http ssh git" + return + ;; + esac +} + +__mbed_complete_import() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --ignore + --depth + --protocol + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -I + -v + -vv + " + return + ;; + esac + case "$prev" in + --protocol) + __mbedcomp "https http ssh git" + return + ;; + esac +} + +__mbed_complete_add() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --ignore + --depth + --protocol + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -I + -v + -vv + " + return + ;; + esac + case "$prev" in + --protocol) + __mbedcomp "https http ssh git" + return + ;; + esac +} + +__mbed_complete_remove() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -v + -vv + " + return + ;; + esac +} + +__mbed_complete_deploy() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --ignore + --depth + --protocol + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -I + -v + -vv + " + return + ;; + esac + case "$prev" in + --protocol) + __mbedcomp "https http ssh git" + return + ;; + esac +} + +__mbed_complete_publish() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --all + --message + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -A + -M + -v + -vv + " + return + ;; + esac +} + +__mbed_complete_update() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --clean + --clean-files + --clean-deps + --ignore + --depth + --protocol + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -C + -I + -v + -vv + " + return + ;; + esac + case "$prev" in + --protocol) + __mbedcomp "https http ssh git" + return + ;; + esac +} + +__mbed_complete_sync() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -v + -vv + " + return + ;; + esac +} + +__mbed_complete_ls() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --all + --ignore + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -a + -I + -v + -vv + " + return + ;; + esac +} + +__mbed_complete_status() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --ignore + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -I + -v + -vv + " + return + ;; + esac +} + +__mbed_complete_compile () { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --toolchain + --target + --profile + --library + --config + --prefix + --source + --build + --clean + --artifact-name + --supported + --app-config + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -t + -m + -c + -N + -S + -v + -vv + " + return + ;; + esac + case "$prev" in + --target|-m) + declare TARGETS=$(mbed target --supported | cut -d '|' -f 2 | sed -n '/^+/!p' | sed -n '/^Supported/!p' | sed -n '/^ [A-Z][A-Z]/p') + __mbedcomp "${TARGETS}" + return + ;; + --toolchain|-t) + declare TOOLCHAINS=$(mbed target --supported | head -n 2 | tail -n 1 | tr '|' '\n' | sed -n '/^ Target/!p' | sed -n '/^ mbed/!p') + __mbedcomp "${TOOLCHAINS}" + return + ;; + esac +} + +__mbed_complete_test() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --toolchain + --target + --compile-list + --run-list + --compile + --run + --tests-by-name + --source + --build + --profile + --clean + --test-spec + --app-config + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -t + -m + -n + -c + -v + -vv + " + return + ;; + esac + case "$prev" in + --target|-m) + declare TARGETS=$(mbed target --supported | cut -d '|' -f 2 | sed -n '/^+/!p' | sed -n '/^Supported/!p' | sed -n '/^ [A-Z][A-Z]/p') + __mbedcomp "${TARGETS}" + return + ;; + --toolchain|-t) + declare TOOLCHAINS=$(mbed target --supported | head -n 2 | tail -n 1 | tr '|' '\n' | sed -n '/^ Target/!p' | sed -n '/^ mbed/!p') + __mbedcomp "${TOOLCHAINS}" + return + ;; + esac +} + +__mbed_complete_export() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --ide + --target + --source + --clean + --supported + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -i + -m + -c + -S + -v + -vv + " + return + ;; + esac + case "$prev" in + --target|-m) + declare TARGETS=$(mbed export --supported | cut -d '|' -f 2 | sed -n '/^+/!p' | sed -n '/^Platform/!p' | sed -n '/^Total/!p') + __mbedcomp "${TARGETS}" + return + ;; + --ide|-i) + declare IDES=$(mbed export --supported | tail -n +1 | head -n 2 | tr '|' '\n' | sed -n '/^+/!p' | sed -n '/^ Platform/!p') + __mbedcomp "${IDES}" + return + ;; + esac +} + +__mbed_complete_detect() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -v + -vv + " + return + ;; + esac +} + +__mbed_complete_config() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --global + --unset + --list + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -G + -U + -L + -v + -vv + " + return + ;; + esac +} + +__mbed_complete_target() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --global + --supported + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -G + -S + -v + -vv + " + return + ;; + esac + case "$prev" in + target|-G|--global|-v|--verbose|-vv|--very_verbose) + declare TARGETS=$(mbed target --supported | cut -d '|' -f 2 | sed -n '/^+/!p' | sed -n '/^Supported/!p' | sed -n '/^ [A-Z][A-Z]/p') + __mbedcomp "${TARGETS}" + return + ;; + esac +} +__mbed_complete_toolchain() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --global + --supported + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -G + -S + -v + -vv + " + return + ;; + esac + case "$prev" in + toolchain|-G|--global|-v|--verbose|-vv|--very_verbose) + declare TOOLCHAINS=$(mbed target --supported | head -n 2 | tail -n 1 | tr '|' '\n' | sed -n '/^ Target/!p' | sed -n '/^ mbed/!p') + __mbedcomp "${TOOLCHAINS}" + return + ;; + esac +} + +__mbed_complete_help() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + --help + --verbose + --very_verbose + " + + return + ;; + -*) + __mbedcomp " + -h + -v + -vv + " + return + ;; + esac +} + +_mbed () { + local i=1 cmd prev + + prev="${COMP_WORDS[COMP_CWORD-1]}" + +# find the subcommand + while [[ "$i" -lt "$COMP_CWORD" ]] + do + local s="${COMP_WORDS[i]}" + case "$s" in + --*) + cmd="$s" + break + ;; + -*) + ;; + *) + cmd="$s" + break + ;; + esac + + i="$((++i))" + done + + # Handle the main command completions + if [[ "$i" -eq "$COMP_CWORD" ]] + then + local cmds=" + --version + new + import + add + remove + deploy + publish + update + sync + ls + status + compile + test + export + detect + config + target + toolchain + help + " + + __mbedcomp "${cmds}" + fi + + # Each subcommand has a completion function based on the parent + case "$cmd" in + new) __mbed_complete_new ;; + import) __mbed_complete_import ;; + add) __mbed_complete_add ;; + remove) __mbed_complete_remove ;; + deploy) __mbed_complete_deploy ;; + publish) __mbed_complete_publish ;; + update) __mbed_complete_update ;; + sync) __mbed_complete_sync ;; + ls) __mbed_complete_ls ;; + status) __mbed_complete_status ;; + compile) __mbed_complete_compile ;; + test) __mbed_complete_test ;; + export) __mbed_complete_export;; + detect) __mbed_complete_detect ;; + config) __mbed_complete_config ;; + target) __mbed_complete_target ;; + toolchain) __mbed_complete_toolchain ;; + *) ;; + esac + +} + +complete -o bashdefault -o default -F _mbed mbed +complete -o bashdefault -o default -F _mbed mbed-cli + diff --git a/tools/bash_completion/templates/.README.md.swp b/tools/bash_completion/templates/.README.md.swp new file mode 100644 index 00000000..8cb82c5c Binary files /dev/null and b/tools/bash_completion/templates/.README.md.swp differ diff --git a/tools/bash_completion/templates/README.md b/tools/bash_completion/templates/README.md new file mode 100644 index 00000000..9c35ed54 --- /dev/null +++ b/tools/bash_completion/templates/README.md @@ -0,0 +1,3 @@ +# Templates + +Note these templates are inspired by the mustache syntax. diff --git a/tools/bash_completion/templates/boilerplate.tmplt b/tools/bash_completion/templates/boilerplate.tmplt new file mode 100644 index 00000000..deaa6076 --- /dev/null +++ b/tools/bash_completion/templates/boilerplate.tmplt @@ -0,0 +1,43 @@ +# Note this file is generated +# Based on mbed auto complete scripts + +__mbedcomp_words_include() { + local i=1 + while [[ "$i" -lt "$COMP_CWORD" ]] + do + if [[ "${COMP_WORDS[i]}" = "$1" ]] + then + return 0 + fi + i="$((++i))" + done + return 1 +} + +# Find the previous non-switch word +__mbedcomp_prev() { + local idx="$((COMP_CWORD - 1))" + local prv="${COMP_WORDS[idx]}" + while [[ "$prv" = -* ]] + do + idx="$((--idx))" + prv="${COMP_WORDS[idx]}" + done + echo "$prv" +} + +__mbedcomp() { +# break $1 on space, tab, and newline characters, +# and turn it into a newline separated list of words + local list s sep=$'\n' IFS=$' '$'\t'$'\n' + local cur="${COMP_WORDS[COMP_CWORD]}" + + for s in $1 + do + __mbedcomp_words_include "$s" && continue + list="$list$s$sep" + done + + IFS="$sep" + COMPREPLY=($(compgen -W "$list" -- "$cur")) +} diff --git a/tools/bash_completion/templates/command.tmplt b/tools/bash_completion/templates/command.tmplt new file mode 100644 index 00000000..726b5f0a --- /dev/null +++ b/tools/bash_completion/templates/command.tmplt @@ -0,0 +1,37 @@ +__mbed_complete_{{COMMAND}}() { + + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$cur" in + --*) + __mbedcomp " + {{#DDASH_COMMANDS}} + {{name}} + {{/DDASH_COMMANDS}} + " + + return + ;; + -*) + __mbedcomp " + {{#DASH_COMMANDS}} + {{name}} + {{/DASH_COMMANDS}} + " + return + ;; + esac + + # Handle the dependent commands + {{#HAVE_PREV}} + case "$prev" in + {{#PREV_CASE}} + {{case}}) + {{code}} + return + ;; + {{/PREV_CASE}} + esac + {{/HAVE_PREV}} + +} diff --git a/tools/bash_completion/templates/ide.tmplt b/tools/bash_completion/templates/ide.tmplt new file mode 100644 index 00000000..99381803 --- /dev/null +++ b/tools/bash_completion/templates/ide.tmplt @@ -0,0 +1,2 @@ +declare IDES=$(mbed export --supported ides) + __mbedcomp "${IDES}" diff --git a/tools/bash_completion/templates/mbed.tmplt b/tools/bash_completion/templates/mbed.tmplt new file mode 100644 index 00000000..134c5c97 --- /dev/null +++ b/tools/bash_completion/templates/mbed.tmplt @@ -0,0 +1,51 @@ + +_mbed () { + local i=1 cmd prev + + prev="${COMP_WORDS[COMP_CWORD-1]}" + +# find the subcommand + while [[ "$i" -lt "$COMP_CWORD" ]] + do + local s="${COMP_WORDS[i]}" + case "$s" in + --*) + cmd="$s" + break + ;; + -*) + ;; + *) + cmd="$s" + break + ;; + esac + + i="$((++i))" + done + + # Handle the main command completions + if [[ "$i" -eq "$COMP_CWORD" ]] + then + local cmds=" + {{#COMMAND}} + {{name}} + {{/COMMAND}} + " + + __mbedcomp "${cmds}" + fi + + # Each subcommand has a completion function based on the parent + case "$cmd" in + {{#COMMAND}} + {{name}}) __mbed_complete_{{name}} ;; + {{/COMMAND}} + *) ;; + esac + +} + +complete -o bashdefault -o default -F _mbed mbed +complete -o bashdefault -o default -F _mbed mbed-cli + diff --git a/tools/bash_completion/templates/protocol.tmplt b/tools/bash_completion/templates/protocol.tmplt new file mode 100644 index 00000000..50744929 --- /dev/null +++ b/tools/bash_completion/templates/protocol.tmplt @@ -0,0 +1 @@ +__mbedcomp "https http ssh git" diff --git a/tools/bash_completion/templates/scm.tmplt b/tools/bash_completion/templates/scm.tmplt new file mode 100644 index 00000000..cc023b66 --- /dev/null +++ b/tools/bash_completion/templates/scm.tmplt @@ -0,0 +1 @@ +__mbedcomp "bld git hg" diff --git a/tools/bash_completion/templates/target.tmplt b/tools/bash_completion/templates/target.tmplt new file mode 100644 index 00000000..938a9bc2 --- /dev/null +++ b/tools/bash_completion/templates/target.tmplt @@ -0,0 +1,2 @@ +declare TARGETS=$(mbed compile --supported targets) + __mbedcomp "${TARGETS}" diff --git a/tools/bash_completion/templates/toolchain.tmplt b/tools/bash_completion/templates/toolchain.tmplt new file mode 100644 index 00000000..42a2a311 --- /dev/null +++ b/tools/bash_completion/templates/toolchain.tmplt @@ -0,0 +1,2 @@ +declare TOOLCHAINS=$(mbed compile --supported toolchains) + __mbedcomp "${TOOLCHAINS}"