Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Docopt.sh – Command-Line Argument Parser for Bash 3.2, 4, and 5 (github.com/andsens)
109 points by stefankuehnel on March 16, 2023 | hide | past | favorite | 23 comments


Why would anyone need a library when we could just do this?

    arg=default
    while [ -n "${1}" ]
    do
        case "${1}" in
            --arg)
                shift
                arg="${1}"
                shift
                ;;
            *)
                print_help_page
                shift
                ;;
        esac
    done
The above is terse, readable, and doesn't rely on any dependencies other than POSIX compatibility.

Often the whole point of shell scripts is that they're dependency free; nothing is needed other than the shell. After all, why code rustup in sh if not for this reason?

People who make libraries like this for shell are, I think, missing the point of shell.


Don't do this: you have a bug when "$1" is ''.

    arg=
    while [[ "$#" -gt 0 ]]; do
      case "$1" in
        --arg) shift; arg="$1" ;;
        *)     help; exit 1 ;;
      esac
      shift
    done


And that's why.


Looks like gibberish to me, and you're conveniently skipping all the documentation and argument parsing that docopt is providing.


> Looks like gibberish to me,

Funny, it looks like perfectly readable, idiomatic and dependency-free shell to me.


As a very fluent user of shell scripting, nothing in shell scripting is idiomatic.


Unless I'm reading the page wrong, this isn't a dependency per-se. That is the scripts you ship around won't depend on this, rather you write your bash script with the help doc information inside and then run this think to generate a new script that has the arg parsing stuff added in. You pass around the new script.

The biggest issue I see with this is the generated code is a minified chunk of noise that can't be easily edited by hand by downstream users


Quite right. Friends don't let friends generate shell script.


mfw you didn't make it into the first paragraph...


For anyone unfamiliar, docopt is an established standard for specifying arguments in a script’s doc string. I use it for Python and it’s lovely. You’re going to write a docstring with examples anyway, why not make them functional?

http://docopt.org/


For context, I haven't used Docopt before (even in other languages) but have written my fair share of Shell. This will be aimed at Bash.

Hate it's argument handling.

I forgive languages with similier capabilities because they're passing a low level array, or aren't designed with command line conventions in mind; but even then I am wishing for better! Bash already provides the args array as a native array, and has no excuse for not incorporating existing command-line help, version, and keyword-argument standards into accessible builtins: one allowing values to be a read (returning `0`, `1`, or `"string"`), and one that's just sugar for `$read_arg "foo" && { printf '%s\n' "$bar"; exit 0; }`.

Might sound trivial, but parsing arguments is a core component of Shell that simply doesn't need written out explicitly as often as it is. GNU Getopts is the best we get, while if we go down the strict POSIX path, users would apparently rather use an idiomatic loop over `shift` than a similer loop over the portable `getopt`. Wonder what ZSH has for this.

Anyways, Docopt's approach sounds pretty neat, love that 'declarative' usage text, that's slick. I want that all over the place. Don't like how hard the generated code is to read (Argbash seems to be a step ahead in that regard), but this is still great, this'd be an improvement almost anywhere, certainly anywhere where that generated code could be hidden in the implimentation, but definitely in Shell.


> GNU Getopts is the best we get, while if we go down the strict POSIX path, users would apparently rather use an idiomatic loop over `shift` than a similer loop over the portable `getopt`

getopts is POSIX, and GNU getopts is an implementation of it. [0] The getopt utility is not POSIX (not the command line tool anyway, not in current POSIX) and should not be used. [1]

[0] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/g...

[1] http://mywiki.wooledge.org/ComplexOptionParsing



I like that this generates readable output that could pass as hand-written code:

https://github.com/matejak/argbash/blob/master/resources/exa...

The docopt.sh output looks as if it went through a JS minifier. Or is there a way to change that? If so I think it should default to that.

https://github.com/andsens/docopt.sh/blob/master/docs/naval_...


Seems like an interesting way of doing it. Why generate the argument configuration from the documentation rather than generating the documentation from the argument configuration? Where there some pain points you wanted to solve from `getopt`, etc.?


Kind of neat that the configuration is the ground truth and that you can't update your interface without updating the documentation, if I understood it correctly.


For those looking for a similar project in Zsh, it is built-in into the shell – search for `zparseopts` in `man zshmodules`.


They both parse opts but that's really the end of the similarity. It's like saying Haskell and Javascript are similar. Yes, they're both general purpose programming languages but we all know the differences happen after that, just like this project and zparseopts.



I love docopt and I love rust. This thing written at [the docopt rust repo.] worries me

> the wider docopt project is mostly unmaintained at this point. Consider using clap or possibly structopt instead.

It's a lovely way to internalize the CLI argument cultural norms, decrease confusing and verbose argument parsing, make argument parsing work-free for the developer, and make argument parsing a copy-paste across languages. There's no greater pleasure than iteratively adding options to your program by just adding a line of text

-n, --new-option Do something new

I honestly think making a docopt parser is just very hard, which may limit its future prospects.

[the docopt rust repo.]: https://github.com/docopt/docopt.rs


Sigh. util-linux's getopt solved this years and years ago.

https://manpages.debian.org/testing/util-linux/getopt.1.en.h...


Nothing about that indicates that it can generate argument parsing from the help text. The whole point of the docopt stuff is that you write the help doc string that you're almost certainly going to write anyway, and it generates the argument parsing stuff for you.


Neat. If it automatically generated a tab-completion script at the same time, I'd be extremely interested. As it is, I'm probably gonna keep doing what I (and djha-skin) currently do: while/case/shift.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: