source: project/wiki/eggref/4/args @ 29513

Last change on this file since 29513 was 29513, checked in by Jim Ursetto, 7 years ago

args: doc 1.4.4

File size: 10.4 KB
Line 
1[[tags:eggs]]
2
3== Args
4
5''args'' provides command-line argument handling, implemented
6on top of [[http://srfi.schemers.org/srfi-37/srfi-37.html|SRFI 37's args-fold]].
7
8[[toc:]]
9
10== Documentation
11
12This extension provides a wrapper around SRFI 37 (args-fold). The main goal is
13to let the user parse command-line arguments without having to write a lot of
14similar support code every time.
15
16By default, options and operands (non-options) are collected into two lists and
17returned by the parser, and unrecognized options complain and display help.
18Therefore, it is very possible not to write any option-procs, operand-procs, or
19unrecognized-procs as required by SRFI 37. However, the capability to
20customize is there should you need it.
21
22Additionally, the help text for your options can be generated for you, so your
23options and usage information don't get out of sync.
24
25=== Creating options
26
27<macro>(args:make-option (OPTION-NAME ...) ARG-DATA DOCSTRING [BODY])</macro>
28
29Make an {{args:option}} record, suitable for passing to {{args:parse}}.
30
31{{OPTION-NAME ...}} is a sequence of short or long option names. They must be
32literal symbols; single-character symbols become short options, and longer
33symbols become long options. So {{(args:make-option (c cookie) ...)}} specifies
34a short option {{-c}} and long option {{--cookie}}. Under the hood, {{(c
35cookie)}} becomes {{'(#\c "cookie")}}, as expected by SRFI 37's {{OPTION}}.
36
37{{ARG-DATA}} is either a pair {{(ARG-TYPE ARG-NAME)}} or a plain keyword
38{{ARG-TYPE}}. {{ARG-TYPE}} is a keyword that specifies whether the option takes
39an argument:
40
41<table class="symbol-table">
42<tr><td>#:required</td><td>Argument is required</td></tr>
43<tr><td>#:optional</td><td>Argument is optional</td></tr>
44<tr><td>#:none</td><td>No argument (actually, any other value than #:required or #:optional is interpreted as #:none)</td></tr>
45</table>
46
47{{ARG-NAME}}, if provided, is a string specifying the name of the argument.
48This name is used in the help text produced by args:usage.
49
50{{DOCSTRING}} is the help text.
51
52{{BODY}} is an optional sequence of statements executed when this option is
53encountered. Behind the scenes, {{BODY}} is wrapped in code which adds the
54current option and its argument to the final options alist. So, simply leave
55{{BODY}} blank and options will be collected for you.
56
57{{BODY}} is an option-processor as defined in SRFI 37, and has access to the
58variables {{OPT}} (the current #<option>), {{NAME}} (the option name) and
59{{ARG}} (argument value or {{#f}}).
60
61
62=== Parsing the command line
63
64<procedure>(args:parse ARGS OPTIONS-LIST [OPTIONALS])</procedure>
65
66Parse {{ARGS}}, a list of command-line arguments given as strings, and return
67two values: an alist of option names (symbols) and their values, and a list of
68operands (non-option arguments).
69
70Operands are returned in order, but options are returned in reverse order.
71Duplicate options are retained in the options alist, so this lets {{assq}} find
72the ''last'' occurrence of any duplicate option on the command line. A (name .
73value) pair is added for each alias of every option found, so any alias is a
74valid lookup key.
75
76{{OPTIONS-LIST}} is a list of accepted options, each created by
77args:make-option.
78
79{{OPTIONALS}} is an optional sequence of keywords and values:
80
81<table class="symbol-table">
82<tr><td>#:operand-proc {{PROC}}</td><td>calls {{PROC}} for each operand, with arguments {{OPERAND}} {{OPTIONS}} {{OPERANDS}}.  PROC must return the next seeds, {{(values OPTIONS OPERANDS)}}.</td></tr>
83<tr><td>#:unrecognized-proc {{PROC}}</td><td>calls {{PROC}} for each unrecognized option, with arguments {{OPTION}} {{NAME}} {{ARG}} {{OPTIONS}} {{OPERANDS}}</td></tr>
84</table>
85
86The default operand-proc is a no-op, and the default unrecognized-proc issues
87an error message and calls the help option's processor. See the args-fold
88documentation for usage information and an explanation of the procedure
89arguments; {{OPTIONS}} and {{OPERANDS}} are seed values.
90
91<parameter>(args:help-options [default: ("help" #\h #\?)])</parameter>
92
93List of option names (strings or single characters, as in SRFI 37) to be
94considered 'help' options, in order of preference. {{args:parse}} uses this to
95select a help option from the option list it is passed. This is currently used
96only for unrecognized options, for which the help option is automatically
97invoked.
98
99=== Usage information
100
101Well-behaved programs display help or usage text when invoked with an option
102such as --help. {{args:usage}} will generate a formatted list of options in the
103GNU style, from a list of {{args:options}}. Around this you might place a
104descriptive header and footer.
105
106<procedure>(args:usage OPTION-LIST)</procedure>
107
108Generate a formatted list of options from {{OPTION-LIST}}, and return a string
109suitable for embedding into help text. The single string consists of multiple
110lines, with a newline at the end of each line. Thus, a typical use would be
111{{(print (args:usage opts)).}}
112
113<parameter>(args:width [default: 25])</parameter>
114
115Width of the left (option) column. We don't automatically format this column
116based on the length of the longest option, but you can set its width manually.
117
118<parameter>(args:separator [default: ", "])</parameter>
119
120The string separator inserted between multiple options on the same line.
121
122<parameter>(args:indent [default: 1])</parameter>
123
124Number of spaces to indent the options from the left.
125
126=== Operands and unrecognized options (advanced)
127
128These are suitable for use with {{#:operand-proc}} or {{#:unrecognized-proc}}
129in {{args:parse}}. Most users will probably not customize these procedures
130themselves, but a couple useful prefabricated ones are provided.
131
132<procedure>(args:ignore-unrecognized-options)</procedure>
133
134Silently ignore unrecognized options, and omit from the options alist.
135
136<procedure>(args:accept-unrecognized-options)</procedure>
137
138Silently add unrecognized options to the options alist.
139
140== Examples
141
142 (use args)
143 
144 (define opts
145  (list (args:make-option (c cookie)    #:none     "give me cookie"
146          (print "cookie was tasty"))
147        (args:make-option (d)           (optional: "LEVEL")  "debug level [default: 1]")
148        (args:make-option (e elephant)  #:required "flatten the argument"
149          (print "elephant: arg is " arg))
150        (args:make-option (f file)      (required: "NAME")   "parse file NAME")
151        (args:make-option (v V version) #:none     "Display version"
152          (print "args-example $Revision: 1.3 $")
153          (exit))
154        (args:make-option (abc)         #:none     "Recite the alphabet")
155        (args:make-option (h help)      #:none     "Display this text"
156          (usage))))
157 
158 (define (usage)
159  (with-output-to-port (current-error-port)
160    (lambda ()
161      (print "Usage: " (car (argv)) " [options...] [files...]")
162      (newline)
163      (print (args:usage opts))
164      (print "Report bugs to zbigniewsz at gmail.")))
165  (exit 1))
166 
167 (receive (options operands)
168     (args:parse (command-line-arguments) opts)
169   (print "-e -> " (alist-ref 'elephant options))) ;; 'e or 'elephant both work
170
171If command line is {{--cookie -e test -e hello}}:
172
173   cookie was tasty
174   elephant: arg is test
175   elephant: arg is hello
176   -e -> hello
177 
178If command line is {{--cookie -e test --foo}}:
179
180 cookie was tasty
181 elephant: arg is test
182 ./args-example: unrecognized option: foo
183 Usage: ./args-example [options...] [files...]
184 
185  -c, --cookie             give me cookie
186  -d [LEVEL]               debug level [default: 1]
187  -e, --elephant=ARG       flatten the argument
188  -f, --file=NAME          parse file NAME
189  -v, -V, --version        Display version
190      --abc                Recite the alphabet
191  -h, --help               Display this text
192 
193 Report bugs to zbigniewsz at gmail.
194
195Using indent 5, width 35 and a single space for the separator:
196
197 #;> (print (parameterize ((args:separator " ")
198                           (args:indent 5)
199                           (args:width 35))
200              (args:usage opts)))
201 
202      -c --cookie                        give me cookie
203      -d [LEVEL]                         debug level [default: 1]
204      -e --elephant=ARG                  flatten the argument
205      -f --file=NAME                     parse file NAME
206      -v -V --version                    Display version
207         --abc                           Recite the alphabet
208      -h --help                          Display this text
209
210Additional examples can be found in [[args-examples.scm|args-examples.scm]].
211
212
213== Bugs
214
215The name {{args:make-option}} is verbose.
216
217== About this egg
218
219=== Author
220
221[[http://3e8.org/zb|Jim Ursetto]]
222
223=== Version history
224
225; 1.4.4 : Allow use of make-option inside hygienic macros
226; 1.4.3 : Use (program-name) to ensure correct $0 in scripts (zb; noticed by hypnocat)
227; 1.4.2 : Accept numerical args, drop args:make-operand-proc (zb)
228; 1.4 : Ported to Chicken 4 [Ivan Raikov]
229; 1.3 : check for presence of required option arguments [Ivan Raikov]
230; 1.2 : commify tail-recursive (Ivan Shmakov); add args:separator, args:indent (zb)
231; 1.1 : Fix exports (Felix, Kon)
232; 1.0 : Initial release
233
234=== Requirements
235
236[[srfi-37]]
237
238=== License
239
240 Copyright (c) 2005-2013 Jim Ursetto.  All rights reserved.
241 
242 Redistribution and use in source and binary forms, with or without
243 modification, are permitted provided that the following conditions are met:
244 
245   Redistributions of source code must retain the above copyright notice,
246   this list of conditions and the following disclaimer. Redistributions in
247   binary form must reproduce the above copyright notice, this list of
248   conditions and the following disclaimer in the documentation and/or
249   other materials provided with the distribution. Neither the name of the
250   author nor the names of its contributors may be used to endorse or
251   promote products derived from this software without specific prior
252   written permission.
253 
254 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
255 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
256 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
257 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
258 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
259 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
260 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
261 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
262 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
263 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
264 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265
Note: See TracBrowser for help on using the repository browser.