aboutsummaryrefslogtreecommitdiffhomepage
path: root/share
diff options
context:
space:
mode:
authorGravatar Fabian Homborg <FHomborg@gmail.com>2016-04-27 14:17:29 +0200
committerGravatar Fabian Homborg <FHomborg@gmail.com>2016-04-27 14:22:16 +0200
commitbc35ca6366dde3f1c6974a459e102afa70e4d11f (patch)
tree96eb679912558892bd374d69c2d8a6e6a1dd357e /share
parentdf10b53c0caecd43a02b7f24515a9ff9edea7056 (diff)
Make busctl completions useful
- More accurate - Fast enough to be usable (previously, this would sometimes take a few seconds) - A bit smaller
Diffstat (limited to 'share')
-rw-r--r--share/completions/busctl.fish246
1 files changed, 102 insertions, 144 deletions
diff --git a/share/completions/busctl.fish b/share/completions/busctl.fish
index ebbba06f..ea3ef276 100644
--- a/share/completions/busctl.fish
+++ b/share/completions/busctl.fish
@@ -1,140 +1,107 @@
# Fish completions for systemd's "busctl" dbus tool
-
-# A ton of functions, all working by the same principle
-# __fish_busctl_*: Get the available options for * via busctl "list" or "introspect"
-# __fish_busctl_has_*: Return 0 when a * is specified (and echo it), else return 1
-# Unfortunately these become a bit slow as they stack because we don't keep state
-# i.e. __fish_busctl_methods needs to know the interface, which needs the object, which needs the busname
-# To speed this up, we'd need to either keep state or just assume e.g. the first non-option argument to "call" is a busname
-
-function __fish_busctl_busnames
+# TODO:
+# One issue is that sometimes these will come to a dead-end e.g. when a particular interface has no properties
+# Another is that some busnames aren't accesible by the current user
+# but this can't be predicted via the user that owns that name, e.g. `org.freedesktop.login1`
+# is usually owned by a root-owned process, yet accessible (at least in part) by normal users
+
+# A simple wrapper to call busctl with the correct mode and output
+function __fish_busctl
+ # TODO: If there's a "--address" argument we need to pass that
+ # We also need to pass the _last_ of these (`busctl --user --system` operates on the system bus)
set -l mode
if __fish_contains_opt user
set mode "--user"
else
set mode "--system"
end
- command busctl $mode list --no-legend --no-pager ^/dev/null | while read a b; echo $a; end
-end
-
-function __fish_busctl_has_busname
- for busname in (__fish_busctl_busnames)
- if contains -- $busname (commandline -opc)
- echo $busname
- return 0
- end
- end
- return 1
+ command busctl $mode $argv --no-legend --no-pager ^/dev/null
end
-
-function __fish_busctl_has_object
- for object in (__fish_busctl_objects)
- if contains -- $object (commandline -opc)
- echo $object
- return 0
- end
- end
- return 1
-end
-
-function __fish_busctl_has_interface
- for interface in (__fish_busctl_interfaces)
- if contains -- $interface (commandline -opc)
- echo $interface
- return 0
- end
- end
- return 1
-end
-
-function __fish_busctl_has_member
- for member in (__fish_busctl_members $argv)
- if contains -- $member (commandline -opc)
- echo $member
- return 0
+
+# Only get the arguments to the actual command, skipping all options and arguments to options
+function __fish_busctl_get_command_args
+ set -l skip
+ set -l skip_next 0
+ set -l cmd (commandline -opc)
+ for token in $cmd
+ switch $token
+ # Options that take arguments - when given without "=", the next token is the arg - skip it
+ case '--address' '--match' '--expect-reply' '--auto-start' '--allow-interactive-authorization' \
+ '--timeout' '--augment-creds' '-H' '--host' '-M' '--machine'
+ set skip_next 1
+ continue
+ # Skip all options themselves
+ case '-*'
+ continue
+ # Command args only start after a command
+ case 'status' 'monitor' 'capture' 'tree' 'introspect' 'call' 'get-property' 'set-property'
+ set -e skip
+ continue
+ # These take no arguments, so abort completion
+ case 'list' 'help'
+ break
+ case '*'
+ if test "$skip_next" -eq 1; or set -q skip
+ set skip_next 0
+ continue
+ end
+ echo $token
end
end
- return 1
end
-
-function __fish_busctl_has_method
- __fish_busctl_has_member method
-end
-
-function __fish_busctl_has_property
- __fish_busctl_has_member property
-end
-
-function __fish_busctl_has_signature
- for signature in (__fish_busctl_signature)
- if contains -- $signature (commandline -opc)
- echo $signature
- return 0
- end
- end
- return 1
+
+function __fish_busctl_busnames
+ __fish_busctl list --acquired | string replace -r '\s+.*$' ''
+ # Describe unique names (":1.32") with their process (e.g. `:1.32\tsteam`)
+ __fish_busctl list --unique | string replace -r '\s+\S+\s+(\S+)\s+.*$' '\t$1'
end
-function __fish_busctl_objects
- set -l mode
- if __fish_contains_opt user
- set mode "--user"
- else
- set mode "--system"
- end
- set -l busname (__fish_busctl_has_busname)
- command busctl $mode tree --list --no-legend --no-pager $busname ^/dev/null | while read a b; echo $a; end
+function __fish_busctl_objects -a busname
+ __fish_busctl tree --list $busname | string replace -r '\s+.*$' ''
end
-function __fish_busctl_interfaces
- set -l mode
- if __fish_contains_opt user
- set mode "--user"
- else
- set mode "--system"
- end
- set -l busname (__fish_busctl_has_busname)
- set -l object (__fish_busctl_has_object)
- command busctl $mode introspect --list --no-legend --no-pager $busname $object ^/dev/null | while read a b; echo $a; end
+function __fish_busctl_interfaces -a busname -a object
+ __fish_busctl introspect --list $busname $object | string replace -r '\s+.*$' ''
end
-function __fish_busctl_members
- set -l mode
- if __fish_contains_opt user
- set mode "--user"
- else
- set mode "--system"
- end
- set -l busname (__fish_busctl_has_busname)
- set -l object (__fish_busctl_has_object)
- set -l interface (__fish_busctl_has_interface)
- command busctl $mode introspect --list --no-legend --no-pager $busname $object $interface ^/dev/null | grep "$argv" | while read a b; echo $a; end | sed -e "s/^\.//"
-end
-
-function __fish_busctl_methods
- __fish_busctl_members method
+function __fish_busctl_members -a type -a busname -a object -a interface
+ __fish_busctl introspect --list $busname $object $interface \
+ | string match -- "* $type *" | string replace -r '.(\S+) .*' '$1'
end
-function __fish_busctl_properties
- __fish_busctl_members property
+function __fish_busctl_signature -a busname -a object -a interface -a member
+ __fish_busctl introspect --list $busname $object $interface \
+ | string match ".$member *" | while read a b c d; echo $c; end
end
-function __fish_busctl_signals
- __fish_busctl_members signal
-end
-
-function __fish_busctl_signature
- set -l mode
- if __fish_contains_opt user
- set mode "--user"
- else
- set mode "--system"
+# This function completes service/busname, object, interface and then whatever the arguments are
+# i.e. if argv[1] is "method", complete methods in the fourth place
+function __fish_busctl_soi
+ set -l args (__fish_busctl_get_command_args)
+ set -l num (count $args)
+ switch $num
+ case 0 # We have nothing, need busname
+ __fish_busctl_busnames
+ case 1 # We have busname, need object
+ __fish_busctl_objects $args
+ case 2 # We have busname and object, need interface
+ __fish_busctl_interfaces $args
+ case '*' # We have busname and object and interface, what we need now depends on the command, so we get it as argument
+ if test $num -ge 4; and set -q argv[2] # Check >= 4 to repeat the last type for get-property
+ # Signatures have to be handled specially, because they're dependent on the member (method/property)
+ # that's at the beginning of the line and prefixed with a "."
+ # I.e. `busctl introspect` will print ".Capacity", but the argument to give to `get-property` is "Capacity"
+ if test "$argv[2]" = "signature"
+ __fish_busctl_signature $args
+ else
+ __fish_busctl_members $argv[2] $args
+ end
+ else if test $num -ge 3; and set -q argv[1]
+ __fish_busctl_members $argv[1] $args
+ else
+ return 1
+ end
end
- set -l busname (__fish_busctl_has_busname)
- set -l object (__fish_busctl_has_object)
- set -l interface (__fish_busctl_has_interface)
- set -l member (__fish_busctl_has_member)
- command busctl $mode introspect --list --no-legend --no-pager $busname $object $interface ^/dev/null | grep "^.$member " | while read a b c d; echo $c; end
end
### Commands
@@ -145,42 +112,33 @@ complete -A -f -c busctl -n "not __fish_seen_subcommand_from $commands" -a "$com
### Arguments to commands
# "status" only takes a single service as argument
-complete -f -c busctl -n "__fish_seen_subcommand_from status; and not __fish_busctl_has_busname" -a "(__fish_busctl_busnames)"
+complete -f -c busctl -n "__fish_seen_subcommand_from status; and not count (__fish_busctl_get_command_args)" -a "(__fish_busctl_busnames)"
# These take multiple services
-complete -f -c busctl -n "__fish_seen_subcommand_from monitor capture tree" -a "(__fish_busctl_busnames)"
-
-# These take "service object interface" (and then maybe something else)
-set -l service_object_interface_commands introspect call get-property set-property
-complete -f -c busctl -n "__fish_seen_subcommand_from $service_object_interface_commands; and not __fish_busctl_has_busname" -a "(__fish_busctl_busnames)"
-complete -f -c busctl -n "__fish_seen_subcommand_from $service_object_interface_commands; and __fish_busctl_has_busname; and not __fish_busctl_has_object" -a "(__fish_busctl_objects)"
-# Having an object implies having a busname, so we only need to check has_object; and not has_interface
-complete -f -c busctl -n "__fish_seen_subcommand_from $service_object_interface_commands; and __fish_busctl_has_object; and not __fish_busctl_has_interface" -a "(__fish_busctl_interfaces)"
-
-# Call takes service object interface method signature arguments
-# We can't complete the arguments (or we'd need to parse the signature)
-complete -f -c busctl -n "__fish_seen_subcommand_from call; and __fish_busctl_has_interface; and not __fish_busctl_has_method" -a "(__fish_busctl_methods)"
-complete -f -c busctl -n "__fish_seen_subcommand_from call; and __fish_busctl_has_method; and not __fish_busctl_has_signature" -a "(__fish_busctl_signature)"
-
-complete -f -c busctl -n "__fish_seen_subcommand_from get-property; and __fish_busctl_has_interface" -a "(__fish_busctl_properties)"
-complete -f -c busctl -n "__fish_seen_subcommand_from set-property; and __fish_busctl_has_interface; and not __fish_busctl_has_property" -a "(__fish_busctl_properties)"
-complete -f -c busctl -n "__fish_seen_subcommand_from set-property; and __fish_busctl_has_property; and not __fish_busctl_has_signature" -a "(__fish_busctl_signature)"
+complete -x -c busctl -n "__fish_seen_subcommand_from monitor capture tree" -a "(__fish_busctl_busnames)"
+# Read the busctl_soi calls as "Complete service, then object, then interface and then the arguments
+# e.g. `call` takes service object interface method signature arguments
+# We can't complete the arguments (without parsing the signature, which can look like "a{sv}" for an array of string-to-variant dictionaries)
+complete -x -c busctl -n "__fish_seen_subcommand_from call" -a "(__fish_busctl_soi method signature)"
+complete -x -c busctl -n "__fish_seen_subcommand_from get-property" -a "(__fish_busctl_soi property)"
+complete -x -c busctl -n "__fish_seen_subcommand_from set-property" -a "(__fish_busctl_soi property signature)"
+complete -x -c busctl -n "__fish_seen_subcommand_from introspect" -a "(__fish_busctl_soi)"
# Flags
# These are incomplete as I have no idea how to complete --address= or --match=
-complete -f -c busctl -n "__fish_seen_subcommand_from call get-property" -l quiet
+complete -f -c busctl -n "__fish_seen_subcommand_from call" -l quiet -d 'Suppress message payload display'
complete -f -c busctl -n "__fish_seen_subcommand_from call get-property" -l verbose
-complete -f -c busctl -n "__fish_seen_subcommand_from tree introspect" -l list
-complete -f -c busctl -n "__fish_seen_subcommand_from call" -l expect-reply= -a "yes no"
-complete -f -c busctl -n "__fish_seen_subcommand_from call" -l auto-start= -a "yes no"
-complete -f -c busctl -n "__fish_seen_subcommand_from call" -l allow-interactive-authorization= -a "yes no"
-complete -f -c busctl -n "__fish_seen_subcommand_from call" -l timeout= -a "(seq 0 100)"
-complete -f -c busctl -n "__fish_seen_subcommand_from list" -l unique
-complete -f -c busctl -n "__fish_seen_subcommand_from list" -l acquired
-complete -f -c busctl -n "__fish_seen_subcommand_from list" -l activatable
-complete -f -c busctl -n "__fish_seen_subcommand_from list" -l show-machine
-complete -f -c busctl -n "__fish_seen_subcommand_from list status" -l augment-creds= -a "yes no"
+complete -f -c busctl -n "__fish_seen_subcommand_from tree" -l list -d 'Show a flat list instead of a tree'
+complete -x -c busctl -n "__fish_seen_subcommand_from call" -l expect-reply -a "yes no"
+complete -x -c busctl -n "__fish_seen_subcommand_from call" -l auto-start -a "yes no" -d 'Activate the peer if necessary'
+complete -x -c busctl -n "__fish_seen_subcommand_from call" -l allow-interactive-authorization -a "yes no"
+complete -x -c busctl -n "__fish_seen_subcommand_from call" -l timeout -a "(seq 0 100)"
+complete -f -c busctl -n "__fish_seen_subcommand_from list" -l unique -d 'Only show unique (:X.Y) names'
+complete -f -c busctl -n "__fish_seen_subcommand_from list" -l acquired -d 'Only show well-known names'
+complete -f -c busctl -n "__fish_seen_subcommand_from list" -l activatable -d 'Only show peers that have not been activated yet but can be'
+complete -f -c busctl -n "__fish_seen_subcommand_from list" -l show-machine -d 'Show the machine the peers belong to'
+complete -x -c busctl -n "__fish_seen_subcommand_from list status" -l augment-creds -a "yes no"
complete -f -c busctl -l user
complete -f -c busctl -l system
complete -f -c busctl -s H -l host= -a "(__fish_print_hostnames)"