zsh-users
 help / color / mirror / code / Atom feed
From: "Alexander Groß" <agross@therightstuff.de>
To: zsh-users@zsh.org
Subject: Writing completion for non-GNU-style command
Date: Sun, 23 Oct 2016 15:56:53 +0200	[thread overview]
Message-ID: <CACcHa=P1r9b0zGr2y40YzsdpYxiPLxWDCmFzDCPtxvZRrXS1jA@mail.gmail.com> (raw)

Hi all,

I'm about to write my first completion script and it seems I picked a
program that is not easy to implement completions for.

The project is question is called Paket
(https://github.com/fsprojects/Paket). Its command line supports
arguments that don't follow the standard GNU conventions. For example,
a valid Paket invocation might look like this:

paket add nuget <package id> [group <group name>] [project <project
file>] [version <version>] [--verbose] [--more-args ...]

e.g.

paket add nuget NUnit group Test --verbose

The command is the "paket add nuget NUnit" part and the rest of the
command line are arguments, despite that "group Test" doesn't look
like one. Apart from "group" there might be more optional arguments
without dashes (i.e. project and version) and with dashes (--verbose).

I'm struggling to find a solution to this as none of the completions I
found (e.g. git) implement a similar command line.

I tried combining _describe (for group etc.) and _arguments (for
--verbose etc.) but then I would need to deduplicate the non-GNU
arguments myself as group can only appear once. _arguments alone
chokes on "group" not starting with a dash. _values won't work because
"group" etc. aren't just values.

What also puzzles me is that zsh removes anything on $line that was
parsed successfully, but doesn't do that for the word following
"nuget" (the package id).

I've attached my current appoach below. There's one additional issue
with it, as options after the line

paket add nuget NUnit group Test -<tab>

don't show up at all.

Any pointers into the right direction are greatly appreciated!

Thanks!

Alex

_paket-add() {
  local curcontext=$curcontext state line ret=1
  local -A opt_args
  local context state_descr
  typeset -A val_args

  local -a args
  args=(
    '(--verbose)'--verbose'[Be verbose]'
    '(--no-install)'--no-install'[Skip install process (patching of
project files) after the generation of paket.lock file]'
  )

  _arguments -C \
    '--help[Display paket add help]' \
    ': :->command' \
    '*:: :->option-or-argument' \
  && ret=0

  case $state in
    (command)
      local -a commands

      commands=(
        nuget:'Add NuGet package by its package ID'
      )

      _describe -t commands command commands && ret=0
      ;;

    (option-or-argument)
      curcontext=${curcontext%:*}-$line[1]:

      case $line[1] in
        (nuget)
          _arguments -C \
            ':package ID: ' \
            '*::: :->option-or-argument' \
          && ret=0

          case $state in
            (option-or-argument)
              case $line[$CURRENT] in
                (group)
                  _arguments '*: :_paket_groups' && ret=0
                  return ret
                  ;;

                (project)
                  _arguments '*:project:_path_files -g "**/*.??proj"' && ret=0
                  return ret
                  ;;

                (version)
                  _arguments '*:version: ' && ret=0
                  return ret
                  ;;
              esac

              local -a should_be_args

              should_be_args=(
                group:'Add the package to the given group. Default: Main group'
                project:'Add the package to a single project only'
                version:'Version of the package'
              )

              # Remove entries from should_be_args that match words.
              # _arguments would have done this automatically, but we can't
              # use it because they are not args (i.e. not starting with -).
              local word
              for word in $words; do
                should_be_args=(${(R)should_be_args:#$word:*})
              done

              ((${#should_be_args} != 0)) && _describe -t
should-be-args 'command option' should_be_args && ret=0
              _arguments $args && ret=0
              ;;
          esac
          ;;
      esac
      ;;
  esac

  return $ret
}


                 reply	other threads:[~2016-10-23 14:04 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CACcHa=P1r9b0zGr2y40YzsdpYxiPLxWDCmFzDCPtxvZRrXS1jA@mail.gmail.com' \
    --to=agross@therightstuff.de \
    --cc=zsh-users@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).