This is solved, I was being dumb. Please see second EDIT below

This isn’t really language specific, but if it helps I’m using Python. I can get the parameters just fine with the Traitlets module, but I’m still a novice really and figuring out which patterns to use is challenging.

Say you have a bunch of command line parameters. Some are booleans, where their presence means True, absence means False. Other parameters must accept one text string, and others can be used multiple times to build a list of strings.

It feels inefficient/wrong to use a bunch of IF/THEN/ELSE statements to decide what to do with the parameters, and prone to edge case errors. Is there a pattern that would invoke the correct method based on the combination of input parameters?

Examples:

app thing --dry-run --create --name=newname01 --name=newname02 --verbose

app thing --create --name=newname01 --name=newname02 --name=newname03

app job --cancel -i 01 -i 02 -i 03

EDIT: Via the Traitlets module, I get those arguments parsed and accessible as self.argname, so getting them into my app is working great. It’s just deciding what to do with them that is confusing me.

Thank you, sorry for my noobness.

EDIT2: I think I understand where I’m going wrong:

I’m creating subcommands based on objects, not actions. i.e. appname thing --action should really be appname action --thing. Once things are divided up into actions, assigning things to those actions will be much, much easier and straightforward.

Sorry for a confusing and fairly pointless post :(

  • nickwitha_k (he/him)@lemmy.sdf.org
    link
    fedilink
    arrow-up
    12
    ·
    1 year ago

    As a few others mentioned, the argparse module from the stdlib is the way to go for Python. It takes care of most of this for you in an optimized way. Here’s a minimal example of the above:

    #!/bin/env python3
    
    import argparse
    
    
    # Setup main parser
    parser = argparse.ArgumentParser(
        prog="app",
        description="App that manages things and jobs",
    )
    parser.add_argument(
        "-v",
        "--verbose",
        action="store_true",
    )
    subparsers = parser.add_subparser(
        help="Sub commands",
        dest="command",
    )
    
    # Setup sub-parsers
    thing_parser = subparsers.add_parser(
        "thing",
        help="Manage things",
    )
    # thing_parser args
    thing_parser.add_argument(
        "--dry_run",
        action="store_true",
        help="dry run",
    )
    thing_parser.add_argument(
        "--create",
        action="store_true",
        help="Create thing",
    )
    thing_parser.add_argument(
        "--name",
        action="store",
        type=str,
        required=True,
        nargs="+",
        help="Thing name",
    )
    
    job_parser = subparsers.add_parser(
        "job",
        help="Manage jobs",
    )
    job_parser.add_argument(
        "--cancel",
        "-c",
        action="store_true",
        help="Cancel job",
    )
    job_parser.add_argument(
        "--index",
        "-i",
        action="store",
        type=int,
        required=True,
        nargs="+",
        help="Job index",
    )
    
    
    def main():
        args=parser.parse_args()
        if args.verbose:
            print("Verbose mode")
        # Match-Case statement for cleaner logic
        match args.command:
            case "thing":
                # thing logic and function calls here
            case "job":
                # job logic and function calls here
            case _:
                parser.print_usage()
    
    if __name__ == "__main__":
        main()
    
      • nickwitha_k (he/him)@lemmy.sdf.org
        link
        fedilink
        arrow-up
        2
        ·
        1 year ago

        You’re very welcome! I’ve spent a lot of time with Python and really think that argparse as of 3.x makes most non-stdlib libraries for parsing are unnecessary. You get a ton of functionally and ability to add end-user documentation as you go, while abstracting away some of the basics like type casting/checking

        The addition of Match-Case, while not adding much, functionally, does a LOT for readability and keeping logic clear.

  • glad_cat@lemmy.sdf.org
    link
    fedilink
    arrow-up
    10
    ·
    1 year ago

    It’s never pointless. Command-line arguments are often tricky to get right, especially when your program can do a lot of different things.

    • bloopernova@programming.devOP
      link
      fedilink
      English
      arrow-up
      1
      ·
      1 year ago

      I was doing it wrong. I was trying to do appname thing --action when I should have been doing appname action --thing. Thank you for commenting, I’m sorry to waste your time.

  • Raikin@feddit.de
    link
    fedilink
    arrow-up
    6
    ·
    1 year ago

    What module are you currently using? I think the built-in module argparse should solve your problem but maybe I’m misunderstanding what you’re asking for.

  • sj_zero@lotide.fbxl.net
    link
    fedilink
    arrow-up
    2
    arrow-down
    1
    ·
    1 year ago

    Seems like a for statement and a case statement could work.

    Detect numargs

    For a = 0 to numargs

    Get core command on arg a (probably read until you hit an equals sign or a space), trim and lcase

    Select Case core command

    Case “thing”

    Do stuff

    Case “–name” Get part after equals and do stuff

    Case “-i” Get next arg and increment a

    End select

    • bloopernova@programming.devOP
      link
      fedilink
      English
      arrow-up
      2
      ·
      1 year ago

      I was doing it wrong. I was trying to do appname thing --action when I should have been doing appname action --thing. Thank you for commenting, I’m sorry to waste your time.