2

I am attempting to write a completion plugin for YunoHost. I am struggling with the following case, where an argument, optional or not, can take multiple values:

ynh app addaccess apps [apps ...] [-u [USERS [USERS ...]]]

Typical usage:

ynh app addaccess foo-app1 bar-app2 -u barfoo1 foobar2

I've managed to get suggestions for those two parameters apps and USERS with the following code but I can't have a behavior coherent with what the command can handle. (_ynh_app_list and _ynh_users_list are calls to compadd)

_yunohost_app_addaccess() {
    _arguments -s -C \
        '1:apps:_ynh_app_list' \
        '*'{-u,--users}'[users]:users:_ynh_users_list'
}

The code above kinda works, except:

  • after entering a single app name, it switches to the users.
  • -u takes a single user (multiple -u instances are valid though)

I tried *:apps:_ynh_app_list, but ynh app addaccess foo-app1 -u user1 <TAB> calls _ynh_app_list instead of _ynh_users_list


What I would like to get is:

  • ynh app addaccess <TAB> shows the completions provided by __ynh_app_list
  • ynh app addaccess foo-app1 <TAB> still shows the completions provided by __ynh_app_list
  • As soon as -u is entered, and whatever the number of words after -u, all completion suggestions should come from __ynh_users_list: yunohost app addaccess foo-app1 bar-app2 -u barfoo1 foobar2 <TAB> still completes with a username form __ynh_users_list

Is it possible to achieve this, at least the last item ([-u USER [USER...]])? Thanks a lot! :)

Lucas
  • 523
  • 2
  • 10
  • 20
Buzuck
  • 23
  • 3

1 Answers1

0

To use a list of exclusion option/argument functionality could rescue:

_yunohost_app_addaccess() {
    _arguments -s -C \
        {1,'*'}:apps:_ynh_app_list \
        '(*)'{-u,--users}'[users]:*:users:_ynh_users_list'
}

The ynh addaccess app [APPS ...] portion could be done by the normal argument SPECs; 1:MESSAGE:ACTION and *:MESSAGE:ACTION.
Shorthanded by a brace expansion: {1,'*'}:apps:_ynh_app_list

The [-u USER [USER...]] portion could be done by the OPTSPECs with a preceded list of exclusions and :*PATTERN:MESSAGE:ACTION with empty PATTERN; '(*)-OPTNAME[EXPLANATION]:*:MESSAGE:ACTION'.


Here is the zsh manual for the list of exclusions for a reference:

_arguments ...
...
Each of the forms above may be preceded by a list in parentheses of option names and argument numbers. If the given option is on the command line, the options and arguments indicated in parentheses will not be offered. For example, (-two -three 1)-one:... completes the option -one; if this appears on the command line, the options -two and -three and the first ordinary argument will not be completed after it. (-foo):... specifies an ordinary argument completion; -foo will not be completed if that argument is already present.

Other items may appear in the list of excluded options to indicate various other items that should not be applied when the current specification is matched: a single star (*) for the rest arguments (i.e. a specification of the form *:...); a colon (:) for all normal (non-option-) arguments; and a hyphen (-) for all options. For example, if (*) appears before an option and the option appears on the command line, the list of remaining arguments (those shown in the above table beginning with *:) will not be completed.

--- zshcompsys(1), _arguments, zshcompsys - zsh completion system

hchbaw
  • 4,894
  • 18
  • 16
  • Thanks! That did it :D Although I read that part of the documentation multiple times, I didn't succeed in implementing it that way... =/ – Buzuck Aug 10 '20 at 15:41