brentyi / tyro

CLI interfaces & config objects, from types
https://brentyi.github.io/tyro
MIT License
504 stars 27 forks source link

Simplified usage - option to don't show all arguments in the usage line? #113

Closed cwerner closed 10 months ago

cwerner commented 10 months ago

Hi all.

I recent found your lovely tyro lib and enjoy using it quite a bit! Thanks for creating it.

Now for my problem: I have a script with a lot of arguments. Everything works fine, however I'd like to simplify the usage line when the help is shown. Basically I only want to see an indicators that options can be used and then the required positional args...

Is it possible to get a line like this?

usage: myscript.py [-h] [OPTIONS] ARG1 ARG2

...
then the details of all arguments

Cheers, C

brentyi commented 10 months ago

Hi!

Unfortunately there isn't a nice way to do this. If you want a quick fix you could try a monkeypatch:

def monkeypatch_tyro_usage() -> None:
    import tyro._argparse_formatter

    _orig_format_usage = (
        tyro._argparse_formatter.TyroArgparseHelpFormatter._format_usage
    )

    def monkeypatch(self, usage, actions, groups, prefix) -> str:
        actions = [
            action
            for action in actions
            if len(action.option_strings) == 0 or "-h" in action.option_strings
        ]
        return _orig_format_usage(self, usage, actions, groups, prefix)

    tyro._argparse_formatter.TyroArgparseHelpFormatter._format_usage = monkeypatch

monkeypatch_tyro_usage()

This should produce something like: usage: myscript.py [-h] ARG1 ARG2

Or, to get the [OPTIONS] in there, maybe just hardcode:

    def monkeypatch(self, usage, actions, groups, prefix) -> str:
        usage = "myscript.py [-h] [OPTIONS] ARG1 ARG2"
        return _orig_format_usage(self, usage, actions, groups, prefix)

For a longer-term fix, I'm happy to consider either or both of:

  1. Making the behavior you described the default behavior, perhaps enabled by some heuristics on the maximum length of the usage text. I think the issue you're describing isn't uncommon, for example in nerfstudio:

image

  1. Supporting a usage: Optional[str] argument to tyro.cli(), which would mirror the usage= argument of argparse.ArgumentParser().

My preference would be (1). Thoughts?

cwerner commented 10 months ago

Oh wow, that screenshot is next level 🫣. I think given that the args are listed in detail below in the help message I’d be fine with a simple usage line that just uses the [options] placeholder and lists the positional args. Or maybe a placeholder for each argument group followed by the positional arguments? So I’d also go for option 1 (maybe with one option placeholder per argument group). But thanks for the hacky solution. For the moment that’ll do…

brentyi commented 10 months ago

Just did a release with Option 1! If there anything looks off please let me know :)

cwerner commented 10 months ago

Great stuff. Thanks 🙏