Add Bash completion script (#60)

* Add completion script
* Add introspection
This commit is contained in:
Tim Byrne 2017-04-06 07:30:28 -05:00
parent eabf9091fb
commit 356c47a19f
No known key found for this signature in database
GPG Key ID: 14DB4FC2465A4B12
6 changed files with 285 additions and 16 deletions

View File

@ -29,7 +29,7 @@ bats:
shellcheck:
@echo Running shellcheck
@shellcheck --version || true
@shellcheck -s bash yadm bootstrap test/*.bash
@shellcheck -s bash yadm bootstrap test/*.bash completion/yadm.bash_completion
@cd test; \
for bats_file in *bats; do \
sed 's/^@test.*{/function test() {/' "$$bats_file" > "/tmp/$$bats_file.bash"; \

19
completion/README.md Normal file
View File

@ -0,0 +1,19 @@
# Prerequisites
**yadm** completion only works if Git completions are also enabled.
# Installation
## Homebrew
If using `homebrew` to install **yadm**, completions should automatically be handled if you also install `brew install bash-completion`. This might require you to include the main completion script in your own bashrc file like this:
```
[ -f /usr/local/etc/bash_completion ] && source /usr/local/etc/bash_completion
```
## Manual installation
Copy the completion script locally, and add this to you bashrc:
```
[ -f /full/path/to/yadm.bash_completion ] && source /full/path/to/yadm.bash_completion
```

View File

@ -0,0 +1,85 @@
# test if git completion is missing, but loader exists, attempt to load
if ! declare -F _git > /dev/null && declare -F _completion_loader > /dev/null; then
_completion_loader git
fi
# only operate if git completion is present
if declare -F _git > /dev/null; then
_yadm() {
local current=${COMP_WORDS[COMP_CWORD]}
local penultimate=${COMP_WORDS[COMP_CWORD-1]}
local antepenultimate=${COMP_WORDS[COMP_CWORD-2]}
local GIT_DIR
# shellcheck disable=SC2034
GIT_DIR="$(yadm introspect repo 2>/dev/null)"
case "$penultimate" in
bootstrap)
COMPREPLY=()
return 0
;;
config)
COMPREPLY=( $(compgen -W "$(yadm introspect configs 2>/dev/null)") )
return 0
;;
decrypt)
COMPREPLY=( $(compgen -W "-l" -- "$current") )
return 0
;;
init)
COMPREPLY=( $(compgen -W "-f -w" -- "$current") )
return 0
;;
introspect)
COMPREPLY=( $(compgen -W "commands configs repo switches" -- "$current") )
return 0
;;
help)
COMPREPLY=() # no specific help yet
return 0
;;
list)
COMPREPLY=( $(compgen -W "-a" -- "$current") )
return 0
;;
esac
case "$antepenultimate" in
clone)
COMPREPLY=( $(compgen -W "-f -w --bootstrap --no-bootstrap" -- "$current") )
return 0
;;
esac
# this condition is so files are completed properly for --yadm-xxx options
if [[ ! "$penultimate" =~ ^- ]]; then
# TODO: somehow solve the problem with [--yadm-xxx option] being
# incompatible with what git expects, namely [--arg=option]
_git
fi
if [[ "$current" =~ ^- ]]; then
local matching
matching=$(compgen -W "$(yadm introspect switches 2>/dev/null)" -- "$current")
__gitcompappend "$matching"
fi
if [ "$COMP_CWORD" == 1 ] || [[ "$antepenultimate" =~ ^- ]] ; then
local matching
matching=$(compgen -W "$(yadm introspect commands 2>/dev/null)" -- "$current")
__gitcompappend "$matching"
fi
# remove duplicates found in COMPREPLY (a native bash way could be better)
if [ -n "${COMPREPLY[*]}" ]; then
COMPREPLY=($(echo "${COMPREPLY[@]}" | sort -u))
fi
}
complete -o bashdefault -o default -F _yadm yadm 2>/dev/null \
|| complete -o default -F _yadm yadm
fi

View File

@ -0,0 +1,99 @@
load common
load_fixtures
status=;output=; #; populated by bats run()
function count_introspect() {
local category="$1"
local expected_status="$2"
local expected_words="$3"
local expected_regex="$4"
run "${T_YADM_Y[@]}" introspect "$category"
local output_words
output_words=$(wc -w <<< "$output")
if [ "$status" -ne "$expected_status" ]; then
echo "ERROR: Unexpected exit code (expected $expected_status, got $status)"
return 1;
fi
if [ "$output_words" -ne "$expected_words" ]; then
echo "ERROR: Unexpected number of output words (expected $expected_words, got $output_words)"
return 1;
fi
if [ -n "$expected_regex" ]; then
if [[ ! "$output" =~ $expected_regex ]]; then
echo "OUTPUT:$output"
echo "ERROR: Output does not match regex: $expected_regex"
return 1;
fi
fi
}
@test "Command 'introspect' (no category)" {
echo "
When 'introspect' command is provided,
And no category is provided
Produce no output
Exit with 0
"
count_introspect "" 0 0
}
@test "Command 'introspect' (invalid category)" {
echo "
When 'introspect' command is provided,
And an invalid category is provided
Produce no output
Exit with 0
"
count_introspect "invalid_cat" 0 0
}
@test "Command 'introspect' (commands)" {
echo "
When 'introspect' command is provided,
And category 'commands' is provided
Produce command list
Exit with 0
"
count_introspect "commands" 0 15 'version'
}
@test "Command 'introspect' (configs)" {
echo "
When 'introspect' command is provided,
And category 'configs' is provided
Produce switch list
Exit with 0
"
count_introspect "configs" 0 11 'yadm\.auto-alt'
}
@test "Command 'introspect' (repo)" {
echo "
When 'introspect' command is provided,
And category 'repo' is provided
Output repo
Exit with 0
"
count_introspect "repo" 0 1 "$T_DIR_REPO"
}
@test "Command 'introspect' (switches)" {
echo "
When 'introspect' command is provided,
And category 'switches' is provided
Produce switch list
Exit with 0
"
count_introspect "switches" 0 7 '--yadm-dir'
}

82
yadm
View File

@ -57,7 +57,7 @@ function main() {
#; parse command line arguments
local retval=0
internal_commands="^(alt|bootstrap|clean|clone|config|decrypt|encrypt|enter|help|init|list|perms|version)$"
internal_commands="^(alt|bootstrap|clean|clone|config|decrypt|encrypt|enter|help|init|introspect|list|perms|version)$"
if [ -z "$*" ] ; then
#; no argumnts will result in help()
help
@ -338,21 +338,13 @@ function config() {
if [ -z "$*" ] ; then
#; with no parameters, provide some helpful documentation
echo "yadm supports the following configurations:"
echo
for supported_config in $(introspect_configs); do
echo " ${supported_config}"
done
echo
cat << EOF
yadm supports the following configurations:
local.class
local.hostname
local.os
local.user
yadm.auto-alt
yadm.auto-perms
yadm.git-program
yadm.gpg-perms
yadm.gpg-program
yadm.gpg-recipient
yadm.ssh-perms
Please read the CONFIGURATION section in the man
page for more details about configurations, and
how to adjust them.
@ -558,6 +550,66 @@ function init() {
}
function introspect() {
case "$1" in
commands|configs|repo|switches)
"introspect_$1"
;;
esac
}
function introspect_commands() {
cat <<-EOF
alt
bootstrap
clean
clone
config
decrypt
encrypt
enter
gitconfig
help
init
introspect
list
perms
version
EOF
}
function introspect_configs() {
cat << EOF
local.class
local.hostname
local.os
local.user
yadm.auto-alt
yadm.auto-perms
yadm.git-program
yadm.gpg-perms
yadm.gpg-program
yadm.gpg-recipient
yadm.ssh-perms
EOF
}
function introspect_repo() {
echo "$YADM_REPO"
}
function introspect_switches() {
cat <<-EOF
--yadm-archive
--yadm-bootstrap
--yadm-config
--yadm-dir
--yadm-encrypt
--yadm-repo
-Y
EOF
}
function list() {
require_repo

14
yadm.1
View File

@ -49,6 +49,9 @@ list
.BR yadm " alt
.BR yadm " perms
.BR yadm " introspect
.I category
.SH DESCRIPTION
.B yadm
is a tool for managing a collection of files across multiple computers,
@ -242,6 +245,17 @@ Print a list of files managed by
option will cause all managed files to be listed.
Otherwise, the list will only include files from the current directory or below.
.TP
.BI introspect " category
Report internal
.B yadm
data. Supported categories are
.IR commands ,
.IR configs ,
.IR repo,
and
.IR switches .
The purpose of introspection is to support command line completion.
.TP
.B perms
Update permissions as described in the PERMISSIONS section.
It is usually unnecessary to run this command, as