diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:35:18 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:35:18 +0000 |
commit | b750101eb236130cf056c675997decbac904cc49 (patch) | |
tree | a5df1a06754bdd014cb975c051c83b01c9a97532 /shell-completion/bash | |
parent | Initial commit. (diff) | |
download | systemd-upstream.tar.xz systemd-upstream.zip |
Adding upstream version 252.22.upstream/252.22upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'shell-completion/bash')
32 files changed, 3887 insertions, 0 deletions
diff --git a/shell-completion/bash/bootctl b/shell-completion/bash/bootctl new file mode 100644 index 0000000..0b7cef7 --- /dev/null +++ b/shell-completion/bash/bootctl @@ -0,0 +1,109 @@ +# bootctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_entry_ids() { + bootctl --no-pager list 2>/dev/null | { while read -r a b; do [[ $a == 'id:' ]] && echo " $b"; done } +} + +_bootctl() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-h --help -p --print-esp-path -x --print-boot-path --version --no-variables --no-pager --graceful' + [ARG]='--esp-path --boot-path --make-machine-id-directory --root --image --install-source' + ) + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --esp-path|--boot-path) + if [[ -z $cur ]]; then + comps=$(compgen -A directory -- "/" ) + else + comps=$(compgen -A directory -- "$cur" ) + fi + compopt -o filenames + ;; + --make-machine-id-directory) + comps="yes no auto" + ;; + --image|--root) + compopt -o nospace + comps=$( compgen -A file -- "$cur" ) + ;; + --install-source) + comps="image host auto" + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + # systemd-efi-options takes an argument, but it is free-form, so we cannot complete it + [STANDALONE]='help status install update remove is-installed random-seed systemd-efi-options list set-timeout set-timeout-oneshot' + [BOOTENTRY]='set-default set-oneshot' + [BOOLEAN]='reboot-to-firmware' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + elif __contains_word "$verb" ${VERBS[BOOTENTRY]}; then + name= + for ((i++; i < COMP_CWORD; i++)); do + if ! __contains_word "${COMP_WORDS[i]}" ${OPTS[*]} ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + name=${COMP_WORDS[i]} + break; + fi + done + + if [[ -z $name ]]; then + comps=$( __get_entry_ids ) + else + comps='' + fi + elif __contains_word "$verb" ${VERBS[BOOLEAN]}; then + comps="yes no" + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _bootctl bootctl diff --git a/shell-completion/bash/busctl b/shell-completion/bash/busctl new file mode 100644 index 0000000..84bd67c --- /dev/null +++ b/shell-completion/bash/busctl @@ -0,0 +1,208 @@ +# busctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + { machinectl list --full --max-addresses=0 --no-legend --no-pager 2>/dev/null; echo ".host"; } | \ + { while read a b; do echo " $a"; done; } | \ + sort -u +} + +__get_busnames() { + local mode=$1 + local a b + busctl $mode list --no-legend --no-pager --full 2>/dev/null | + { while read a b; do echo " $a"; done; }; +} + +__get_objects() { + local mode=$1 + local busname=$2 + local a b + busctl $mode tree --list --no-legend --no-pager $busname 2>/dev/null | + { while read a b; do echo " $a"; done; }; +} + +__get_interfaces() { + local mode=$1 + local busname=$2 + local path=$3 + local a b c + busctl $mode introspect --list --no-legend --no-pager $busname $path 2>/dev/null | + { while read a b c; do [[ "$b" == "interface" ]] && echo " $a"; done; }; +} + +__get_members() { + local mode=$1 + local busname=$2 + local path=$3 + local interface=$4 + local type=$5 + local flags=$6 + local a b c d e + busctl $mode introspect --list --no-legend --no-pager $busname $path $interface 2>/dev/null | + sed -e 's/^\.//' | + { while read a b c d e; do [[ "$b" == "$type" && ( -z $flags || "$e" == "$flags" ) ]] && echo " $a"; done; }; +} + +__get_signature() { + local mode=$1 + local busname=$2 + local path=$3 + local interface=$4 + local member=$5 + local a b c d + busctl $mode introspect --list --no-legend --no-pager $busname $path $interface 2>/dev/null | + sed -e 's/^\.//' | { while read a b c d; do [[ "$a" == "$member" && "$c" != '-' ]] && echo " \"$c\""; done; }; +} + +_busctl() { + local i n verb comps mode + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-h --help --version --no-pager --no-legend --system --user + --show-machine --unique --acquired --activatable --list + -q --quiet --verbose --expect-reply=no --auto-start=no + --allow-interactive-authorization=no --augment-creds=no + --watch-bind=yes -j -l --full --xml-interface' + [ARG]='--address -H --host -M --machine --match --timeout --size --json + --destination' + ) + + if __contains_word "--user" ${COMP_WORDS[*]}; then + mode=--user + else + mode=--system + fi + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --json) + comps=$( busctl --json=help 2>/dev/null ) + ;; + --destination) + comps=$( __get_busnames $mode ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [STANDALONE]='list help' + [BUSNAME]='status monitor capture tree' + [OBJECT]='introspect' + [METHOD]='call' + [EMIT]='emit' + [PROPERTY_GET]='get-property' + [PROPERTY_SET]='set-property' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + n=$(($COMP_CWORD - $i)) + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + elif __contains_word "$verb" ${VERBS[BUSNAME]}; then + comps=$( __get_busnames $mode) + elif __contains_word "$verb" ${VERBS[OBJECT]}; then + if [[ $n -eq 1 ]] ; then + comps=$( __get_busnames $mode) + elif [[ $n -eq 2 ]] ; then + comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 3 ]] ; then + comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) + else + comps='' + fi + elif __contains_word "$verb" ${VERBS[METHOD]}; then + if [[ $n -eq 1 ]] ; then + comps=$( __get_busnames $mode) + elif [[ $n -eq 2 ]] ; then + comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 3 ]] ; then + comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 4 ]] ; then + comps=$( __get_members $mode ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]} method) + elif [[ $n -eq 5 ]] ; then + comps=$( __get_signature $mode ${COMP_WORDS[COMP_CWORD-4]} ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) + else + comps='' + fi + elif __contains_word "$verb" ${VERBS[EMIT]}; then + comps='' + elif __contains_word "$verb" ${VERBS[PROPERTY_GET]}; then + if [[ $n -eq 1 ]] ; then + comps=$( __get_busnames $mode) + elif [[ $n -eq 2 ]] ; then + comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 3 ]] ; then + comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 4 ]] ; then + comps=$( __get_members $mode ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]} property) + else + comps='' + fi + elif __contains_word "$verb" ${VERBS[PROPERTY_SET]}; then + if [[ $n -eq 1 ]] ; then + comps=$( __get_busnames $mode) + elif [[ $n -eq 2 ]] ; then + comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 3 ]] ; then + comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 4 ]] ; then + comps=$( __get_members $mode ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]} property writable) + elif [[ $n -eq 5 ]] ; then + comps=$( __get_signature $mode ${COMP_WORDS[COMP_CWORD-4]} ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) + else + comps='' + fi + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _busctl busctl diff --git a/shell-completion/bash/coredumpctl b/shell-completion/bash/coredumpctl new file mode 100644 index 0000000..b571990 --- /dev/null +++ b/shell-completion/bash/coredumpctl @@ -0,0 +1,97 @@ +# coredumpctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC} + ERRNO SYSLOG_{FACILITY,IDENTIFIER,PID} COREDUMP_EXE + _{P,U,G}ID _COMM _EXE _CMDLINE + _AUDIT_{SESSION,LOGINUID} + _SYSTEMD_{CGROUP,SESSION,UNIT,OWNER_UID} + _SELINUX_CONTEXT _SOURCE_REALTIME_TIMESTAMP + _{BOOT,MACHINE}_ID _HOSTNAME _TRANSPORT + _KERNEL_{DEVICE,SUBSYSTEM} + _UDEV_{SYSNAME,DEVNODE,DEVLINK} + __CURSOR __{REALTIME,MONOTONIC}_TIMESTAMP) +_coredumpctl() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local OPTS='-h --help --version --no-pager --no-legend -o --output -F --field -1 + -r --reverse -S --since -U --until -D --directory -q --quiet --debugger + -A --debugger-arguments --json -n --all --file --root --image' + + local -A VERBS=( + [LIST]='list info' + [DUMP]='dump debug' + ) + + if __contains_word "$prev" --output -o --file --image; then + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + elif __contains_word "$prev" -D --directory --root; then + comps=$( compgen -A directory -- "$cur" ) + compopt -o filenames + elif __contains_word "$prev" '--debugger'; then + comps=$( compgen -A command -- "$cur" ) + compopt -o filenames + elif __contains_word "$prev" --field -F; then + comps=$( compgen -W '${__journal_fields[*]}' -- "$cur" ) + elif __contains_word "$prev" '--json'; then + comps=$( compgen -W 'pretty short off' -- "$cur" ) + elif [[ $cur = -* ]]; then + comps=${OPTS} + elif __contains_word "$prev" ${VERBS[*]} && + ! __contains_word ${COMP_WORDS[COMP_CWORD-2]} \ + '--output -o -D --directory -F --field --debugger'; then + compopt -o nospace + COMPREPLY=( $(compgen -W '${__journal_fields[*]}' -S= -- "$cur") ) + return 0 + elif [[ $cur = *=* ]]; then + mapfile -t field_vals < <(coredumpctl -F "${prev%=}" 2>/dev/null) + COMPREPLY=( $(compgen -W '${field_vals[*]}' -- "${cur#=}") ) + return 0 + elif [[ $prev = '=' ]]; then + mapfile -t field_vals < <(coredumpctl -F "${COMP_WORDS[COMP_CWORD-2]}" 2>/dev/null) + comps=${field_vals[*]} + else + for ((i=0; i <= COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[LIST]} ${VERBS[DUMP]}; then + comps='' + fi + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _coredumpctl coredumpctl diff --git a/shell-completion/bash/homectl b/shell-completion/bash/homectl new file mode 100644 index 0000000..166a508 --- /dev/null +++ b/shell-completion/bash/homectl @@ -0,0 +1,190 @@ +# homectl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + machinectl list --full --no-legend --no-pager 2>/dev/null | + { while read a b; do echo " $a"; done; }; +} + +__get_homes() { + homectl --no-pager --no-legend list 2>/dev/null +} + +_homectl() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + + local -A OPTS=( + [STANDALONE]='-h --help --version + --no-pager --no-legend --no-ask-password + -j -E -P' + [ARG]=' -H --host + -M --machine + --identity + --json + --export-format + -c --real-name + --realm + --email-address + --location + --icon-name + -d --home-dir + --uid + -G --member-of + --skel + --shell + --setenv + --timezone + --language + --ssh-authorized-keys + --pkcs11-token-uri + --locked + --not-before + --not-after + --rate-limit-interval + --rate-limit-burst + --password-hint + --enforce-password-policy + --password-change-now + --password-change-min + --password-change-max + --password-change-warn + --password-change-inactive + --disk-size + --access-mode + --umask + --nice + --rlimit + --tasks-max + --memory-high + --memory-max + --cpu-weight + --io-weight + --storage + --image-path + --fs-type + --luks-discard + --luks-offline-discard + --luks-cipher + --luks-cipher-mode + --luks-volume-key-size + --luks-pbkdf-type + --luks-pbkdf-hash-algorithm + --luks-pbkdf-time-cost + --luks-pbkdf-memory-cost + --luks-pbkdf-parallel-threads + --luks-sector-size + --nosuid + --nodev + --noexec + --cifs-domain + --cifs-user-name + --cifs-service + --stop-delay + --kill-processes + --auto-login' + ) + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --identity|--image-path) + comps=$(compgen -A file -- "$cur" ) + compopt -o filenames + ;; + --json) + comps='pretty short off' + ;; + --export-format) + comps='full stripped minimal' + ;; + --locked|--enforce-password-policy|--password-change-now|--luks-discard|--luks-offline-discard|--nosuid|--nodev|--noexec|--kill-processes|--auto-login) + comps='yes no' + ;; + -d|--home-dir|--skel) + comps=$(compgen -A directory -- "$cur" ) + compopt -o dirnames + ;; + -G|--member-of) + comps=$(compgen -A group -- "$cur" ) + ;; + --shell) + comps=$(cat /etc/shells) + ;; + --fs-type) + comps='btrfs ext4 xfs' + ;; + --cifs-user-name) + comps=$(compgen -A user -- "$cur" ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [STANDALONE]='list lock-all' + [CREATE]='create' + [NAMES]='activate deactivate inspect authenticate remove lock unlock' + [NAME]='update passwd' + [RESIZE]='resize' + [WITH]='with' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[NAME]}; then + comps=$(__get_homes) + elif __contains_word "$verb" ${VERBS[NAMES]}; then + comps=$(__get_homes) + elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[CREATE]} ${VERBS[RESIZE]}; then + comps=$(__get_homes) + elif __contains_word "$verb" ${VERBS[WITH]}; then + comps=$(__get_homes) + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _homectl homectl diff --git a/shell-completion/bash/hostnamectl b/shell-completion/bash/hostnamectl new file mode 100644 index 0000000..63edc08 --- /dev/null +++ b/shell-completion/bash/hostnamectl @@ -0,0 +1,92 @@ +# hostnamectl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + machinectl list --full --no-legend --no-pager 2>/dev/null | + { while read a b; do echo " $a"; done; }; +} + +_hostnamectl() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-h --help --version --transient --static --pretty --no-ask-password' + [ARG]='-H --host -M --machine --json' + ) + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --json) + comps=$( hostnamectl --json=help 2>/dev/null ) + ;; + *) + return 0 + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [STANDALONE]='status' + [ICONS]='icon-name' + [NAME]='hostname deployment location' + [CHASSIS]='chassis' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[CHASSIS]}; then + comps='desktop laptop convertible server tablet handset watch embedded vm container' + elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[ICONS]} ${VERBS[NAME]}; then + comps='' + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _hostnamectl hostnamectl diff --git a/shell-completion/bash/journalctl b/shell-completion/bash/journalctl new file mode 100644 index 0000000..067b053 --- /dev/null +++ b/shell-completion/bash/journalctl @@ -0,0 +1,154 @@ +# journalctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + { machinectl list --full --max-addresses=0 --no-legend --no-pager 2>/dev/null; echo ".host"; } | \ + { while read a b; do echo " $a"; done; } | \ + sort -u +} + +__syslog_priorities=(emerg alert crit err warning notice info debug) +__syslog_facilities=(kern user mail daemon auth syslog lpr news uucp cron authpriv ftp local0 local1 local2 local3 local4 local5 local6 local7) + +_journalctl() { + local field_vals= cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-a --all --full --system --user + --disk-usage -f --follow --header + -h --help -l --local -m --merge --no-pager + --no-tail -q --quiet --setup-keys --verify + --version --list-catalog --update-catalog --list-boots + --show-cursor --dmesg -k --pager-end -e -r --reverse + --utc -x --catalog --no-full --force --dump-catalog + --flush --rotate --sync --no-hostname -N --fields' + [ARG]='-b --boot -D --directory --file -F --field -t --identifier --facility + -M --machine -o --output -u --unit --user-unit -p --priority + --root --case-sensitive' + [ARGUNKNOWN]='-c --cursor --interval -n --lines -S --since -U --until + --after-cursor --cursor-file --verify-key -g --grep + --vacuum-size --vacuum-time --vacuum-files --output-fields' + ) + + # Use the default completion for shell redirect operators + if __contains_word "$prev" '>' '>>' '&>'; then + compopt -o filenames + COMPREPLY=( $(compgen -f -- "$cur") ) + return 0; + fi + + if __contains_word "$prev" ${OPTS[ARG]} ${OPTS[ARGUNKNOWN]}; then + case $prev in + --boot|-b) + comps=$(journalctl -F '_BOOT_ID' 2>/dev/null) + ;; + --directory|-D|--root) + comps=$(compgen -d -- "$cur") + compopt -o filenames + ;; + --file) + comps=$(compgen -f -- "$cur") + compopt -o filenames + ;; + --output|-o) + comps=$( journalctl --output=help 2>/dev/null ) + ;; + --field|-F) + comps=$(journalctl --fields | sort 2>/dev/null) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --facility) + comps=${__syslog_facilities[*]} + ;; + --priority|-p) + comps=${__syslog_priorities[*]} + compopt -o nosort + ;; + --unit|-u) + comps=$(journalctl -F '_SYSTEMD_UNIT' 2>/dev/null) + # Similarly to systemctl, we need to distinguish between + # escaped and unescaped names in order to be able to correctly + # complete them. In this particular case, if the name we're + # trying to complete is unescaped (i.e. foo\x2dbaz), escape + # it first, so the compgen below works as expected. For more + # information about these shenanigans see the systemctl + # completion file + if ! [[ $cur =~ '\\' ]]; then + cur="$(printf '%q' $cur)" + fi + compopt -o filenames + ;; + --user-unit) + comps=$(journalctl -F '_SYSTEMD_USER_UNIT' 2>/dev/null) + ;; + --identifier|-t) + comps=$(journalctl -F 'SYSLOG_IDENTIFIER' 2>/dev/null) + ;; + --case-sensitive) + comps='yes no' + ;; + *) + return 0 + ;; + esac + COMPREPLY=( $(compgen -o filenames -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + elif [[ $cur = *=* ]]; then + mapfile -t field_vals < <(journalctl -F "${prev%=}" 2>/dev/null) + COMPREPLY=( $(compgen -W '${field_vals[*]}' -- "${cur#=}") ) + elif [[ $cur = /dev* ]]; then + compopt -o filenames + COMPREPLY=( $(compgen -f -- "${cur}") ) + elif [[ $cur = /* ]]; then + # Append /dev/ to the list of completions, so that + # after typing /<TAB><TAB> the user sees /dev/ as one + # of the alternatives. Later on the rule above will + # take care of showing device files in /dev/. + mapfile -t field_vals < <(journalctl -F "_EXE" 2>/dev/null; echo '/dev/') + COMPREPLY=( $(compgen -W '${field_vals[*]}' -- "${cur}") ) + if [[ "${COMPREPLY[@]}" = '/dev/' ]]; then + compopt -o filenames + COMPREPLY=( $(compgen -f -- "${cur}") ) + fi + elif [[ $prev = '=' ]]; then + mapfile -t field_vals < <(journalctl -F "${COMP_WORDS[COMP_CWORD-2]}" 2>/dev/null) + COMPREPLY=( $(compgen -W '${field_vals[*]}' -- "$cur") ) + else + mapfile -t field_vals < <(journalctl --fields 2>/dev/null) + compopt -o nospace + COMPREPLY=( $(compgen -W '${field_vals[*]}' -S= -- "$cur") ) + fi +} + +complete -F _journalctl journalctl diff --git a/shell-completion/bash/kernel-install b/shell-completion/bash/kernel-install new file mode 100644 index 0000000..4708777 --- /dev/null +++ b/shell-completion/bash/kernel-install @@ -0,0 +1,48 @@ +# kernel-install(8) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +_kernel_install() { + local comps + local MACHINE_ID + local cur=${COMP_WORDS[COMP_CWORD]} + + case $COMP_CWORD in + 1) + comps="add remove" + ;; + 2) + comps=$(cd /lib/modules; echo [0-9]*) + if [[ ${COMP_WORDS[1]} == "remove" ]] && [[ -f /etc/machine-id ]]; then + read MACHINE_ID < /etc/machine-id + if [[ $MACHINE_ID ]] && ( [[ -d /boot/$MACHINE_ID ]] || [[ -L /boot/$MACHINE_ID ]] ); then + comps=$(cd "/boot/$MACHINE_ID"; echo [0-9]*) + fi + fi + ;; + 3) + [[ "$cur" ]] || cur=/lib/modules/${COMP_WORDS[2]}/vmlinuz + comps=$(compgen -f -- "$cur") + compopt -o filenames + ;; + esac + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _kernel_install kernel-install diff --git a/shell-completion/bash/localectl b/shell-completion/bash/localectl new file mode 100644 index 0000000..b601343 --- /dev/null +++ b/shell-completion/bash/localectl @@ -0,0 +1,96 @@ +# localectl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__locale_fields=( LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME + LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER + LC_NAME LC_ADDRESS LC_TELEPHONE + LC_MEASUREMENT LC_IDENTIFICATION ) +# LC_ALL is omitted on purpose + +_localectl() { + local i verb comps locale_vals + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local OPTS='-h --help --version --no-convert --no-pager --no-ask-password + -H --host -M --machine' + + if __contains_word "$prev" $OPTS; then + case $prev in + --host|-H) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [STANDALONE]='status list-locales list-keymaps list-x11-keymap-models list-x11-keymap-layouts list-x11-keymap-options' + [VARIANTS]='list-x11-keymap-variants' + [LOCALES]='set-locale' + [KEYMAPS]='set-keymap' + [X11]='set-x11-keymap' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[VARIANTS]}; then + comps=$(command localectl list-x11-keymap-layouts) + elif __contains_word "$verb" ${VERBS[LOCALES]}; then + if [[ $cur = *=* ]]; then + mapfile -t locale_vals < <(command localectl list-locales 2>/dev/null) + COMPREPLY=( $(compgen -W '${locale_vals[*]}' -- "${cur#=}") ) + elif [[ $prev = "=" ]]; then + mapfile -t locale_vals < <(command localectl list-locales 2>/dev/null) + COMPREPLY=( $(compgen -W '${locale_vals[*]}' -- "$cur") ) + else + compopt -o nospace + COMPREPLY=( $(compgen -W '${__locale_fields[*]}' -S= -- "$cur") ) + fi + return 0 + elif __contains_word "$verb" ${VERBS[KEYMAPS]}; then + comps=$(command localectl list-keymaps) + elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[X11]}; then + comps='' + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _localectl localectl diff --git a/shell-completion/bash/loginctl b/shell-completion/bash/loginctl new file mode 100644 index 0000000..b307e42 --- /dev/null +++ b/shell-completion/bash/loginctl @@ -0,0 +1,125 @@ +# loginctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_all_sessions () { loginctl --no-legend list-sessions | { while read -r a b; do printf "%s\n" "$a"; done; } ; } +__get_all_users () { loginctl --no-legend list-users | { while read -r a b; do printf "%s\n" "$b"; done; } ; } +__get_all_seats () { loginctl --no-legend list-seats | { while read -r a b; do printf "%s\n" "$a"; done; } ; } + +__get_machines() { + local a b + { machinectl list --full --max-addresses=0 --no-legend --no-pager 2>/dev/null; echo ".host"; } | \ + { while read a b; do echo " $a"; done; } | \ + sort -u +} + +_loginctl () { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local i verb comps + + local -A OPTS=( + [STANDALONE]='--all -a --help -h --no-pager --version + --no-legend --no-ask-password -l --full --value' + [ARG]='--host -H --kill-whom --property -p --signal -s -M --machine + -n --lines -o --output -P' + ) + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --signal|-s) + _signals + return + ;; + --kill-whom|--kill-who) + comps='all leader' + ;; + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --property|-p|-P) + comps='' + ;; + --output|-o) + comps=$( loginctl --output=help 2>/dev/null ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [SESSIONS]='session-status show-session activate lock-session unlock-session terminate-session kill-session' + [USERS]='user-status show-user enable-linger disable-linger terminate-user kill-user' + [SEATS]='seat-status show-seat terminate-seat' + [STANDALONE]='list-sessions lock-sessions unlock-sessions list-users list-seats flush-devices' + [ATTACH]='attach' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z ${verb-} ]]; then + comps="${VERBS[*]}" + + elif __contains_word "$verb" ${VERBS[SESSIONS]}; then + comps=$( __get_all_sessions ) + + elif __contains_word "$verb" ${VERBS[USERS]}; then + comps=$( __get_all_users ) + + elif __contains_word "$verb" ${VERBS[SEATS]}; then + comps=$( __get_all_seats ) + + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + + elif __contains_word "$verb" ${VERBS[ATTACH]}; then + if [[ $prev = $verb ]]; then + comps=$( __get_all_seats ) + else + comps=$(compgen -A file -- "$cur" ) + compopt -o filenames + fi + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _loginctl loginctl diff --git a/shell-completion/bash/machinectl b/shell-completion/bash/machinectl new file mode 100644 index 0000000..b28769b --- /dev/null +++ b/shell-completion/bash/machinectl @@ -0,0 +1,117 @@ +# machinectl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + { machinectl list-images --full --no-legend --no-pager 2>/dev/null; machinectl list --full --max-addresses=0 --no-legend --no-pager 2>/dev/null; echo ".host"; } | \ + { while read a b; do echo " $a"; done; } | \ + sort -u +} + +_machinectl() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword + local i verb comps + + local -A OPTS=( + [STANDALONE]='--all -a -l --full --help -h --no-ask-password --no-legend --no-pager --version --value + --mkdir --read-only --force -q --quiet' + [ARG]='--host -H --kill-whom -M --machine --property -p --signal -s --uid -E --setenv -n --lines + -o --output --verify --format --max-addresses' + ) + + local -A VERBS=( + [STANDALONE]='list list-images clean pull-tar pull-raw list-transfers cancel-transfer import-fs' + [MACHINES]='status show start stop login shell enable disable poweroff reboot terminate kill bind + copy-to copy-from image-status show-image clone rename read-only remove set-limit + export-tar export-raw' + [FILE]='import-tar import-raw' + ) + + _init_completion || return + + for ((i=0; i <= COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --signal|-s) + _signals + return + ;; + --kill-whom|--kill-who) + comps='all leader' + ;; + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --property|-p) + comps='' + ;; + --output|-o) + comps=$( machinectl --output=help 2>/dev/null ) + ;; + --verify) + comps=$( machinectl --verify=help 2>/dev/null ) + ;; + --format) + comps='uncompressed xz gzip bzip2' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + + elif __contains_word "$verb" ${VERBS[MACHINES]}; then + comps=$( __get_machines ) + + elif __contains_word "$verb" ${VERBS[FILE]}; then + comps=$(compgen -f -- "cur") + compopt -o filenames + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _machinectl machinectl diff --git a/shell-completion/bash/meson.build b/shell-completion/bash/meson.build new file mode 100644 index 0000000..0446be7 --- /dev/null +++ b/shell-completion/bash/meson.build @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +bashcompletiondir = get_option('bashcompletiondir') +if bashcompletiondir == '' + bash_completion = dependency('bash-completion', required : false) + if bash_completion.found() + bashcompletiondir = bash_completion.get_pkgconfig_variable('completionsdir') + else + bashcompletiondir = datadir / 'bash-completion/completions' + endif +endif + +custom_target( + 'systemctl', + input : 'systemctl.in', + output : 'systemctl', + command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'], + install : bashcompletiondir != 'no', + install_dir : bashcompletiondir) + +items = [['busctl', ''], + ['journalctl', ''], + ['systemd-analyze', ''], + ['systemd-cat', ''], + ['systemd-cgls', ''], + ['systemd-cgtop', ''], + ['systemd-delta', ''], + ['systemd-detect-virt', ''], + ['systemd-id128', ''], + ['systemd-nspawn', ''], + ['systemd-path', ''], + ['systemd-run', ''], + ['udevadm', ''], + ['bootctl', 'HAVE_GNU_EFI'], + ['coredumpctl', 'ENABLE_COREDUMP'], + ['homectl', 'ENABLE_HOMED'], + ['hostnamectl', 'ENABLE_HOSTNAMED'], + ['kernel-install', 'ENABLE_KERNEL_INSTALL'], + ['localectl', 'ENABLE_LOCALED'], + ['loginctl', 'ENABLE_LOGIND'], + ['machinectl', 'ENABLE_MACHINED'], + ['networkctl', 'ENABLE_NETWORKD'], + ['oomctl', 'ENABLE_OOMD'], + ['portablectl', 'ENABLE_PORTABLED'], + ['resolvectl', 'ENABLE_RESOLVE'], + ['systemd-cryptenroll', 'HAVE_LIBCRYPTSETUP'], + ['systemd-dissect', 'HAVE_BLKID'], + ['systemd-resolve', 'ENABLE_RESOLVE'], + ['systemd-sysext', 'ENABLE_SYSEXT'], + ['timedatectl', 'ENABLE_TIMEDATED']] + +foreach item : items + if bashcompletiondir != 'no' and (item[1] == '' or conf.get(item[1]) == 1) + install_data(item[0], + install_dir : bashcompletiondir) + endif +endforeach diff --git a/shell-completion/bash/networkctl b/shell-completion/bash/networkctl new file mode 100644 index 0000000..db59a9c --- /dev/null +++ b/shell-completion/bash/networkctl @@ -0,0 +1,84 @@ +# networkctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done + return 1 +} + +__get_links() { + networkctl list --no-legend --no-pager --all --full | { while read -r a b c; do echo " $b"; done; }; +} + +_networkctl() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword + local -A OPTS=( + [STANDALONE]='-a --all -h --help --version --no-pager --no-legend -s --stats -l --full' + [ARG]='-n --lines --json' + ) + + local -A VERBS=( + [STANDALONE]='label reload' + [LINKS]='status list lldp delete renew up down forcerenew reconfigure' + ) + + _init_completion || return + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --json) + comps=$(networkctl --json=help | sort 2>/dev/null) + ;; + *) + return 0 + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + elif __contains_word "$verb" ${VERBS[LINKS]}; then + comps=$( __get_links ) + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _networkctl networkctl diff --git a/shell-completion/bash/oomctl b/shell-completion/bash/oomctl new file mode 100644 index 0000000..dc45ba5 --- /dev/null +++ b/shell-completion/bash/oomctl @@ -0,0 +1,57 @@ +# oomctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +_oomctl() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local OPTS='-h --help --version --no-pager' + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [STANDALONE]='help dump' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _oomctl oomctl diff --git a/shell-completion/bash/portablectl b/shell-completion/bash/portablectl new file mode 100644 index 0000000..519c5c0 --- /dev/null +++ b/shell-completion/bash/portablectl @@ -0,0 +1,116 @@ +# portablectl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + { machinectl list --full --max-addresses=0 --no-legend --no-pager 2>/dev/null; echo ".host"; } | \ + { while read a b; do echo " $a"; done; } | \ + sort -u +} + +_portablectl() { + local i n comps verb + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-q --quiet --runtime --no-reload --cat --no-pager --no-legend + --no-ask-password --enable --now -h --help --version' + [ARG]='-p --profile --copy -H --host -M --machine --extension' + ) + + local -A VERBS=( + [STANDALONE]='list' + [IMAGE]='attach detach reattach inspect is-attached set-limit' + [IMAGES]='remove' + [IMAGE_WITH_BOOL]='read-only' + ) + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --profile|-p) + comps="default nonetwork strict trusted" + ;; + --copy) + comps="copy symlink auto" + ;; + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --extension) + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + n=$(($COMP_CWORD - $i)) + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + elif __contains_word "$verb" ${VERBS[IMAGE]}; then + if [[ $n == 1 ]]; then + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + else + comps='' + fi + elif __contains_word "$verb" ${VERBS[IMAGES]}; then + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + elif __contains_word "$verb" ${VERBS[IMAGE_WITH_BOOL]}; then + if [[ $n == 1 ]]; then + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + elif [[ $n == 2 ]]; then + comps='yes no' + else + comps='' + fi + fi + + COMPREPLY=( $(compgen -o filenames -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _portablectl portablectl diff --git a/shell-completion/bash/resolvectl b/shell-completion/bash/resolvectl new file mode 100644 index 0000000..21f8014 --- /dev/null +++ b/shell-completion/bash/resolvectl @@ -0,0 +1,204 @@ +# resolvectl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_interfaces(){ + local name + for name in $(cd /sys/class/net && command ls); do + [[ "$name" != "lo" ]] && echo "$name" + done +} + +_resolvectl() { + local i comps verb name + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-h --help --version -4 -6 --legend=no --cname=no + --validate=no --synthesize=no --cache=no --zone=no + --trust-anchor=no --network=no --service-address=no + --service-txt=no --search=no --no-pager' + [ARG]='-t --type -c --class -i --interface -p --protocol --raw' + ) + local -A VERBS=( + [DOMAIN]='query service openpgp' + [FAMILY]='tlsa' + [STATUS]='status' + [LINK]='revert dns domain nta' + [BOOLEAN]='default-route' + [RESOLVE]='llmnr mdns' + [DNSSEC]='dnssec' + [DNSOVERTLS]='dnsovertls' + [STANDALONE]='statistics reset-statistics flush-caches reset-server-features' + [LOG_LEVEL]='log-level' + ) + local -A ARGS=( + [FAMILY]='tcp udp sctp' + [BOOLEAN]='yes no' + [RESOLVE]='yes no resolve' + [DNSSEC]='yes no allow-downgrade' + [DNSOVERTLS]='yes no opportunistic' + ) + local interfaces=$( __get_interfaces ) + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --interface|-i) + comps="$interfaces" + ;; + --protocol|-p|--type|-t|--class|-c) + comps=$( resolvectl --legend=no "$prev" help; echo help ) + ;; + --raw) + comps="payload packet" + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z ${verb-} ]]; then + comps="${VERBS[*]}" + + elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[DOMAIN]}; then + comps='' + + elif __contains_word "$verb" ${VERBS[STATUS]}; then + comps="$interfaces" + + elif __contains_word "$verb" ${VERBS[LOG_LEVEL]}; then + comps='debug info notice warning err crit alert emerg' + + elif __contains_word "$verb" ${VERBS[FAMILY]}; then + for ((i++; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${ARGS[FAMILY]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + name=${COMP_WORDS[i]} + break; + fi + done + if [[ -z $name ]]; then + comps=${ARGS[FAMILY]} + else + comps="" + fi + + elif __contains_word "$verb" ${VERBS[LINK]} ${VERBS[BOOLEAN]} ${VERBS[RESOLVE]} ${VERBS[DNSSEC]} ${VERBS[DNSOVERTLS]}; then + for ((i++; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" $interfaces && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + name=${COMP_WORDS[i]} + break; + fi + done + + if [[ -z $name ]]; then + comps="$interfaces" + + elif __contains_word "$verb" ${VERBS[RESOLVE]}; then + name= + for ((i++; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${ARGS[RESOLVE]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + name=${COMP_WORDS[i]} + break; + fi + done + + if [[ -z $name ]]; then + comps=${ARGS[RESOLVE]} + else + comps='' + fi + + elif __contains_word "$verb" ${VERBS[BOOLEAN]}; then + name= + for ((i++; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${ARGS[BOOLEAN]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + name=${COMP_WORDS[i]} + break; + fi + done + + if [[ -z $name ]]; then + comps=${ARGS[BOOLEAN]} + else + comps='' + fi + + elif __contains_word "$verb" ${VERBS[DNSSEC]}; then + name= + for ((i++; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${ARGS[DNSSEC]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + name=${COMP_WORDS[i]} + break; + fi + done + + if [[ -z $name ]]; then + comps=${ARGS[DNSSEC]} + else + comps='' + fi + + elif __contains_word "$verb" ${VERBS[DNSOVERTLS]}; then + name= + for ((i++; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${ARGS[DNSOVERTLS]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + name=${COMP_WORDS[i]} + break; + fi + done + + if [[ -z $name ]]; then + comps=${ARGS[DNSOVERTLS]} + else + comps='' + fi + + else + comps='' + fi + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _resolvectl resolvectl diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in new file mode 100644 index 0000000..a926178 --- /dev/null +++ b/shell-completion/bash/systemctl.in @@ -0,0 +1,394 @@ +# systemctl(1) completion -*- shell-script -*- +# vi: ft=sh +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita + +__systemctl() { + local mode=$1; shift 1 + systemctl $mode --full --legend=no --no-pager --plain "$@" 2>/dev/null +} + +__systemd_properties() { + {{ROOTLIBEXECDIR}}/systemd --dump-bus-properties +} + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +{% raw -%} +__filter_units_by_properties () { + local mode=$1 properties=$2; shift 2 + local units=("$@") + local props i p n + local names= count=0 + + IFS=$',' read -r -a p < <(echo "Names,$properties") + n=${#p[*]} + readarray -t props < \ + <(__systemctl $mode show --property "Names,$properties" -- "${units[@]}") + + for ((i=0; i < ${#props[*]}; i++)); do + if [[ -z ${props[i]} ]]; then + if (( count == n )) && [[ -n $names ]]; then + echo $names + fi + names= + count=0 + else + (( count++ )) + if [[ ${props[i]%%=*} == 'Names' ]]; then + names=${props[i]#*=} + fi + fi + done + if (( count == n )) && [[ -n $names ]]; then + echo $names + fi +} +{% endraw %} + +__get_all_units () { { __systemctl $1 list-unit-files "$2*"; __systemctl $1 list-units --all "$2*"; } \ + | { while read -r a b; do echo " $a"; done; }; } +__get_non_template_units() { { __systemctl $1 list-unit-files "$2*"; __systemctl $1 list-units --all "$2*"; } \ + | { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; }; } +__get_template_names () { __systemctl $1 list-unit-files "$2*" \ + | { while read -r a b; do [[ $a =~ @\. ]] && echo " ${a%%@.*}@"; done; }; } +__get_active_units () { __systemctl $1 list-units "$2*" \ + | { while read -r a b; do echo " $a"; done; }; } +__get_active_services() { __systemctl $1 list-units "$2*.service" \ + | { while read -r a b; do echo " $a"; done; }; } + +__get_not_masked_unit_files() { + # filter out masked, not-found, or template units. + __systemctl $1 list-unit-files --state enabled,enabled-runtime,linked,linked-runtime,static,indirect,disabled,generated,transient "$2*" | \ + { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; } +} + +__get_startable_units () { + __filter_units_by_properties $1 ActiveState=inactive,CanStart=yes $( + { __get_not_masked_unit_files $1 $2 + # get inactive template units + __systemctl $1 list-units --state inactive,failed "$2*" | \ + { while read -r a b c; do [[ $b == "loaded" ]] && echo " $a"; done; } + } | sort -u ) +} +__get_restartable_units () { + # filter out masked and not-found + __filter_units_by_properties $1 CanStart=yes $( + { __get_not_masked_unit_files $1 $2 + __get_active_units $1 $2 + } | sort -u ) +} + +__get_stoppable_units () { + # filter out masked and not-found + local units=$( + { __get_not_masked_unit_files $1 $2 + __get_active_units $1 $2 + } | sort -u ) + __filter_units_by_properties $1 ActiveState=active,CanStop=yes $units + __filter_units_by_properties $1 ActiveState=reloading,CanStop=yes $units + __filter_units_by_properties $1 ActiveState=activating,CanStop=yes $units +} + +__get_reloadable_units () { + # filter out masked and not-found + __filter_units_by_properties $1 ActiveState=active,CanReload=yes $( + { __get_not_masked_unit_files $1 $2 + __get_active_units $1 $2 + } | sort -u ) +} + +__get_failed_units() { __systemctl $1 list-units "$2*" \ + | while read -r a b c d; do [[ $c == "failed" ]] && echo " $a"; done; } +__get_enabled_units() { __systemctl $1 list-unit-files "$2*" \ + | while read -r a b c ; do [[ $b == "enabled" ]] && echo " $a"; done; } +__get_disabled_units() { __systemctl $1 list-unit-files "$2*" \ + | while read -r a b c ; do [[ $b == "disabled" ]] && echo " $a"; done; } +__get_masked_units() { __systemctl $1 list-unit-files "$2*" \ + | while read -r a b c ; do [[ $b == "masked" ]] && echo " $a"; done; } +__get_all_unit_files() { __systemctl $1 list-unit-files "$2*" | while read -r a b; do echo " $a"; done; } + +__get_machines() { + local a + + while read a _; do + echo " $a" + done < <(machinectl list --full --max-addresses=0 --no-legend --no-pager 2>/dev/null | sort -u; echo ".host") +} + +_systemctl () { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local i verb comps mode cur_orig + + local -A OPTS=( + [STANDALONE]='--all -a --reverse --after --before --defaults --force -f --full -l --global + --help -h --no-ask-password --no-block --legend=no --no-pager --no-reload --no-wall --now + --quiet -q --system --user --version --runtime --recursive -r --firmware-setup + --show-types --plain --failed --value --fail --dry-run --wait' + [ARG]='--host -H --kill-whom --property -p --signal -s --type -t --state --job-mode --root + --preset-mode -n --lines -o --output -M --machine --message --timestamp --check-inhibitors' + ) + + if __contains_word "--user" ${COMP_WORDS[*]}; then + mode=--user + elif __contains_word "--global" ${COMP_WORDS[*]}; then + mode=--user + else + mode=--system + fi + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --signal|-s) + _signals + return + ;; + --type|-t) + comps=$(__systemctl $mode -t help) + ;; + --state) + comps=$(__systemctl $mode --state=help) + ;; + --job-mode) + comps='fail replace replace-irreversibly isolate + ignore-dependencies ignore-requirements flush' + ;; + --kill-whom|--kill-who) + comps='all control main' + ;; + --root) + comps=$(compgen -A directory -- "$cur" ) + compopt -o filenames + ;; + --host|-H) + comps=$(compgen -A hostname) + ;; + --property|-p) + comps=$(__systemd_properties) + ;; + --preset-mode) + comps='full enable-only disable-only' + ;; + --output|-o) + comps=$( systemctl --output=help 2>/dev/null ) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --timestamp) + comps='pretty us µs utc us+utc µs+utc' + ;; + --check-inhibitors) + comps='auto yes no' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [ALL_UNITS]='cat mask' + [NONTEMPLATE_UNITS]='is-active is-failed is-enabled status show preset help list-dependencies edit set-property revert' + [ENABLED_UNITS]='disable' + [DISABLED_UNITS]='enable' + [REENABLABLE_UNITS]='reenable' + [FAILED_UNITS]='reset-failed' + [STARTABLE_UNITS]='start' + [STOPPABLE_UNITS]='stop condstop kill try-restart condrestart' + [ISOLATABLE_UNITS]='isolate' + [RELOADABLE_UNITS]='reload condreload try-reload-or-restart force-reload' + [RESTARTABLE_UNITS]='restart reload-or-restart' + [TARGET_AND_UNITS]='add-wants add-requires' + [MASKED_UNITS]='unmask' + [JOBS]='cancel' + [ENVS]='set-environment unset-environment import-environment' + [STANDALONE]='daemon-reexec daemon-reload default + emergency exit halt hibernate hybrid-sleep + suspend-then-hibernate kexec list-jobs list-sockets + list-timers list-units list-unit-files poweroff + reboot rescue show-environment suspend get-default + is-system-running preset-all list-automounts' + [FILE]='link switch-root' + [TARGETS]='set-default' + [MACHINES]='list-machines' + [LOG_LEVEL]='log-level' + [LOG_TARGET]='log-target' + [SERVICE_LOG_LEVEL]='service-log-level' + [SERVICE_LOG_TARGET]='service-log-target' + [SERVICE_WATCHDOGS]='service-watchdogs' + [MOUNT]='bind mount-image' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + # When trying to match a unit name with certain special characters in its name (i.e + # foo\x2dbar:01) they get (un)escaped by bash along the way, thus causing any possible + # match to fail. + # The following condition solves two cases: + # 1) We're trying to complete an already escaped unit name part, + # i.e foo\\x2dba. In this case we need to unescape the name, so it + # gets properly matched with the systemctl output (i.e. foo\x2dba). + # However, we need to keep the original escaped name as well for the + # final match, as the completion machinery does the unescaping + # automagically. + # 2) We're trying to complete an unescaped (literal) unit name part, + # i.e. foo\x2dba. That means we don't have to do the unescaping + # required for correct matching with systemctl's output, however, + # we need to escape the name for the final match, where the completion + # expects the string to be escaped. + cur_orig=$cur + if [[ $cur =~ '\\' ]]; then + cur="$(echo $cur | xargs echo)" + else + cur_orig="$(printf '%q' $cur)" + fi + + if [[ -z ${verb-} ]]; then + comps="${VERBS[*]}" + + elif __contains_word "$verb" ${VERBS[ALL_UNITS]}; then + comps=$( __get_all_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[NONTEMPLATE_UNITS]}; then + comps=$( __get_non_template_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[ENABLED_UNITS]}; then + comps=$( __get_enabled_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[DISABLED_UNITS]}; then + comps=$( __get_disabled_units $mode "$cur"; + __get_template_names $mode "$cur") + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[REENABLABLE_UNITS]}; then + comps=$( __get_disabled_units $mode "$cur"; + __get_enabled_units $mode "$cur"; + __get_template_names $mode "$cur") + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[STARTABLE_UNITS]}; then + comps=$( __get_startable_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[RESTARTABLE_UNITS]}; then + comps=$( __get_restartable_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[STOPPABLE_UNITS]}; then + comps=$( __get_stoppable_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[RELOADABLE_UNITS]}; then + comps=$( __get_reloadable_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[ISOLATABLE_UNITS]}; then + comps=$( __filter_units_by_properties $mode AllowIsolate=yes \ + $( __get_non_template_units $mode "$cur" ) ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[FAILED_UNITS]}; then + comps=$( __get_failed_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[MASKED_UNITS]}; then + comps=$( __get_masked_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[TARGET_AND_UNITS]}; then + if __contains_word "$prev" ${VERBS[TARGET_AND_UNITS]} \ + || __contains_word "$prev" ${OPTS[STANDALONE]}; then + comps=$( __systemctl $mode list-unit-files --type target --all "$cur*" \ + | { while read -r a b; do echo " $a"; done; } ) + else + comps=$( __get_all_unit_files $mode "$cur" ) + fi + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + + elif __contains_word "$verb" ${VERBS[JOBS]}; then + comps=$( __systemctl $mode list-jobs | { while read -r a b; do echo " $a"; done; } ) + + elif [ "$verb" = 'unset-environment' ]; then + comps=$( __systemctl $mode show-environment \ + | while read -r line; do echo " ${line%%=*}"; done ) + compopt -o nospace + + elif [ "$verb" = 'set-environment' ]; then + comps=$( __systemctl $mode show-environment \ + | while read -r line; do echo " ${line%%=*}="; done ) + compopt -o nospace + + elif [ "$verb" = 'import-environment' ]; then + COMPREPLY=( $(compgen -A variable -- "$cur_orig") ) + return 0 + + elif __contains_word "$verb" ${VERBS[FILE]}; then + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[TARGETS]}; then + comps=$( __systemctl $mode list-unit-files --type target --full --all "$cur*" \ + | { while read -r a b; do echo " $a"; done; } ) + elif __contains_word "$verb" ${VERBS[LOG_LEVEL]}; then + comps='debug info notice warning err crit alert emerg' + elif __contains_word "$verb" ${VERBS[LOG_TARGET]}; then + comps='console journal kmsg journal-or-kmsg null' + elif __contains_word "$verb" ${VERBS[SERVICE_LOG_LEVEL]}; then + if __contains_word "$prev" ${VERBS[SERVICE_LOG_LEVEL]}; then + comps=$( __get_all_unit_files $mode "$cur" ) + elif __contains_word "$prev" debug info notice warning err crit alert emerg; then + return 0 + else + comps='debug info notice warning err crit alert emerg' + fi + elif __contains_word "$verb" ${VERBS[SERVICE_LOG_TARGET]}; then + if __contains_word "$prev" ${VERBS[SERVICE_LOG_TARGET]}; then + comps=$( __get_all_unit_files $mode "$cur" ) + elif __contains_word "$prev" console journal kmsg journal-or-kmsg null; then + return 0 + else + comps='console journal kmsg journal-or-kmsg null' + fi + elif __contains_word "$verb" ${VERBS[SERVICE_WATCHDOGS]}; then + comps='on off' + elif __contains_word "$verb" ${VERBS[MOUNT]}; then + if __contains_word "$prev" ${VERBS[MOUNT]}; then + comps=$( __get_active_services $mode "$cur" ) + elif [[ "$prev" =~ .service ]]; then + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + else + return 0 + fi + fi + + COMPREPLY=( $(compgen -o filenames -W '$comps' -- "$cur_orig") ) + return 0 +} + +complete -F _systemctl systemctl diff --git a/shell-completion/bash/systemd-analyze b/shell-completion/bash/systemd-analyze new file mode 100644 index 0000000..da38574 --- /dev/null +++ b/shell-completion/bash/systemd-analyze @@ -0,0 +1,204 @@ +# systemd-analyze(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + { machinectl list --full --max-addresses=0 --no-legend --no-pager 2>/dev/null; echo ".host"; } | \ + { while read a b; do echo " $a"; done; } | \ + sort -u +} + +__get_units_all() { + systemctl list-units --no-legend --no-pager --plain --all | \ + { while read -r a b c; do echo " $a"; done } +} + +__get_services() { + systemctl list-units --no-legend --no-pager --plain -t service --all $1 | \ + { while read -r a b c; do [[ $b == "loaded" ]]; echo " $a"; done } +} + +__get_syscall_sets() { + local line + systemd-analyze syscall-filter --no-pager | while IFS= read -r line; do + if [[ $line == @* ]]; then + printf '%s\n' "$line" + fi + done +} + +_systemd_analyze() { + local i verb comps mode + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword + + local -A OPTS=( + [STANDALONE]='-h --help --version --system --user --global --order --require --no-pager + --man=no --generators=yes -q --quiet' + [ARG]='-H --host -M --machine --fuzz --from-pattern --to-pattern --root' + ) + + local -A VERBS=( + [STANDALONE]='time blame plot unit-paths exit-status calendar timestamp timespan' + [CRITICAL_CHAIN]='critical-chain' + [DOT]='dot' + [DUMP]='dump' + [VERIFY]='verify' + [SECCOMP_FILTER]='syscall-filter' + [CAT_CONFIG]='cat-config' + [SECURITY]='security' + [CONDITION]='condition' + [INSPECT_ELF]='inspect-elf' + ) + + local CONFIGS='systemd/bootchart.conf systemd/coredump.conf systemd/journald.conf + systemd/journal-remote.conf systemd/journal-upload.conf systemd/logind.conf + systemd/resolved.conf systemd/networkd.conf systemd/resolved.conf + systemd/sleep.conf systemd/system.conf systemd/timedated.conf + systemd/timesyncd.conf systemd/user.conf udev/udev.conf' + + _init_completion || return + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ -z ${verb-} && $cur = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + if [[ $cur = -* ]]; then + comps='--help --version --system --user --global --no-pager' + fi + + elif __contains_word "$verb" ${VERBS[CRITICAL_CHAIN]}; then + if [[ $cur = -* ]]; then + comps='--help --version --system --user --fuzz --no-pager' + else + comps=$( __get_units_all ) + fi + + elif __contains_word "$verb" ${VERBS[DOT]}; then + if [[ $cur = -* ]]; then + comps='--help --version --system --user --global --from-pattern --to-pattern --order --require' + fi + + elif __contains_word "$verb" ${VERBS[DUMP]}; then + if [[ $cur = -* ]]; then + comps='--help --version --system --user --no-pager' + else + comps=$( __get_units_all ) + fi + + elif __contains_word "$verb" ${VERBS[SECCOMP_FILTER]}; then + if [[ $cur = -* ]]; then + comps='--help --version --no-pager' + else + comps=$( __get_syscall_sets ) + fi + + elif __contains_word "$verb" ${VERBS[VERIFY]}; then + if [[ $cur = -* ]]; then + comps='--help --version --system --user --global --man=no --generators=yes --root --image --recursive-errors=no --recursive-errors=yes --recursive-errors=one' + else + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + fi + + elif __contains_word "$verb" ${VERBS[CAT_CONFIG]}; then + if [[ $cur = -* ]]; then + comps='--help --version --root --no-pager' + elif [[ -z $cur ]]; then + comps="$CONFIGS" + compopt -o filenames + else + comps="$CONFIGS $( compgen -A file -- "$cur" )" + compopt -o filenames + fi + + elif __contains_word "$verb" ${VERBS[SECURITY]}; then + if [[ $cur = -* ]]; then + comps='--help --version --no-pager --system --user -H --host -M --machine --offline --threshold --security-policy --json=off --json=pretty --json=short --root --image --profile=default --profile=nonetwork --profile=strict --profile=trusted' + elif ! __contains_word "--offline" ${COMP_WORDS[*]}; then + if __contains_word "--user" ${COMP_WORDS[*]}; then + mode=--user + else + mode=--system + fi + comps=$( __get_services $mode ) + else + comps="$CONFIGS $( compgen -A file -- "$cur" )" + compopt -o filenames + fi + + elif __contains_word "$verb" ${VERBS[CONDITION]}; then + if [[ $cur = -* ]]; then + comps='--help --version --system --user --global --no-pager --root --image' + elif [[ $prev = "-u" ]] || [[ $prev = "--unit" ]]; then + if __contains_word "--user" ${COMP_WORDS[*]}; then + mode=--user + else + mode=--system + fi + comps=$( __get_services $mode ) + fi + + elif __contains_word "$verb" ${VERBS[INSPECT_ELF]}; then + if [[ $cur = -* ]]; then + comps='--help --version --json=off --json=pretty --json=short' + else + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + fi + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _systemd_analyze systemd-analyze diff --git a/shell-completion/bash/systemd-cat b/shell-completion/bash/systemd-cat new file mode 100644 index 0000000..b209140 --- /dev/null +++ b/shell-completion/bash/systemd-cat @@ -0,0 +1,57 @@ +# systemd-cat(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +_systemd_cat() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword + local i verb comps + + local -A OPTS=( + [STANDALONE]='-h --help --version' + [ARG]='-t --identifier -p --priority --level-prefix' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --identifier|-t) + comps='' + ;; + --priority|-p) + comps='emerg alert crit err warning notice info debug' + ;; + --level-prefix) + comps='yes no' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) +} + +complete -F _systemd_cat systemd-cat diff --git a/shell-completion/bash/systemd-cgls b/shell-completion/bash/systemd-cgls new file mode 100644 index 0000000..8dda5a8 --- /dev/null +++ b/shell-completion/bash/systemd-cgls @@ -0,0 +1,71 @@ +# systemd-cgls(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + { machinectl list --full --max-addresses=0 --no-legend --no-pager 2>/dev/null; echo ".host"; } | \ + { while read a b; do echo " $a"; done; } | \ + sort -u +} + +__get_units_have_cgroup() { + systemctl $1 --full --no-legend --no-pager --plain list-units | { + while read -r a b c d; do + [[ $c == "active" && ${a##*.} =~ (service|socket|mount|swap|slice|scope) ]] && echo " $a" + done + }; +} + +_systemd_cgls() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword + local i verb comps + + local -A OPTS=( + [STANDALONE]='-h --help --version --all -l --full -k --no-pager --xattr=no --cgroup-id=no' + [ARG]='-M --machine -u --unit --user-unit' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --machine|-M) + comps=$( __get_machines ) + ;; + --unit|-u) + comps=$( __get_units_have_cgroup --system ) + ;; + --user-unit) + comps=$( __get_units_have_cgroup --user ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) +} + +complete -F _systemd_cgls systemd-cgls diff --git a/shell-completion/bash/systemd-cgtop b/shell-completion/bash/systemd-cgtop new file mode 100644 index 0000000..731d9c9 --- /dev/null +++ b/shell-completion/bash/systemd-cgtop @@ -0,0 +1,68 @@ +# systemd-cgtop(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + { machinectl list --full --max-addresses=0 --no-legend --no-pager 2>/dev/null; echo ".host"; } | \ + { while read a b; do echo " $a"; done; } | \ + sort -u +} + +_systemd_cgtop() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword + local comps + + local -A OPTS=( + [STANDALONE]='-h --help --version -p -t -c -m -i -b --batch -r --raw -k -P' + [ARG]='--cpu --depth -M --machine --recursive -n --iterations -d --delay --order' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --machine|-M) + comps=$( __get_machines ) + ;; + --recursive) + comps='yes no' + ;; + --order) + comps='path tasks cpu memory io' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + if [ -d /sys/fs/cgroup/systemd/ ]; then + COMPREPLY+=( $(cd /sys/fs/cgroup/systemd/ && compgen -o nospace -o dirnames "$cur") ) + elif [ -d /sys/fs/cgroup/ ]; then + COMPREPLY+=( $(cd /sys/fs/cgroup/ && compgen -o nospace -o dirnames "$cur") ) + fi +} + +complete -F _systemd_cgtop systemd-cgtop diff --git a/shell-completion/bash/systemd-cryptenroll b/shell-completion/bash/systemd-cryptenroll new file mode 100644 index 0000000..5953814 --- /dev/null +++ b/shell-completion/bash/systemd-cryptenroll @@ -0,0 +1,110 @@ +# systemd-cryptenroll(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_fido2_devices() { + local i + for i in /dev/hidraw*; do + [ -c "$i" ] && printf '%s\n' "$i" + done +} + +__get_tpm2_devices() { + local i + for i in /dev/tpmrm*; do + [ -c "$i" ] && printf '%s\n' "$i" + done +} + +__get_block_devices() { + local i + for i in /dev/*; do + [ -b "$i" ] && printf '%s\n' "$i" + done +} + +_systemd-cryptenroll() { + local comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword + local -A OPTS=( + [STANDALONE]='-h --help --version + --password --recovery-key' + [ARG]='--unlock-key-file + --pkcs11-token-uri + --fido2-credential-algorithm + --fido2-device + --fido2-with-client-pin + --fido2-with-user-presence + --fido2-with-user-verification + --tpm2-device + --tpm2-pcrs + --tpm2-public-key + --tpm2-public-key-pcrs + --tpm2-signature + --tpm2-with-pin + --wipe-slot' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --unlock-key-file|--tpm2-public-key|--tpm2-signature) + comps=$(compgen -A file -- "$cur") + compopt -o filenames + ;; + --pkcs11-token-uri) + comps='auto list pkcs11:' + ;; + --fido2-credential-algorithm) + comps='es256 rs256 eddsa' + ;; + --fido2-device) + comps="auto list $(__get_fido2_devices)" + ;; + --fido2-with-client-pin|--fido2-with-user-presence|--fido2-with-user-verification|--tpm2-with-pin) + comps='yes no' + ;; + --tpm2-device) + comps="auto list $(__get_tpm2_devices)" + ;; + --wipe-slot) + comps='all empty password recovery pkcs11 fido2 tpm2' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + comps=$(__get_block_devices) + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _systemd-cryptenroll systemd-cryptenroll diff --git a/shell-completion/bash/systemd-delta b/shell-completion/bash/systemd-delta new file mode 100644 index 0000000..b148755 --- /dev/null +++ b/shell-completion/bash/systemd-delta @@ -0,0 +1,60 @@ +# systemd-delta(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +_systemd-delta() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword + local comps + + local -A OPTS=( + [STANDALONE]='--help -h --no-pager --version' + [ARG]='--diff --type -t' + ) + + _init_completion || return + + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --diff) + comps='yes no' + ;; + --type|-t) + comps='masked equivalent redirected overridden unchanged extended default' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]] || [[ -z ${comps-} ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + COMPREPLY=( $(compgen -W '${comps-}' -- "$cur") ) + return 0 +} + +complete -F _systemd-delta systemd-delta diff --git a/shell-completion/bash/systemd-detect-virt b/shell-completion/bash/systemd-detect-virt new file mode 100644 index 0000000..05e4490 --- /dev/null +++ b/shell-completion/bash/systemd-detect-virt @@ -0,0 +1,40 @@ +# systemd-detect-virt(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +_systemd_detect_virt() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword + local i verb comps + + local -A OPTS=( + [STANDALONE]='-h --help --version -c --container -v --vm -q --quiet + --private-users' + ) + + _init_completion || return + + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) +} + +complete -F _systemd_detect_virt systemd-detect-virt diff --git a/shell-completion/bash/systemd-dissect b/shell-completion/bash/systemd-dissect new file mode 100644 index 0000000..5e1ce05 --- /dev/null +++ b/shell-completion/bash/systemd-dissect @@ -0,0 +1,104 @@ +# systemd-dissect(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +_systemd_dissect() { + local comps + local cur=${COMP_WORDS[COMP_CWORD]} prev_1=${COMP_WORDS[COMP_CWORD-1]} prev_2=${COMP_WORDS[COMP_CWORD-2]} words cword + local -A OPTS=( + [STANDALONE]='-h --help --version + --no-pager + --no-legend + -r --read-only + --mkdir + --rmdir' + [ARG]='-m --mount -M + -u --umount -U + -x --copy-from + -a --copy-to + --fsck + --growfs + --discard + --root-hash + --root-hash-sig + --verity-data + --json' + ) + + _init_completion || return + + if __contains_word "$prev_1" ${OPTS[ARG]}; then + case $prev_1 in + -m|--mount|-M|-x|--copy-from|-a|--copy-to|--verity-data) + comps=$(compgen -A file -- "$cur") + compopt -o filenames + ;; + -u|--umount|-U) + comps=$(compgen -A directory -- "$cur" ) + compopt -o dirnames + ;; + --fsck|--growfs) + comps='yes no' + ;; + --discard) + comps='disabled loop all crypto' + ;; + --root-hash-sig) + comps="base64: $(compgen -A file -- "$cur")" + compopt -o filenames + ;; + --json) + comps='pretty short off' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if __contains_word "$prev_2" ${OPTS[ARG]}; then + case $prev_2 in + -m|--mount|-M) + comps=$(compgen -A directory -- "$cur" ) + compopt -o dirnames + ;; + *) + comps=$(compgen -A file -- "$cur" ) + compopt -o filenames + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + COMPREPLY=( $(compgen -A file -- "$cur") ) + compopt -o filenames + return 0 +} + +complete -F _systemd_dissect systemd-dissect diff --git a/shell-completion/bash/systemd-id128 b/shell-completion/bash/systemd-id128 new file mode 100644 index 0000000..1c19639 --- /dev/null +++ b/shell-completion/bash/systemd-id128 @@ -0,0 +1,74 @@ +# systemd-id128(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done + return 1 +} + +_systemd_id128() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword + local -A OPTS=( + [STANDALONE]='-h --help --version -p --pretty' + [ARG]='-a --app-specific' + ) + + local -A VERBS=( + [STANDALONE]='new machine-id boot-id invocation-id help' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --app-specific|-a) + comps="" + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _systemd_id128 systemd-id128 diff --git a/shell-completion/bash/systemd-nspawn b/shell-completion/bash/systemd-nspawn new file mode 100644 index 0000000..cc3d2f6 --- /dev/null +++ b/shell-completion/bash/systemd-nspawn @@ -0,0 +1,200 @@ +# systemd-nspawn(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_users() { + local a b + loginctl list-users --no-legend --no-pager | { while read a b; do echo " $b"; done; }; +} + +__get_slices() { + local a b + systemctl list-units -t slice --no-legend --no-pager --plain | { while read a b; do echo " $a"; done; }; +} + +__get_machines() { + local a b + { machinectl list --full --max-addresses=0 --no-legend --no-pager 2>/dev/null; echo ".host"; } | \ + { while read a b; do echo " $a"; done; } | \ + sort -u +} + +__get_env() { + local a + env | { while read a; do echo " ${a%%=*}"; done; }; +} + +__get_interfaces(){ + local name + for name in $(cd /sys/class/net && command ls); do + [[ "$name" != "lo" ]] && echo "$name" + done +} + +__get_rlimit() { + local i + for i in $(systemd-nspawn --rlimit=help 2>/dev/null); do + echo " ${i}=" + done +} + +_systemd_nspawn() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword + local i verb comps + + local -A OPTS=( + [STANDALONE]='-h --help --version --private-network -b --boot --read-only -q --quiet --share-system + --keep-unit -n --network-veth -j -x --ephemeral -a --as-pid2 -U --suppress-sync=yes' + [ARG]='-D --directory -u --user --uuid --capability --drop-capability --link-journal --bind --bind-ro + -M --machine -S --slice -E --setenv -Z --selinux-context -L --selinux-apifs-context + --register --network-interface --network-bridge --personality -i --image --tmpfs + --volatile --network-macvlan --kill-signal --template --notify-ready --root-hash --chdir + --pivot-root --property --private-users --private-users-ownership --network-namespace-path + --network-ipvlan --network-veth-extra --network-zone -p --port --system-call-filter --overlay + --overlay-ro --settings --rlimit --hostname --no-new-privileges --oom-score-adjust --cpu-affinity + --resolv-conf --timezone --root-hash-sig' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --directory|-D|--template) + compopt -o nospace + comps=$(compgen -S/ -A directory -- "$cur" ) + ;; + --user|-u) + comps=$( __get_users ) + ;; + --uuid|--root-hash) + comps='' + ;; + --capability) + comps='CAP_BLOCK_SUSPEND CAP_IPC_LOCK CAP_MAC_ADMIN CAP_MAC_OVERRIDE CAP_SYS_MODULE CAP_SYS_PACCT CAP_SYS_RAWIO + CAP_SYS_TIME CAP_SYSLOG CAP_WAKE_ALARM CAP_NET_ADMIN' + ;; + --drop-capability) + comps='CAP_AUDIT_CONTROL CAP_AUDIT_WRITE CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_FSETID + CAP_IPC_OWNER CAP_KILL CAP_LEASE CAP_LINUX_IMMUTABLE CAP_MKNOD CAP_NET_ADMIN CAP_NET_BIND_SERVICE + CAP_NET_BROADCAST CAP_NET_RAW CAP_SETFCAP CAP_SETGID CAP_SETPCAP CAP_SETUID CAP_SYS_ADMIN CAP_SYS_BOOT + CAP_SYS_CHROOT CAP_SYS_NICE CAP_SYS_PTRACE CAP_SYS_RESOURCE CAP_SYS_TTY_CONFIG' + ;; + --link-journal) + comps='no auto guest try-guest host try-host' + ;; + --bind|--bind-ro) + compopt -o nospace -o filenames + comps=$(compgen -f -- "$cur" ) + ;; + --tmpfs) + compopt -o nospace + comps=$(compgen -S/ -A directory -- "$cur" ) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --slice|-S) + comps=$( __get_slices ) + ;; + --setenv|-E) + comps=$( __get_env ) + ;; + --selinux-context|-Z) + comps='' + ;; + --selinux-apifs-context|-L) + comps='' + ;; + --register) + comps='yes no' + ;; + --network-interface) + comps=$(__get_interfaces) + ;; + --network-bridge) + comps='' + ;; + --network-macvlan) + comps='' + ;; + --personality) + comps='x86 x86-64' + ;; + --volatile) + comps=$( systemd-nspawn --volatile=help 2>/dev/null ) + ;; + --image|-i) + compopt -o nospace + comps=$( compgen -A file -- "$cur" ) + ;; + --kill-signal) + _signals + return + ;; + --notify-ready) + comps='yes no' + ;; + --private-users) + comps='yes no pick' + ;; + --network-namespace-path) + comps=$( compgen -A file -- "$cur" ) + ;; + --settings) + comps='yes no override trusted' + ;; + --rlimit) + comps=$( __get_rlimit ) + ;; + --hostname) + comps='' + ;; + --no-new-privileges) + comps='yes no' + ;; + --oom-score-adjust) + comps='' + ;; + --cpu-affinity) + comps='' + ;; + --resolv-conf) + comps=$( systemd-nspawn --resolv-conf=help 2>/dev/null ) + ;; + --timezone) + comps=$( systemd-nspawn --timezone=help 2>/dev/null ) + ;; + --root-hash-sig) + compopt -o nospace + comps=$( compgen -A file -- "$cur" ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) +} + +complete -F _systemd_nspawn systemd-nspawn diff --git a/shell-completion/bash/systemd-path b/shell-completion/bash/systemd-path new file mode 100644 index 0000000..40e2f7e --- /dev/null +++ b/shell-completion/bash/systemd-path @@ -0,0 +1,61 @@ +# systemd-path(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done + return 1 +} + +__get_names() { + systemd-path | { while IFS=: read -r a b; do echo " $a"; done; } +} + +_systemd_path() { + local comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword + local -A OPTS=( + [STANDALONE]='-h --help --version' + [ARG]='--suffix' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --suffix) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + comps=$( __get_names ) + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _systemd_path systemd-path diff --git a/shell-completion/bash/systemd-resolve b/shell-completion/bash/systemd-resolve new file mode 100644 index 0000000..20d904a --- /dev/null +++ b/shell-completion/bash/systemd-resolve @@ -0,0 +1,80 @@ +# systemd-resolve(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_interfaces(){ + local name + for name in $(cd /sys/class/net && command ls); do + [[ "$name" != "lo" ]] && echo "$name" + done +} + +_systemd-resolve() { + local i comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-h --help --version --no-pager -4 -6 + --service --openpgp --tlsa --status --statistics + --reset-statistics --service-address=no --service-txt=no + --cname=no --search=no --legend=no --flush-caches + --reset-server-features --revert' + [ARG]='-i --interface -p --protocol -t --type -c --class --raw + --set-dns --set-domain --set-llmnr --set-mdns --set-dnssec --set-nta' + ) + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --interface|-i) + comps=$( __get_interfaces ) + ;; + --protocol|-p|--type|-t|--class|-c) + comps=$( systemd-resolve --legend=no "$prev" help; echo help ) + ;; + --raw) + comps="payload packet" + ;; + --set-dns|--set-domain|--set-nta) + comps="" + ;; + --set-llmnr|--set-mdns) + comps="yes no resolve" + ;; + --set-dnssec) + comps="yes no allow-downgrade" + ;; + --set-dnsovertls) + comps="yes no opportunistic" + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]] || [[ -z ${comps-} ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi +} + +complete -F _systemd-resolve systemd-resolve diff --git a/shell-completion/bash/systemd-run b/shell-completion/bash/systemd-run new file mode 100644 index 0000000..c18228d --- /dev/null +++ b/shell-completion/bash/systemd-run @@ -0,0 +1,132 @@ +# systemd-run(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__systemctl() { + local mode=$1; shift 1 + systemctl $mode --full --no-legend --no-pager --plain "$@" +} + +__get_slice_units () { __systemctl $1 list-units --all -t slice \ + | { while read -r a b c d; do echo " $a"; done; }; } + +__get_machines() { + local a b + { machinectl list --full --max-addresses=0 --no-legend --no-pager 2>/dev/null; echo ".host"; } | \ + { while read a b; do echo " $a"; done; } | \ + sort -u +} + +_systemd_run() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local OPTS='--no-ask-password --scope -u --unit -p --property --description --slice --slice-inherit + -r --remain-after-exit --send-sighup --service-type --uid --gid --nice + --working-directory -d --same-dir -E --setenv -t --pty -P --pipe -S --shell -q --quiet + --on-active --on-boot --on-startup --on-unit-active --on-unit-inactive --on-calendar + --on-clock-change --on-timezone-change --path-property --socket-property + --timer-property --no-block --wait -G --collect --user --system -H --host -M --machine + -h --help --version' + + local mode=--system + local i + local opts_with_values=( + --unit -p --property --slice --description --service-type --uid --gid --nice --working-directory + -E --setenv --on-active --on-boot --on-startup --on-unit-active --on-unit-inactive --on-calendar + --path-property --socket-property --timer-property -H --host -M --machine + ) + for (( i=1; i <= COMP_CWORD; i++ )); do + if [[ ${COMP_WORDS[i]} != -* ]]; then + local root_command=${COMP_WORDS[i]} + _command_offset $i + return + fi + + [[ ${COMP_WORDS[i]} == "--user" ]] && mode=--user + + [[ $i -lt $COMP_CWORD && " ${opts_with_values[@]} " =~ " ${COMP_WORDS[i]} " ]] && ((i++)) + done + + case "$prev" in + --unit|--description|--on-active|--on-boot|--on-startup|--on-unit-active|--on-unit-inactive|--on-calendar) + # argument required but no completions available + return + ;; + --slice) + local comps=$(__get_slice_units $mode) + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + ;; + --service-type) + local comps='simple forking oneshot dbus notify idle' + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + ;; + -p|--property) + local comps='CPUAccounting= MemoryAccounting= BlockIOAccounting= SendSIGHUP= + SendSIGKILL= MemoryLimit= CPUShares= BlockIOWeight= User= Group= + DevicePolicy= KillMode= ExitType= DeviceAllow= BlockIOReadBandwidth= + BlockIOWriteBandwidth= BlockIODeviceWeight= Nice= Environment= + KillSignal= RestartKillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA= + LimitSTACK= LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC= + LimitMEMLOCK= LimitLOCKS= LimitSIGPENDING= LimitMSGQUEUE= + LimitNICE= LimitRTPRIO= LimitRTTIME= PrivateTmp= PrivateDevices= + PrivateNetwork= NoNewPrivileges= WorkingDirectory= RootDirectory= + TTYPath= SyslogIdentifier= SyslogLevelPrefix= SyslogLevel= + SyslogFacility= TimerSlackNSec= OOMScoreAdjust= ReadWritePaths= + ReadOnlyPaths= InaccessiblePaths= EnvironmentFile= + ProtectSystem= ProtectHome= RuntimeDirectory= PassEnvironment=' + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + ;; + -H|--host) + local comps=$(compgen -A hostname) + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + ;; + -M|--machine) + local comps=$( __get_machines ) + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + ;; + --timer-property) + local comps='AccuracySec= WakeSystem=' + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + ;; + --working-directory) + local comps + if [[ -z $cur ]]; then + comps=$(compgen -A directory -- "/" ) + else + comps=$(compgen -A directory -- "$cur" ) + fi + compopt -o filenames + COMPREPLY=( $(compgen -W '$comps' -- "$cur" ) ) + return 0 + ;; + esac + + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 +} + +complete -F _systemd_run systemd-run diff --git a/shell-completion/bash/systemd-sysext b/shell-completion/bash/systemd-sysext new file mode 100644 index 0000000..b3f9f32 --- /dev/null +++ b/shell-completion/bash/systemd-sysext @@ -0,0 +1,85 @@ +# systemd-sysext(8) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +_systemd-sysext() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} words cword + local -A OPTS=( + [STANDALONE]='-h --help --version + --no-pager + --no-legend + --force' + [ARG]='--root + --json' + ) + + local -A VERBS=( + [STANDALONE]='status + merge + unmerge + refresh + list' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --root) + comps=$(compgen -A directory -- "$cur" ) + compopt -o dirnames + ;; + --json) + comps='pretty short off' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _systemd-sysext systemd-sysext diff --git a/shell-completion/bash/timedatectl b/shell-completion/bash/timedatectl new file mode 100644 index 0000000..768b4a5 --- /dev/null +++ b/shell-completion/bash/timedatectl @@ -0,0 +1,97 @@ +# timedatectl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + { machinectl list --full --max-addresses=0 --no-legend --no-pager 2>/dev/null; echo ".host"; } | \ + { while read a b; do echo " $a"; done; } | \ + sort -u +} + +__get_interfaces(){ + local name + for name in $(cd /sys/class/net && command ls); do + [[ "$name" != "lo" ]] && echo "$name" + done +} +_timedatectl() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local OPTS='-h --help --version --adjust-system-clock --no-pager + --no-ask-password -H --host -M --machine --monitor + -p --property -a --all --value' + + if __contains_word "$prev" $OPTS; then + case $prev in + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [BOOLEAN]='set-local-rtc set-ntp' + [STANDALONE]='status show list-timezones timesync-status show-timesync' + [TIMEZONES]='set-timezone' + [TIME]='set-time' + [IFNAME]='ntp-servers revert' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z ${verb-} ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[BOOLEAN]}; then + comps='true false' + elif __contains_word "$verb" ${VERBS[TIMEZONES]}; then + comps=$(command timedatectl list-timezones) + elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[TIME]}; then + comps='' + elif __contains_word "$verb" ${VERBS[TIMEZONES]}; then + comps=$( __get_interfaces ) + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _timedatectl timedatectl diff --git a/shell-completion/bash/udevadm b/shell-completion/bash/udevadm new file mode 100644 index 0000000..99d4aa5 --- /dev/null +++ b/shell-completion/bash/udevadm @@ -0,0 +1,296 @@ +# udevadm(8) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see <https://www.gnu.org/licenses/>. + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_all_sysdevs() { + local -a devs=(/sys/bus/*/devices/*/ /sys/class/*/*/) + printf '%s\n' "${devs[@]%/}" +} + +__get_all_devs() { + local i + for i in /dev/* /dev/*/* /dev/*/*/*; do + echo $i + done +} + +__get_all_device_units() { + systemctl list-units -t device --full --no-legend --no-pager --plain 2>/dev/null | \ + { while read -r a b; do echo "$a"; done; } +} + +_udevadm() { + local i verb comps builtin + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [COMMON]='-h --help -V --version' + [DEBUG]='-d --debug' + [INFO_STANDALONE]='-r --root -a --attribute-walk -x --export -e --export-db -c --cleanup-db + -w --wait-for-initialization --value' + [INFO_ARG]='-q --query -p --path -n --name -P --export-prefix -d --device-id-of-file --property' + [TRIGGER_STANDALONE]='-v --verbose -n --dry-run -q --quiet -w --settle --wait-daemon --uuid + --initialized-match --initialized-nomatch' + [TRIGGER_ARG]='-t --type -c --action -s --subsystem-match -S --subsystem-nomatch + -a --attr-match -A --attr-nomatch -p --property-match + -g --tag-match -y --sysname-match --name-match -b --parent-match + --prioritized-subsystem' + [SETTLE]='-t --timeout -E --exit-if-exists' + [CONTROL_STANDALONE]='-e --exit -s --stop-exec-queue -S --start-exec-queue -R --reload --ping' + [CONTROL_ARG]='-l --log-priority -p --property -m --children-max -t --timeout' + [MONITOR_STANDALONE]='-k --kernel -u --udev -p --property' + [MONITOR_ARG]='-s --subsystem-match -t --tag-match' + [TEST]='-a --action -N --resolve-names' + [TEST_BUILTIN]='-a --action' + [WAIT]='-t --timeout --initialized=no --removed --settle' + [LOCK]='-t --timeout -d --device -b --backing -p --print' + ) + + local verbs=(info trigger settle control monitor test-builtin test wait lock) + local builtins=(blkid btrfs hwdb input_id keyboard kmod net_id net_setup_link path_id usb_id uaccess) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" "${verbs[@]}"; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z ${verb-} ]]; then + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[COMMON]} ${OPTS[DEBUG]}' -- "$cur") ) + else + COMPREPLY=( $(compgen -W '${verbs[*]}' -- "$cur") ) + fi + return 0 + fi + + case $verb in + 'info') + if __contains_word "$prev" ${OPTS[INFO_ARG]}; then + case $prev in + -q|--query) + comps='name symlink path property all' + ;; + -p|--path) + comps=$( __get_all_sysdevs ) + local IFS=$'\n' + ;; + -n|--name) + comps=$( __get_all_devs ) + ;; + *) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + comps="${OPTS[COMMON]} ${OPTS[INFO_STANDALONE]} ${OPTS[INFO_ARG]}" + else + comps=$( __get_all_sysdevs; __get_all_device_units ) + local IFS=$'\n' + fi + ;; + + 'trigger') + if __contains_word "$prev" ${OPTS[TRIGGER_ARG]}; then + case $prev in + -t|--type) + comps='all devices subsystems' + ;; + -c|--action) + comps=$( udevadm trigger --action help ) + ;; + -y|--sysname-match|-b|--parent-match) + comps=$( __get_all_sysdevs ) + local IFS=$'\n' + ;; + --name-match) + comps=$( __get_all_devs ) + ;; + *) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + comps="${OPTS[COMMON]} ${OPTS[TRIGGER_STANDALONE]} ${OPTS[TRIGGER_ARG]}" + else + comps=$( __get_all_sysdevs; __get_all_device_units ) + local IFS=$'\n' + fi + ;; + + 'settle') + if __contains_word "$prev" ${OPTS[SETTLE]}; then + case $prev in + -E|--exit-if-exists) + comps=$( compgen -A file -- "$cur" ) + ;; + *) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + comps="${OPTS[COMMON]} ${OPTS[SETTLE]}" + ;; + + 'control') + if __contains_word "$prev" ${OPTS[CONTROL_ARG]}; then + case $prev in + -l|--log-priority) + comps='alert crit debug emerg err info notice warning' + ;; + *) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + comps="${OPTS[COMMON]} ${OPTS[CONTROL_STANDALONE]} ${OPTS[CONTROL_ARG]}" + ;; + + 'monitor') + if __contains_word "$prev" ${OPTS[MONITOR_ARG]}; then + case $prev in + *) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + comps="${OPTS[COMMON]} ${OPTS[MONITOR_STANDALONE]} ${OPTS[MONITOR_ARG]}" + ;; + + 'test') + if __contains_word "$prev" ${OPTS[TEST]}; then + case $prev in + -a|--action) + comps=$( udevadm test --action help ) + ;; + -N|--resolve-names) + comps='early late never' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + comps="${OPTS[COMMON]} ${OPTS[TEST]}" + else + comps=$( __get_all_sysdevs ) + local IFS=$'\n' + fi + ;; + + 'test-builtin') + if __contains_word "$prev" ${OPTS[TEST_BUILTIN]}; then + case $prev in + -a|--action) + comps=$( udevadm test-builtin --action help ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" "${builtins[@]}"; then + builtin=${COMP_WORDS[i]} + break + fi + done + + if [[ -z $builtin ]]; then + comps="${builtins[@]}" + elif [[ $cur = -* ]]; then + comps="${OPTS[COMMON]} ${OPTS[TEST_BUILTIN]}" + else + comps=$( __get_all_sysdevs ) + local IFS=$'\n' + fi + ;; + + 'wait') + if __contains_word "$prev" ${OPTS[WAIT]}; then + case $prev in + *) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + comps="${OPTS[COMMON]} ${OPTS[WAIT]}" + else + comps=$( __get_all_devs ) + local IFS=$'\n' + fi + ;; + + 'lock') + if __contains_word "$prev" ${OPTS[LOCK]}; then + case $prev in + *) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + comps="${OPTS[COMMON]} ${OPTS[LOCK]}" + else + comps='' + fi + ;; + + *) + comps=${VERBS[*]} + ;; + esac + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _udevadm udevadm |