pegjs icon indicating copy to clipboard operation
pegjs copied to clipboard

Rewrite bin/pegjs using a command-line option parsing library

Open dmajda opened this issue 8 years ago • 11 comments

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.

dmajda avatar Jun 21 '16 13:06 dmajda

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.

seanich avatar Aug 05 '16 14:08 seanich

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:
    1. These messages need to be consistent with other messages produced by bin/pegjs.
    2. These messages are part of bin/pegjs’s interface which shouldn’t change if the underlying option-handling library changes in the future.
  • 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 as pegjs -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.

dmajda avatar Aug 24 '16 12:08 dmajda

I believe that yargs covers all of those requirements. I'll get to work on this and submit a PR this week. :)

seanich avatar Aug 29 '16 15:08 seanich

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.

dmajda avatar Dec 13 '16 14:12 dmajda

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.

dmajda avatar Dec 13 '16 14:12 dmajda

Have you looked at gnu-option?

paularmstrong avatar Dec 13 '16 14:12 paularmstrong

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, both A and 5 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.

dmajda avatar Dec 14 '16 14:12 dmajda

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.

jaubourg avatar Dec 14 '16 14:12 jaubourg

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 :-)

dmajda avatar Dec 15 '16 13:12 dmajda

Maybe this: http://peg.arcanis.fr/3Jf8sm/ :)

Mingun avatar Dec 15 '16 16:12 Mingun

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

futagoza avatar Aug 18 '17 07:08 futagoza