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

Customizing argbash proposals #3

Open
edannenberg opened this issue Feb 13, 2017 · 5 comments
Open

Customizing argbash proposals #3

edannenberg opened this issue Feb 13, 2017 · 5 comments

Comments

@edannenberg
Copy link

edannenberg commented Feb 13, 2017

A few minor proposals that would smooth out argbash integration as described in #1. Didn't want to spam x issues and it's all a bit related.


Problem:

I want to avoid duplicate static text as much as possible in my argbash templates.

Use case:

Contextual help setup as described in the linked issue. Currently every "subparser" has to duplicate some static app header text in it's help message. On changes I need to touch potentially many files.

Proposal:

Add something like ARG_HELP_HEADER(["some header text"]) that, if defined, would display it's text before ARG_HELP, this could then be defined once and included via ARGBASH_WRAP in multiple scripts with different ARG_HELP texts.

Edit: On second thought, I guess I could just define a _app_help_header="my app (c) foo" variable in the main script and use ARG_HELP(["${_app_help_header} - command help"]) in the sourced templates?

EditEdit: ARG_HELP_FOOTER or the ability to disable the argument validation in the generated code, so I could print some further text after the generated help, would also be very helpful. For example displaying the available commands in the main script.


Problem:

For certain scripts I may need to override if print_help; exit 0 is called when --help is passed to the script.

Use case:

Contextual help setup as described in the linked issue. The main script that wraps the "subparsers" should not display it's help text if --help was intended for a valid sub-command, i.e. ./main.sh some-valid-cmd --help

Proposal:

Make automatic display of the help text in the generated parsing code configurable via template. When the auto-display is disabled the generated parsing code should instead define a variable like $_arg_help which would enable handling of the help display by the script itself.


Problem:

I want to configure the error messages related to argument parsing, mainly for too few/many arguments, per template. Currently it always displays FATAL ERROR: Not enough positional arguments - we require at least 1, but got only 0. for too few arguments. New users that may not be very familiar with bash are probably gonna be confused what a positional argument could refer to. For example Error: Expected a filename - we require at least 1, but got only 0. would most likely be much clearer for most people.

Use case:

Every script.

Proposal:

Make error message configurable. Maybe a configurable error prefix might be enough?


Problem:

For a contextual help setup I need to modify the script prefix in the help display.

Use case:

Contextual help setup as described in the linked issue. Example:

$ ./main.sh some-cmd --help
This is the help text of some-cmd!
Usage: ./main.sh [--(no-)no-deps]

The displayed help is the help text of a sourced sub command template. Ideally it would display Usage: ./main.sh some-cmd ....

Proposal:

Add something like ARG_HELP_USAGE_SCRIPT_ARG_PREFIX(["some-cmd"]) that would then be inserted in the help text usage line.


With these resolved argbash could be used to completly handle the parsing for a variety of constructs in a clean and elegant way. Thanks for this neat project!

@matejak
Copy link
Owner

matejak commented Feb 14, 2017

Thank you very much for your input!

On second thought, I guess I could just define a _app_help_header="my app (c) foo" variable in the main script and use ARG_HELP(["${_app_help_header} - command help"]) in the sourced templates?

Exactly. You can use Bash variables. You can declare them between the beginning of the script and beginning of the Argbash section. That will be fine if the declarations don't contain square brackets (this issue will be much easier to deal with as the parsing of the command-line gets its own function that you will be able from a place of your choice within the script.

For certain scripts I may need to override if print_help; exit 0 is called when --help is passed to the script.

You can make your own action argument that will take over the ARG_HELP - the latter is just a shortcut for ARG_OPTIONAL_ACTION([help], [h], [Prints help], [print_help]).
The print_help function is defined every time (it is used e.g. when a non-conforming command-line is encountered).
However, the exit 0 command should be substituted by exit $?.

I want to configure the error messages ...

Great idea, I have created #4 for this purpose.

For a contextual help setup I need to modify the script prefix in the help display.

This seems to be quite complex, I have to study your other issue first to get a clear understanding of what you mean.

I appreciate your energy you dedicated to the Argbash project by submitting those issues! I am sure that it will contribute to Argbash improvement.

@edannenberg
Copy link
Author

edannenberg commented Feb 15, 2017

Exactly. You can use Bash variables.

One tiny issue with this approach though, newlines in the variable are currently not respected. echo -e in print_help would be nice.

You can declare them between the beginning of the script and beginning of the Argbash section

Even better, I assumed everything besides Argbash config block and the payload would be discarded when regenerating.


You can make your own action argument that will take over the ARG_HELP

Ah, while not quite what I needed (the main script would still exit when it should not) this put me on the right track. Given the example project from the linked issue:

argbash/opt-main.sh:

# ARG_OPTIONAL_BOOLEAN([help],[h],[Prints help])

And then just don't display the help and "delegate" --help to sub-command if passed in main.sh:

<include argbash/opt-main.sh>

# only display main --help if no command was passed
[[ -z "${_arg_command}" ]] && [[ "${_arg_help}" == "on" ]] && print_help && exit 0

<include sub-command with it's own parser>

Pretty much case closed, except now I can't use the _app_help_header approach for the main help any more. The input validation will always display the default print_help on errors, which now misses the additional echo you get by using ARG_HELP.

⚠️ On a side note, given that /main.sh has a required positional, I think the input validation should not throw an error on ./main.sh --help and just display the help and exit.


For a contextual help setup I need to modify the script prefix in the help display.

This seems to be quite complex, I have to study your other issue first to get a clear understanding of what you mean.

Most of this ticket comes down to being able to customize print_help as much as possible. Now that things are slowly clicking on my end I think the following could be a good generic approach that would solve most, if not all, of such use cases:

Currently the generated print_help for opt-main.sh script looks like this:

print_help ()
{
    printf 'Usage: %s [--(no-)verbose] [--(no-)help] <command> ... \n' "$0"
    printf "\t%s\n" "<command>: command to run"
    printf "\t%s\n" "... : command-options"
    printf "\t%s\n" "-h,--help,--no-help: Prints help (off by default)"
}

Splitting the important parts into vars or smaller functions would enable composing the help output. If there also was a knob (with a big fat warning in the docs) to disable generating of print_help itself this would allow for complete user control:

# always generated
_help_usage_options='[--(no-)verbose] [--(no-)help] <command> ...'

# always generated
print_help_options ()
{
    printf "\t%s\n" "<command>: command to run"
    printf "\t%s\n" "... : command-options"
    printf "\t%s\n" "-h,--help,--no-help: Prints help (off by default)"
}

# example default generated print_help
# there should be a knob to not generate this so a parent script can provide it's own
print_help ()
{
    printf 'Usage: %s %s \n' "$0" ${_help_usage_options}
    print_help_options
}

Now I could add headers/footers/ascii porn or even a script prefix by defining my custom print_help in main.sh once (or even directly in the template above the argbash block?) and have it consistent with all parsers. To illustrate the script prefix use case:

print_help ()
{
    printf 'Usage: %s %s %s \n' "$0" "${_arg_command}" ${_help_usage_options}
    print_help_options
}

<include main parser>

@matejak
Copy link
Owner

matejak commented Apr 7, 2017

One tiny issue with this approach though, newlines in the variable are currently not respected. echo -e in print_help would be nice.

Actually, you can include literal newlines in bash variables and they should be respected. Although echo -e would work, it is considered to be non-standard. See #7 for more info on this matter.


Concerning your other points, I plan to introduce callable functions (for parsing, validation, help, ...) that one will be able not to call, or override. Although it is not exactly what you would like, it would be a significant step on the way forward.

@edannenberg
Copy link
Author

edannenberg commented Apr 7, 2017

Concerning your other points, I plan to introduce callable functions (for parsing, validation, help, ...) that one will be able not to call, or override. Although it is not exactly what you would like, it would be a significant step on the way forward.

That would indeed be most welcome. Biggest issues for me currently are the default functions like die() and the boolean display (--(no-)foo). Currently I just manually remove/modify them. If you want to take a look at some real life usage: https://github.com/edannenberg/kubler, the Argbash code is in lib/argbash. To see the manual changes I have to make currently you can use the argbash-regen.sh script in that same dir and check the git diff afterwards.

It's not that big of a deal as it rarely changes, though a tiny bit I do dread the day another arg needs to be added. Still an acceptable price for the benefits Argbash brings to the table. :)

@matejak
Copy link
Owner

matejak commented Aug 6, 2017

Hello, I require more time for the boolean arguments, but the current master (and the upcoming release) support the DIY mode (see http://argbash.readthedocs.io/en/latest/guide.html#action-macro). This enables you to have finer control over the argument parsing (and possibly skip e.g. supplied arguments checks under certain conditions).

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