Skip to content

Commit 42d6e84

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 584b218 commit 42d6e84

File tree

6 files changed

+137
-5
lines changed

6 files changed

+137
-5
lines changed

meson.build

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,18 @@ if build_tools
573573
install_data('tools/xkbcli-zsh-completion.zsh',
574574
rename: '_xkbcli',
575575
install_dir: zsh_completion_path)
576+
install_data('tools/xkb-model-zsh-completion.zsh',
577+
rename: '_xkb_model',
578+
install_dir: zsh_completion_path)
579+
install_data('tools/xkb-layout-zsh-completion.zsh',
580+
rename: '_xkb_layout',
581+
install_dir: zsh_completion_path)
582+
install_data('tools/xkb-variant-zsh-completion.zsh',
583+
rename: '_xkb_variant',
584+
install_dir: zsh_completion_path)
585+
install_data('tools/xkb-options-zsh-completion.zsh',
586+
rename: '_xkb_options',
587+
install_dir: zsh_completion_path)
576588
endif
577589

578590
# 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: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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='.layouts[] | select(.variant != "") | "\(.layout)(\(.variant)):\(.description)"'
12+
local yq_prog2='.layouts[] | select(.variant != "") | "\(.variant):\(.description)"'
13+
local -a variants1 variants2
14+
variants1=( ${(@f)"$(printf '%s\n' $variants_yaml | _call_program -l xkb-parse-yaml yq ${(q)yq_prog1})"} )
15+
variants2=( ${(@f)"$(printf '%s\n' $variants_yaml | _call_program -l xkb-parse-yaml yq ${(q)yq_prog2})"} )
16+
17+
case $status in
18+
127 ) _message "xkb model completion requires yq" && return 127 ;;
19+
<1->) _message "error completing xkb variants" && return 1 ;;
20+
esac
21+
22+
_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)