Add Bash completion script (#60)
* Add completion script * Add introspection
This commit is contained in:
parent
eabf9091fb
commit
356c47a19f
6 changed files with 285 additions and 16 deletions
2
Makefile
2
Makefile
|
@ -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
19
completion/README.md
Normal 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
|
||||||
|
```
|
85
completion/yadm.bash_completion
Normal file
85
completion/yadm.bash_completion
Normal 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
|
99
test/115_accept_introspect.bats
Normal file
99
test/115_accept_introspect.bats
Normal 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
82
yadm
|
@ -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
14
yadm.1
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue