Fish-shell: Docopt based option parsing facility for functions and builtins

Created on 26 Dec 2012  路  54Comments  路  Source: fish-shell/fish-shell

This is a less aggressive version of issue #447. I did attempt an implementation of syntactically significant options (for the interested it's at https://github.com/xiaq/fish-shell/tree/opt-parse), but I held back and decided that it's not a good idea, since the inevitable inconsistency with external commands feels really bad to me.

Still, as pointed out by @cben, the option parsing facility is orthogonal to the parser changes, and I don't want to throw away all the codes I wrote :-), so I opened this new proposal. The basic idea is:

  • Functions and builtins have _signatures_, which describe the options they accept, constraints on the options (whether they accept arguments or not, and if they do, how many, etc.) and the descriptions for them. With this information completions can be _automatically generated_, avoiding a lot of duplicate work.
  • Option parsing is done just before a function or builtin is called, so that recognized options (and possibly their arguments) are removed from $argv and appear somewhere else.

For builtins, a std::map<wcstring, wcstring_list_t> opts is passed in addition to argv (This also reduces the LoC of builtin.cpp drastically. :). For functions, options are put in corresponding environment variables. For boolean options (aka _switches_), an empty array is created (and can be tested with set -q); for non-boolean options, the specified values are kept.

Some details, summarized from issue #447:

  • The exact syntax for function signatures still needs some thoughts. I originally proposed

function foo -o h,help,'Display help' -o c:,count:,'Specify a count' ... end

which has the advantage of not requiring any special syntax, but doesn't look very nice, and makes it clumsy to write long option lists. @ridiculousfish proposed two forms,

function history function --options --save,-s: 'Save all changes in history file' --clear: 'Delete all history items' --search "command": Searches for the given command end <body of function> end

and

function history option 'prefix:' --description 'Match history items that start with the given prefix' end

The former visually resembles option specifications in manpages, but calls for some special syntax for the signature specification. The latter has the advantage of not requiring syntax change. I tried implementing the latter, but after the attempt I'm not in favor of it - it breaks the usual "skipped execution" semantics of commands within functions. It can be misleading for option to look like an ordinary builtin but is actually part of the function declaration. @cben additionally proposed that option _can_ be an ordinary builtin, but it will require option to mangle the $argv in the _calling frame_, which I found not really good a bit later.

  • How option variables should be named need some thoughts too. The rule I proposed was:

    1. If a short option has an long form, it's canonicalized into the long form.

    2. Options are kept in $opt_optname.

So calling f -a a -b b --long some, supposing -a is equivalent to --arg and -b having no long form, results in $opt_arg, $opt_b and $opt_long assigned a, b and c, respectively.

@maxfl proposed that we drop the $opt_ prefix for long options. I was originally for this, but after realizing that this makes it impractical to have --status and --version, which are plausible option names since they will shadow the well-known variables $status and $version , I think it's worthwhile to keep the $opt_ prefix in all cases.

RFC enhancement

Most helpful comment

Should we implement a getopt() equivalent for fish scripts? This issue has been open for four years. As issue #3403 opened by @floam points out our standard method for option parsing in fish scripts is not compatible with fish builtin commands (or most external commands). Perhaps we should implement a fish getopt builtin for use by fish scripts. Doing so is borderline trivial. It would allow us to make our fish scripts (functions) parse flags in a manner compatible with builtin commands. If and when this is implemented both builtin and function flag parsing can be changed.

All 54 comments

The function signature syntax should also make it possible to specify whether the signature is _authoritative_ - that is, whether unrecognized options should result in an error or kept in $argv.

The distinction between boolean vs. non-boolean options can be part of more general constraints on the _number_ of option arguments: 0 argument = boolean, 1+ argument = non-boolean. Another common use case can be mandating _exactly 1_ argument, so that you can rely on some option variable $opt_foo to expands into exactly 1 word.

Attribution: argument number constraint was proposed by @maxfl.

For switches, I think you meant to write set -q instead of test -q

Sounds good to me so far. Complementary goals here:

  1. Make it easier for functions and builtins to parse their options
  2. Make functions more self-documenting
  3. Allow syntax highlighting and tab-completions to leverage the function signature, eliminating the need for a separate completion
  4. Improve the syntax for specifying completions

The last two are the most ambitious, and also imply we should be able to write a function signature for an external command, not just a function.

I thought it would be useful to list the option properties we may want to support. Global properties for an option specification:

  1. Authoritative: whether there may be more options, or this is it
  2. Files only: the non-option arguments are always files
  3. Files never: the non-option arguments are never files (https://github.com/fish-shell/fish-shell/issues/379)
  4. Old long options: all long options use one dash ('-foo' not '--foo') (maybe this is a per-option thing instead)
  5. (Maybe) All options must be literal: 'count --help'
  6. (Maybe) Options apply to a subcommand: ('git checkout ...')
  7. (Maybe) Supports two dashes to mean "end of options" (maybe we just always assume this is on)
  8. (Maybe) Alias: use the same completions as this other command (https://github.com/fish-shell/fish-shell/issues/393)
  9. (Maybe) At least one argument is required.

Properties for an individual option:

  1. Description
  2. Long name: '--foo'
  3. Short name: '-f', with the understanding that these may be combined: ('rm -Rf')
  4. (Maybe) Long name with one dash: '-foo' (what fish calls "old style")
  5. Has argument: whether the option takes a parameter
  6. (Maybe) Argument to option is always a file
  7. (Maybe) Parameter uses equals: ('gcc -std=c99')
  8. (Maybe) Option must be literal ('count --help')
  9. Condition: a shell command that must return 0 if the completion is to be used

I struggle to read completions, so hope the syntax will be highly readable, and as close as possible to the actual command usage so it serves as an example.

A lot of scripting languages have libraries for option specification and parsing, often more than one. We should do a survey to see how they handle it and whether they have any good syntax ideas we could use.

Another syntactic possibility is to make the entire signature a single argument to function, but the argument typically spans multiple lines by using quotes:

function history --options '
        -s, --save: Save all changes in history file
        -c, --clear: Delete all history items
    '
    <body of function>
end

docopt has some nice syntax. None of the existing implementations use a suitable language, but they might appreciate our contributing a C++ implementation.

@ridiculousfish Fixed: s/test -q/set -q/.

@ridiculousfish I'm not sure whether docopt did the correct thing - it is very readable, but I also feel it somehow obscures the structure. I would prefer something a bit more formal.

I'm getting back to this after a few weeks. I have taken another closer look at docopt. Many of its ideas like pattern matching, a single dict for all results (be it an option, option argument or positional argument) are inspiring.

I think a docopt-like solution is viable, but there are two problems I see now. First is how it fits within fish syntax. An easy approach to enclose docopt in single quotes, but that makes syntax highlighting clumsy (if possible at all). If we put it unquoted we'll likely have to introduce a special "docopt block" to alter the usual syntax.

Secondly it would need some extensions. Particularly I wish the syntax for writing completions be a superset aof signature syntax, and supporting completions would require at least the following extensions:

  • Specifying a possibly non-exhaustive list of candidates for arguments, like completion. That's the reason why completions exist, and it can be useful in signatures too (generate completion, check the argument against the list if it's exhaustive).
  • Full programmability. We can hardly cover every possible flavor of option specification; in that case, give the completion writer full control.

The following can be optionally supported, but since I covered "full programmability" they are optional :) :

  • Exotic option leaders. e.g. sh(1p) supports +, so that sh +ab is equivalent to sh +a +b.
  • Where the possible choices are limited, unambiguous prefixes resolve to the full word. Linux ip(8) is an example of this: it has subcommands including link, addr, route, etc. and ip route can be abbreviated to any of ip rout, ip rou and ip ro (ip r is actually an accepted abbreviation, but it's not an unambiguous prefix). When the user has written any of these the completion should acts as if ip route is seen.

I'm wondering about this, and decided to experiment with this a little by making self documenting format. Let's assume something simple, like the following command (if somebody needs something really complex (like options starting with +), they shouldn't have used fish parser to parse the command).

cut --as-well-as-possible --budget=5000 -x --name=Me --name=Him something else

This could be represented as this.

function cut --description 'It cuts!'
    options --as-well-as-possible/-a --budget/-b= -x --name=... rest-arguments...
    if test $x
        echo "You provided $rest_arguments."
    end
end

Alternatively, with documentation.

function cut --description 'It cuts!'
    options --as-well-as-possible/-a: 'Does stuff as well as possible.' \
            --short/-s=: 'Does something important for sure.'
end

The syntax provided here is intended to be simple and self documenting (declaration mimics use, like in C). ... means multiple arguments (in CoffeeScript style), / is alternation (the first variable in it would be final variable name (but the , would work as well)), = means that the option takes arguments, : is documentation, and that's about it. Yes, I'm aware of issue with _ and -, but I cannot think of solution for it, sadly.

Just wondering, what is your opinion about my proposal?

Seems like a good start! The 'options' command is especially interesting.

A key feature is going to be constraints on arguments. We want to be able to express that arguments are only files, never files, only directories (cd), only commands (sudo), or are determined programmatically (git checkout ...). We also want to be able to name arguments, for the automatic parameter-parsing facility within fish functions. I encourage you to consider how these might fit in to the syntax.

I just noticed that docops now has a C++ implementation. Might be worth looking into again. https://github.com/docopt/docopt.cpp

I vote for docopt too. It was fun to use it in Python and even C. I think that it's easier to implement and understand docopt spec enclosed in single quotes. Highlighting is an issue, but I think it can be solved by writing universal vim/emacs/etc. plugin that handles docopt spec in python/c++/fish/etc. sources.

I added a wiki page with some samples of what it would look like to write signatures with an extended docopt syntax, and some thoughts on how we would extend it. Contributions welcome.

@ridiculousfish has there been any progress on this lately?

Yes, lots of work in the docopt branch.

I missed that branch. Great news :100: :+1:

Here's my work so far. This is turning into a very large feature, but it will subsume other features so I think it overall reduces the complexity. I'm posting this to get feedback - please read and share your thoughts.

Summary

We add a notion of a command _signature_, with a syntax based on docopt. The signature is a piece of metadata that provides fish with lots of information about how the command is invoked.

To give you a taste:

complete --signature '
Usage: cowsay [options] [<message>...]
Options: -e, --eye <eyestr>         Specify eye string
         -f, --cowfile <cowname>    Specify cow file name
         -help                      Display help and exit
         -l, --list                 List all cowfiles
         -n                         No word wrapping
         -T                         Specify tongue string
         -W, --width <colwidth>     Column width

Conditions: <cowname>  (cowsay -l|tail -n +2|tr \  \n)

Cowsay generates an ASCII picture of a cow saying something provided by the user. If
run with no arguments, it accepts standard input, word-wraps the message given at
about 40 columns, and prints the cow saying the given message on standard output.
'

Goals

The signature plays multiple roles:

  1. It becomes the preferred way to write tab completions. complete flags like -l, -s, and -o will be deprecated in preference to signatures, which are more powerful.
  2. It is used by syntax highlighting. Since it provides more information than completions, the syntax highlighting becomes more precise.
  3. It parses $argv in fish functions (and builtins). fish functions can be made simpler and will no longer聽 have to shell out to getopt.
  4. It replaces the command's usage spec. Files like doc_src/complete.txt can go away. Help text will be derived directly from the signature (with light filtering), either at build time or runtime.

Usage

The commands complete and function both gain a new option --signature (short option -g), whose argument is a signature. The signature is an ordinary string argument, and so is subject to the usual quoting and escaping rules.

The unescaped signature must be valid _fish-flavored docopt_, which is a somewhat stricter set of docopt. The differences are described here.

When specifying a signature, you can omit the command name to complete and it will be read from the signature. If you do specify a command name, it takes precedence over the one in the signature.

Syntax

Note: users and completion authors are not expected to become experts in this stuff. Instead the man page for complete and function will have a few samples, that users can copy and modify following a (hopefully obvious) syntax. As this is fish, syntax errors are reported with outstanding diagnostic messages.

The signature has three sections: "Usage", "Options", and "Conditions". Only the Usage section is required. Sections boundaries are based on indentation, like blocks in Python. Other sections are ignored by fish, except when printing the signature for help.

The Usage section shows different usage patterns for invoking the command. docopt.org describes these in more detail, subject to fish-flavored differences.

The literal "[options]" in a usage pattern is a proxy for the Options section. Descriptions may be given for individual options, and these will appear as the descriptions in tab completions.

The "Conditions" section is unique to fish-flavored docopt, and determines allowed values for variables. Within the section, specify the variable (including brackets), followed by at least two spaces, and then an argument list which may contain subshells, identical to complete -a. This is only used during tab completion (the section is omitted when printing help.

Inferred Conditions

A variable may have inferred conditions based on a suffix of its name:

- *file -> only files
- *dir or *directory -> only directories
- *path -> any valid path (the destination does not have to exist, but intermediate directories do)
- *command or *cmd -> only commands (e.g. for sudo)

For example: Usage: rmdir <directory> ... or Usage: cat [<file> ...] will only tab-complete to directories and files, respectively. Syntax highlighting will also check these conditions. This makes it very simple to achieve common tab completion behavior.

Argument parsing

When a function has a signature, $argv will be parsed according to the signature and variables automatically populated. This is based on xiaq's design. We populate variables for the options, commands, and variables in the signature:

  • Options get canonicalized to the corresponding long name, if it exists. Dashes are replaced with underscores, and then opt_ is prepended, e.g. --foo => $opt_foo. The value is set to 1.
  • A subcommand like checkout corresponds to the variable $cmd_checkout.
  • A variable has its name used directly. (This implies that you cannot use certain variable names like <status>, but variable names do not affect the invocation syntax so this is not a burden).

Examples for this signature:

Usage: cowsay [options] [<message>...]
Options: -e, --eye <eyestr>          Specify eye string
         -f, --cow-file <cowname>    Specify cow file name

run with:

cowsay -e XX --cow-file dragon hello world [<message>...]

will result in the following function-scoped variables and values:

  • $opt_eye = 1
  • $opt_cow_file = 1
  • $eyestr = XX
  • $cowname = dragon
  • $message = hello world <- list of length 2

Of course $argv will also be set to the full list of arguments.

Prefer set -q within the function to check for the presence of flags.

Authoritative vs unauthoritative

Function signatures respect the -A/--authoritative and -u/--unauthoritative options to complete, and we will add these options to function too.

When a function is invoked with an authoritative signature, its arguments are matched against the usage specifications. If the match is imperfect (unrecognized options, or missing/excessive arguments), the function does not execute, and instead help (derived from the signature) is printed. In this way, a function is saved from having to do validation.

If the function's signature is unauthoritative, then fish makes a best-effort to choose a pattern and populate variables based on that, and the function is executed.

By default, function signatures are authoritative. This behavior only applies to functions, not external commands.

Multiple signatures

A command may have multiple signatures. This is convenient for breaking up a large command like git into multiple signatures (e.g. one for each subcommand).

The behavior is as if the multiple signatures are merged into a single one. In case of ambiguity, the most-recently specified signature takes precedence.

I haven't read very much about docopt yet, but I like where this is heading. I'm curious though, how will generated tab-completion values fit into this framework? For example, the tab completion for git-add will complete relevant file names, and git-checkout will complete branch names. Will we still have to use the existing complete options, or does docopt have some way of specifying that?

git checkout tab completion old way:

complete --no-files --command git \
         --description Branch \
         --arguments '(__fish_git_branches)' \
         --condition '__fish_git_using_command checkout'

New way:

complete --signature '
    Usage: git checkout [<branch>]
    Conditions:
        <branch>  (__fish_git_branches)
'

Or working on it a bit more:

complete --signature '
    Usage:
        git checkout [-q | --quiet] [<checkout_target>]
        git checkout -b <new_branch>

    Options:
        -q, --quiet   Quiet mode
        -b, --branch  Create a new branch

    Conditions:
        <checkout_target>  (__fish_git_branches) (__fish_git_tags) (__fish_git_modified_files)
'

As you can see there's a lot less boilerplate, and subcommand support comes for free - none of this __fish_git_using_command business (though git aliases will complicate it).

Soo... I like the general idea of this, but there's a few cases we need to think of:

  • busctl's "staged" stuff (also seen in ip) - first the bus, then the object, then the method, then the arguments. Order is really important here, and completions for every argument depend on the arguments before
  • Option-before-command - i.e. git --help checkout, but also systemctl --now [enable|disable|mask|unmask] - this easily has the possiblity of blowing up the signature

I also don't quite get why it's called "Conditions" - it's not like the old complete --condition ("-n"), but more like complete --argument ("-a") - why isn't it called "argument"? How would this work with arbitrary conditions? As an additional "-n" outside of the signature? Are arbitrary conditions actually used or just for subcommand shenanigans?

Could we also have argument descriptions or hints (#2201)?

@faho Thank you for taking the time to read it and your thoughtful reply :smile:

docopt's support for ordered positionals is powerful. You can write for example:

Usage:
      ip link show <device>
      ip addr [add | del] <ifaddr> dev <devname>
      ip route [ add | del | change | append | replace | monitor ] <route>

etc. and it will figure out which pattern to use. For example ip link route would be reported as an error.

For busctl I guess we have:

Usage: busctl call <service> <object> <interface> <method>

You can provide separate completions for each variable. However there's no natural way to make the completions for <object> depend on those in <service>, except for falling back to commandline like we do today.

Options can be reordered arbitrarily with respect to positionals in argv: docopt assumes that git --help checkout and git checkout --help are the same. Do you know if there are any commands that violate that? (I'd say they're ill-behaved but we may need to support them anyways).

I should mention that it also supports -- to indicate that remaining arguments are all positionals.

I think "Arguments" is a much clearer name than "Conditions", thanks for the suggestion.

I like the idea of incorporating argument descriptions. Do you have ideas for how they could be incorporated? The idea is to make it look like man pages, but those don't set much precedent here.

One possibility is to make them look like comments:

Usage: ln [options] <source_file> [<target_file>]
Arguments:
    <source_file>  # Linked-from file
    <target_file>  # New link file

or a realistic example that requires arguments:

Usage: ssh [<user> | <hostname>] [<command_to_run>] [options]
Arguments:
    <hostname>  # Remote host name
        (__fish_print_hostnames)
        (
        #Prepend any username specified in the completion to the hostname
        echo (commandline -ct)|sed -ne 's/\(.*@\).*/\1/p'
        )(__fish_print_hostnames)

basically the hint would go on the same line as the variable name. What do you think?

docopt's support for ordered positionals is powerful. You can write for example:

Great!

However there's no natural way to make the completions for <object> depend on those in <service>

(github seems to think my entire comment is a quote when I don't quote that as code, sorry)

Wishing for ponies: How about putting the other arguments into special variables for the completion functions, e.g.

Usage: busctl call <service> <object> <interface> <method>
Arguments:
    <service> (__fish_busctl_services)
    <object>  (__fish_busctl_objects $service)

There might be an issue that "$service" might clash with another variable. Special syntax might also be possible, e.g.

<object> (__fish_busctl_objects <service>)

Do you know if there are any commands that violate that?

When you're looking for an ill-behaved no-good weird-syntax CLI tool, ip is always a great example :smile:.

$ ip -f inet addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 
inet 127.0.0.1/8 scope host lo
   valid_lft forever preferred_lft forever
$ ip addr -f inet
Command "-f" is unknown, try "ip addr help".

One possibility is to make them look like comments

That looks good, though it of course means you need to be careful where you place actual comments. I've also thought of using the argument name as the description, but that would clash with the "backreferences" and means you might need to type a nice description multiple times when writing the declaration.

Edit: Add actual ip output.

Oh, also, how about duplicate options (#1315) - some commands want them, like pacman, e.g. pacman -Su upgrades packages, while pacman -Suu also downgrades them.

Or aptitude moo, which takes up to (IIRC) seven "-v".

Man, you think of everything!

Counted flags can be specified with the ... syntax, e.g.:

Usage: rsync -v... 

This allows for correct syntax highlighting and completion.

For writing functions, I suppose we can just set the variable's value to its count, i.e. rsync -vvv would result in $opt_verbose = 3

Another weak point of the current system I hit yesterday: "List arguments".

Some commands take, for some options, multiple values, usually separated with a ",".

E.g.

pacman -Syu --ignore linux,bbswitch,nvidia

which will update everything but the packages "linux" (the kernel), "nvidia" and "bbswitch" (which are kernel modules). The current system leaves it up to the individual script to take care of this, in which case it would need to complete e.g.

pacman -Syu --ignore linux,bbs<TAB> to "linux,bbswitch", not just "bbswitch".

The gpg completions used to unconditionally offer each completion on its own and with a "," appended which led to a huge argument-soup (though all the masking characters didn't help).

Then there's also #368 and #369 - ponysay is even weird if you ignore all the ponies.

To answer my own question: docopt.org has:

 -i <file>, --input <file>   # with comma, without "=" sign

so it seems to already work, and is quite intuitive.

Sadly I think that does not do what you hope. The comma is just a separator in docopt syntax. It doesn't imply that a separator appears in the arguments.

Forgive me for a "plus-oneish" comment, but I just want to say that this is absolutely fantastic. I write a lot of shell scripts for this and that, and it seems like every script starts out small and then grows options and arguments. getopt and getopts are okay, but I usually find them wanting and end up parsing manually. This looks like the ultimate solution! Powerful, yet easy to use, and saves so much time. I can't wait to use this in Fish!

@alphapapa Glad you think so, I do too! My hope is that we amass a collection of docopt-descriptions of Unix commands, that eventually takes on a life of its own, becoming a repository for machine-parseable commandline usage specifications that can be used in many more circumstances beyond fish. It's kind of silly that this doesn't exist already!

@ridiculousfish Hm, that's an interesting idea. It seems like most of those should be in -h/--help and man pages already, but I guess not all utilities are so well-documented. I would suggest getting those docopt-descriptions upstream for each one, though, because keeping a separate repository up-to-date sounds like a nightmare to me. D:

https://github.com/mbrubeck/compleat for my own reference - a Haskell attempt with a more minimalist syntax.

I've just been sort of slow to get this in because it adds a fair amount of complexity. I'm hoping to think of ways to simplify it.

This would allow the git integration to be much more complete, and if no one else takes a stab at it I'll look into it. But right now it is such hassle to do, especially since git is fairly complex.

@bucaran xiaq doesn't seem to be here, this issue is 3 years ago.

@pickfire Maybe he's done with fish and switched to elvish? :laughing:

Any updates here?

I'll pick this up after we release 2.3.0. You can play with it now on the docopt branch if you are so inclined however.

Any updates now that 2.3.0 is out?

@gusmonod What are you trying to do exactly?

Well, I was thinking on writing a fisherman plugin doing this same feature in order to use it in one of my projects, so I wanted to know if this will eventually get merged in the main branch.

@gusmonod This should be able to help.

I wanted to know if this will eventually get merged in the main branch.

It will. The docopt branch is alive (last updated 3 days ago) and that is the plan.

Should we implement a getopt() equivalent for fish scripts? This issue has been open for four years. As issue #3403 opened by @floam points out our standard method for option parsing in fish scripts is not compatible with fish builtin commands (or most external commands). Perhaps we should implement a fish getopt builtin for use by fish scripts. Doing so is borderline trivial. It would allow us to make our fish scripts (functions) parse flags in a manner compatible with builtin commands. If and when this is implemented both builtin and function flag parsing can be changed.

Would it be possible to include getopts.fish in Fish itself? It works very well. The only downside I have found is that it treats all arguments after the first non-option argument as non-option arguments, rather than the typical behavior of using -- to end the option list.

I certainly don't oppose a getopt equivalent either. (Note: I think getopt is superior to the Bash getopts builtin, since getopt allows both long and short versions of options.)

@alphapapa, the fact the _getopts.fish_ script you referenced isn't actually compatible with the fish builtin wgetopt() function argues against using it. Unless, of course, it can be easily modified to be compatible with the version used by our builtin commands. Personally I'd prefer to simply expose our wgetopt() function as a builtin command usable by fish scripts. Thus ensuring compatibility. Also, can you provide a link to the script you referred to so we can evaluate its fitness as an alternative solution?

@ridiculousfish, How likely is it that the docopt solution will be made public in, say, the next six months? If the probability is low I'd like to open a new issue to implement a getopt command usable by fish scripts. Implementing that should be almost trivial and would allow commands implemented as functions to behave identically to builtins vis-a-vis flag parsing.

Oops, I thought getopts.fish was linked here already. It looks like the current home for it is https://github.com/fisherman/getopts and it appears to have been updated since I last looked at it, so I'm not sure if the downside I mentioned still applies.

... is that a getopt implementation in awk? That's amazing.

Let's move the getopt conversation to a new issue.

Er...my mistake, I should have looked more closely at that link. It's by the same author, but apparently he rewrote it in awk. It does seem much simpler, but the one I was referring to is the one here: https://github.com/alphapapa/bucket/blob/master/getopts.fish I don't know if there's a canonical home for the fish-native version...

I've decided the approach advocated in this issue and its predecessor, #447, are not viable. See issue #4190 for a more modest proposal that maintains compatibility with existing builtin commands and makes it trivial to have the same behavior in fish script. I intend to merge that solution in the next day or two unless someone yells "stop".

A DocOpt based solution might be ideal (i.e., perfect) but could only be done in a major release. And since this issue has been open for more than four years it is not obvious it will ever be implemented. Especially since it is now more than three months past the deadline previously committed to for implementing a DocOpt based solution.

I don't see the point of a DocOpt based solution. Practicality and clarity trumps the aesthetics of a DocOpt solution.

I do plan to pick this up again at some point. I think my first attempt had too much complexity so I want to find a way to do it more simply.

I think the idea is fatally flawed and the Python implementation seems to be dead since it hasn't been updated in more than two years and still isn't deemed good enough for a 1.0 release. See https://github.com/docopt/docopt/issues/371

Was this page helpful?
0 / 5 - 0 ratings