-
Notifications
You must be signed in to change notification settings - Fork 53
Home
Sylvain303 edited this page Sep 21, 2021
·
8 revisions
The wiki pages are used for discussion. Feel free to contribute.
docopts
documentation lives in README
EBNF like prototype:
(*
here is grammar definition for docopt language, in EBNF.
Only the "Usage: prog" is mandatory
*)
Docopt = [ Prologue ]
, Usage
, [ Free_text ]
, [ Options ]
, [ Free_text ]
;
(*
Prologue can be used to introduce the program.
Matching USAGE leaves the Prologue.
*)
Prologue = Line_of_text, NEWLINE | { Prologue } ;
NEWLINE = ? all line ending char combination ? ;
Line_of_text = ALL_CHARACTERS - USAGE ;
ALL_CHARACTERS = ? all visible characters ? ;
USAGE = ? "Usage:" case insensitive ? ;
Usage = USAGE , First_Program_Usage | { Program_Usage } ;
First_Program_Usage = PROG_NAME , [ Expr ] ;
(*
PROG_NAME is catched at first definition and stay the same literal for all the parsing
Program_Usage can be break multi-line: Indent + PROG_NAME will start a new Program_Usage
Usage: ./my_program.sh [-h] [--lovely-option] FILENAME
./my_program.sh another LINE OF --usage
my_program will continue [--above] <usage-definition>
PROG_NAME on first usage parsing it becomes: "./my_program.sh"
*)
PROG_NAME = ? any non space characters ? ;
Program_Usage = Indent , PROG_NAME [ Expr ] ;
Indent = ? Long_space at the beginning of the line ? ;
Long_space = " " , { ' ' } | '\t' , { '\t' } ;
Expr = Seq , { '|' , Seq } ;
Seq = Atom , [ "..." ] ;
Atom = '(' , Expr , ')'
| '[' , Expr , ']'
| "options"
| Long_def
| Shorts_option
| Argument
| Command
| '-' | "--" (* single-dash and double-dash *)
;
Shorts_option = Short | Short , Argument ;
Long_def = Long | Long , Argument | Long , '=' , Argument ;
Long = '--' , Chars , Chars { '_' | '-' | Chars } ;
Short = '-' , Chars ;
Chars = Lowercase | Capital | Digit ;
Lowercase = ? lowercase latin1 letters ? ;
Capital = ? Uppercase latin1 letters ? ;
Digit = ? numbers 0 at 9 ? ;
Argument = Angle_Argument | Capital_Argument ;
Angle_Argument = '<' , Lowercase , { Lowercase | '_' | '-' | Digit } , '>' ;
Capital_Argument = Capital , { Capital | '_' | Digit } ;
Options = OPTIONS_KEYWORD , Options_Help { Options_Help } ;
OPTIONS_KEYWORD = ? "Options:" case insensitive ? ;
Options_Help = Indent , Option_Flag , Option_description ;
Option_Flag = ( Short_def | Long_def ) , [ ( " " | "," ) , Option_Flag ] ;
Short_def = Short | Short Argument ;
Option_description = Long_space , Description_text , [ Default_value ] ;
Description_text = ALL_CHARACTERS - Default_value ;
(*
Value_for_default:
']' can be given for default that way: [default: "]"]
double quote can be escaped too: [default: "{ \"I love \" : \"JSON\" }"]
emtpy string: [default: ""]
This is not done that way in python:
https://github.com/docopt/docopt/blob/20b9c4ffec71d17cee9fd963238c8ec240905b65/docopt.py#L200
first value found for "default:" note the first space is not part of the value.
matched = re.findall('\[default: (.*)\]', description, flags=re.I)
value = matched[0] if matched else None
*)
Default_value = '[' , "default:" , ' ' , Value_for_default , ']' ;
Value_for_default = string
| ALL_CHARACTERS - ']'
;
string = '"' , { ALL_CHARACTERS - '"' | escaped_double_quote } , '"' ;
escaped_double_quote = '\' , '"' ;
(*
Free_text allow to add help information in a section like message, which is eaten by the parser.
Free_text could be extend and or parsed on grammar extension, new defined sections for example:
Arguments:
FILENAME Inputfile
COUNTER Number of time to repeat the action.
etc.
Howto:
Some information, bla, bla
Indent is not mandatory, it's free.
Usage: <== this will fail? or not? as usage is already parsed. (failure on python's version 0.6.1)
*)
Free_text = ALL_CHARACTERS - USAGE - OPTIONS_KEYWORD , NEWLINE | { Free_text } ;
# auto extract the Usage string from the top shell script comment
# ie: help=$(sed -n -e '/^# Usage:/,/^$/ s/^# \?//p' < $0)
help_string=$(docopt_get_help_string $0)
# if the option as multiples values, you can get it into an array
array_opt=( $(docopt_get_values args --multiple-time) )
See python/docopt
Source: naval_fate.sh
naval_fate.sh ship Guardian move 100 150 --speed=15
returned $parsed string to be evaluated:
declare -A arguments
arguments['--drifting']=false
arguments['mine']=false
arguments['--help']=false
arguments['move']=true
arguments['--moored']=false
arguments['new']=false
arguments['--speed']='15'
arguments['remove']=false
arguments['--version']=false
arguments['set']=false
arguments['<name>']='Guardian'
arguments['ship']=true
arguments['<x>']='100'
arguments['shoot']=false
arguments['<y>']='150'
- repeatable options with filename with space inside, will not be easily split on $IFS, but old fake nested array is still available or use an helper
eval "$(docopt_get_eval_array args FILE myarray)"
API_proposal.md Was issue #7 for the discussion and proposing your changes.