From 7f7275550d43bdfa787e2cd1cd3e56b083ffeaf1 Mon Sep 17 00:00:00 2001 From: JP Bochi Date: Fri, 23 Sep 2022 23:34:55 -0400 Subject: [PATCH] Allow bash completion to complete tasks in other directories (#1303) --- .github/workflows/ci.yaml | 1 + completions/just.bash | 9 ++- src/completions.rs | 9 ++- tests/completions/just.bash | 102 ++++++++++++++++++++++++++++++ tests/completions/justfile | 5 ++ tests/completions/subdir/justfile | 2 + 6 files changed, 126 insertions(+), 2 deletions(-) create mode 100755 tests/completions/just.bash create mode 100755 tests/completions/justfile create mode 100755 tests/completions/subdir/justfile diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3f3cfc4..ee7331e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -66,6 +66,7 @@ jobs: run: | ./bin/generate-completions git diff --no-ext-diff --quiet --exit-code + ./tests/completions/just.bash - name: Check for Forbidden Words if: ${{ matrix.os == 'ubuntu-latest' }} diff --git a/completions/just.bash b/completions/just.bash index 8ef93b6..59d118a 100644 --- a/completions/just.bash +++ b/completions/just.bash @@ -25,7 +25,14 @@ _just() { COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 elif [[ ${COMP_CWORD} -eq 1 ]]; then - local recipes=$(just --summary --color never 2> /dev/null) + local recipes=$(just --summary 2> /dev/null) + + if echo "${cur}" | grep -qF '/'; then + local path_prefix=$(echo "${cur}" | sed 's/[/][^/]*$/\//') + local recipes=$(just --summary 2> /dev/null -- "${path_prefix}") + local recipes=$(printf "${path_prefix}%s\t" $recipes) + fi + if [[ $? -eq 0 ]]; then COMPREPLY=( $(compgen -W "${recipes}" -- "${cur}") ) return 0 diff --git a/src/completions.rs b/src/completions.rs index 5292e67..2897ceb 100644 --- a/src/completions.rs +++ b/src/completions.rs @@ -166,7 +166,14 @@ pub(crate) const BASH_COMPLETION_REPLACEMENTS: &[(&str, &str)] = &[ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 elif [[ ${COMP_CWORD} -eq 1 ]]; then - local recipes=$(just --summary --color never 2> /dev/null) + local recipes=$(just --summary 2> /dev/null) + + if echo "${cur}" | grep -qF '/'; then + local path_prefix=$(echo "${cur}" | sed 's/[/][^/]*$/\//') + local recipes=$(just --summary 2> /dev/null -- "${path_prefix}") + local recipes=$(printf "${path_prefix}%s\t" $recipes) + fi + if [[ $? -eq 0 ]]; then COMPREPLY=( $(compgen -W "${recipes}" -- "${cur}") ) return 0 diff --git a/tests/completions/just.bash b/tests/completions/just.bash new file mode 100755 index 0000000..d9c74bb --- /dev/null +++ b/tests/completions/just.bash @@ -0,0 +1,102 @@ +#!/usr/bin/env bash + +# --- Shared functions --- + +cdroot() { + cd "$(git rev-parse --show-toplevel)" > /dev/null +} + +setup() { + cdroot + cd tests/completions > /dev/null +} + +cleanup() { + unset COMP_WORDS + unset COMP_CWORD + unset COMPREPLY +} + +reply_equals() { + local reply=$(declare -p COMPREPLY) + local expected="$1" + + if [ "$reply" = "$expected" ]; then + echo "${FUNCNAME[1]}: ok" + else + exit_code='1' + echo >&2 "${FUNCNAME[1]}: failed! Completion for \`${COMP_WORDS[*]}\` does not match." + + echo + diff -U3 --label expected <(echo "$expected") --label actual <(echo "$reply") >&2 + echo + fi +} + +# --- Initial Setup --- +cdroot +source ./completions/just.bash +PATH="$(git rev-parse --show-toplevel)/target/debug:$PATH" +exit_code='0' + +# --- Tests --- + +test_just_is_accessible() { + if just --version > /dev/null; then + echo "${FUNCNAME[0]}: ok" + else + echo "${FUNCNAME[0]}: failed! Can't find just binary." + echo " PATH=$PATH" + echo + exit_code='1' + fi +} +setup +test_just_is_accessible + +test_complete_all_recipes() { + COMP_WORDS=(just) + COMP_CWORD=1 _just just + reply_equals 'declare -a COMPREPLY=([0]="deploy" [1]="install" [2]="publish" [3]="push" [4]="test")' +} +cleanup +setup +test_complete_all_recipes + +test_complete_recipes_starting_with_i() { + COMP_WORDS=(just i) + COMP_CWORD=1 _just just + reply_equals 'declare -a COMPREPLY=([0]="install")' +} +cleanup +setup +test_complete_recipes_starting_with_i + +test_complete_recipes_starting_with_p() { + setup + COMP_WORDS=(just p) + COMP_CWORD=1 _just just + reply_equals 'declare -a COMPREPLY=([0]="publish" [1]="push")' +} +cleanup +setup +test_complete_recipes_starting_with_p + +test_complete_recipes_from_subdirs() { + COMP_WORDS=(just subdir/) + COMP_CWORD=1 _just just + reply_equals 'declare -a COMPREPLY=([0]="subdir/special" [1]="subdir/surprise")' +} +cleanup +setup +test_complete_recipes_from_subdirs +cleanup + +# --- Conclusion --- + +if [ "$exit_code" = '0' ]; then + echo "All tests passed." +else + echo "Some test[s] failed." +fi +exit "$exit_code" diff --git a/tests/completions/justfile b/tests/completions/justfile new file mode 100755 index 0000000..e075d04 --- /dev/null +++ b/tests/completions/justfile @@ -0,0 +1,5 @@ +install: +test: +deploy: +push: +publish: diff --git a/tests/completions/subdir/justfile b/tests/completions/subdir/justfile new file mode 100755 index 0000000..1d4e289 --- /dev/null +++ b/tests/completions/subdir/justfile @@ -0,0 +1,2 @@ +special: +surprise: