Systemd/shell-completion/bash/systemctl.in
Zbigniew Jędrzejewski-Szmek c6a373a263 bash-completion: use list-unit-files to get "all" units
I think that it is better to return good results slightly more slowly,
than partial quickly. Also reading from disk seems fast enough. Even
the delay on first try with completely cold cache is acceptable.

This is just for bash, 'cause zsh was already doing this.

https://bugzilla.redhat.com/show_bug.cgi?id=790768
2014-07-26 20:15:38 -04:00

229 lines
9.7 KiB
Bash

# systemctl(1) completion -*- shell-script -*-
#
# 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 <http://www.gnu.org/licenses/>.
__systemctl() {
local mode=$1; shift 1
systemctl $mode --full --no-legend "$@"
}
__systemd_properties() {
local mode=$1
{ __systemctl $mode show --all;
@rootlibexecdir@/systemd --dump-configuration-items; } |
while IFS='=' read -r key value; do
[[ $value ]] && echo "$key"
done
}
__contains_word () {
local w word=$1; shift
for w in "$@"; do
[[ $w = "$word" ]] && return
done
}
__filter_units_by_property () {
local mode=$1 property=$2 value=$3 ; shift 3
local units=("$@")
local props
IFS=$'\n' read -rd '' -a props < \
<(__systemctl $mode show --property "$property" -- "${units[@]}")
for ((i=0; $i < ${#units[*]}; i++)); do
if [[ "${props[i]}" = "$property=$value" ]]; then
echo " ${units[i]}"
fi
done
}
__get_all_units () { { __systemctl $1 list-unit-files; __systemctl $1 list-units --all; } \
| { while read -r a b; do echo " $a"; done; }; }
__get_active_units () { __systemctl $1 list-units \
| { while read -r a b; do echo " $a"; done; }; }
__get_startable_units () { {
__systemctl $1 list-units --all -t service,timer,socket,mount,automount,path,snapshot,swap
__systemctl $1 list-unit-files -t service,timer,socket,mount,automount,path,snapshot,swap; } \
| { while read -r a b c d; do [[ $c == "inactive" || $c == "failed" ]] && echo " $a"; done; }; }
__get_failed_units () { __systemctl $1 list-units \
| { while read -r a b c d; do [[ $c == "failed" ]] && echo " $a"; done; }; }
__get_enabled_units () { __systemctl $1 list-unit-files \
| { while read -r a b c ; do [[ $b == "enabled" ]] && echo " $a"; done; }; }
__get_disabled_units () { __systemctl $1 list-unit-files \
| { while read -r a b c ; do [[ $b == "disabled" ]] && echo " $a"; done; }; }
__get_masked_units () { __systemctl $1 list-unit-files \
| { while read -r a b c ; do [[ $b == "masked" ]] && echo " $a"; done; }; }
_systemctl () {
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
local i verb comps mode
local -A OPTS=(
[STANDALONE]='--all -a --reverse --after --before --defaults --fail --ignore-dependencies --failed --force -f --full -l --global
--help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall
--quiet -q --privileged -P --system --user --version --runtime --recursive -r'
[ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --root'
)
if __contains_word "--user" ${COMP_WORDS[*]}; then
mode=--user
else
mode=--system
fi
if __contains_word "$prev" ${OPTS[ARG]}; then
case $prev in
--signal|-s)
comps=$(compgen -A signal)
;;
--type|-t)
comps='automount busname device mount path service snapshot socket swap target timer'
;;
--state)
comps='loaded not-found stub
active inactive
dead elapsed exited listening mounted plugged running waiting'
;;
--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 $mode)
;;
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]='is-active is-failed is-enabled status show cat mask preset help list-dependencies'
[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 reload-or-try-restart force-reload'
[RESTARTABLE_UNITS]='restart reload-or-restart'
[MASKED_UNITS]='unmask'
[JOBS]='cancel'
[SNAPSHOTS]='delete'
[ENVS]='set-environment unset-environment'
[STANDALONE]='daemon-reexec daemon-reload default
emergency exit halt hibernate hybrid-sleep kexec list-jobs
list-sockets list-timers list-units list-unit-files poweroff
reboot rescue show-environment suspend get-default'
[NAME]='snapshot'
[FILE]='link'
[TARGETS]='set-default'
)
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[ALL_UNITS]}; then
comps=$( __get_all_units $mode )
elif __contains_word "$verb" ${VERBS[ENABLED_UNITS]}; then
comps=$( __get_enabled_units $mode )
elif __contains_word "$verb" ${VERBS[DISABLED_UNITS]}; then
comps=$( __get_disabled_units $mode )
elif __contains_word "$verb" ${VERBS[REENABLABLE_UNITS]}; then
comps=$( __get_disabled_units $mode;
__get_enabled_units $mode )
elif __contains_word "$verb" ${VERBS[STARTABLE_UNITS]}; then
comps=$( __filter_units_by_property $mode CanStart yes \
$( __get_startable_units $mode))
elif __contains_word "$verb" ${VERBS[RESTARTABLE_UNITS]}; then
comps=$( __filter_units_by_property $mode CanStart yes \
$( __get_all_units $mode \
| while read -r line; do \
[[ "$line" =~ \.(device|snapshot|socket|timer)$ ]] || echo " $line"; \
done ))
elif __contains_word "$verb" ${VERBS[STOPPABLE_UNITS]}; then
comps=$( __filter_units_by_property $mode CanStop yes \
$( __get_active_units $mode ) )
elif __contains_word "$verb" ${VERBS[RELOADABLE_UNITS]}; then
comps=$( __filter_units_by_property $mode CanReload yes \
$( __get_active_units $mode ) )
elif __contains_word "$verb" ${VERBS[ISOLATABLE_UNITS]}; then
comps=$( __filter_units_by_property $mode AllowIsolate yes \
$( __get_all_units $mode ) )
elif __contains_word "$verb" ${VERBS[FAILED_UNITS]}; then
comps=$( __get_failed_units $mode )
elif __contains_word "$verb" ${VERBS[MASKED_UNITS]}; then
comps=$( __get_masked_units $mode )
elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[NAME]}; then
comps=''
elif __contains_word "$verb" ${VERBS[JOBS]}; then
comps=$( __systemctl $mode list-jobs | { while read -r a b; do echo " $a"; done; } )
elif __contains_word "$verb" ${VERBS[SNAPSHOTS]}; then
comps=$( __systemctl $mode list-units --type snapshot --full --all \
| { while read -r a b; do echo " $a"; done; } )
elif __contains_word "$verb" ${VERBS[ENVS]}; then
comps=$( __systemctl $mode show-environment \
| while read -r line; do echo " ${line%%=*}=";done )
compopt -o nospace
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 \
| { while read -r a b; do echo " $a"; done; } )
fi
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
return 0
}
complete -F _systemctl systemctl