Skip to content

Commit e3651a0

Browse files
committed
tools: add zsh completion for RMLVO components
To spare parsing yaml output in zsh code, these completers rely on yq to parse the xkbcli output. If yq is not installed, the completion will fallback to a more rudimentary version using only sed for parsing.
1 parent 66d91e5 commit e3651a0

File tree

6 files changed

+146
-5
lines changed

6 files changed

+146
-5
lines changed

meson.build

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,18 @@ if build_tools
663663
install_data('tools/xkbcli-zsh-completion.zsh',
664664
rename: '_xkbcli',
665665
install_dir: zsh_completion_path)
666+
install_data('tools/xkb-model-zsh-completion.zsh',
667+
rename: '_xkb_model',
668+
install_dir: zsh_completion_path)
669+
install_data('tools/xkb-layout-zsh-completion.zsh',
670+
rename: '_xkb_layout',
671+
install_dir: zsh_completion_path)
672+
install_data('tools/xkb-variant-zsh-completion.zsh',
673+
rename: '_xkb_variant',
674+
install_dir: zsh_completion_path)
675+
install_data('tools/xkb-options-zsh-completion.zsh',
676+
rename: '_xkb_options',
677+
install_dir: zsh_completion_path)
666678
endif
667679

668680
# Tool: compile-keymap
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#compdef -value-,XKB_DEFAULT_LAYOUT,-default-
2+
3+
local layouts_yaml
4+
layouts_yaml="$(_call_program -l xkb-yaml xkbcli list)"
5+
6+
case $status in
7+
127 ) _message "xkb layout completion requires xkbcli" && return 127 ;;
8+
<1->) _message "error listing xkb layouts" && return 1 ;;
9+
esac
10+
11+
local yq_prog='.layouts[] | select(.variant == "") | "\(.layout):\(.description)"'
12+
local -a xkb_layouts
13+
xkb_layouts=( ${(@f)"$(printf '%s\n' $layouts_yaml | _call_program -l xkb-parse-yaml yq ${(q)yq_prog})"} )
14+
15+
case $status in
16+
127)
17+
local sed_layouts='/^layouts:/,/^$/p'
18+
local sed_names="s/- layout: '([^']+)'/\\1/p" sed_variant="s/ variant: '([^']*)'/v\1/p" sed_descs="s/ description: //p"
19+
local layouts_sed="$(_call_program -l sed sed -n ${(q)sed_layouts} <<< $layouts_yaml)"
20+
local -a layout_names=( ${(@f)"$(_call_program -l sed-names sed -En ${(q)sed_names} <<< $layouts_sed)"} )
21+
local -a layout_variants=( ${(@f)"$(_call_program -l sed-variant sed -En ${(q)sed_variant} <<< $layouts_sed)"} )
22+
local -a layout_descs=( ${(@f)"$(_call_program -l sed-descs sed -n ${(q)sed_descs} <<< $layouts_sed)"} )
23+
local -a xkb_layouts1 xkb_layouts2
24+
printf -v xkb_layouts1 '%s:%s' ${layout_names:^layout_variants}
25+
printf -v xkb_layouts2 '%s:%s' ${xkb_layouts1:^layout_descs}
26+
xkb_layouts=( ${${(M)xkb_layouts2:#*:v:*}:s/:v:/:} )
27+
;;
28+
<1->) _message "error completing xkb layouts" && return 1 ;;
29+
esac
30+
31+
_describe -t xkb-layout 'xkb layout' xkb_layouts "$@"

tools/xkb-model-zsh-completion.zsh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#compdef -value-,XKB_DEFAULT_MODEL,-default-
2+
3+
local models_yaml
4+
models_yaml="$(_call_program -l xkb-yaml xkbcli list)"
5+
6+
case $status in
7+
127 ) _message "xkb model completion requires xkbcli" && return 127 ;;
8+
<1->) _message "error listing xkb models" && return 1 ;;
9+
esac
10+
11+
local yq_prog='.models[] | "\(.name):\(.description)"'
12+
local -a models
13+
models=( ${(@f)"$(printf '%s\n' $models_yaml | _call_program -l xkb-parse-yaml yq ${(q)yq_prog})"} )
14+
case $status in
15+
127)
16+
local sed_models='/^models:/,/^$/p' sed_names='s/- name: //p' sed_descriptions='s/ description: //p'
17+
local models_sed="$(_call_program -l sed sed -n ${(q)sed_models} <<< $models_yaml)"
18+
local -a model_names=( ${(@f)"$(_call_program -l sed-names sed -n ${(q)sed_names} <<< $models_sed)"})
19+
local -a model_descriptions=( ${(@f)"$(_call_program -l sed-models sed -n ${(q)sed_descriptions} <<< $models_sed)"})
20+
printf -v models '%s:%s' ${model_names:^model_descriptions}
21+
;;
22+
23+
<1->) _message "error completing xkb models" && return 1 ;;
24+
esac
25+
26+
_describe -t xkb-model 'xkb model' models "$@"
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#compdef -value-,XKB_DEFAULT_OPTIONS,-default-
2+
3+
local options_yaml
4+
options_yaml="$(_call_program -l xkb-yaml xkbcli list)"
5+
6+
case $status in
7+
127 ) _message "xkb option completion requires xkbcli" && return 127 ;;
8+
<1->) _message "error listing xkb options" && return 1 ;;
9+
esac
10+
11+
local yq_prog='.option_groups[] as $grp | $grp.options[].name | sub(":.*", "") as $name | "*\($name)[\($grp.description)]: :->option-\($name)"'
12+
local -Ua option_groups
13+
option_groups=( ${(@f)"$(printf '%s\n' $options_yaml | _call_program -l xkb-parse-yaml yq ${(q)yq_prog})"} )
14+
15+
case $status in
16+
127 )
17+
# fallback with sed
18+
local sed_options='/^option_groups:/,/^$/p'
19+
local sed_names="s/ - name: '([^']+)'/\\1/p" sed_descs="s/ description: '([^']+)'/\\1/p"
20+
local options_sed="$(printf '%s\n' $options_yaml | _call_program -l sed sed -n ${(q)sed_options})"
21+
local -a options_names=( ${(@f)"$(_call_program -l sed-names sed -En ${(q)sed_names} <<< $options_sed)"})
22+
local -a options_descs=( ${(@f)"$(_call_program -l sed-desc sed -En ${(q)sed_descs} <<< $options_sed)"})
23+
local -a xkb_options
24+
printf -v xkb_options '%s:%s' ${${options_names:s/:/\\:}:^options_descs}
25+
_describe -t xkb-option 'xkb option' xkb_options
26+
return
27+
;;
28+
<1->) _message "error completing xkb options" && return 1 ;;
29+
esac
30+
31+
local context state state_descr line
32+
typeset -A val_args
33+
34+
_values -s, -S: 'xkb option' ${option_groups}
35+
if [[ $state == option-* ]]; then
36+
local optname=${state#option-}
37+
local -a xkb_options
38+
yq_prog='.option_groups[].options[] | select(.name | test("'$optname'" + ":")) | "\(.name):\(.description)"'
39+
xkb_options=( ${${(@f)"$(printf '%s\n' $options_yaml | _call_program -l xkb-parse-yaml yq ${(q)yq_prog})"}#*:} )
40+
_describe -t xkb-option 'xkb option' xkb_options -qS,
41+
fi
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#compdef -value-,XKB_DEFAULT_VARIANT,-default-
2+
3+
local variants_yaml
4+
variants_yaml="$(_call_program -l xkb-yaml xkbcli list)"
5+
6+
case $status in
7+
127 ) _message "xkb model completion requires xkbcli" && return 127 ;;
8+
<1->) _message "error listing xkb variants" && return 1 ;;
9+
esac
10+
11+
local yq_prog1 yq_prog2 layout=${(v)opt_args[(I)*layout]}
12+
if [[ ${(t)opt_args} == *association* && -n $layout ]]; then
13+
# If we're called from _arguments this will attempt to match the layout
14+
# given in any --layout option previously seen on the command line
15+
yq_prog1='.layouts[] | select(.variant != "" and .layout == '${(qqq)${(Q)layout}}') | "\(.layout)(\(.variant)):\(.description)"'
16+
yq_prog2='.layouts[] | select(.variant != "" and .layout == '${(qqq)${(Q)layout}}') | "\(.variant):\(.description)"'
17+
else
18+
yq_prog1='.layouts[] | select(.variant != "") | "\(.layout)(\(.variant)):\(.description)"'
19+
yq_prog2='.layouts[] | select(.variant != "") | "\(.variant):\(.description)"'
20+
fi
21+
22+
local -a variants1 variants2
23+
variants1=( ${(@f)"$(printf '%s\n' $variants_yaml | _call_program -l xkb-parse-yaml yq ${(q)yq_prog1})"} )
24+
variants2=( ${(@f)"$(printf '%s\n' $variants_yaml | _call_program -l xkb-parse-yaml yq ${(q)yq_prog2})"} )
25+
26+
case $status in
27+
127 ) _message "xkb model completion requires yq" && return 127 ;;
28+
<1->) _message "error completing xkb variants" && return 1 ;;
29+
esac
30+
31+
_describe -t xkb-model 'xkb model' variants1 variants2 "$@"

tools/xkbcli-zsh-completion.zsh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ _xkbcli_commands() {
2323
}
2424

2525
local -a rmlvo_opts_common=(
26-
'--rules=[the XKB ruleset]:rules:()'
27-
'--model=[the XKB model]:model:()'
28-
'--layout=[the XKB layout]:layout:()'
29-
'--variant=[the XKB variant]:variant:()'
30-
'--options=[the XKB options]:options:()'
26+
'--rules=[the XKB ruleset]:rules:(base evdev)'
27+
'--model=[the XKB model]:model:_xkb_model'
28+
'--layout=[the XKB layout]:layout:_xkb_layout'
29+
'--variant=[the XKB variant]:variant:_xkb_variant'
30+
'--options=[the XKB options]:options:_xkb_options'
3131
'--enable-environment-names[set the default RMLVO values from the environment]'
3232
)
3333

0 commit comments

Comments
 (0)