-
-
Notifications
You must be signed in to change notification settings 8000 - Fork 2.2k
Description
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
$argvand appear somewhere else.For builtins, a
std::map<wcstring, wcstring_list_t> optsis passed in addition toargv(This also reduces the LoC ofbuiltin.cppdrastically. :). For functions, options are put in corresponding environment variables. For boolean options (aka switches), an empty array is created (and can be tested withset -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' ... endwhich 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> endand
function history option 'prefix:' --description 'Match history items that start with the given prefix' endThe 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
optionto look like an ordinary builtin but is actually part of the function declaration. @cben additionally proposed thatoptioncan be an ordinary builtin, but it will requireoptionto mangle the$argvin 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:
- If a short option has an long form, it's canonicalized into the long form.
- Options are kept in
$opt_optname.
So calling
f -a a -b b --long some, supposing-ais equivalent to--argand-bhaving no long form, results in$opt_arg,$opt_band$opt_longassigneda,bandc, 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--statusand--version, which are plausible option names since they will shadow the well-known variables$statusand$version, I think it's worthwhile to keep the$opt_prefix in all cases.