Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A way to prevent parsing of options after positionals #359

Open
teohhanhui opened this issue Apr 27, 2024 · 9 comments
Open

A way to prevent parsing of options after positionals #359

teohhanhui opened this issue Apr 27, 2024 · 9 comments

Comments

@teohhanhui
Copy link

Perhaps related to #302, I'd like to be able to prevent parsing of options after positionals.

Given:

Usage: krun [--net=NET_MODE] [--passt-socket=PATH] COMMAND [COMMAND_ARGS]...

Available positional items:
    COMMAND                  the command you want to execute in the vm
    COMMAND_ARGS             arguments of COMMAND

Available options:
        --net=NET_MODE       Set network mode        NET_MODE can be either TSI (default) or PASST
                             [default: TSI]
        --passt-socket=PATH  Instead of starting passt, connect to passt socket at PATH
    -h, --help               Prints help information

If I do:

krun --net=PASST box64 --help

It should not be parsed as the --help option.

Sure, it's possible to just add -- but that's not always user-friendly.

@pacak
Copy link
Owner

pacak commented Apr 27, 2024

So I can better understand the problem - what's the motivation for that?

@pacak pacak changed the title Option to prevent parsing of options afer positionals Option to prevent parsing of options after positionals Apr 27, 2024
@pacak pacak changed the title Option to prevent parsing of options after positionals A way to prevent parsing of options after positionals Apr 27, 2024
@teohhanhui
Copy link
Author

As illustrated above, it's to pass all COMMAND_ARGS to COMMAND. So basically like any, but without this "problem":

“before” in the previous line means in the parser definition, not on the user input, here --turbo gets consumed by turbo parser even the argument goes

https://docs.rs/bpaf/latest/bpaf/fn.any.html#use-any-to-capture-the-remaining-arguments

@pacak
Copy link
Owner

pacak commented Apr 28, 2024

As illustrated above, it's to pass all COMMAND_ARGS to COMMAND.

I see. That's a bit tricky, my usual approach is to have different flags between inner and outer commands. To apply the restriction you want parser needs to run on arguments in order they are given on a command line, at the moment it runs in order they are specified in your parser. I need to think about an efficient way to allow this, might take some time.

@teohhanhui
Copy link
Author

my usual approach is to have different flags between inner and outer commands

COMMAND in this case is just any external program. So we don't know / don't care what the arguments are.

@teohhanhui
Copy link
Author

teohhanhui commented May 6, 2024

I have identified another (perhaps related) issue with any. I can't seem to get it to behave similarly like positional, while still consuming anything that comes after it.

To illustrate:

Given (the same program as before, but updated):

$ krun --help
Usage: krun [-e=ENV]... [--net=NET_MODE] [--passt-socket=PATH] COMMAND [COMMAND_ARGS]...

Available positional items:
    COMMAND                  the command you want to execute in the vm
    COMMAND_ARGS             arguments of COMMAND

Available options:
    -e, --env=ENV            Set environment variable to be passed to the microVM
                                     ENV should be in KEY=VALUE format, or KEY on its own to inherit the
                                     current value from the local environment
        --net=NET_MODE       Set network mode        NET_MODE can be either TSI (default) or PASST
                             [default: TSI]
        --passt-socket=PATH  Instead of starting passt, connect to passt socket at PATH
    -h, --help               Prints help information

If I do:

$ krun --net=PASST --net=PASST -- box64 --version

The second unconsumed --net=PASST ends up being consumed by any (COMMAND_ARGS). There should be a way to consume anything only from the current position, i.e. after COMMAND.

The code is here for your reference: https://github.com/teohhanhui/krun/blob/283a1f716f8c2078e9fbe6a4f2174bcba38b559e/crates/krun/src/cli_options.rs

@pacak
Copy link
Owner

pacak commented May 6, 2024

I got some ideas how to implement it and for now I'm done messing with cargo-show-asm. I'll try to make something that can solve your problem soon-ish.

@pacak
Copy link
Owner

pacak commented Jul 2, 2024

I pushed a right-adj branch that implements start_adjacent() method on parser trait. The idea is that the whole annotated block must be either directly adjacent to the beginning or to fully parsed block, so if you make it so xxx parses --net=PASST, but not box64 - parser like listed above will parse krun --net=PASST box64 --help by capturing "PASST" into xxx and ["box64", "--help"] into tail. At least for as long as xxx succeeds.

let option_parsers = xxx.start_adjacent();
let tail = any::<OsString, _, _>("TAIL", Some).many();
let parser = construct!(option_parsers, tail)

I'm planning to release a new version with it in a few days after covering some of other remaining issues.

@teohhanhui
Copy link
Author

This is addressing the original issue, right? But what about the other issue I found? 🙈

@pacak
Copy link
Owner

pacak commented Jul 2, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants