commandlineparser / commandline

The best C# command line parser that brings standardized *nix getopt style, for .NET. Includes F# support
MIT License
4.53k stars 477 forks source link

Single dash in value treated as Option #735

Open jacekard opened 3 years ago

jacekard commented 3 years ago

Hi, this seems strange, but I'm having problem with using Parser like: --parameter "-someValue", because Parser treats "-someValue" as Option, which can't find.

Here in wiki, we can see --suffix parameter with value "-2019". It doesn't seem to work in my project. https://github.com/commandlineparser/commandline/wiki/Option-Groups

option EnableDashDash = true doesn't help either. Any help with this?

elgonzo commented 3 years ago

Yeah, i have the same problem (i tried with 2.9.0-preview1). And so have others (https://github.com/commandlineparser/commandline/issues/709).

This is actually a showstopper for a project of mine that uses this (otherwise great) commandline parser library, as there doesn't seem an easy way around this problem. In my case, it's an argument for providing file names, where the file names can be like "-alpha12345.png". The only choice i have right now for this project is to not use this commandline parser for the time being (until the issue is being fixed). Luckily, the affected project only uses half a dozen commandline arguments, whose parsing/evaluation i can relatively quickly hand-code (without the conveniences of help texts and proper handling of invalid commandline arguments, of course...)

Btw, i have looked into the source code. I don't hold hope for a quick fix, i am afraid. The tokenizer as written currently does not take the arity of the commandline arguments into account and tries to tokenize the overall commandline at once, with every single argument string analyzed based on the presence/abscence of dashes. The tokenizer has a special code path to detect if an argument string starts with hypen-digit (for instance "-1hullo") as it seems, but that doesn't obviously won't help if an argument value is a not having a digit right right after the hypen like "-foobar". Fixing the issue would involve a substantial rewrite of the tokenizer, which has to either become aware of the the nature/kind of an argument string, i.e., does the string represent an argument/option name or an argument value, or change the tokenizer and parser in a way that tokenizes and parses the commandline only step by step from left to right, with only one option/argument being tokenized and processed at a time.

jacekard commented 3 years ago

@elgonzo Hi, the only temporary solution I came across during playing around with single dashes is to provide a whitespace (a 'space' being specific) before the hyphen, for example --param " -foobar". Parser gets this right and then you could manually trim all the whitespaces before/after "foobar". This seems like an inconvience but for my use it was the only way I could make it work. Cheers!

Edit: It could be also possible to write some kind of logic before invoking Parser methods which will modify string[] args items by adding whitespace to them if they start with "-" and not "--" (indicating this is parameter and not a value). Then in the logic handling given action values can be then trimmed. The only workaround I have in mind right now, but this might work for you.

elgonzo commented 3 years ago

For simpler CLI setups, your suggested workaround can indeed help getting around the issue. It handily beats hand-coding the whole args handling, even where the CLI is rather simple.

rmunn commented 3 years ago

PR #684 (merged into develop branch already, though hopefully #690 will also be merged before release 2.9 happens) fixes this by creating a "strict getopt" mode, where --param -foobar will be interpreted as "the value of param should be -foorbar", precisely the way getopt does. Once #690 gets merged, the syntax will be:

var parser = new Parser(with => {
    with.ParserMode = ParserMode.GetoptParserV2;
});

And then that will cause the parser to treat a value starting with a hyphen as a value, not an option, if (and only if) it immediately follows an option that expects a value.

rmunn commented 3 years ago

Until 2.9.0 is released, you can actually make this work by using the = syntax: --parameter=-someValue. This is a workaround, not the ideal solution, because it means that --parameter=-someValue and --parameter -someValue have different effects. Once 2.9.0 comes out, ParserMode.GetoptParserV2 will be what you're asking for.

rmunn commented 3 years ago

This is essentially a duplicate of #601, BTW.

jacekard commented 3 years ago

Great! That's good news. Thank you.

jacekard commented 3 years ago

@rmunn Hi Robin, could you give an estimate when this MR will be merged? https://github.com/commandlineparser/commandline/pull/690

rmunn commented 3 years ago

@jacekard wrote:

@rmunn Hi Robin, could you give an estimate when this MR will be merged?

690

I can't give you an estimate, sorry. I'd have merged it months ago if I was a repo maintainer. But the repo maintainers (which AFAIK are just @moh-hassan and @gsscoder) haven't responded to any of my pings in the past months. So I have no idea when #690 will be merged, sorry.