wholerabbit
wholerabbit

Reputation: 11546

Apply completion options dynamically

I have a fish shell completion like this for docker:

# 'docker-subcommands.txt' is an exhaustive list derived from the "Usage" message.
set -l subcoms (cat /etc/fish/completions/docker-subcommands.txt)

# Found '__fish_seen_subcommand_from' in the completion for `systemctl`
# (in /usr/share/fish/completions/...).
complete -f -c docker -n "not __fish_seen_subcommand_from $subcoms" -a "$subcoms"

function _docker_container_action
# The placeholder is needed here because fish will choke on an empty completion list.
        echo (docker ps -aq) '{z-placeholder}'
end

function _docker_image_action
        echo (docker images -q) '{z-placeholder}'
end

for sc in cp exec inspect restart rm start stop
        complete -c docker -n "contains $sc (commandline -poc)" -x -a (_docker_container_action)
end

for sc in rmi run
        complete -c docker -n "contains $sc (commandline -poc)" -x -a (_docker_image_action)
end

The problem is that the completion for image and container IDs needs to be dynamic (like file completion), whereas the above seems to run the -a command when the completion file is (re-)sourced.

How can I make this refresh the options when the completion is actually being applied?

I should mention that I've tried quoting the -a command, as seems to be common practice. But then instead of an option for each ID, I get only one completion option, a long string with space escapes in it (\) containing the IDs and \{z-placeholder} at the end. :(


[...] Quoting the -a command does work as long as its output is not produced by echo (which stringifies it). Turns out -a's "choking" problem is not having an argument, which is what happens if you put docker ps -aq there directly and there are no container IDs to list. So this pattern works:

function _docker_container_action
    docker ps -aq
end

complete -c docker -n "contains $sc (commandline -poc)" -x -a "(_docker_container_action)"

And no need for my placeholder either.

Upvotes: 1

Views: 220

Answers (1)

faho
faho

Reputation: 15924

whereas the above seems to run the -a command when the completion file is (re-sourced).

That's because you've included it here as a command substitution, so when the file is sourced, it expands, and the completion system has no idea what it was before.

But the -a option knows to expand its argument at completion-time, so all you need to do is quote it:

complete -c docker -n "contains $sc (commandline -poc)" -x -a "(_docker_container_action)"

Upvotes: 4

Related Questions