Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bash completions #384

Merged
merged 2 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ man_pages = []
# Tools
build_tools = get_option('enable-tools') and cc.has_header_symbol('getopt.h', 'getopt_long', prefix: '#define _GNU_SOURCE')
if build_tools
# Common resources
libxkbcommon_tools_internal_sources = [
'tools/tools-common.h',
'tools/tools-common.c',
Expand All @@ -432,10 +433,27 @@ if build_tools
dependencies: dep_libxkbcommon,
)

# Tool: xkbcli
executable('xkbcli', 'tools/xkbcli.c',
dependencies: tools_dep, install: true)
install_man('tools/xkbcli.1')

if get_option('enable-bash-completion')
bash_completion_path = get_option('bash-completion-path')
if bash_completion_path == ''
bash_completion = dependency('bash-completion', required: false)
if bash_completion.found()
bash_completion_path = bash_completion.get_variable(pkgconfig: 'completionsdir')
else
bash_completion_path = get_option('datadir') / 'bash-completion/completions'
endif
endif
install_data('tools/xkbcli-bash-completion.sh',
rename: 'xkbcli',
install_dir: bash_completion_path)
endif
wismill marked this conversation as resolved.
Show resolved Hide resolved

# Tool: compile-keymap
xkbcli_compile_keymap = executable('xkbcli-compile-keymap',
'tools/compile-keymap.c',
dependencies: tools_dep,
Expand All @@ -450,19 +468,25 @@ if build_tools
c_args: ['-DENABLE_PRIVATE_APIS'],
include_directories: [include_directories('src', 'include')],
install: false)

# Tool: compose
executable('compose',
'tools/compose.c',
dependencies: tools_dep,
include_directories: [include_directories('src', 'include')],
install: false)
configh_data.set10('HAVE_XKBCLI_COMPILE_KEYMAP', true)

# Tool: how-to-type
executable('xkbcli-how-to-type',
'tools/how-to-type.c',
dependencies: tools_dep,
install: true,
install_dir: dir_libexec)
install_man('tools/xkbcli-how-to-type.1')
configh_data.set10('HAVE_XKBCLI_HOW_TO_TYPE', true)

# Tool: interactive-evdev
if cc.has_header('linux/input.h')
executable('xkbcli-interactive-evdev',
'tools/interactive-evdev.c',
Expand All @@ -481,6 +505,8 @@ if build_tools
include_directories: [include_directories('src', 'include')],
install: false)
endif

# Tool: interactive-x11
if get_option('enable-x11')
x11_tools_dep = declare_dependency(
link_with: libxkbcommon_x11,
Expand All @@ -498,6 +524,8 @@ if build_tools
install_man('tools/xkbcli-interactive-x11.1')
configh_data.set10('HAVE_XKBCLI_INTERACTIVE_X11', true)
endif

# Tool: interactive-wayland
if get_option('enable-wayland')
wayland_client_dep = dependency('wayland-client', version: '>=1.2.0', required: false)
wayland_protocols_dep = dependency('wayland-protocols', version: '>=1.12', required: false)
Expand Down Expand Up @@ -534,6 +562,7 @@ You can disable the Wayland xkbcli programs with -Denable-wayland=false.''')
configh_data.set10('HAVE_XKBCLI_INTERACTIVE_WAYLAND', true)
endif

# Tool: list
if get_option('enable-xkbregistry')
configh_data.set10('HAVE_XKBCLI_LIST', true)
executable('xkbcli-list',
Expand All @@ -544,6 +573,7 @@ You can disable the Wayland xkbcli programs with -Denable-wayland=false.''')
install_man('tools/xkbcli-list.1')
endif

# Tool: check-messages
executable('xkb-check-messages',
'tools/check-messages.c',
'tools/messages.c',
Expand Down
11 changes: 11 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ option(
type: 'string',
description: 'The X locale root [default=$datadir/X11/locale]',
)
option(
'bash-completion-path',
type: 'string',
description: 'Directory for bash completion scripts'
)
option(
'default-rules',
type: 'string',
Expand Down Expand Up @@ -79,3 +84,9 @@ option(
value: true,
description: 'Enable building libxkbregistry',
)
option(
'enable-bash-completion',
type: 'boolean',
value: true,
description: 'Enable installing bash completion scripts',
)
2 changes: 2 additions & 0 deletions tools/compile-keymap.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ usage(char **argv)
"Compile the given RMLVO to a keymap and print it\n"
"\n"
"Options:\n"
" --help\n"
" Print this help and exit\n"
" --verbose\n"
" Enable verbose debugging output\n"
#if ENABLE_PRIVATE_APIS
Expand Down
2 changes: 2 additions & 0 deletions tools/interactive-evdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ usage(FILE *fp, char *progname)
" --enable-compose (enable Compose)\n"
" --consumed-mode={xkb|gtk} (select the consumed modifiers mode, default: xkb)\n"
" --without-x11-offset (don't add X11 keycode offset)\n"
"Other:\n"
" --help (display this help and exit)\n"
);
}

Expand Down
1 change: 1 addition & 0 deletions tools/registry-list.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ usage(const char *progname, FILE *fp)
" --ruleset=foo .......... Load the 'foo' ruleset\n"
" --skip-default-paths ... Do not load the default XKB paths\n"
" --load-exotic .......... Load the exotic (extra) rulesets\n"
" --help ................. Print this help and exit\n"
"\n"
"Trailing arguments are treated as XKB base directory installations.\n",
progname);
Expand Down
96 changes: 96 additions & 0 deletions tools/xkbcli-bash-completion.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# bash completion support for xkbcli.

# See completion API documentation: https://github.com/scop/bash-completion
# NOTE: The script parses the commands help messages to provide the completions,
# thus any new subcommand or option will be supported, as long as it has its
# entry in the help messages. This should result in low maintenancei effort.

___xkbcli_main()
{
# Initialization: https://github.com/scop/bash-completion/blob/fdf4456186eb4548ef628e65fb1be73d8e4695e9/bash_completion.d/000_bash_completion_compat.bash#L205
local cur prev words cword cmd
_init_completion -s || return

# Find subcommand
local i=1
while [[ "$i" -lt "$COMP_CWORD" ]]; do
local s="${COMP_WORDS[i]}"
case "$s" in
-*) ;;
*)
cmd="$s"
break
;;
esac
(( i++ ))
done

# Parse available subcommands
local line
local is_command_list=false
local subcommands=()
while IFS='' read -r line; do
# Traverse subcommand list
if [[ "$is_command_list" == true ]]; then
# Check for subcommand based on the indentation
if [[ "$line" =~ ^[[:blank:]]{2}([[:alpha:]]([[:alnum:]]|-)+)$ ]]; then
subcommands+=("${BASH_REMATCH[1]}")
# Detect end of subcommand list based on indentation
elif [[ "$line" =~ ^[[:graph:]] ]]; then
is_command_list=false
fi
# Detect start of subcommand list
elif [[ "$line" == "Commands:" ]]; then
is_command_list=true
fi
# NOTE: <( COMMAND ) Bash construct is “process substitution”.
done < <(xkbcli --help)

# No previous subcommand or incomplete: completion for root xkbcli command
if [[ "$i" -eq "$COMP_CWORD" ]]; then
local opts
# Doc for _parse_help: https://github.com/scop/bash-completion/blob/fdf4456186eb4548ef628e65fb1be73d8e4695e9/bash_completion.d/000_bash_completion_compat.bash#L311
opts=$(_parse_help xkbcli)
local cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=($(compgen -W "${subcommands[*]} $opts" -- "$cur"))
return
fi

# Found a supported subcommand: proceed to completion
if [[ "${subcommands[*]}" =~ (^| )$cmd( |$) ]]; then
___xkbcli_subcommand "$cmd"
fi
}

___xkbcli_subcommand()
{
# Some special cases
case $1 in
compile-keymap | interactive-evdev)
case ${COMP_WORDS[COMP_CWORD-1]} in
--include | --keymap)
_filedir
return;;
esac
;;
list)
if [[ ${COMP_WORDS[COMP_CWORD]} != -* ]]; then
_filedir
return
fi
;;
esac

# Parse help to get command options
local opts
# Doc for _parse_usage and _parse_help:
# • https://github.com/scop/bash-completion/blob/fdf4456186eb4548ef628e65fb1be73d8e4695e9/bash_completion.d/000_bash_completion_compat.bash#L335
# • https://github.com/scop/bash-completion/blob/fdf4456186eb4548ef628e65fb1be73d8e4695e9/bash_completion.d/000_bash_completion_compat.bash#L311
# We need both as the current help messages adopt both GNU and BSD styles.
opts=$(_parse_usage xkbcli "$1 --help")
opts+=$(_parse_help xkbcli "$1 --help")
local cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=($(compgen -W "$opts" -- "$cur"))
}

complete -F ___xkbcli_main xkbcli
3 changes: 3 additions & 0 deletions tools/xkbcli-how-to-type.1
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ The XKB layout variant
.
.It Fl \-options Ar options
The XKB options
.
.It Fl \-help
Print a help message and exit.
.El
.
.Sh SEE ALSO
Expand Down
3 changes: 3 additions & 0 deletions tools/xkbcli-interactive-evdev.1
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ The XKB options
Specify a keymap path.
This option is mutually exclusive with the RMLVO options.
.
.It Fl \-short
Do not print layout nor Unicode keysym translation.
.
.It Fl \-report\-state\-changes
Report changes to the keyboard state
.
Expand Down
3 changes: 3 additions & 0 deletions tools/xkbcli.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ usage(void)
"Global options:\n"
" -h, --help ...... show this help and exit\n"
" -V, --version ... show version information and exit\n"
/* WARNING: The following is parsed by the bash completion script.
* Any change to the format (in particular to the indentation)
* should kept in the script in sync. */
"Commands:\n"
#if HAVE_XKBCLI_LIST
" list\n"
Expand Down