pegjs
pegjs copied to clipboard
Rewrite bin/pegjs using a command-line option parsing library
Right now, bin/pegjs
parses options manually. This means some slightly advanced things like using =
to separate option name and value or combining short options (-abc
= -a -b -c
) are not supported.
Let’s rewrite bin/pegjs
using a proper command-line option parsing library which supports all these things out of the box. Possible candidates are yargs, argp, or cli.
Do you mind if I take a crack at this? I'm fairly familiar with yargs so I'd like to use that if that's okay.
My requirements for any library used for the rewrite:
- Full support for GNU-style option handling. See e.g. here, here, or here for a description.
- Ability to customize error messages produced in cases like invalid option, missing option value, invalid option value, etc. This is important for two reasons:
- These messages need to be consistent with other messages produced by
bin/pegjs
. - These messages are part of
bin/pegjs
’s interface which shouldn’t change if the underlying option-handling library changes in the future.
- These messages need to be consistent with other messages produced by
- Ability to handle repeated options in different ways. For some options, specifying them repeatedly means the last value “wins” (e.g
pegjs -e foo -e bar
is the same aspegjs -e bar
). For other options, all specified values are acted upon (e.g.pegjs --plugin foo --plugin bar
loads both plugins). - It should be reasonably well written, documented, and maintained. It doesn’t necessarily have to be popular.
- Using it should lead to code that is clean and readable.
@seanich I didn’t dive into yargs sufficiently to determine if is fulfills all the requirements (in fact, I’m not sure if any library does :-) But if you think so, feel free to go ahead with the rewrite if you still fell like it — just let me know. And sorry for not replying for so long — I was focusing at other things in the past weeks.
I believe that yargs covers all of those requirements. I'll get to work on this and submit a PR this week. :)
I looked at argp.
Full support for GNU-style option handling.
Not as robust as claimed. For example, consider this program:
let argp = require("argp");
let argv = argp.createParser({ once: true })
.body()
.option({ short: "a" })
.option({ short: "b", metavar: "x" })
.argv();
console.log(argv);
When executed with argument -ba
, it should do the same as if executed with -b a
, but it produces an error (“short-opts: Option '-b' requires an argument”).
Ability to customize error messages produced in cases like invalid option, missing option value, invalid option value, etc.
There is a generic error
event that can be used for that, but specific errors can’t be distinguished from each other except by parsing the messages.
Ability to handle repeated options in different ways.
No direct support, but looks doable using a reviver.
It should be reasonably well written, documented, and maintained.
Reasonably well written and documented, but not touched for 3 years. Looks abandoned.
Using it should lead to code that is clean and readable.
The API is somewhat clunky but good enough.
Overall verdict: Unsuitable
The biggest issue is a lack of maintenance, without which technical issues with option handling and error customization can’t be resolved.
I looked at Commander.js.
Full support for GNU-style option handling.
There is at least one bug. Consider this program:
let program = require('commander');
program
.option('-a, --alpha')
.option('-b, --beta <x>')
.parse(process.argv);
console.log(program);
When executed with argument -ba
, it should do the same as if executed with -b a
, but it sets program.beta
to "-a"
.
Ability to customize error messages produced in cases like invalid option, missing option value, invalid option value, etc.
Doable by creating a subclass of the Command
class and overriding certain methods.
Ability to handle repeated options in different ways.
Doable using coercion.
It should be reasonably well written, documented, and maintained.
Reasonably well written and documented, but looks abandoned. There are quite some unattended issues and PRs.
Using it should lead to code that is clean and readable.
All good here.
Overall verdict: Unsuitable
Again, the biggest issue is a lack of maintenance. While I found only one technical issue which would be trivial to resolve, the sheer number of reported and unattended issues doesn’t exactly inspire confidence.
Have you looked at gnu-option?
Have you looked at gnu-option?
I looked briefly. The API looks terrible to me, plus there is this paragraph in README.md
:
Cannot correctly parse when including POSIX option that immediately followed by its value like
-A5
. In this case, bothA
and5
will be treated as option name. I will fix this issue in the future release.
This means gnu-option is no better than the other alternatives I explored.
I also briefly looked at Optionator, which caught my eye because it is used by ESLint. It looked usable until I found this in its README.md
:
Name arguments of any length are prefixed with
--
(eg.--go
), and those of one character may be prefixed with either--
or-
(eg.-g
).
In other words, no GNU-style options again.
I’m really frustrated by now. It looks like the Node.js community produced dozens of command-line option parsing libraries, but none of them is able to fulfill requirements that I consider pretty basic. At least, I wasn’t able to find one.
It’s even more frustrating given that I come from the Ruby world, where a library fulfilling these requirements more than satisfactorily exists in the standard library. It even supports conventions like respecting POSIXLY_CORRECT
, which is something relatively obscure and which I wouldn’t mind ignoring.
Do I require too much by insisting on adherence to option parsing conventions used by pretty much all Unix software? Did they became irrelevant without me noticing? Does anyone else care? Are Node.js libraries written by attention-deficit teenagers?
I don’t know.
What I do know is that I’ll let this issue linger for a while. If someone knows about a library that fulfills the requirements, please let me know. Otherwise I’ll probably write it myself.
https://www.npmjs.com/package/optparse claims to be based on Ruby's OptionParser but it's quite old, not that popular and doesn't seem to be maintained.
At this point, sounds like somebody has to fork/create a parser if you want your OptionParser goodies.
Thank you for pegjs, it's a key component of a project I'm working on and I cannot tell you how much I appreciate the work and dedication you put into it.
At this point, sounds like somebody has to fork/create a parser if you want your OptionParser goodies.
Actually, the best outcome would probably be someone stepping in as an active maintainer of Commander.js (one of the better and more popular libraries) and fixing its issues.
Thank you for pegjs, it's a key component of a project I'm working on and I cannot tell you how much I appreciate the work and dedication you put into it.
Thanks :-)
Maybe this: http://peg.arcanis.fr/3Jf8sm/ :)
I'm moving this to 1.0 as it's hard to find one that suites the above conditions, although I'm leaning towards a custom fork of Commander.js with the bug mentioned fixed.
EDIT:
Rewrote command line tool, see https://github.com/pegjs/pegjs/commit/0ed8c6f89a37dad7883680af64bc99641c54823e