source: project/wiki/eggref/5/args @ 36727

Last change on this file since 36727 was 36401, checked in by Kooda, 13 months ago

Document srfi-37, args and records for CHICKEN 5

File size: 11.3 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.  {{BODY}} is an option-processor as defined in SRFI 37, and has
54access to the variables {{OPT}} (the current #<option>), {{NAME}} (the option
55name) and {{ARG}} (argument value).   
56
57Behind the scenes, {{BODY}} is wrapped in code which adds the current option
58{{NAME}} and its argument {{ARG}} to the final options alist. So, simply leave
59{{BODY}} blank and options will be collected for you.
60
61When the option takes no argument (is of type {{#:none}}) then ARG is {{#t}},
62turning it into a boolean.  On the other hand, when the option takes an
63optional argument that is omitted, then {{ARG}} is {{#f}}; so to set a
64default of {{foo}}, one may say in the body:
65
66 (set! arg (or arg "foo"))
67
68=== Parsing the command line
69
70<procedure>(args:parse ARGS OPTIONS-LIST [OPTIONALS])</procedure>
71
72Parse {{ARGS}}, a list of command-line arguments given as strings, and return
73two values: an alist of option names (symbols) and their values, and a list of
74operands (non-option arguments).
75
76Operands are returned in order, but options are returned in reverse order.
77Duplicate options are retained in the options alist, so this lets {{assq}} find
78the ''last'' occurrence of any duplicate option on the command line. A (name .
79value) pair is added for each alias of every option found, so any alias is a
80valid lookup key.
81
82{{OPTIONS-LIST}} is a list of accepted options, each created by
83args:make-option.
84
85{{OPTIONALS}} is an optional sequence of keywords and values:
86
87<table class="symbol-table">
88<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>
89<tr><td>#:unrecognized-proc {{PROC}}</td><td>calls {{PROC}} for each unrecognized option, with arguments {{OPTION}} {{NAME}} {{ARG}} {{OPTIONS}} {{OPERANDS}}</td></tr>
90</table>
91
92The default operand-proc is a no-op, and the default unrecognized-proc issues
93an error message and calls the help option's processor. See the args-fold
94documentation for usage information and an explanation of the procedure
95arguments; {{OPTIONS}} and {{OPERANDS}} are seed values.
96
97<parameter>(args:help-options [default: ("help" #\h #\?)])</parameter>
98
99List of option names (strings or single characters, as in SRFI 37) to be
100considered 'help' options, in order of preference. {{args:parse}} uses this to
101select a help option from the option list it is passed. This is currently used
102only for unrecognized options, for which the help option is automatically
103invoked.
104
105=== Usage information
106
107Well-behaved programs display help or usage text when invoked with an option
108such as --help. {{args:usage}} will generate a formatted list of options in the
109GNU style, from a list of {{args:options}}. Around this you might place a
110descriptive header and footer.
111
112<procedure>(args:usage OPTION-LIST)</procedure>
113
114Generate a formatted list of options from {{OPTION-LIST}}, and return a string
115suitable for embedding into help text. The single string consists of multiple
116lines, with a newline at the end of each line. Thus, a typical use would be
117{{(print (args:usage opts)).}}
118
119<parameter>(args:width [default: 25])</parameter>
120
121Width of the left (option) column. We don't automatically format this column
122based on the length of the longest option, but you can set its width manually.
123
124<parameter>(args:separator [default: ", "])</parameter>
125
126The string separator inserted between multiple options on the same line.
127
128<parameter>(args:indent [default: 1])</parameter>
129
130Number of spaces to indent the options from the left.
131
132=== Operands and unrecognized options (advanced)
133
134These are suitable for use with {{#:operand-proc}} or {{#:unrecognized-proc}}
135in {{args:parse}}. Most users will probably not customize these procedures
136themselves, but a couple useful prefabricated ones are provided.
137
138<procedure>(args:ignore-unrecognized-options)</procedure>
139
140Silently ignore unrecognized options, and omit from the options alist.
141
142<procedure>(args:accept-unrecognized-options)</procedure>
143
144Silently add unrecognized options to the options alist.
145
146== Examples
147
148 (import (chicken process-context)
149         (chicken port)
150         args)
151
152 ;;; Note that missing required args can only be detected if their option appears last,
153 ;;; and optional args must not be separated from their option by a space
154 ;;; (e.g. -d2 or --debug=2, not -d 2 or --debug 2).
155 
156 (define opts
157  (list (args:make-option (c cookie)    #:none     "give me cookie"
158          (print "cookie was tasty"))
159        (args:make-option (d)           (optional: "LEVEL")  "debug level [default: 1]"
160          (set! arg (string->number (or arg "1"))))
161        (args:make-option (e elephant)  #:required "flatten the argument"
162          (print "elephant: arg is " arg))
163        (args:make-option (f file)      (required: "NAME")   "parse file NAME")
164        (args:make-option (v V version) #:none     "Display version"
165          (print "args-example $Revision: 1.3 $")
166          (exit))
167        (args:make-option (abc)         #:none     "Recite the alphabet")
168        (args:make-option (h help)      #:none     "Display this text"
169          (usage))))
170 
171 (define (usage)
172  (with-output-to-port (current-error-port)
173    (lambda ()
174      (print "Usage: " (car (argv)) " [options...] [files...]")
175      (newline)
176      (print (args:usage opts))
177      (print "Report bugs to zbigniewsz at gmail.")))
178  (exit 1))
179 
180 (receive (options operands)
181     (args:parse (command-line-arguments) opts)
182   (print "-e -> " (alist-ref 'elephant options))) ;; 'e or 'elephant both work
183
184If command line is {{--cookie -e test -e hello}}:
185
186   cookie was tasty
187   elephant: arg is test
188   elephant: arg is hello
189   -e -> hello
190 
191If command line is {{--cookie -e test --foo}}:
192
193 cookie was tasty
194 elephant: arg is test
195 ./args-example: unrecognized option: foo
196 Usage: ./args-example [options...] [files...]
197 
198  -c, --cookie             give me cookie
199  -d [LEVEL]               debug level [default: 1]
200  -e, --elephant=ARG       flatten the argument
201  -f, --file=NAME          parse file NAME
202  -v, -V, --version        Display version
203      --abc                Recite the alphabet
204  -h, --help               Display this text
205 
206 Report bugs to zbigniewsz at gmail.
207
208Using indent 5, width 35 and a single space for the separator:
209
210 #;> (print (parameterize ((args:separator " ")
211                           (args:indent 5)
212                           (args:width 35))
213              (args:usage opts)))
214 
215      -c --cookie                        give me cookie
216      -d [LEVEL]                         debug level [default: 1]
217      -e --elephant=ARG                  flatten the argument
218      -f --file=NAME                     parse file NAME
219      -v -V --version                    Display version
220         --abc                           Recite the alphabet
221      -h --help                          Display this text
222
223Additional examples can be found in [[http://bugs.call-cc.org/browser/release/5/args/trunk/args-examples.scm|args-examples.scm]].
224
225
226== Bugs
227
228The name {{args:make-option}} is verbose.
229
230== About this egg
231
232=== Author
233
234[[http://3e8.org/zb|Jim Ursetto]]
235
236=== Version history
237
238; 1.6.0 : Ported to CHICKEN 5 [Kooda]
239; 1.5.1 : Bugfix for 1.5.0 -- ensure option body sees transformed {{#t}} arg value
240; 1.5.0 : {{#:optional}} args return a {{#t}} instead of {{#f}} value (suggested by Matt Gushee and Peter Bex)
241; 1.4.4 : Allow use of make-option inside hygienic macros
242; 1.4.3 : Use (program-name) to ensure correct $0 in scripts (zb; noticed by hypnocat)
243; 1.4.2 : Accept numerical args, drop args:make-operand-proc (zb)
244; 1.4 : Ported to Chicken 4 [Ivan Raikov]
245; 1.3 : check for presence of required option arguments [Ivan Raikov]
246; 1.2 : commify tail-recursive (Ivan Shmakov); add args:separator, args:indent (zb)
247; 1.1 : Fix exports (Felix, Kon)
248; 1.0 : Initial release
249
250=== Requirements
251
252[[srfi-37]]
253
254=== License
255
256 Copyright (c) 2005-2013 Jim Ursetto.  All rights reserved.
257 
258 Redistribution and use in source and binary forms, with or without
259 modification, are permitted provided that the following conditions are met:
260 
261   Redistributions of source code must retain the above copyright notice,
262   this list of conditions and the following disclaimer. Redistributions in
263   binary form must reproduce the above copyright notice, this list of
264   conditions and the following disclaimer in the documentation and/or
265   other materials provided with the distribution. Neither the name of the
266   author nor the names of its contributors may be used to endorse or
267   promote products derived from this software without specific prior
268   written permission.
269 
270 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
271 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
272 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
273 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
274 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
275 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
276 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
277 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
278 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
279 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
280 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
281
Note: See TracBrowser for help on using the repository browser.