mirror of
https://github.com/spf13/cobra
synced 2024-11-24 22:57:12 +00:00
Merge pull request #265 from sttts/sttts-shellcheck
Run shellcheck on bash completion
This commit is contained in:
commit
4c05eb1145
3 changed files with 51 additions and 15 deletions
|
@ -4,6 +4,10 @@ go:
|
||||||
- 1.4.2
|
- 1.4.2
|
||||||
- 1.5.1
|
- 1.5.1
|
||||||
- tip
|
- tip
|
||||||
|
before_install:
|
||||||
|
- mkdir -p bin
|
||||||
|
- curl -Lso bin/shellcheck https://github.com/caarlos0/shellcheck-docker/releases/download/v0.4.3/shellcheck
|
||||||
|
- chmod +x bin/shellcheck
|
||||||
script:
|
script:
|
||||||
- go test -v ./...
|
- PATH=$PATH:$PWD/bin go test -v ./...
|
||||||
- go build
|
- go build
|
||||||
|
|
|
@ -61,7 +61,7 @@ __contains_word()
|
||||||
|
|
||||||
__handle_reply()
|
__handle_reply()
|
||||||
{
|
{
|
||||||
__debug "${FUNCNAME}"
|
__debug "${FUNCNAME[0]}"
|
||||||
case $cur in
|
case $cur in
|
||||||
-*)
|
-*)
|
||||||
if [[ $(type -t compopt) = "builtin" ]]; then
|
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||||
|
@ -75,7 +75,7 @@ __handle_reply()
|
||||||
fi
|
fi
|
||||||
COMPREPLY=( $(compgen -W "${allflags[*]}" -- "$cur") )
|
COMPREPLY=( $(compgen -W "${allflags[*]}" -- "$cur") )
|
||||||
if [[ $(type -t compopt) = "builtin" ]]; then
|
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||||
[[ $COMPREPLY == *= ]] || compopt +o nospace
|
[[ "${COMPREPLY[0]}" == *= ]] || compopt +o nospace
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# complete after --flag=abc
|
# complete after --flag=abc
|
||||||
|
@ -88,11 +88,13 @@ __handle_reply()
|
||||||
flag="${cur%%=*}"
|
flag="${cur%%=*}"
|
||||||
__index_of_word "${flag}" "${flags_with_completion[@]}"
|
__index_of_word "${flag}" "${flags_with_completion[@]}"
|
||||||
if [[ ${index} -ge 0 ]]; then
|
if [[ ${index} -ge 0 ]]; then
|
||||||
COMPREPLY=() PREFIX="" cur="${cur#*=}"
|
COMPREPLY=()
|
||||||
|
PREFIX=""
|
||||||
|
cur="${cur#*=}"
|
||||||
${flags_completion[${index}]}
|
${flags_completion[${index}]}
|
||||||
if [ -n "${ZSH_VERSION}" ]; then
|
if [ -n "${ZSH_VERSION}" ]; then
|
||||||
# zfs completion needs --flag= prefix
|
# zfs completion needs --flag= prefix
|
||||||
eval COMPREPLY=( "\${COMPREPLY[@]/#/${flag}=}" )
|
eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
@ -149,7 +151,7 @@ __handle_subdirs_in_dir_flag()
|
||||||
|
|
||||||
__handle_flag()
|
__handle_flag()
|
||||||
{
|
{
|
||||||
__debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"
|
__debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
|
||||||
|
|
||||||
# if a command required a flag, and we found it, unset must_have_one_flag()
|
# if a command required a flag, and we found it, unset must_have_one_flag()
|
||||||
local flagname=${words[c]}
|
local flagname=${words[c]}
|
||||||
|
@ -160,15 +162,15 @@ __handle_flag()
|
||||||
flagname=${flagname%%=*} # strip everything after the =
|
flagname=${flagname%%=*} # strip everything after the =
|
||||||
flagname="${flagname}=" # but put the = back
|
flagname="${flagname}=" # but put the = back
|
||||||
fi
|
fi
|
||||||
__debug "${FUNCNAME}: looking for ${flagname}"
|
__debug "${FUNCNAME[0]}: looking for ${flagname}"
|
||||||
if __contains_word "${flagname}" "${must_have_one_flag[@]}"; then
|
if __contains_word "${flagname}" "${must_have_one_flag[@]}"; then
|
||||||
must_have_one_flag=()
|
must_have_one_flag=()
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# keep flag value with flagname as flaghash
|
# keep flag value with flagname as flaghash
|
||||||
if [ ${flagvalue} ] ; then
|
if [ -n "${flagvalue}" ] ; then
|
||||||
flaghash[${flagname}]=${flagvalue}
|
flaghash[${flagname}]=${flagvalue}
|
||||||
elif [ ${words[ $((c+1)) ]} ] ; then
|
elif [ -n "${words[ $((c+1)) ]}" ] ; then
|
||||||
flaghash[${flagname}]=${words[ $((c+1)) ]}
|
flaghash[${flagname}]=${words[ $((c+1)) ]}
|
||||||
else
|
else
|
||||||
flaghash[${flagname}]="true" # pad "true" for bool flag
|
flaghash[${flagname}]="true" # pad "true" for bool flag
|
||||||
|
@ -189,7 +191,7 @@ __handle_flag()
|
||||||
|
|
||||||
__handle_noun()
|
__handle_noun()
|
||||||
{
|
{
|
||||||
__debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"
|
__debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
|
||||||
|
|
||||||
if __contains_word "${words[c]}" "${must_have_one_noun[@]}"; then
|
if __contains_word "${words[c]}" "${must_have_one_noun[@]}"; then
|
||||||
must_have_one_noun=()
|
must_have_one_noun=()
|
||||||
|
@ -203,20 +205,20 @@ __handle_noun()
|
||||||
|
|
||||||
__handle_command()
|
__handle_command()
|
||||||
{
|
{
|
||||||
__debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"
|
__debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
|
||||||
|
|
||||||
local next_command
|
local next_command
|
||||||
if [[ -n ${last_command} ]]; then
|
if [[ -n ${last_command} ]]; then
|
||||||
next_command="_${last_command}_${words[c]//:/__}"
|
next_command="_${last_command}_${words[c]//:/__}"
|
||||||
else
|
else
|
||||||
if [[ $c -eq 0 ]]; then
|
if [[ $c -eq 0 ]]; then
|
||||||
next_command="_$(basename ${words[c]//:/__})"
|
next_command="_$(basename "${words[c]//:/__}")"
|
||||||
else
|
else
|
||||||
next_command="_${words[c]//:/__}"
|
next_command="_${words[c]//:/__}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
c=$((c+1))
|
c=$((c+1))
|
||||||
__debug "${FUNCNAME}: looking for ${next_command}"
|
__debug "${FUNCNAME[0]}: looking for ${next_command}"
|
||||||
declare -F $next_command >/dev/null && $next_command
|
declare -F $next_command >/dev/null && $next_command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,12 +228,12 @@ __handle_word()
|
||||||
__handle_reply
|
__handle_reply
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
__debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"
|
__debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}"
|
||||||
if [[ "${words[c]}" == -* ]]; then
|
if [[ "${words[c]}" == -* ]]; then
|
||||||
__handle_flag
|
__handle_flag
|
||||||
elif __contains_word "${words[c]}" "${commands[@]}"; then
|
elif __contains_word "${words[c]}" "${commands[@]}"; then
|
||||||
__handle_command
|
__handle_command
|
||||||
elif [[ $c -eq 0 ]] && __contains_word "$(basename ${words[c]})" "${commands[@]}"; then
|
elif [[ $c -eq 0 ]] && __contains_word "$(basename "${words[c]}")" "${commands[@]}"; then
|
||||||
__handle_command
|
__handle_command
|
||||||
else
|
else
|
||||||
__handle_noun
|
__handle_noun
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -23,6 +24,26 @@ func check(t *testing.T, found, expected string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func runShellCheck(s string) error {
|
||||||
|
excluded := []string{
|
||||||
|
"SC2034", // PREFIX appears unused. Verify it or export it.
|
||||||
|
}
|
||||||
|
cmd := exec.Command("shellcheck", "-s", "bash", "-", "-e", strings.Join(excluded, ","))
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
|
||||||
|
stdin, err := cmd.StdinPipe()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer stdin.Close()
|
||||||
|
stdin.Write([]byte(s))
|
||||||
|
}()
|
||||||
|
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
// World worst custom function, just keep telling you to enter hello!
|
// World worst custom function, just keep telling you to enter hello!
|
||||||
const (
|
const (
|
||||||
bashCompletionFunc = `__custom_func() {
|
bashCompletionFunc = `__custom_func() {
|
||||||
|
@ -107,4 +128,13 @@ func TestBashCompletions(t *testing.T) {
|
||||||
check(t, str, `flags_completion+=("__handle_subdirs_in_dir_flag themes")`)
|
check(t, str, `flags_completion+=("__handle_subdirs_in_dir_flag themes")`)
|
||||||
|
|
||||||
checkOmit(t, str, cmdDeprecated.Name())
|
checkOmit(t, str, cmdDeprecated.Name())
|
||||||
|
|
||||||
|
// if available, run shellcheck against the script
|
||||||
|
if err := exec.Command("which", "shellcheck").Run(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := runShellCheck(str)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("shellcheck failed: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue