]> ruderich.org/simon Gitweb - config/dotfiles.git/blob - shell/zsh/functions/_systemctl
vcs: gitconfig: sort tags as version numbers
[config/dotfiles.git] / shell / zsh / functions / _systemctl
1 #compdef systemctl
2 # SPDX-License-Identifier: LGPL-2.1+
3
4 (( $+functions[_systemctl_command] )) || _systemctl_command()
5 {
6   local -a _systemctl_cmds
7   _systemctl_cmds=(
8     "list-sockets:List sockets"
9     "list-timers:List timers"
10     "list-units:List units"
11     "start:Start (activate) one or more units"
12     "stop:Stop (deactivate) one or more units"
13     "reload:Reload one or more units"
14     "restart:Start or restart one or more units"
15     "condrestart:Restart one or more units if active"
16     "try-restart:Restart one or more units if active"
17     "reload-or-restart:Reload one or more units if possible, otherwise start or restart"
18     "force-reload:Reload one or more units if possible, otherwise restart if active"
19     "hibernate:Hibernate the system"
20     "hybrid-sleep:Hibernate and suspend the system"
21     "suspend-then-hibernate:Suspend the system for a period of time, and then hibernate it"
22     "try-reload-or-restart:Reload one or more units if possible, otherwise restart if active"
23     "isolate:Start one unit and stop all others"
24     "kill:Send signal to processes of a unit"
25     "is-active:Check whether units are active"
26     "is-failed:Check whether units are failed"
27     "status:Show runtime status of one or more units"
28     "show:Show properties of one or more units/jobs or the manager"
29     "cat:Show the source unit files and drop-ins"
30     "reset-failed:Reset failed state for all, one, or more units"
31     "list-unit-files:List installed unit files"
32     "enable:Enable one or more unit files"
33     "disable:Disable one or more unit files"
34     "add-wants:Add Wants= dependencies to a unit"
35     "add-requires:Add Requires= dependencies to a unit"
36     "reenable:Reenable one or more unit files"
37     "preset:Enable/disable one or more unit files based on preset configuration"
38     "set-default:Set the default target"
39     "get-default:Query the default target"
40     "edit:Edit one or more unit files"
41     "is-system-running:Query overall status of the system"
42     "help:Show documentation for specified units"
43     "list-dependencies:Show unit dependency tree"
44     "mask:Mask one or more units"
45     "unmask:Unmask one or more units"
46     "link:Link one or more units files into the search path"
47     "is-enabled:Check whether unit files are enabled"
48     "list-jobs:List jobs"
49     "cancel:Cancel all, one, or more jobs"
50     "show-environment:Dump environment"
51     "set-environment:Set one or more environment variables"
52     "unset-environment:Unset one or more environment variables"
53     "daemon-reload:Reload systemd manager configuration"
54     "daemon-reexec:Reexecute systemd manager"
55     "default:Enter system default mode"
56     "rescue:Enter system rescue mode"
57     "emergency:Enter system emergency mode"
58     "halt:Shut down and halt the system"
59     "suspend:Suspend the system"
60     "poweroff:Shut down and power-off the system"
61     "reboot:Shut down and reboot the system"
62     "kexec:Shut down and reboot the system with kexec"
63     "exit:Ask for user instance termination"
64     "switch-root:Change root directory"
65     "revert:Revert unit files to their vendor versions"
66   )
67
68   if (( CURRENT == 1 )); then
69     _describe -t commands 'systemctl command' _systemctl_cmds || compadd "$@"
70   else
71     local curcontext="$curcontext" expl
72
73     cmd="${${_systemctl_cmds[(r)$words[1]:*]%%:*}}"
74     # Deal with any aliases
75     case $cmd in
76       condrestart) cmd="try-restart";;
77       force-reload) cmd="try-reload-or-restart";;
78     esac
79
80     # CHANGED: my aliases
81     case $words[1] in
82       c)  cmd=cat     ;;
83       d)  cmd=disable ;;
84       e)  cmd=enable  ;;
85       k)  cmd=kill    ;;
86       m)  cmd=mask    ;;
87       r)  cmd=restart ;;
88       rl) cmd=reload  ;;
89       s)  cmd=status  ;;
90       sa) cmd=start   ;;
91       so) cmd=stop    ;;
92       u)  cmd=unmask  ;;
93     esac
94
95     if (( $#cmd )); then
96       curcontext="${curcontext%:*:*}:systemctl-${cmd}:"
97
98       local update_policy
99       zstyle -s ":completion:${curcontext}:" cache-policy update_policy
100       if [[ -z "$update_policy" ]]; then
101         zstyle ":completion:${curcontext}:" cache-policy _systemctl_caching_policy
102       fi
103
104       _call_function ret _systemctl_$cmd || _message 'no more arguments'
105     else
106       _message "unknown systemctl command: $words[1]"
107     fi
108     return ret
109   fi
110 }
111
112 __systemctl()
113 {
114   systemctl $_sys_service_mgr --full --no-legend --no-pager "$@" 2>/dev/null
115 }
116
117
118 # Fills the unit list
119 _systemctl_all_units()
120 {
121   if ( [[ ${+_sys_all_units} -eq 0 ]] || _cache_invalid SYS_ALL_UNITS$_sys_service_mgr ) ||
122     ! _retrieve_cache SYS_ALL_UNITS$_sys_service_mgr;
123   then
124     _sys_all_units=( ${${(f)"$(__systemctl list-units --all "$PREFIX*" )"}%% *} )
125     _store_cache SYS_ALL_UNITS$_sys_service_mgr _sys_all_units
126   fi
127 }
128
129 # Fills the unit list including all file units
130 _systemctl_really_all_units()
131 {
132   local -a all_unit_files;
133   local -a really_all_units;
134   if ( [[ ${+_sys_really_all_units} -eq 0 ]] || _cache_invalid SYS_REALLY_ALL_UNITS$_sys_service_mgr ) ||
135     ! _retrieve_cache SYS_REALLY_ALL_UNITS$_sys_service_mgr;
136   then
137     all_unit_files=( ${${(f)"$(__systemctl list-unit-files "$PREFIX*" )"}%% *} )
138     _systemctl_all_units
139     really_all_units=($_sys_all_units $all_unit_files)
140     _sys_really_all_units=(${(u)really_all_units})
141     _store_cache SYS_REALLY_ALL_UNITS$_sys_service_mgr _sys_really_all_units
142   fi
143 }
144
145 _filter_units_by_property() {
146   local property=$1 value=$2; shift 2
147   local -a units; units=("${(q-)@}")
148   local -A props
149   props=(${(f)"$(_call_program units "$service $_sys_service_mgr show --no-pager --property=\"Id,$property\" -- ${units} 2>/dev/null")"})
150   echo -E - "${(@g:o:)${(k@)props[(Re)$property=$value]}#Id=}"
151 }
152
153 _systemctl_get_non_template_names() { echo -E - ${^${(R)${(f)"$(
154     __systemctl $mode list-unit-files "$PREFIX*"
155     __systemctl $mode list-units --all "$PREFIX*"
156   )"}:#*@.*}%%[[:space:]]*} }
157
158 _systemctl_get_template_names() { echo -E - ${^${(M)${(f)"$(__systemctl list-unit-files "$PREFIX*" )"}##*@.[^[:space:]]##}%%@.*}@ }
159
160
161 _systemctl_active_units()  {_sys_active_units=(  ${${(f)"$(__systemctl list-units "$PREFIX*" )"}%% *} )}
162
163 _systemctl_startable_units(){
164   _sys_startable_units=( $( _filter_units_by_property ActiveState inactive $(
165     _filter_units_by_property CanStart yes ${${${(f)"$(
166       __systemctl $mode list-unit-files --state enabled,enabled-runtime,linked,linked-runtime,static,indirect,disabled,generated,transient "$PREFIX*"
167       __systemctl $mode list-units --state inactive,failed "$PREFIX*"
168     )"}:#*@.*}%%[[:space:]]*}
169   )) )
170 }
171
172 _systemctl_restartable_units(){
173   _sys_restartable_units=( $( _filter_units_by_property CanStart yes ${${${(f)"$(
174     __systemctl $mode list-unit-files --state enabled,disabled,static "$PREFIX*"
175     __systemctl $mode list-units "$PREFIX*"
176   )"}:#*@.*}%%[[:space:]]*} ) )
177 }
178
179 _systemctl_failed_units()  {_sys_failed_units=( ${${(f)"$(__systemctl list-units --state=failed "$PREFIX*" )"}%% *} ) }
180 _systemctl_unit_state() { typeset -gA _sys_unit_state; _sys_unit_state=( $(__systemctl list-unit-files "$PREFIX*" ) ) }
181
182 local fun
183 # Completion functions for ALL_UNITS
184 for fun in cat mask ; do
185   (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
186   {
187     _systemctl_really_all_units
188     _wanted systemd-units expl unit \
189       compadd "$@" -a - _sys_really_all_units
190   }
191 done
192
193 # Completion functions for NONTEMPLATE_UNITS
194 for fun in is-active is-failed is-enabled status show preset help list-dependencies edit revert add-wants add-requires ; do
195   (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
196   {
197     _wanted systemd-units expl unit \
198       compadd "$@" - $(_systemctl_get_non_template_names)
199   }
200 done
201
202 # Completion functions for ENABLED_UNITS
203 (( $+functions[_systemctl_disable] )) || _systemctl_disable()
204 {
205     local _sys_unit_state; _systemctl_unit_state
206     _wanted systemd-units expl 'enabled unit' \
207       compadd "$@" - ${(k)_sys_unit_state[(R)enabled]}
208 }
209
210 (( $+functions[_systemctl_reenable] )) || _systemctl_reenable()
211 {
212     local _sys_unit_state; _systemctl_unit_state
213     _wanted systemd-units expl 'enabled/disabled unit' \
214       compadd "$@" - ${(k)_sys_unit_state[(R)(enabled|disabled)]} $(_systemctl_get_template_names)
215 }
216
217 # Completion functions for DISABLED_UNITS
218 (( $+functions[_systemctl_enable] )) || _systemctl_enable()
219 {
220   local _sys_unit_state; _systemctl_unit_state
221   _wanted systemd-units expl 'disabled unit' \
222     compadd "$@" - ${(k)_sys_unit_state[(R)disabled]} $(_systemctl_get_template_names)
223 }
224
225 # Completion functions for FAILED_UNITS
226 (( $+functions[_systemctl_reset-failed] )) || _systemctl_reset-failed()
227 {
228   local _sys_failed_units; _systemctl_failed_units
229   _wanted systemd-units expl 'failed unit' \
230     compadd "$@" -a - _sys_failed_units || _message "no failed unit found"
231 }
232
233 # Completion functions for STARTABLE_UNITS
234 (( $+functions[_systemctl_start] )) || _systemctl_start()
235 {
236    local _sys_startable_units; _systemctl_startable_units
237    _wanted systemd-units expl 'startable unit' \
238      compadd "$@" - ${_sys_startable_units[*]}
239 }
240
241 # Completion functions for STOPPABLE_UNITS
242 for fun in stop kill try-restart condrestart ; do
243   (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
244   {
245     local _sys_active_units; _systemctl_active_units
246     _wanted systemd-units expl 'stoppable unit' \
247       compadd "$@" - $( _filter_units_by_property CanStop yes \
248         ${_sys_active_units[*]} )
249   }
250 done
251
252 # Completion functions for ISOLATABLE_UNITS
253 (( $+functions[_systemctl_isolate] )) || _systemctl_isolate()
254 {
255   _systemctl_all_units
256   _wanted systemd-units expl 'isolatable unit' \
257     compadd "$@" - $( _filter_units_by_property AllowIsolate yes \
258       ${_sys_all_units[*]} )
259 }
260
261 # Completion functions for RELOADABLE_UNITS
262 for fun in reload try-reload-or-restart force-reload ; do
263   (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
264   {
265     local _sys_active_units; _systemctl_active_units
266     _wanted systemd-units expl 'reloadable unit' \
267       compadd "$@" - $( _filter_units_by_property CanReload yes \
268         ${_sys_active_units[*]} )
269   }
270 done
271
272 # Completion functions for RESTARTABLE_UNITS
273 for fun in restart reload-or-restart ; do
274   (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
275   {
276     local _sys_restartable_units; _systemctl_restartable_units
277     _wanted systemd-units expl 'restartable unit' \
278       compadd "$@" - ${_sys_restartable_units[*]}
279   }
280 done
281
282 # Completion functions for MASKED_UNITS
283 (( $+functions[_systemctl_unmask] )) || _systemctl_unmask()
284 {
285   local _sys_unit_state; _systemctl_unit_state
286   _wanted systemd-units expl 'masked unit' \
287     compadd "$@" - ${(k)_sys_unit_state[(R)masked]} || _message "no masked units found"
288 }
289
290 # Completion functions for JOBS
291 (( $+functions[_systemctl_cancel] )) || _systemctl_cancel()
292 {
293   _wanted systemd-jobs expl job \
294     compadd "$@" - ${${(f)"$(__systemctl list-jobs)"}%% *} ||
295       _message "no jobs found"
296 }
297
298 # Completion functions for TARGETS
299 (( $+functions[_systemctl_set-default] )) || _systemctl_set-default()
300 {
301   _wanted systemd-targets expl target \
302     compadd "$@" - ${${(f)"$(__systemctl list-unit-files --type target --all "$PREFIX*" )"}%% *} ||
303       _message "no targets found"
304 }
305
306 # Completion functions for ENVS
307 for fun in set-environment unset-environment ; do
308   (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
309   {
310     local fun=$0 ; fun=${fun##_systemctl_}
311     local suf
312     if [[ "${fun}" = "set-environment" ]]; then
313       suf='-S='
314     fi
315     _wanted systemd-environment expl 'environment variable' \
316       compadd "$@" ${suf} - ${${(f)"$(systemctl show-environment)"}%%=*}
317   }
318 done
319
320 (( $+functions[_systemctl_link] )) || _systemctl_link() {
321    _sd_unit_files
322 }
323
324 (( $+functions[_systemctl_switch-root] )) || _systemctl_switch-root() {
325    _files
326 }
327
328 # no systemctl completion for:
329 #    [STANDALONE]='daemon-reexec daemon-reload default
330 #                  emergency exit halt kexec list-jobs list-units
331 #                  list-unit-files poweroff reboot rescue show-environment'
332
333 _systemctl_caching_policy()
334 {
335   local _sysunits
336   local -a oldcache
337
338   # rebuild if cache is more than a day old
339   oldcache=( "$1"(mh+1) )
340   (( $#oldcache )) && return 0
341
342   _sysunits=(${${(f)"$(__systemctl --all)"}%% *})
343
344   if (( $#_sysunits )); then
345     for unit in $_sysunits; do
346       [[ "$unit" -nt "$1" ]] && return 0
347     done
348   fi
349
350   return 1
351 }
352
353 _unit_states() {
354     local -a _states
355     _states=("${(fo)$(__systemctl --state=help)}")
356     _values -s , "${_states[@]}"
357 }
358
359 _unit_types() {
360     local -a _types
361     _types=("${(fo)$(__systemctl -t help)}")
362     _values -s , "${_types[@]}"
363 }
364
365 _unit_properties() {
366   if ( [[ ${+_sys_all_properties} -eq 0 ]] || _cache_invalid SYS_ALL_PROPERTIES$_sys_service_mgr ) ||
367     ! _retrieve_cache SYS_ALL_PROPERTIES$_sys_service_mgr;
368   then
369     _sys_all_properties=( ${${(M)${(f)"$(/lib/systemd/systemd --dump-bus-properties)"}}} )
370     _store_cache SYS_ALL_PROPERTIES$_sys_service_mgr _sys_all_properties
371   fi
372   _values -s , "${_sys_all_properties[@]}"
373 }
374
375 _job_modes() {
376     local -a _modes
377     _modes=(fail replace replace-irreversibly isolate ignore-dependencies ignore-requirements flush)
378     _values -s , "${_modes[@]}"
379 }
380
381 # Build arguments for "systemctl" to be used in completion.
382 local -a _modes; _modes=("--user" "--system")
383 # Use the last mode (they are exclusive and the last one is used).
384 local _sys_service_mgr=${${words:*_modes}[(R)(${(j.|.)_modes})]}
385 _arguments -s \
386     {-h,--help}'[Show help]' \
387     '--version[Show package version]' \
388     {-t+,--type=}'[List only units of a particular type]:unit type:_unit_types' \
389     '--state=[Display units in the specified state]:unit state:_unit_states' \
390     '--job-mode=[Specify how to deal with other jobs]:mode:_job_modes' \
391     {-p+,--property=}'[Show only properties by specific name]:unit property:_unit_properties' \
392     {-a,--all}'[Show all units/properties, including dead/empty ones]' \
393     '--reverse[Show reverse dependencies]' \
394     '--after[Show units ordered after]' \
395     '--before[Show units ordered before]' \
396     {-l,--full}"[Don't ellipsize unit names on output]" \
397     '--show-types[When showing sockets, show socket type]' \
398     {-i,--ignore-inhibitors}'[When executing a job, ignore jobs dependencies]' \
399     {-q,--quiet}'[Suppress output]' \
400     '--no-block[Do not wait until operation finished]' \
401     '--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \
402     '--no-pager[Do not pipe output into a pager]' \
403     '--system[Connect to system manager]' \
404     '--user[Connect to user service manager]' \
405     "--no-wall[Don't send wall message before halt/power-off/reboot]" \
406     '--global[Enable/disable/mask unit files globally]' \
407     "--no-reload[When enabling/disabling unit files, don't reload daemon configuration]" \
408     '--no-ask-password[Do not ask for system passwords]' \
409     '--kill-who=[Who to send signal to]:killwho:(main control all)' \
410     {-s+,--signal=}'[Which signal to send]:signal:_signals' \
411     {-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \
412     '--root=[Enable/disable/mask unit files in the specified root directory]:directory:_directories' \
413     '--runtime[Enable/disable/mask unit files only temporarily until next reboot]' \
414     {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \
415     {-P,--privileged}'[Acquire privileges before execution]' \
416     {-n+,--lines=}'[Journal entries to show]:number of entries' \
417     {-o+,--output=}'[Change journal output mode]:modes:_sd_outputmodes' \
418     '--firmware-setup[Tell the firmware to show the setup menu on next boot]' \
419     '--plain[When used with list-dependencies, print output as a list]' \
420     '--failed[Show failed units]' \
421     '*::systemctl command:_systemctl_command'