From e5f1efa5a23213fdeb64907fbb5fc8db37aa5e0a Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 24 Oct 2011 11:32:41 +0000 Subject: Foudil Brétel: 29842: major update to systemctl completion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChangeLog | 7 +- Completion/Unix/Command/_systemctl | 339 +++++++++++++++++++++++++++++-------- 2 files changed, 270 insertions(+), 76 deletions(-) diff --git a/ChangeLog b/ChangeLog index 47fc89954..2f20a43af 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-24 Peter Stephenson + + * Foudil Brétel: 29842: Completion/Unix/Command/_systemctl: + major rewrite. + 2011-10-24 Phil Pennock * 29838: Src/Modules/pcre.c: metafy/unmetafy strings, to @@ -15492,5 +15497,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5482 $ +* $Revision: 1.5483 $ ***************************************************** diff --git a/Completion/Unix/Command/_systemctl b/Completion/Unix/Command/_systemctl index 5dd35db7a..801a8e060 100644 --- a/Completion/Unix/Command/_systemctl +++ b/Completion/Unix/Command/_systemctl @@ -1,102 +1,291 @@ #compdef systemctl -# Completion for systemd's systemctl -# Version 1.0 ARF 3 August 2011 +# Copyright (c) 2011 Foudil Brétel +# +# This file is released under the GPLv3. +# +# inspired from _yum and systemctl-bash-completion.sh (shipped with systemctl) +# +# TODO: enable options after commands. Ex: systemctl list-units --all --full -# list the unit completions. -_systemd_units(){ - local -a units - local expl - units=(${(f)"$( systemctl --full list-units | sed -e 's/ .*//' )"}) - _wanted keys expl 'units' compadd "$units[@]" -} - -# list the job completions. -_systemd_jobs(){ - local -a jobs - local expl - jobs=(${(f)"$( systemctl --full list-jobs | sed -e 's/ .*//' )"}) - _wanted keys expl 'jobs' compadd "$jobs[@]" -} - -# list the snapshot completions. -_systemd_snapshots(){ - local -a ss - local expl - ss=(${(f)"$( - systemctl dump | sed -n -e 's/^-> Unit \(.*\.snapshot\):/\1/p' - )"}) - _wanted keys expl 'snapshots' compadd "$ss[@]" -} - -_systemctl(){ - local -a _systemctl_cmds +# Main dispatcher +_systemctl() +{ + local curcontext="$curcontext" state lstate line - # Determine the sub commands - #$(systemctl --help | sed -n -e 's/^ \([a-z]\)/\1/p' | sed -e 's/ .*//') - _systemctl_cmds=( - list-units start stop reload restart try-restart reload-or- - restart reload-or-try-restart isolate kill is-active status show - reset-failed enable disable is-enabled load list-jobs cancel - monitor dump dot snapshot delete daemon-reload daemon-reexec show- - environment set-environment unset-environment default rescue - emergency halt poweroff reboot kexec exit - ) - - local curcontext="$curcontext" state line expl - typeset -A opt_args - - # Initial flags - _arguments -A '-*' \ - '--help[Show help]' \ + # -s for aggregated options like -aP + _arguments -s \ + {-h,--help}'[Show help]' \ '--version[Show package version]' \ - '(-a,--all)'{-a,--all}'[Show all units/properties, including dead/empty ones]' \ - '--full[Dont ellipsize unit names on output]' \ + {-t,--type=}'[List only units of a particular type]:unit type:(automount device mount path service snapshot socket swap target timer)' \ + \*{-p,--property=}'[Show only properties by specific name]:unit property:' \ + {-a,--all}'[Show all units/properties, including dead/empty ones]' \ '--failed[Show only failed units]' \ + "--full[Don't ellipsize unit names on output]" \ '--fail[When queueing a new job, fail if conflicting jobs are pending]' \ - '--ignore-dependencies[ignore dependencies]' \ - '(-p,--privileged)'{-p,--privileged}'[Acquire privileges before execution]' \ - '(-q,--quiet)'{-q,--quiet}'[Suppress output]' \ + '--ignore-dependencies[When queueing a new job, ignore all its dependencies]' \ + '--kill-mode=[How to send signal]:killmode:(control-group process)' \ + '--kill-who=[Who to send signal to]:killwho:(main control all)' \ + {-s,--signal=}'[Which signal to send]:signal:_signals' \ + {-H,--host=}'[Show information for remote host]:userathost:_hosts_or_user_at_host' \ + {-P,--privileged}'[Acquire privileges before execution]' \ + {-q,--quiet}'[Suppress output]' \ '--no-block[Do not wait until operation finished]' \ - '--no-wall[Dont send wall message before halt/power-off/reboot]' \ - '--no-reload[dont reload daemon configuration]' \ - '--no-pager[Do use pager]' \ + "--no-wall[Don't send wall message before halt/power-off/reboot]" \ + "--no-reload[When enabling/disabling unit files, don't reload daemon configuration]" \ + '--no-pager[Do not pipe output into a pager]' \ '--no-ask-password[Do not ask for system passwords]' \ '--order[When generating graph for dot, show only order]' \ '--require[When generating graph for dot, show only requirement]' \ '--system[Connect to system manager]' \ '--user[Connect to user service manager]' \ '--global[Enable/disable unit files globally]' \ - '(-f,--force)'{-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \ + {-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \ '--defaults[When disabling unit files, remove default symlinks only]' \ - '*::command:->subcmd' && return 0 + '*::systemctl command:_systemctl_command' +} + +_hosts_or_user_at_host() +{ + _alternative \ + 'users-hosts:: _user_at_host' \ + 'hosts:: _hosts' +} + +(( $+functions[_systemctl_command] )) || _systemctl_command() +{ + local -a _systemctl_cmds + _systemctl_cmds=( + "list-units:List units" + "start:Start (activate) one or more units" + "stop:Stop (deactivate) one or more units" + "reload:Reload one or more units" + "restart:Start or restart one or more units" + "try-restart:Restart one or more units if active" + "reload-or-restart:Reload one or more units is possible, otherwise start or restart" + "reload-or-try-restart:Reload one or more units is possible, otherwise restart if active" + "isolate:Start one unit and stop all others" + "kill:Send signal to processes of a unit" + "is-active:Check whether units are active" + "status:Show runtime status of one or more units" + "show:Show properties of one or more units/jobs or the manager" + "reset-failed:Reset failed state for all, one, or more units" + "enable:Enable one or more unit files" + "disable:Disable one or more unit files" + "is-enabled:Check whether unit files are enabled" + "load:Load one or more units" + "list-jobs:List jobs" + "cancel:Cancel all, one, or more jobs" + "monitor:Monitor unit/job changes" + "dump:Dump server status" + "dot:Dump dependency graph for dot(1)" + "snapshot:Create a snapshot" + "delete:Remove one or more snapshots" + "daemon-reload:Reload systemd manager configuration" + "daemon-reexec:Reexecute systemd manager" + "show-environment:Dump environment" + "set-environment:Set one or more environment variables" + "unset-environment:Unset one or more environment variables" + "default:Enter system default mode" + "rescue:Enter system rescue mode" + "emergency:Enter system emergency mode" + "halt:Shut down and halt the system" + "poweroff:Shut down and power-off the system" + "reboot:Shut down and reboot the system" + "kexec:Shut down and reboot the system with kexec" + "exit:Ask for user instance termination" + ) - # Complete subcommands. if (( CURRENT == 1 )); then - _describe -t commands "command" _systemctl_cmds - return + _describe -t commands 'systemctl command' _systemctl_cmds || compadd "$@" + else + local curcontext="$curcontext" + + cmd="${${_systemctl_cmds[(r)$words[1]:*]%%:*}}" + # Deal with any aliases + case $cmd in + condrestart) cmd="try-restart";; + force-reload) cmd="reload-or-try-restart";; + esac + + if (( $#cmd )); then + curcontext="${curcontext%:*:*}:systemctl-${cmd}:" + + local update_policy + zstyle -s ":completion:${curcontext}:" cache-policy update_policy + if [[ -z "$update_policy" ]]; then + zstyle ":completion:${curcontext}:" cache-policy _systemctl_caching_policy + fi + + _call_function ret _systemctl_$cmd || _message 'no more arguments' + else + _message "unknown systemctl command: $words[1]" + fi + return ret fi +} - # handle arguments to the subcommands. - case $words[1] in - start|restart|reload|stop|status|try-restart|reload-or-restart|reload-or-try-restart|isolate|kill|is-active|show|reset-failed|enable|disable|is-enabled|load) - # many units can be listed - _arguments "*:key:_systemd_units" - ;; +# Fills the unit lists +_systemctl_all_units() +{ + if ( [[ ${+_sys_all_units} -eq 0 ]] || _cache_invalid SYS_ALL_UNITS ) && + ! _retrieve_cache SYS_ALL_UNITS; + then + _sys_all_units=( $(systemctl list-units --full --all | cut -d' ' -f1 \ + 2>/dev/null) ) + _store_cache SYS_ALL_UNITS _sys_all_units + fi +} - cancel) _arguments "*:key:_systemd_jobs" ;; +_systemctl_inactive_units() +{ + _sys_inactive_units=( $(systemctl list-units --full --all \ + | awk '$3 != "active" {print $1}' 2>/dev/null) ) +} - # snapshots - snapshot) _normal ;; - delete) _arguments "*:key:_systemd_snapshots" ;; +_systemctl_active_units() +{ + _sys_active_units=( $(systemctl list-units --full | cut -d' ' -f1 \ + 2>/dev/null) ) +} - # no arguments - dump|dot|monitor|daemon-reload|daemon-reexec|show-environment|default|rescue|emergency|halt|poweroff|reboot|kexec|exit|list-jobs|list-units) - ;; +_systemctl_failed_units() +{ + _sys_failed_units=( $(systemctl list-units --full --failed | cut -d' ' -f1 + 2>/dev/null) ) +} + +_filter_units_by_property () { + local property=$1 value=$2 ; shift ; shift + local -a units ; units=($*) + local -a props ; props=( $(systemctl show --property "$property" -- \ + ${units[*]} | grep -v '^$') ) + for ((i=0; $i < ${#units[*]}; i++)); do + if [[ "${props[i]}" = "$property=$value" ]]; then + echo "${units[i]}" + fi + done +} + +# Completion functions for ALL_UNITS +for fun in enable disable is-active is-enabled status show ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + _systemctl_all_units + compadd "$@" -a -- _sys_all_units + } +done + +# Completion functions for STARTABLE_UNITS +(( $+functions[_systemctl_start] )) || _systemctl_start() +{ + _systemctl_inactive_units + compadd "$@" -- $( _filter_units_by_property CanStart yes \ + ${_sys_inactive_units[*]} | grep -Ev '\.(device|snapshot)$' ) +} + +# Completion functions for RESTARTABLE_UNITS +for fun in restart reload-or-restart ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + _systemctl_all_units + compadd "$@" -- $( _filter_units_by_property CanStart yes \ + ${_sys_all_units[*]} | grep -Ev '\.(device|snapshot|socket|timer)$' ) + } +done + +# Completion functions for STOPPABLE_UNITS +for fun in stop kill try-restart condrestart ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + _systemctl_active_units + compadd "$@" -- $( _filter_units_by_property CanStop yes \ + ${_sys_active_units[*]} ) + } +done + +# Completion functions for RELOADABLE_UNITS +for fun in reload reload-or-try-restart force-reload ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + _systemctl_active_units + compadd "$@" -- $( _filter_units_by_property CanReload yes \ + ${_sys_active_units[*]} ) + } +done + +# Completion functions for ISOLATABLE_UNITS +(( $+functions[_systemctl_isolate] )) || _systemctl_isolate() +{ + _systemctl_all_units + compadd "$@" -- $( _filter_units_by_property AllowIsolate yes \ + ${_sys_all_units[*]} ) +} + +# Completion functions for FAILED_UNITS +(( $+functions[_systemctl_reset-failed] )) || _systemctl_reset-failed() +{ + _systemctl_failed_units + compadd "$@" -a -- _sys_failed_units || _message "no failed-unit found" +} + +# Completion functions for JOBS +(( $+functions[_systemctl_cancel] )) || _systemctl_cancel() +{ + compadd "$@" -- $( systemctl list-jobs | cut -d' ' -f1 2>/dev/null ) || \ + _message "no job found" +} + +# Completion functions for SNAPSHOTS +(( $+functions[_systemctl_delete] )) || _systemctl_delete() +{ + compadd "$@" -- $( systemctl list-units --type snapshot --full --all \ + | cut -d' ' -f1 2>/dev/null ) || _message "no snampshot found" +} + +# Completion functions for ENVS +(( $+functions[_systemctl_set-environment] )) || _systemctl_set-environment() +{ + compadd "$@" -S '' -- $( systemctl show-environment \ + | sed 's_\([^=]\+=\).*_\1_' ) +} +(( $+functions[_systemctl_unset-environment] )) || _systemctl_unset-environment() +{ + compadd "$@" -S '' -- $( systemctl show-environment \ + | sed 's_\([^=]\+\)=.*_\1_' ) +} + +# no completion for: +# [STANDALONE]='daemon-reexec daemon-reload default dot dump emergency exit +# halt kexec list-jobs list-units monitor poweroff reboot +# rescue show-environment' +# [NAME]='snapshot load' + +_systemctl_caching_policy() +{ + local _sysunits + local -a oldcache + + # rebuild if cache is more than a day old + oldcache=( "$1"(mh+1) ) + (( $#oldcache )) && return 0 + + _sysunits=($(systemctl --full --all | cut -d' ' -f1)) + + if (( $#_sysunits )); then + for unit in $_sysunits; do + [[ "$unit" -nt "$1" ]] && return 0 + done + fi - *) _message "unknown systemctl command: $words[1]" ;; - esac + return 1 } _systemctl "$@" +# Local Variables: +# mode: sh +# sh-indentation: 2 +# indent-tabs-mode: nil +# sh-basic-offset: 2 +# End: -- cgit 1.4.1