source: project/wiki/eggref/3/tool @ 13939

Last change on this file since 13939 was 13939, checked in by Ivan Raikov, 11 years ago

Nice try

File size: 9.1 KB
Line 
1[[toc:]]
2[[tags: egg]]
3
4== Introduction
5
6The {{tool}} extension provides a flexible declarative alternative to
7[[http://www.call-with-current-continuation.org/eggs/srfi-37.html|SRFI-37]]
8and [[http://www.call-with-current-continuation.org/eggs/args.html|args]].
9
10== Requirements
11
12[[http://www.call-with-current-continuation.org/eggs/srfi-37.html|srfi-37]],
13[[args-doc]] and
14[[http://www.call-with-current-continuation.org/eggs/srfi-95.html|srfi-95]]
15
16== Interface
17
18Use {{define-option}} to define command-line options and {{define-command}}
19for defining ''subcommands'' that control specific sub-functionality. Basic
20usage of a program that uses this facility is
21
22 PROGRAM [OPTION | ARGUMENT] ...
23
24or
25
26 PROGRAM [COMMAND [OPTION | ARGUMENT] ...]
27
28where {{PROGRAM}} is the program name, {{COMMAND}} is an optional subcommand
29and {{OPTION}} and {{ARGUMENT}} are command-line options and arguments to those,
30respectively. {{define-option}} defines global or subcommand-specific
31command-line options, {{define-command}} defines subcommands and specifies
32their behaviour. After you have finished declaring options and commands,
33invoke {{tool-main}} to process the remainingcommand-line arguments and invoke
34command and option processors.
35
36The option {{-h}} / {{--help}} is predefined and invokes {{tool-usage}}.
37
38This extension supports static linking.
39
40=== define-option
41
42 [syntax] (define-option OPTION DOCUMENTATION [PROC])
43
44Defines the command-line option {{OPTION}} which may be a character,
45string or SRFI-37 {{option}} value. The option expects a required
46argument.  If an {{option}}, the option argument flag (required or
47optional) must be a string which is used in {{tool-usage}} to show a
48more informative option documentation. {{DOCUMENTATION}} should be a
49string describing the option.
50
51{{PROC}}, if given, should be an option-processor as described in
52[[http://srfi.schemers.org/srfi-37/srfi-37.html|SRFI-37]] or a
53symbol. If {{PROC}} is a symbol then giving this option on the command
54line will set the global variable with the same name to the option
55argument. If {{PROC}} is missing the name of option global variable is
56the same as {{OPTION}} which should be a string, symbol or character.
57
58=== define-flag
59
60 [syntax] (define-flag OPTIONNAME DOCUMENTATION [VARIABLE])
61
62Defines an option that takes no arguments and sets {{VARIABLE}} to
63{{#t}} if the option is given. If {{VARIABLE}} is not specified, the
64name of the variable is the same as {{OPTIONNAME}} which should be a
65string, symbol or character.
66
67=== define-command
68
69 [syntax] (define-command NAME DOCUMENTATION BODY ...)
70
71Defines a subcommand. {{NAME}} should be a string or symbol. {{DOCUMENTATION}}
72should be a string describing the operation of this command. {{BODY ...}}
73is evaluated and should return a one-argument procedure that is invoked
74when the subcommand is specified on the command-line, with all non-option arguments
75collected in a list.
76
77If a tool provides subcommands, then the command name must be the first program
78argument given on the command line.
79
80Note that you can use {{define-option}} and {{define-flag}} in the body to
81declare command-specific options.
82
83=== define-tool
84
85 [syntax] (define-tool (NAME [INPUTVAR [COUNTVAR [INDEXVAR]]]) HELPSTRING BODY ...)
86
87A convenience macro that wraps common uses of {{tool-name}},
88{{tool-help}} and {{tool-main}}. Defines a tool named {{NAME}} with a
89help string {{HELP}}, and calls {{tool-main}} with the value of
90{{(command-line-arguments)}} and an argument processor that invokes
91{{body ...}} for each given command line argument, with {{INPUTVAR}}
92bound to the current argument. If no command line arguments were given, the
93value of {{(current-input-port)}} will be bound to {{INPUTVAR}}. When
94{{INPUTVAR}} is missing the variable named {{argument}} is in scope.
95
96The number of arguments is bound to {{COUNTVAR}}. When {{COUNTVAR}} is
97missing the variable named {{arguments-count}} is in scope.
98
99The current argument index is bound to {{INDEXVAR}}. When {{INDEXVAR}} is
100missing the variable named {{arguments-index}} is in scope.
101
102{{define-tool}} can be defined like this:
103
104<enscript highlight=scheme>
105(define-macro (define-tool head help . body)
106  (let-optionals head ((name (string->symbol (tool-name)))
107                       (input 'argument)
108                       (args-cnt-var 'argument-count)
109                       (args-idx-var 'argument-index))
110    (let ((args-var (gensym)))
111      `(begin
112         (tool-name ,(symbol->string name))
113         (tool-help ,help)
114         (tool-main
115           (command-line-arguments)
116           (lambda (,args-var)
117             (let ((,args-cnt-var (length ,args-var))
118                   (,args-idx-var 0))
119               (for-each (lambda (,input) ,@body (set! ,args-idx-var (+ ,args-idx-var 1)))
120                         (if (null? ,args-var)
121                             (list (current-input-port))
122                             ,args-var) ) ) ) ) ) ) ) )
123</enscript>
124
125=== tool-main
126
127 [procedure] (tool-main ARGUMENTS [PROC [THUNK]])
128
129Starts command-line processing of {{ARGUMENTS}}. If no arguments are
130given {{THUNK}} is invoked (which defaults to a procedure that calls
131{{(tool-usage 1)}}). If non-option arguments are supplied, {{PROC}} is called
132with the argument list, if given.
133
134=== tool-name
135
136 [procedure] (tool-name [STRING])
137
138Sets or returns the name of the program, which defaults to {{(car (argv))}}.
139
140=== tool-help
141
142 [procedure] (tool-help STRING)
143
144Sets or returns the program description.
145
146=== tool-usage
147
148 [procedure] (tool-usage STATUS [COMMAND])
149
150Shows usage information collected from {{(tool-help)}} and the option and
151subcommand documentation and exits with status code {{STATUS}}. If {{COMMAND}}
152is given, the usage information shown lists global options and the description
153of the command. If no command is given, then global options and all available
154subcommands are shown. Finally {{(tool-exit STATUS)}} is invoked.
155
156=== tool-exit
157
158 [procedure] (tool-exit [STATUS])
159
160Terminates the program and returns {{STATUS}} (which defaults to 0). If invoked
161inside the dynamic scope of {{tool-main}}, then the call to {{tool-main}}
162returns with the given status code. If called outside of the dynamic scope
163of {{tool-main}}, {{(exit STATUS)}} is performed.
164
165=== tool-error
166
167 [procedure] (tool-error MESSAGE [STATUS [COMMAND]])
168
169Displays an error {{MESSAGE}} and invokes {{tool-usage}} with the any optional
170arguments. Default value for {{STATUS}} is {{1}}. Default value for {{COMMAND}}
171is the same as {{tool-usage}}.
172
173== Example
174
175A simple {{cat(1)}} tool:
176
177<enscript highlight=scheme>
178;;;; cat.scm
179
180(use tool utils format-modular)
181
182(define-flag #\n "number output lines" numlines)
183
184(tool-name "cat")
185(tool-help "Concatenate input files (or standard input) to standard output")
186
187(tool-main
188 (command-line-arguments)
189 (lambda (args)
190   (for-each
191    (lambda (f)
192      (if numlines
193          (do ((i 1 (add1 i))
194               (lns (read-lines f) (cdr lns)) )
195              ((null? lns))
196            (format #t "~6d\t~a~%" i (car lns)) )
197          (display (read-all f)) ) )
198    (if (null? args)
199        (list (current-input-port))
200        args) ) ) )
201</enscript>
202
203== Authors
204
205[[felix winkelmann]]
206
207== License
208
209 Copyright (c) 2007, Felix L. Winkelmann
210 All rights reserved.
211
212 Redistribution and use in source and binary forms, with or without
213 modification, are permitted provided that the following conditions are met:
214
215   Redistributions of source code must retain the above copyright notice,
216     this list of conditions and the following disclaimer.
217   Redistributions in binary form must reproduce the above copyright notice,
218     this list of conditions and the following disclaimer in the
219     documentation and/or other materials provided with the distribution.
220   Neither the name of the author nor the names of its contributors may be
221     used to endorse or promote products derived from this software without
222     specific prior written permission.
223
224 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
225 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
227 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
228 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
229 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
230 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
232 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
233 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
234 POSSIBILITY OF SUCH DAMAGE.
235
236== Version History
237
238; 0.703 : added 'tool-error' procedure, "argument-index" to 'define-tool' [Kon Lovett]
239; 0.702 : binding of 'tool-exit' in 'tool-main' should be "fluid" [Kon Lovett]
240; 0.701 : added count of non-option arguments to 'define-tool' [Kon Lovett]
241; 0.7 : didn't work with syntax-case at all
242; 0.6 : uses [[args-doc]] for usage information [Thanks to Ivan Shmakov]
243; 0.5 : toplevel help output is somewhat compressed
244; 0.4 : fixed bug in handling of option processor in {{define-option}}
245; 0.3 : order of non-option arguments was reversed
246; 0.2 : added {{define-tool}} [suggested by Arto Bendiken]
247; 0.1 : initial release
Note: See TracBrowser for help on using the repository browser.