docopt / docopts

Shell interpreter for docopt, the command-line interface description language.
Other
494 stars 53 forks source link

'Options:' part of help string is not printed on parse error #30

Closed rdonkin closed 5 years ago

rdonkin commented 5 years ago

Tested on latest master dab1ec9 using bash 4.4.19(1)-release on Linux.

None of the examples scripts that have an 'Options:' section include this in the output when an invalid option is given. Also noticed on one of my own scripts.

Issue appears to be in docopts.go or in how its output is handled (see unit test below), as debugging of my shell script showed that docopts.sh was sending the complete usage string including 'Options:` section.

Examples:

$ grep Options: *.sh
arguments_example.sh:# Options:
calculator_example.sh:# Options:
cat-n_wrapper_example.sh:# Options:
naval_fate.sh:# Options:
rock_no-stdin_example.sh:# Options:
rock_stdin_example.sh:Options:

$ bash arguments_example.sh  -asdfasdf
error: 
Usage: arguments_example.sh [-vqrh] [FILE] ...
          arguments_example.sh (--left | --right) CORRECTION FILE
vagrant@vagrant:~/src/docopts/examples$ bash calculator_example.sh -asfasdf
echo 'error: 
Usage:
  calculator_example.sh <value> ( ( + | - | * | / ) <value> )...
  calculator_example.sh <function> <value> [( , <value> )]...
  calculator_example.sh (-h | --help)' >&2
exit 64
error: 
Usage:
  calculator_example.sh <value> ( ( + | - | * | / ) <value> )...
  calculator_example.sh <function> <value> [( , <value> )]...
  calculator_example.sh (-h | --help)

$ bash cat-n_wrapper_example.sh -asdfasdf
error: 
Usage: cat-n_wrapper_example.sh [--count=N] FILE...

$ bash rock_stdin_example.sh 
error: 
Usage: rock [options] <argv>...

$ bash naval_fate.sh -asdfasdf
error: 
Usage:
  naval_fate.sh ship new <name>...
  naval_fate.sh ship <name> move <x> <y> [--speed=<kn>]
  naval_fate.sh ship shoot <x> <y>
  naval_fate.sh mine (set|remove) <x> <y> [--moored|--drifting]
  naval_fate.sh -h | --help
  naval_fate.sh --version

Unit test:

I wrote a test in bats based on the rock_stdin_example.sh case, parsing the help string from comment.

See PR I will log for the code, which is derived from the docopts_help_string test - output is:

$ ./bats/bin/bats .
 ✓ docopt_auto_parse testing internal behavior
 ✓ docopt_auto_parse functionnal testing
 ✓ no source
 ✓ global eval
 ✓ docopts error
 ✓ --no-declare
 ✓ docopt_get_help_string
 ✗ docopt_get_help_string_with_options
   (in test file ./docopts.bats, line 58)
     `[[ ${#lines[@]} -eq 6 ]]' failed
 ✓ docopt_get_values
 ✓ docopt_get_eval_array
 ✓ docopt_get_raw_value
 ✓ docopt_print_ARGS

12 tests, 1 failure

$ cat log
---
--- output ---
Usage: rock [options] <argv>...

Options:
      --verbose  Generate verbose messages.
      --help     Show help options.
      --version  Print program version.
--- lines ---
Usage: rock [options] <argv>...
Options:
      --verbose  Generate verbose messages.
      --help     Show help options.
      --version  Print program version.
---
Line count = 5

The output from bats $output is correct, but the $lines array is missing the blank line before 'Options:'.

Sylvain303 commented 5 years ago

no much time today, but on my OS:

$ git branch 
  debug-issues
  dexpota-master
  docopts-go
  json-api
  master
  packaging-debian
* rdonkin-feat-bash-3.2-support

On your code, idem on my master branch:

For me, docopt_get_help_string works as expected, it's doctops which raises an error only with Usage See bellow.

cd examples
. ../docopts.sh
 for s in $(grep -l 'Options:' *.sh) ; do echo "=========== $s"; docopt_get_help_string $s; done
=========== arguments_example.sh
Usage: arguments_example.sh [-vqrh] [FILE] ...
          arguments_example.sh (--left | --right) CORRECTION FILE

Process FILE and optionally apply correction to either left-hand side or
right-hand side.

Arguments:
  FILE        optional input file
  CORRECTION  correction angle, needs FILE, --left or --right to be present

Options:
  -h --help
  -v       verbose mode
  -q       quiet mode
  -r       make report
  --left   use left-hand side
  --right  use right-hand side

=========== calculator_example.sh
Usage:
  calculator_example.sh <value> ( ( + | - | * | / ) <value> )...
  calculator_example.sh <function> <value> [( , <value> )]...
  calculator_example.sh (-h | --help)

Examples:
  calculator_example.sh 1 + 2 + 3 + 4 + 5
  calculator_example.sh 1 + 2 '*' 3 / 4 - 5    # note quotes around '*'
  calculator_example.sh sum 10 , 20 , 30 , 40

Options:
  -h, --help

Example:
  ./calculator_example.sh 30 + 23 - 22

=========== cat-n_wrapper_example.sh
Usage: cat-n_wrapper_example.sh [--count=N] FILE...

Arguments:
  FILE     input file

Options:
  --count=N   limit the number of line to display

Examples:
   ./cat-n_wrapper.sh --count=3 cat-n_wrapper.sh  quick_example.sh 

=========== naval_fate.sh
Usage:
  naval_fate.sh ship new <name>...
  naval_fate.sh ship <name> move <x> <y> [--speed=<kn>]
  naval_fate.sh ship shoot <x> <y>
  naval_fate.sh mine (set|remove) <x> <y> [--moored|--drifting]
  naval_fate.sh -h | --help
  naval_fate.sh --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.

=========== rock_no-stdin_example.sh
Usage: rock [options] <argv>...

Options:
      --verbose  Generate verbose messages.
      --help     Show help options.
      --version  Print program version.
=========== rock_stdin_example.sh

As far I'm remembering is the "expected" behavior on argument parse error, it's only displays Usage: , not all the documentation that is available with -h, its allow shorter failure message.

I quickly looked at original source in python without too much analyze.

I will look deeper and do some backward tests to see if the behavior was altered. For me it is OK for version 0.6.2 to mimic historical python's behavior.

rdonkin commented 5 years ago

Sorry, I didn't realise there were two types of usage errors, and I am new to docopts generally - so let's close this as it's not a bug.

Sylvain303 commented 5 years ago

no problem.

Despite the fact of docopts 0.6.2 behavior, we may hit a bats bug here:

This simple test, show up that empty lines are not collected in $lines

#!/bin/bash

usage() {
  cat << EOT
pipo

molo
EOT
}

@test "test lines with empty line" {
  run usage
  echo "$output" >> log
  num_lines=$(wc -l <<<"$output")
  [[ $num_lines -eq 3 ]]
  n=${#lines[@]}
  for i in $(seq 0 $((n - 1)))
  do
    echo "$i:${lines[$i]}" >> log
  done
  num_lines=$(wc -l <<<"$output")
  [[ ${lines[0]} == "pipo" ]]
  [[ ${lines[1]} == "" ]]
  [[ ${lines[2]} == "molo" ]]
  [[ $num_lines -eq ${#lines[@]} ]]
}

even bats-core is failing, quite strange.

~/code/bats-core/bin/bats t.bats 
 ✗ test lines with empty line
   (in test file t.bats, line 18)
     `[[ $num_lines -eq ${#lines[@]} ]]' failed

1 test, 1 failure
rdonkin commented 5 years ago

Interesting - I guess we should raise a bug on bats-core and close this one.

Sylvain303 commented 5 years ago

OK created: https://github.com/bats-core/bats-core/issues/224

This issue is closed, wont fix. This is a normal behavior.