-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add bash programmable completion for vcgencmd
The completion file should be renamed "vcgencmd" and installed in /usr/share/bash-completion/completions/.
- Loading branch information
Showing
2 changed files
with
323 additions
and
0 deletions.
There are no files selected for viewing
199 changes: 199 additions & 0 deletions
199
host_applications/linux/apps/gencmd/vcgencmd-completion-test.bats
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
#!/usr/bin/env bats | ||
# Integration tests for vcgencmd command completion. | ||
# Runs on Raspberry Pi, requires bats-core package. | ||
|
||
load /usr/share/bash-completion/bash_completion || true | ||
load /usr/share/bash-completion/completions/vcgencmd | ||
|
||
|
||
complete_command() { | ||
local cmd="$*" | ||
|
||
COMP_LINE="${cmd}" | ||
mapfile -t COMP_WORDS < <( compgen -W "${cmd}" ) | ||
|
||
# index of current word in $COMP_WORDS array | ||
COMP_CWORD=$(( ${#COMP_WORDS[@]} - 1 )) | ||
if [[ ${cmd: -1} == " " ]]; then | ||
COMP_CWORD=$(( COMP_CWORD + 1 )) | ||
fi | ||
|
||
# current pointer position in line | ||
COMP_POINT="${#cmd}" | ||
|
||
# name of completion function | ||
complete_func=$(complete -p "${COMP_WORDS[0]}" | sed 's/.*-F \([^ ]*\) .*/\1/') | ||
[[ -n $complete_func ]] | ||
|
||
# Run completion function. Sets the COMPREPLY array. | ||
$complete_func "${COMP_WORDS[0]}" || true | ||
|
||
if [[ $DEBUG_VCGENCMD_TEST ]]; then | ||
echo >&3 | ||
echo "COMP_LINE='${COMP_LINE}'" >&3 | ||
echo "COMP_WORDS='${COMP_WORDS[*]}'" >&3 | ||
echo "length COMP_WORDS = ${#COMP_WORDS[@]}" >&3 | ||
echo "COMP_CWORD=${COMP_CWORD}" >&3 | ||
echo "COMP_POINT=${COMP_POINT}" >&3 | ||
echo "COMPREPLY=${COMPREPLY[*]}" >&3 | ||
echo "length COMPREPLY=${#COMPREPLY[@]}" >&3 | ||
fi | ||
} | ||
|
||
is_pi4() { | ||
grep -qE '^Model.* Raspberry Pi 4' /proc/cpuinfo | ||
} | ||
|
||
@test "vcgencmd - -> -t -h --help" { | ||
complete_command "vcgencmd -" | ||
[[ "${COMPREPLY[*]}" == "-t -h --help" ]] | ||
} | ||
|
||
@test "--h -> --help" { | ||
complete_command "vcgencmd --h" | ||
[[ "${COMPREPLY[*]}" == "--help" ]] | ||
} | ||
|
||
@test "--help -> (nothing)" { | ||
complete_command "vcgencmd --help " | ||
[[ "${#COMPREPLY[@]}" -eq 0 ]] | ||
} | ||
|
||
@test "vcgencmd -xxx -> (nothing)" { | ||
complete_command "vcgencmd -xxx " | ||
[[ "${#COMPREPLY[@]}" -eq 0 ]] | ||
} | ||
|
||
@test "vcgencmd foobar -> (nothing)" { | ||
complete_command "vcgencmd foobar " | ||
[[ "${#COMPREPLY[@]}" -eq 0 ]] | ||
} | ||
|
||
@test "vcgencmd -> commands version get_config measure_temp ..." { | ||
complete_command "vcgencmd " | ||
[[ "${#COMPREPLY[@]}" -gt 60 ]] | ||
echo "${COMPREPLY[*]}" | grep -Ewo "(commands|version|get_config|measure_temp)" | ||
} | ||
|
||
@test "vcgencmd -t -> commands version get_config measure_temp ..." { | ||
complete_command "vcgencmd -t " | ||
[[ "${#COMPREPLY[@]}" -gt 60 ]] | ||
echo "${COMPREPLY[*]}" | grep -Ewo "(commands|version|get_config|measure_temp)" | ||
} | ||
|
||
@test "codec_enabled -> FLAC MJPG ..." { | ||
complete_command "vcgencmd codec_enabled " | ||
echo "${COMPREPLY[*]}" | grep -Ewo "(FLAC|MJPG|H263|PCM|VORB)" | ||
} | ||
|
||
@test "measure_clock -> arm core uart ..." { | ||
complete_command "vcgencmd measure_clock " | ||
echo "${COMPREPLY[*]}" | grep -Ewo "(arm|core|uart|hdmi)" | ||
} | ||
|
||
@test "measure_volts -> core sdram_[cip]" { | ||
complete_command "vcgencmd measure_clock " | ||
echo "${COMPREPLY[*]}" | grep -Ewo "(core|sdram_[cip])" | ||
} | ||
|
||
@test "get_mem -> arm gpu" { | ||
complete_command "vcgencmd get_mem " | ||
echo "${COMPREPLY[*]}" | grep -Ewo "(arm|gpu)" | ||
} | ||
|
||
@test "get_config -> int str arm_freq ..." { | ||
complete_command "vcgencmd get_config " | ||
[[ "${#COMPREPLY[@]}" -gt 30 ]] | ||
echo "${COMPREPLY[*]}" | grep -Ewo "(int|str|device_tree|arm_freq|total_mem|hdmi_cvt:0|enable_tvout)" | ||
} | ||
|
||
@test "get_config hdmi_cvt: -> 0 1" { | ||
complete_command "vcgencmd get_config hdmi_cvt:" | ||
[[ "${COMPREPLY[*]}" == "0 1" ]] | ||
} | ||
|
||
# Pi 4B has two hdmi pixel freq limits 0 and 1, Pi 2 and 3 just have one | ||
@test "get_config hdmi_pixel_freq_li -> hdmi_pixel_freq_limit:0" { | ||
if is_pi4; then | ||
skip "test only valid with 1 hdmi (earlier pi models)" | ||
fi | ||
complete_command "vcgencmd get_config hdmi_pixel_freq_li" | ||
[[ "${COMPREPLY[*]}" == "hdmi_pixel_freq_limit:0" ]] | ||
} | ||
|
||
@test "get_config hdmi_pixel_freq_li -> hdmi_pixel_freq_limit:" { | ||
if ! is_pi4; then | ||
skip "test requires Pi 4 with 2 hdmi outputs" | ||
fi | ||
complete_command "vcgencmd get_config hdmi_pixel_freq_li" | ||
[[ "${COMPREPLY[*]}" == "hdmi_pixel_freq_limit:0 hdmi_pixel_freq_limit:1" ]] | ||
} | ||
|
||
@test "get_config hdmi_pixel_freq_limit: -> 0 1" { | ||
if ! is_pi4; then | ||
skip "test requires Pi 4 with 2 hdmi outputs" | ||
fi | ||
complete_command "vcgencmd get_config hdmi_pixel_freq_limit:" | ||
[[ "${COMPREPLY[*]}" == "0 1" ]] | ||
} | ||
|
||
@test "vcos -> version log" { | ||
complete_command "vcgencmd vcos " | ||
echo "${COMPREPLY[*]}" | grep -Ewo "(version|log)" | ||
} | ||
|
||
@test "display_power -> 0 1 -1" { | ||
complete_command "vcgencmd display_power " | ||
[[ "${COMPREPLY[*]}" == "0 1 -1" ]] | ||
} | ||
|
||
@test "-t display_power -> 0 1 -1" { | ||
complete_command "vcgencmd -t display_power " | ||
[[ "${COMPREPLY[*]}" == "0 1 -1" ]] | ||
} | ||
|
||
@test "display_power [0, 1] -> 0 1 2 3 7" { | ||
local display_nums="0 1 2 3 7" | ||
complete_command "vcgencmd display_power 0 " | ||
[[ "${COMPREPLY[*]}" == "$display_nums" ]] | ||
complete_command "vcgencmd display_power 1 " | ||
[[ "${COMPREPLY[*]}" == "$display_nums" ]] | ||
} | ||
|
||
@test "display_power -1 -> 0 1 2 3 7" { | ||
local display_nums="0 1 2 3 7" | ||
complete_command "vcgencmd display_power -1 " | ||
[[ "${COMPREPLY[*]}" == "$display_nums" ]] | ||
} | ||
|
||
@test "BADARG display_power -1 -> (nothing)" { | ||
complete_command "vcgencmd BADARG display_power -1 " | ||
echo "${COMPREPLY[*]}" | ||
[[ "${COMPREPLY[*]}" == "" ]] | ||
} | ||
|
||
@test "display_power BADARG -1 -> (nothing)" { | ||
complete_command "vcgencmd display_power BADARG -1 " | ||
echo "${COMPREPLY[*]}" | ||
[[ "${COMPREPLY[*]}" == "" ]] | ||
} | ||
|
||
@test "-t display_power -1 -> 0 1 2 3 7" { | ||
complete_command "vcgencmd -t display_power -1 " | ||
[[ "${COMPREPLY[*]}" == "0 1 2 3 7" ]] | ||
} | ||
|
||
@test "vcos log -> status" { | ||
complete_command "vcgencmd vcos log " | ||
[[ "${COMPREPLY[*]}" == "status" ]] | ||
} | ||
|
||
@test "-t vcos log -> status" { | ||
complete_command "vcgencmd -t vcos log " | ||
[[ "${COMPREPLY[*]}" == "status" ]] | ||
} | ||
|
||
@test "vcos 0 -> (nothing)" { | ||
complete_command "vcgencmd vcos 0 " | ||
[[ "${#COMPREPLY[@]}" -eq 0 ]] | ||
} |
124 changes: 124 additions & 0 deletions
124
host_applications/linux/apps/gencmd/vcgencmd-completion.bash
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
# vcgencmd(1) completion -*- shell-script -*- | ||
|
||
_vcgencmd_commands() | ||
{ | ||
local commands fallback re | ||
commands="$(/usr/bin/vcgencmd commands 2> /dev/null)" | ||
fallback="codec_enabled commands display_power get_camera get_config | ||
get_lcd_info get_mem get_throttled measure_temp measure_volts | ||
mem_oom version" | ||
re='commands="(.*)"' | ||
|
||
if [[ $commands =~ $re ]]; then | ||
commands="${BASH_REMATCH[1]}" | ||
commands="${commands//,}" | ||
else | ||
commands="${fallback}" | ||
fi | ||
|
||
compgen -W "$commands" -- "$cur" | ||
} | ||
|
||
# This function counts the number of args, excluding options, | ||
# providing exceptions for option-like arguments. | ||
# @param $1 chars Characters out of $COMP_WORDBREAKS which should | ||
# NOT be considered word breaks. See __reassemble_comp_words_by_ref. | ||
# @param $2 non_opt_args arguments that look like options, but aren't | ||
_vcgencmd_count_args() | ||
{ | ||
local i cword words non_opt_args | ||
__reassemble_comp_words_by_ref "$1" words cword | ||
|
||
args=1 | ||
non_opt_args="$2" | ||
|
||
for i in "${words[@]:1:cword-1}"; do | ||
if [[ "$i" != -* ]]; then | ||
args=$((args+1)) | ||
else | ||
for a in $non_opt_args; do | ||
[[ "$i" == "$a" ]] && args=$((args+1)) | ||
done | ||
fi | ||
done | ||
} | ||
|
||
_vcgencmd() { | ||
local cur prev cword words opts='' args | ||
_init_completion -n ':' || return | ||
_vcgencmd_count_args ':' '-1' | ||
|
||
if [[ $cword -eq 1 && $cur == -* ]] ; then | ||
mapfile -t COMPREPLY < <( compgen -W '-t -h --help' -- "$cur" ) | ||
return 0 | ||
fi | ||
|
||
if [[ $args -eq 1 ]]; then | ||
case "$prev" in | ||
-h|--help) | ||
;; | ||
-t|vcgencmd) | ||
mapfile -t COMPREPLY < <( _vcgencmd_commands ) | ||
;; | ||
-*) | ||
;; | ||
esac | ||
return 0 | ||
fi | ||
|
||
if [[ $args -eq 2 ]]; then | ||
case "$prev" in | ||
codec_enabled) | ||
opts='AGIF FLAC H263 H264 MJPA MJPB MJPG MPG2 MPG4 MVC0 PCM | ||
THRA VORB VP6 VP8 WMV9 WVC1' | ||
;; | ||
measure_clock) | ||
opts='arm core h264 isp v3d uart pwm emmc pixel vec hdmi dpi' | ||
;; | ||
measure_volts) | ||
opts='core sdram_c sdram_i sdram_p' | ||
;; | ||
get_mem) | ||
opts='arm gpu' | ||
;; | ||
get_config) | ||
opts='int str' | ||
opts+=" $("$1" get_config str | command sed -e 's/=.*$//')" | ||
opts+=" $("$1" get_config int | command sed -e 's/=.*$//')" | ||
;; | ||
display_power) | ||
opts='0 1 -1' | ||
;; | ||
vcos) | ||
opts='log version' | ||
;; | ||
esac | ||
fi | ||
|
||
if [[ $args -eq 3 ]]; then | ||
case "${words[cword - 2]}" in | ||
display_power) | ||
case "$prev" in | ||
0|1|-1) | ||
opts='0 1 2 3 7' | ||
;; | ||
esac | ||
;; | ||
vcos) | ||
case "$prev" in | ||
log) | ||
opts='status' | ||
;; | ||
esac | ||
;; | ||
esac | ||
fi | ||
|
||
[[ -n $opts ]] && mapfile -t COMPREPLY < <( compgen -W "$opts" -- "$cur" ) | ||
[[ $prev == "get_config" ]] && __ltrim_colon_completions "$cur" | ||
|
||
return 0 | ||
} && | ||
complete -F _vcgencmd vcgencmd | ||
|
||
# ex: filetype=sh |