From 76451e52cc700b7a75e34bca014c853bb8b9cd7a Mon Sep 17 00:00:00 2001 From: Isaac Schaaf Date: Sun, 13 Jan 2019 16:02:53 -0800 Subject: [PATCH 1/5] WIP working on interface for completions --- bake-completion.sh | 8 +++++--- sandbox/Bakefile | 37 +++++++++++++++++++++++++++++++++++++ sandbox/Bakefile.completers | 28 ++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 sandbox/Bakefile create mode 100644 sandbox/Bakefile.completers diff --git a/bake-completion.sh b/bake-completion.sh index e926dd7..ef4a5fa 100644 --- a/bake-completion.sh +++ b/bake-completion.sh @@ -1,13 +1,15 @@ #!/usr/bin/env bash _bake () { - local cword cur tasks - _get_comp_words_by_ref -n : -c cur cword + local cword cur tasks words + _get_comp_words_by_ref -n : -c cur cword words tasks="$(bake | grep -v BAKEFILE | grep '^ ' | sed 's/^ //g' | cut -f1 -d' ')" if [[ "$cword" -eq "1" ]]; then mapfile -t COMPREPLY < <(compgen -W "$tasks" -- "$cur") else - mapfile -t COMPREPLY < <(compgen -o default -- "$cur") + source Bakefile.completers + local completion_fn="${words[1]}" # task name + mapfile -t COMPREPLY < <("$completion_fn.bake-completion" "$cur") fi # NB: this is a workaround for bash's default of splitting words on colons diff --git a/sandbox/Bakefile b/sandbox/Bakefile new file mode 100644 index 0000000..ee42528 --- /dev/null +++ b/sandbox/Bakefile @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +bake_supertask build "Various tasks for building the project" + +bake_subtask build frontend "build the frontend" +function build-frontend () { + echo "Building the frontend" +} + +# Kinda redundent to include a bake_task declaration +# but this is to show that it does not interfere with aliases +bake_task +function run.my.program () { + echo "lets run the program! $*" +} + +function run.completer () { + echo "hello world" +} + + +function run.tests () { + echo "Running tests!" +} + +function run.docker () { + command docker "$@" +} + + +# Alias the "run.my.program" function to "run" +bake_task_alias run run.my.program "Run the program [alias]" +bake_task_alias docker run.docker "call docker cli" + +# Aliases also allows us to create bake tasks with the same name +# as built in functions without overriding them +bake_task_alias test run.tests "Run the tests" diff --git a/sandbox/Bakefile.completers b/sandbox/Bakefile.completers new file mode 100644 index 0000000..60b4be5 --- /dev/null +++ b/sandbox/Bakefile.completers @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +function run () { + local cur cwords words + _get_comp_words_by_ref -n : -c cur cword words + compgen -W "hello world" -- "$cur" +} + +function docker.bake-completion () { + local cur cword words + _get_comp_words_by_ref -n : -c cur cword words + COMP_WORDS=( "${words[@]:1}" ) + COMP_LINE="${words[*]:1}" + COMP_POINT="${#COMP_LINE}" + COMP_CWORD="$(( cword - 1 ))" + # >&2 echo "COMP_WORDS=${COMP_WORDS[*]}" + # >&2 echo "COMP_LINE=$COMP_LINE" + # >&2 echo "COMP_POINT=$COMP_POINT" + # >&2 echo "COMP_CWORD=$COMP_CWORD" + _completion_loader docker + compgen -W "$(_docker; echo "${COMPREPLY[*]}")" -- "$cur" +} + + +# COMP_LINE +# COMP_WORDS +# COMP_POINT +# COMP_CWORD From aef6ab18c0dedc73fcd8df45a13cb3432b832bad Mon Sep 17 00:00:00 2001 From: Isaac Schaaf Date: Sun, 13 Jan 2019 17:47:42 -0800 Subject: [PATCH 2/5] added completion support using Bakefile.completions --- bake-completion.sh | 73 ++++++++++++++++++++++++++++++++++-- sandbox/Bakefile | 1 - sandbox/Bakefile.completers | 28 -------------- sandbox/Bakefile.completions | 8 ++++ 4 files changed, 77 insertions(+), 33 deletions(-) delete mode 100644 sandbox/Bakefile.completers create mode 100644 sandbox/Bakefile.completions diff --git a/bake-completion.sh b/bake-completion.sh index ef4a5fa..0acb2d1 100644 --- a/bake-completion.sh +++ b/bake-completion.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +BAKE_COMPLETIONS="${BAKE_COMPLETIONS:-Bakefile.completions}" + _bake () { local cword cur tasks words _get_comp_words_by_ref -n : -c cur cword words @@ -7,9 +9,22 @@ _bake () { if [[ "$cword" -eq "1" ]]; then mapfile -t COMPREPLY < <(compgen -W "$tasks" -- "$cur") else - source Bakefile.completers - local completion_fn="${words[1]}" # task name - mapfile -t COMPREPLY < <("$completion_fn.bake-completion" "$cur") + if [ -f "$BAKE_COMPLETIONS" ]; then + # shellcheck disable=SC1090 + source "$BAKE_COMPLETIONS" + else + mapfile -t COMPREPLY < <(compgen -o default -- "$cur") + return 0 + fi + + local completion_fn="_bake_completions_${words[1]}" # task name + if declare -F "$completion_fn" &>/dev/null; then + # complete using provided completer + mapfile -t COMPREPLY < <("$completion_fn" "$cur") + else + # fallback on default completer + mapfile -t COMPREPLY < <(compgen -o default -- "$cur") + fi fi # NB: this is a workaround for bash's default of splitting words on colons @@ -27,5 +42,55 @@ _bake () { } - complete -F _bake bake + +# +# Author: Brian Beffa +# Original source: https://brbsix.github.io/2015/11/29/accessing-tab-completion-programmatically-in-bash/ +# License: LGPLv3 (http://www.gnu.org/licenses/lgpl-3.0.txt) +# + +get_completions(){ + local completion COMP_CWORD COMP_LINE COMP_POINT COMP_WORDS COMPREPLY=() + + # load bash-completion if necessary + declare -F _completion_loader &>/dev/null || { + source /usr/share/bash-completion/bash_completion + } + + COMP_LINE=$* + COMP_POINT=${#COMP_LINE} + + eval set -- "$@" + + COMP_WORDS=("$@") + + # add '' to COMP_WORDS if the last character of the command line is a space + [[ ${COMP_LINE[*]: -1} = ' ' ]] && COMP_WORDS+=('') + + # index of the last word + COMP_CWORD=$(( ${#COMP_WORDS[@]} - 1 )) + + # determine completion function + completion=$(complete -p "$1" 2>/dev/null | awk '{print $(NF-1)}') + + # run _completion_loader only if necessary + [[ -n $completion ]] || { + + # load completion + _completion_loader "$1" + + # detect completion + completion=$(complete -p "$1" 2>/dev/null | awk '{print $(NF-1)}') + + } + + # ensure completion was detected + [[ -n $completion ]] || return 1 + + # execute completion function + "$completion" + + # print completions to stdout + printf '%s\n' "${COMPREPLY[@]}" | LC_ALL=C sort +} diff --git a/sandbox/Bakefile b/sandbox/Bakefile index ee42528..f0edd01 100644 --- a/sandbox/Bakefile +++ b/sandbox/Bakefile @@ -9,7 +9,6 @@ function build-frontend () { # Kinda redundent to include a bake_task declaration # but this is to show that it does not interfere with aliases -bake_task function run.my.program () { echo "lets run the program! $*" } diff --git a/sandbox/Bakefile.completers b/sandbox/Bakefile.completers deleted file mode 100644 index 60b4be5..0000000 --- a/sandbox/Bakefile.completers +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash - -function run () { - local cur cwords words - _get_comp_words_by_ref -n : -c cur cword words - compgen -W "hello world" -- "$cur" -} - -function docker.bake-completion () { - local cur cword words - _get_comp_words_by_ref -n : -c cur cword words - COMP_WORDS=( "${words[@]:1}" ) - COMP_LINE="${words[*]:1}" - COMP_POINT="${#COMP_LINE}" - COMP_CWORD="$(( cword - 1 ))" - # >&2 echo "COMP_WORDS=${COMP_WORDS[*]}" - # >&2 echo "COMP_LINE=$COMP_LINE" - # >&2 echo "COMP_POINT=$COMP_POINT" - # >&2 echo "COMP_CWORD=$COMP_CWORD" - _completion_loader docker - compgen -W "$(_docker; echo "${COMPREPLY[*]}")" -- "$cur" -} - - -# COMP_LINE -# COMP_WORDS -# COMP_POINT -# COMP_CWORD diff --git a/sandbox/Bakefile.completions b/sandbox/Bakefile.completions new file mode 100644 index 0000000..9451fe9 --- /dev/null +++ b/sandbox/Bakefile.completions @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +function _bake_completions_docker () { + local cur words docker_cmd + _get_comp_words_by_ref -n : -c cur words + docker_cmd=( "${words[@]:1}" ) + compgen -W "$(get_completions "${docker_cmd[@]}")" -- "$cur" +} From ced1cc4e23337db82e44769eef4c644e68f40f0e Mon Sep 17 00:00:00 2001 From: Isaac Schaaf Date: Sun, 13 Jan 2019 23:17:02 -0800 Subject: [PATCH 3/5] moved get_completions out of bake-completions --- bake-completion.sh | 52 +------------------------------------ sandbox/Bakefile.completers | 10 +++++++ sandbox/get_completions.sh | 50 +++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 51 deletions(-) create mode 100644 sandbox/Bakefile.completers create mode 100644 sandbox/get_completions.sh diff --git a/bake-completion.sh b/bake-completion.sh index 0acb2d1..9a87b0a 100644 --- a/bake-completion.sh +++ b/bake-completion.sh @@ -42,55 +42,5 @@ _bake () { } -complete -F _bake bake - -# -# Author: Brian Beffa -# Original source: https://brbsix.github.io/2015/11/29/accessing-tab-completion-programmatically-in-bash/ -# License: LGPLv3 (http://www.gnu.org/licenses/lgpl-3.0.txt) -# - -get_completions(){ - local completion COMP_CWORD COMP_LINE COMP_POINT COMP_WORDS COMPREPLY=() - - # load bash-completion if necessary - declare -F _completion_loader &>/dev/null || { - source /usr/share/bash-completion/bash_completion - } - - COMP_LINE=$* - COMP_POINT=${#COMP_LINE} - - eval set -- "$@" - - COMP_WORDS=("$@") - - # add '' to COMP_WORDS if the last character of the command line is a space - [[ ${COMP_LINE[*]: -1} = ' ' ]] && COMP_WORDS+=('') - - # index of the last word - COMP_CWORD=$(( ${#COMP_WORDS[@]} - 1 )) - # determine completion function - completion=$(complete -p "$1" 2>/dev/null | awk '{print $(NF-1)}') - - # run _completion_loader only if necessary - [[ -n $completion ]] || { - - # load completion - _completion_loader "$1" - - # detect completion - completion=$(complete -p "$1" 2>/dev/null | awk '{print $(NF-1)}') - - } - - # ensure completion was detected - [[ -n $completion ]] || return 1 - - # execute completion function - "$completion" - - # print completions to stdout - printf '%s\n' "${COMPREPLY[@]}" | LC_ALL=C sort -} +complete -F _bake bake diff --git a/sandbox/Bakefile.completers b/sandbox/Bakefile.completers new file mode 100644 index 0000000..52a3300 --- /dev/null +++ b/sandbox/Bakefile.completers @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +source get_completions.sh + +function _bake_completions_docker () { + local cur words docker_cmd + _get_comp_words_by_ref -n : -c cur words + docker_cmd=( "${words[@]:1}" ) + compgen -W "$(get_completions "${docker_cmd[@]}")" -- "$cur" +} diff --git a/sandbox/get_completions.sh b/sandbox/get_completions.sh new file mode 100644 index 0000000..2bbdb63 --- /dev/null +++ b/sandbox/get_completions.sh @@ -0,0 +1,50 @@ +# +# Author: Brian Beffa +# Original source: https://brbsix.github.io/2015/11/29/accessing-tab-completion-programmatically-in-bash/ +# License: LGPLv3 (http://www.gnu.org/licenses/lgpl-3.0.txt) +# + +get_completions(){ + local completion COMP_CWORD COMP_LINE COMP_POINT COMP_WORDS COMPREPLY=() + + # load bash-completion if necessary + declare -F _completion_loader &>/dev/null || { + source /usr/share/bash-completion/bash_completion + } + + COMP_LINE=$* + COMP_POINT=${#COMP_LINE} + + eval set -- "$@" + + COMP_WORDS=("$@") + + # add '' to COMP_WORDS if the last character of the command line is a space + [[ ${COMP_LINE[*]: -1} = ' ' ]] && COMP_WORDS+=('') + + # index of the last word + COMP_CWORD=$(( ${#COMP_WORDS[@]} - 1 )) + + # determine completion function + completion=$(complete -p "$1" 2>/dev/null | awk '{print $(NF-1)}') + + # run _completion_loader only if necessary + [[ -n $completion ]] || { + + # load completion + _completion_loader "$1" + + # detect completion + completion=$(complete -p "$1" 2>/dev/null | awk '{print $(NF-1)}') + + } + + # ensure completion was detected + [[ -n $completion ]] || return 1 + + # execute completion function + "$completion" + + # print completions to stdout + printf '%s\n' "${COMPREPLY[@]}" | LC_ALL=C sort +} From 958fbbb021fba72daf8c0d331005d7d112f69f0b Mon Sep 17 00:00:00 2001 From: Isaac Schaaf Date: Sun, 13 Jan 2019 23:17:55 -0800 Subject: [PATCH 4/5] removed extra file --- sandbox/Bakefile.completers | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 sandbox/Bakefile.completers diff --git a/sandbox/Bakefile.completers b/sandbox/Bakefile.completers deleted file mode 100644 index 52a3300..0000000 --- a/sandbox/Bakefile.completers +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -source get_completions.sh - -function _bake_completions_docker () { - local cur words docker_cmd - _get_comp_words_by_ref -n : -c cur words - docker_cmd=( "${words[@]:1}" ) - compgen -W "$(get_completions "${docker_cmd[@]}")" -- "$cur" -} From a40a67740d2f64131928ff0913b4c9b720efa835 Mon Sep 17 00:00:00 2001 From: Isaac Schaaf Date: Sun, 13 Jan 2019 23:25:07 -0800 Subject: [PATCH 5/5] cleaned out bakefile for completions --- sandbox/Bakefile | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/sandbox/Bakefile b/sandbox/Bakefile index f0edd01..1811ad7 100644 --- a/sandbox/Bakefile +++ b/sandbox/Bakefile @@ -1,36 +1,6 @@ #!/usr/bin/env bash -bake_supertask build "Various tasks for building the project" - -bake_subtask build frontend "build the frontend" -function build-frontend () { - echo "Building the frontend" -} - -# Kinda redundent to include a bake_task declaration -# but this is to show that it does not interfere with aliases -function run.my.program () { - echo "lets run the program! $*" -} - -function run.completer () { - echo "hello world" -} - - -function run.tests () { - echo "Running tests!" -} - -function run.docker () { +bake_task docker +function docker () { command docker "$@" } - - -# Alias the "run.my.program" function to "run" -bake_task_alias run run.my.program "Run the program [alias]" -bake_task_alias docker run.docker "call docker cli" - -# Aliases also allows us to create bake tasks with the same name -# as built in functions without overriding them -bake_task_alias test run.tests "Run the tests"