Skip to content

WIP: New builtin parse_args (implements #361)

BafDyce requested to merge BafDyce/ion:builtin_parse_args into master

I've started implementing a PoC for an argument parser as requested in #361 (closed)

Details

  • This adds a new builtin (parse_args for now).
  • The builtin must be called with a list of arguments (e.g. typically parse_args @args) from within a script.
  • The builtin uses a (currently) hard-coded env variable (SCRIPT_ARGS_DEFINITION for now) which defines the argument parsing rules
  • For this, we use claps yaml format (third example on the linked page)
  • After parsing (with clap) we store the results in a new env variable (also hard-coded name) as an Ion dictionary. not yet implemented

Necessary design decisions

  • Better name suggestions for the name of the builtin?
  • Should the builtin take the names of the env variables to use (yaml definition, where to store results)?
  • What should we use as default names?

Current problems

Actually, the parsing is implemented, however, when passing -h, --help, -v, or --version to the script, it prints Ions' help/version and I dont know why :(

Edit: Actually, this is apparently caused because when invoking a script it passes all arguments to ion itself (which, in turn, will evaluate the -h flags BEFORE executing the script..)

Also, I just discovered another issue: When calling parse_args -h it will always print the help of the builtin, so this whole approach may not be usable :/ Any other ideas?

Examples of this behavior:

$ ./tests/parse_args.ion
args: [
    On stack: 'parse_args',
    On heap: './tests/parse_args.ion',
]
SCRIPT_ARGS_DEFINITION: On heap: 'name: myapp
version: "1.0"
author: Kevin K. <kbknapp@gmail.com>
about: Does awesome things
args:
    - config:
        short: c
        long: config
        value_name: FILE
        help: Sets a custom config file
        takes_value: true
    - INPUT:
        help: Sets the input file to use
        required: true
        index: 1
    - verbose:
        short: v
        multiple: true
        help: Sets the level of verbosity
subcommands:
    - test:
        about: controls testing features
        version: "1.3"
        author: Someone E. <someone_else@other.com>
        args:
            - debug:
                short: d
                help: print debug information
'
matches: Err(Error { message: "\u{1b}[1;31merror:\u{1b}[0m The following required arguments were not provided:\n    \u{1b}[1;31m<INPUT>\u{1b}[0m\n\nUSAGE:\n    parse_args.ion [FLAGS] [OPTIONS] <INPUT> [SUBCOMMAND]\n\nFor more information try \u{1b}[32m--help\u{1b}[0m", kind: MissingRequiredArgument, info: None })                                                        
$ ./tests/parse_args.ion myinput
args: [
    On stack: 'parse_args',
    On heap: './tests/parse_args.ion',
    On heap: 'myinput',
]
SCRIPT_ARGS_DEFINITION: On heap: 'name: myapp
version: "1.0"
author: Kevin K. <kbknapp@gmail.com>
about: Does awesome things
args:
    - config:
        short: c
        long: config
        value_name: FILE
        help: Sets a custom config file
        takes_value: true
    - INPUT:
        help: Sets the input file to use
        required: true
        index: 1
    - verbose:
        short: v
        multiple: true
        help: Sets the level of verbosity
subcommands:
    - test:
        about: controls testing features
        version: "1.3"
        author: Someone E. <someone_else@other.com>
        args:
            - debug:
                short: d
                help: print debug information
'
matches: Ok(ArgMatches { args: {"INPUT": MatchedArg { occurs: 1, indices: [1], vals: ["myinput"] }}, subcommand: None, usage: Some("USAGE:\n    parse_args.ion [FLAGS] [OPTIONS] <INPUT> [SUBCOMMAND]") })                                                         
$ ./tests/parse_args.ion myinput --config myconfig
args: [
    On stack: 'parse_args',
    On heap: './tests/parse_args.ion',
    On heap: 'myinput',
    On heap: '--config',
    On heap: 'myconfig',
]
SCRIPT_ARGS_DEFINITION: On heap: 'name: myapp
version: "1.0"
author: Kevin K. <kbknapp@gmail.com>
about: Does awesome things
args:
    - config:
        short: c
        long: config
        value_name: FILE
        help: Sets a custom config file
        takes_value: true
    - INPUT:
        help: Sets the input file to use
        required: true
        index: 1
    - verbose:
        short: v
        multiple: true
        help: Sets the level of verbosity
subcommands:
    - test:
        about: controls testing features
        version: "1.3"
        author: Someone E. <someone_else@other.com>
        args:
            - debug:
                short: d
                help: print debug information
'
matches: Ok(ArgMatches { args: {"config": MatchedArg { occurs: 1, indices: [3], vals: ["myconfig"] }, "INPUT": MatchedArg { occurs: 1, indices: [1], vals: ["myinput"] }}, subcommand: None, usage: Some("USAGE:\n    parse_args.ion [FLAGS] [OPTIONS] <INPUT> [SUBCOMMAND]") })
$ ./tests/parse_args.ion myinput --config myconfig -h
ion 1.0.0-alpha
The fast, safe, modern rust shell. Ion is a commandline shell created to be a faster and easier to use alternative to
the currently available shells. It is not POSIX compliant.

USAGE:
    ion [FLAGS] [OPTIONS] [args]...

FLAGS:
    -f, --fake-interactive    Use a fake interactive mode, where errors don't exit the shell
    -h, --help                Prints help information
    -i, --interactive         Force interactive mode
    -n, --no-execute          Do not execute any commands, perform only syntax checking
    -x                        Print commands before execution
    -v, --version             Print the version, platform and revision of Ion then exit

OPTIONS:
    -c <command>             Evaluate given commands instead of reading from the commandline
    -o <key-bindings>        Shortcut layout. Valid options: "vi", "emacs"

ARGS:
    <args>...    Script arguments (@args). If the -c option is not specified, the first parameter is taken as a
                 filename to execute
Edited by matu3ba

Merge request reports