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: shellcheck:
@echo Running shellcheck @echo Running shellcheck
@shellcheck --version || true @shellcheck --version || true
@shellcheck -s bash yadm bootstrap test/*.bash @shellcheck -s bash yadm bootstrap test/*.bash completion/yadm.bash_completion
@cd test; \ @cd test; \
for bats_file in *bats; do \ for bats_file in *bats; do \
sed 's/^@test.*{/function test() {/' "$$bats_file" > "/tmp/$$bats_file.bash"; \ 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 #; parse command line arguments
local retval=0 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 if [ -z "$*" ] ; then
#; no argumnts will result in help() #; no argumnts will result in help()
help help
@ -338,21 +338,13 @@ function config() {
if [ -z "$*" ] ; then if [ -z "$*" ] ; then
#; with no parameters, provide some helpful documentation #; 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 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 Please read the CONFIGURATION section in the man
page for more details about configurations, and page for more details about configurations, and
how to adjust them. 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() { function list() {
require_repo require_repo

14
yadm.1
View File

@ -49,6 +49,9 @@ list
.BR yadm " alt .BR yadm " alt
.BR yadm " perms .BR yadm " perms
.BR yadm " introspect
.I category
.SH DESCRIPTION .SH DESCRIPTION
.B yadm .B yadm
is a tool for managing a collection of files across multiple computers, 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. option will cause all managed files to be listed.
Otherwise, the list will only include files from the current directory or below. Otherwise, the list will only include files from the current directory or below.
.TP .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 .B perms
Update permissions as described in the PERMISSIONS section. Update permissions as described in the PERMISSIONS section.
It is usually unnecessary to run this command, as It is usually unnecessary to run this command, as