8000 Docopt based option parsing facility for functions and builtins · Issue #478 · fish-shell/fish-shell · GitHub
[go: up one dir, main page]

Skip to content

Docopt based option parsing facility for functions and builtins #478

@xiaq

Description

@xiaq

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0