about summary refs log tree commit diff
path: root/Completion/X
diff options
context:
space:
mode:
authorOliver Kiddle <opk@zsh.org>2024-08-31 11:58:33 +0200
committerOliver Kiddle <opk@zsh.org>2024-08-31 11:58:33 +0200
commit678fb68879e52a7e608dbbb859f98c2f9ff171eb (patch)
tree2cbf074fe539c21bba4080e717b6f1044a13edc3 /Completion/X
parent606ef4b430a8848e89e07dbc3e3db47fc019a505 (diff)
downloadzsh-678fb68879e52a7e608dbbb859f98c2f9ff171eb.tar.gz
zsh-678fb68879e52a7e608dbbb859f98c2f9ff171eb.tar.xz
zsh-678fb68879e52a7e608dbbb859f98c2f9ff171eb.zip
53052: update setxkbmap completion with newer options
Diffstat (limited to 'Completion/X')
-rw-r--r--Completion/X/Command/_setxkbmap210
1 files changed, 114 insertions, 96 deletions
diff --git a/Completion/X/Command/_setxkbmap b/Completion/X/Command/_setxkbmap
index 882a6f939..0850d5419 100644
--- a/Completion/X/Command/_setxkbmap
+++ b/Completion/X/Command/_setxkbmap
@@ -1,101 +1,119 @@
 #compdef setxkbmap
 
-# TODO:
-# model, option, symbols and types suggestions
-# take -layout and -variant into account
-
-_setxkbmap() {
-    emulate -L zsh
-    setopt extendedglob
-
-    # xkb files may be in different places depending on system
-    local dir sourcedir fullname
-    local -a searchdirs=(${XDG_DATA_HOME:-~/.local/share} ${(s.:.)XDG_DATA_DIRS:-/usr/lib:/usr/share:/usr/local/lib:/usr/local/share})
-    for dir in $searchdirs; do
-        fullname="$dir/X11/xkb"
-        if [ -d $fullname ] ; then
-           sourcedir=$fullname
-           break
-        fi
-    done
-    [ -d $sourcedir ] || return 1
-
-    local -a arguments
-
-    arguments=(
-        '-compat[compatibility map]:compatibility:_setxkbmap_compat'
-        '-config[configuration file]:configuration:_files'
-        '-display[display]:display:_x_display'
-        '-geometry[geometry component]:geometry:_setxkbmap_geometry'
-        '-model[model name]:model:'
-        '-option[xkb option]:option:'
-        '(-)'-print'[print component names]'
-        '-rules[rules file]:rules:_files'
-        '-symbols[symbols components]:symbols:'
-        '(-)'{-help,-h}'[display help message]'
-        '-synch[force synchronization]'
-        '-types[types components]:types:'
-        '(-verbose -v)'{-verbose,-v}'[set verbosity level]:verbosity:(0 1 2 3 4 5 6 7 8 9)'
-        '*::keyboard:_setxkbmap_dispatcher'
+local curcontext="$curcontext" sourcedir layout ret=1
+local -a state state_descr line expl matches suf
+local -A opt_args
+
+_arguments -C \
+  '(-)'{-\?,-help}'[display help message]' \
+  '-compat[compatibility map]:compatibility:->compatmaps' \
+  '-config[configuration file]:configuration:_files' \
+  '-device[specify numeric id of the input device]:device:->devices' \
+  '-display[display]:display:_x_display' \
+  '-geometry[geometry component]:geometry:->geometries' \
+  '*-I+[add a directory to be searched for layout or rules files]: :_directories' \
+  '-keycodes[specify keycodes component name]:name' \
+  '-keymap[specify keymap to load]:keymap' \
+  '-layout[specify layout used to choose component names]:layout:->layouts' \
+  '-model[specify model used to choose component names]:model:->models' \
+  '*-option[add an xkb option]:option:->options' \
+  '(-)'-print'[print a complete xkb_keymap description]' \
+  '-query[print the current layout settings]' \
+  '-rules[specify rules file to use]:rules:->rules' \
+  '-symbols[specify symbols component name]:symbol' \
+  '-synch[force synchronization]' \
+  '-types[types components]:type:->types' \
+  '(-verbose -v)'{-verbose,-v}'[set verbosity level]:verbosity:(0 1 2 3 4 5 6 7 8 9)' \
+  '(-)-version[display version information]' \
+  '-variant[specify layout variant used to choose component name]:variant:->variants' \
+  '1:layout:->layouts' \
+  '2:variant:->variants' \
+  '*:option:->options' && ret=0
+
+if [[ -n $state ]]; then
+  local open='(' close=')'
+  compquote open close
+
+  layout=${opt_args[-layout]:-$line[1]}
+  if [[ $state = layouts ]]; then
+    compset -P '*,'
+    if compset -P 1 '*\('; then
+      layout="${${IPREFIX%$open}##*,}"
+      state=variants state_descr=variant
+      suf=( -S"$close$compstate[quote] " )
+    else
+      suf=( -S$open -r ",('\" \t\n\-" )
+    fi
+  fi
+
+  _description $state expl $state_descr
+  if (( $+commands[localectl] )); then
+    case $state in
+      layouts) matches=( $(_call_program layouts localectl list-x11-keymap-layouts) ) ;;
+      models) matches=( $(_call_program layouts localectl list-x11-keymap-models) ) ;;
+      options) matches=( $(_call_program layouts localectl list-x11-keymap-options) ) ;;
+      variants) matches=( $(_call_program layouts localectl list-x11-keymap-variants $layout) ) ;;
+    esac
+  fi
+  if (( ! $#matches )); then
+    sourcedir=$(pkg-config xkeyboard-config --variable=xkb_base 2>/dev/null)
+    [[ -z $sourcedir ]] && sourcedir=(
+      ${XDG_DATA_HOME:-~/.local/share}/X11/xkb(N/)
+      ${(s.:.)XDG_DATA_DIRS:-/usr/lib:/usr/share:/usr/local/lib:/usr/local/share}/X11/xkb(N/)
     )
-    _arguments $arguments
-}
-
-_setxkbmap_dispatcher () {
-
-    case $CURRENT in
-        1)
-            _setxkbmap_layout
-        ;;
-        2)
-            _setxkbmap_variant "$words[1]"
-        ;;
+    (( $#sourcedir )) && case $state in
+      layouts) matches=( $sourcedir/symbols/**/^README(.Ne."REPLY=\${REPLY#*/symbols/}".) ) ;;
+      compatmaps) matches=( $sourcedir/compat/^README(.:t) ) ;;
+      models) matches=( $(sed -n '/modelList/,/\/modelList/ s, *<name>\(.*\)</name>,\1,p' $sourcedir/rules/(evdev|base).xml(.N[1])) ) ;;
+      options) matches=( $(sed -n '/optionList/,/\/optionList/ s, *<name>\(.*\)</name>,\1,p' $sourcedir/rules/(evdev|base).xml(.N[1])) ) ;;
+      rules) matches=( $sourcedir/rules/*.lst(-.:t:r) ) ;;
+      types) matches=( $sourcedir/types/^README(.:t) ) ;;
+      variants)
+        [[ -n $layout && -r $sourcedir/symbols/$layout ]] && matches=(
+            ${${${(M)${(f)"$(<$sourcedir/symbols/$layout)"}:#*xkb_symbols*\"([^\"])##\"*}##*xkb_symbols([^\"])##\"}%%\"*}
+        )
+      ;;
+      geometries)
+        if compset -P 1 '*\('; then
+          layout="${${IPREFIX%$open}##*,}"
+          suf=( -S"$close$compstate[quote] " )
+          matches=( $(sed -n -e '/xkb_geometry/ s/[^"]*"\([^"]*\).*/\1/p' $sourcedir/geometry/${IPREFIX%%[\\(]#}(.N)) )
+        else
+          suf=( -S$open -r "('\" \t\n\-" )
+          matches=( $sourcedir/geometry/^README(.:t) )
+        fi
+      ;;
+      devices)
+        # copied from _xinput
+        if (( $+commands[xinput] )); then
+          local -a ids names disp
+          local out
+          ids=( ${${(f)"$(_call_program input-devices xinput list --id-only)"}#? } )
+          names=( ${${(f)"$(_call_program input-devices xinput list --name-only)"}#? } )
+          disp=( ${(f)"$(_call_program input-devices xinput list --short)"} )
+
+          if [[ $PREFIX$SUFFIX = [^-]*[^0-9]* ]]; then
+            # match based on the names but insert IDs
+            compadd "$expl[@]" -M 'b:=* m:{[:lower:]}={[:upper:]}' -D ids -D disp -a names
+            compadd "$expl[@]" -U -ld disp -a ids && ret=0
+
+            zstyle -s ":completion:${curcontext}:input-devices" insert-ids out || out=menu
+            case "$out" in
+              menu)   compstate[insert]=menu ;;
+              single) [[ $#ids -ne 1 && $compstate[insert] != menu ]] &&
+                          compstate[insert]= ;;
+              *)      [[ ${#:-$PREFIX$SUFFIX} -gt ${#compstate[unambiguous]} ]] &&
+                          compstate[insert]=menu ;;
+            esac
+          else
+            compadd "$expl[@]" -M 'B:0=' -o nosort -ld disp -a ids && ret=0
+          fi
+        fi
+        return ret
+      ;;
     esac
-}
-
-_setxkbmap_files () {
-    local dir="$1"
-    local label="$2"
-
-    local -a fullpath shortpath expl
-
-    fullpath=($sourcedir/$dir/**/*~*README(.))
-    shortpath=(${fullpath#$sourcedir\/$dir\/})
-
-    _wanted layout expl $label compadd -a - shortpath
-
-}
-
-(( $+functions[_setxkbmap_compat] )) ||
-_setxkbmap_compat() {
-    _setxkbmap_files "compat" "compatibility"
-}
-
-(( $+functions[_setxkbmap_layout] )) ||
-_setxkbmap_layout () {
-    _setxkbmap_files "symbols" "layout"
-}
-
-(( $+functions[_setxkbmap_geometry] )) ||
-_setxkbmap_geometry () {
-    _setxkbmap_files "geometry" "geometry"
-}
-
-(( $+functions[_setxkbmap_variant] )) ||
-_setxkbmap_variant () {
-    local file=$sourcedir/symbols/${1}
-    local -a variants lines expl
-
-    if [ ! -f $file ]; then
-        _message "no such layout: ${1}"
-        return 1
-    fi
-
-    lines=("${(f)$(< ${file})}")
-    variants=(${${${(M)lines:#*xkb_symbols*\"([^\"])##\"*}##*xkb_symbols([^\"])##\"}%%\"*})
-    
-    _wanted variant expl 'variant' compadd -a variants
-
-}
+  fi
+  compadd "$expl[@]" $suf -a matches && ret=0
+fi
 
-_setxkbmap "$@"
+return ret