xkbcli-bash-completion.sh 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. # bash completion support for xkbcli.
  2. # See completion API documentation: https://github.com/scop/bash-completion
  3. # NOTE: The script parses the commands help messages to provide the completions,
  4. # thus any new subcommand or option will be supported, as long as it has its
  5. # entry in the help messages. This should result in low maintenancei effort.
  6. ___xkbcli_main()
  7. {
  8. # Initialization: https://github.com/scop/bash-completion/blob/fdf4456186eb4548ef628e65fb1be73d8e4695e9/bash_completion.d/000_bash_completion_compat.bash#L205
  9. local cur prev words cword cmd
  10. _init_completion -s || return
  11. # Find subcommand
  12. local i=1
  13. while [[ "$i" -lt "$COMP_CWORD" ]]; do
  14. local s="${COMP_WORDS[i]}"
  15. case "$s" in
  16. -*) ;;
  17. *)
  18. cmd="$s"
  19. break
  20. ;;
  21. esac
  22. (( i++ ))
  23. done
  24. # Parse available subcommands
  25. local line
  26. local is_command_list=false
  27. local subcommands=()
  28. while IFS='' read -r line; do
  29. # Traverse subcommand list
  30. if [[ "$is_command_list" == true ]]; then
  31. # Check for subcommand based on the indentation
  32. if [[ "$line" =~ ^[[:blank:]]{2}([[:alpha:]]([[:alnum:]]|-)+)$ ]]; then
  33. subcommands+=("${BASH_REMATCH[1]}")
  34. # Detect end of subcommand list based on indentation
  35. elif [[ "$line" =~ ^[[:graph:]] ]]; then
  36. is_command_list=false
  37. fi
  38. # Detect start of subcommand list
  39. elif [[ "$line" == "Commands:" ]]; then
  40. is_command_list=true
  41. fi
  42. # NOTE: <( COMMAND ) Bash construct is “process substitution”.
  43. done < <(xkbcli --help)
  44. # No previous subcommand or incomplete: completion for root xkbcli command
  45. if [[ "$i" -eq "$COMP_CWORD" ]]; then
  46. local opts
  47. # Doc for _parse_help: https://github.com/scop/bash-completion/blob/fdf4456186eb4548ef628e65fb1be73d8e4695e9/bash_completion.d/000_bash_completion_compat.bash#L311
  48. opts=$(_parse_help xkbcli)
  49. local cur="${COMP_WORDS[COMP_CWORD]}"
  50. COMPREPLY=($(compgen -W "${subcommands[*]} $opts" -- "$cur"))
  51. return
  52. fi
  53. # Found a supported subcommand: proceed to completion
  54. if [[ "${subcommands[*]}" =~ (^| )$cmd( |$) ]]; then
  55. ___xkbcli_subcommand "$cmd"
  56. fi
  57. }
  58. ___xkbcli_subcommand()
  59. {
  60. # Some special cases
  61. case $1 in
  62. compile-keymap | interactive-evdev)
  63. case ${COMP_WORDS[COMP_CWORD-1]} in
  64. --include | --keymap)
  65. _filedir
  66. return;;
  67. esac
  68. if [[ ${COMP_WORDS[COMP_CWORD]} != -* ]]; then
  69. _filedir
  70. return
  71. fi
  72. ;;
  73. compile-compose)
  74. case ${COMP_WORDS[COMP_CWORD-1]} in
  75. --file)
  76. _filedir
  77. return;;
  78. esac
  79. if [[ ${COMP_WORDS[COMP_CWORD]} != -* ]]; then
  80. _filedir
  81. return
  82. fi
  83. ;;
  84. list)
  85. if [[ ${COMP_WORDS[COMP_CWORD]} != -* ]]; then
  86. _filedir
  87. return
  88. fi
  89. ;;
  90. esac
  91. # Parse help to get command options
  92. local opts
  93. # Doc for _parse_usage and _parse_help:
  94. # • https://github.com/scop/bash-completion/blob/fdf4456186eb4548ef628e65fb1be73d8e4695e9/bash_completion.d/000_bash_completion_compat.bash#L335
  95. # • https://github.com/scop/bash-completion/blob/fdf4456186eb4548ef628e65fb1be73d8e4695e9/bash_completion.d/000_bash_completion_compat.bash#L311
  96. # We need both as the current help messages adopt both GNU and BSD styles.
  97. opts=$(_parse_usage xkbcli "$1 --help")
  98. opts+="
  99. "
  100. opts+=$(_parse_help xkbcli "$1 --help")
  101. local cur="${COMP_WORDS[COMP_CWORD]}"
  102. COMPREPLY=($(compgen -W "$opts" -- "$cur"))
  103. }
  104. complete -F ___xkbcli_main xkbcli