You are looking at historical revision 3033 of this page. It may differ significantly from its current revision.

Introduction

The tool extension provides a flexible declarative alternative to SRFI-37 and args.

Requirements

srfi-37

Interface

Use define-option to define command-line options and define-command for defining subcommands that control specific sub-functionality. Basic usage of a program that uses this facility is

PROGRAM [OPTION | ARGUMENT] ...

or

PROGRAM [COMMAND [OPTION | ARGUMENT] ...]

where PROGRAM is the program name, COMMAND is an optional subcommand and OPTION and ARGUMENT are command-line options and arguments to those, repsectively. define-option defines global or subcommand-specific command-line options, define-command defines subcommands and specifies their behaviour. After you have finished declaring options and commands, invoke tool-main to process the given command-line arguments and invoke command and option processors.

The option -h / --help is predefined and invokes tool-usage.

This extension supports static linking.

define-option

[syntax] (define-option OPTION DOCUMENTATION [PROC])

Defines the command-line option OPTION which may be a character, string or SRFI-37 option value. The option expects a required argument. If an option, the option argument flag (required or optional) may be a string which is used in tool-usage to show a more informative opton documentaton. DOCUMENTATION should be a string describing the option. PROC, if given, should be an option-processor as described in SRFI-37 or a symbol. If PROC is a symbol then giving this option on the command line will set the global variable with the same name to the option argument.

define-flag

[syntax] (define-flag OPTIONNAME DOCUMENTATION [VARIABLE])

Defines an option that takes no arguments and sets VARIABLE to #t if the option is given. If VARIABLE is not specified, the name of the variable is the same as OPTIONNAME which should be a string, symbol or character.

define-command

[syntax] (define-command NAME DOCUMENTATION BODY ...)

Defines a subcommand. NAME should be a string or symbol. DOCUMENTATION should be a string describing the operation of this command. BODY ... is evaluated and should return a one-argument procedure that is invoked when the subcommand is specified on the command-line, with all non-option arguments collected in a list.

If a tool provides subcommands, then the command name must be the first program argument given on the command line.

tool-main

[procedure] (tool-main ARGUMENTS [PROC [THUNK]])

Starts command-line processing of ARGUMENTS. If no arguments are given THUNK is invoked (which defaults to a procedure that calls (tool-usage 1)). If non-option arguments are supplied, PROC is called with the argument list, if given.

tool-name

[procedure] (tool-name [STRING])

Sets or returns the name of the program, which defaults to (car (argv)).

tool-help

[procedure] (tool-help STRING)

Sets or returns the program description.

tool-usage

[procedure] (tool-usage STATUS [COMMAND])

Shows usage information collected from (tool-help) and the option and subcommand documentation and exits with status code STATUS. If COMMAND is given, the usage information shown lists global options and the description of the command. If no command is given, then global options and all available subcommands are shown. Finally (tool-exit STATUS) is invoked.

tool-exit

[procedure] (tool-exit [STATUS])

Terminates the program and returns STATUS (which defaults to 0). If invoked inside the dynamic scope of tool-main, then the call to tool-main returns with the given status code. If called outside of the dynamic scope of tool-main, (exit STATUS) is performed.

Example

A simple cat(1) tool:

;;;; cat.scm

(use tool utils format-modular)

(define-flag #\n "number output lines" numlines)

(tool-name "cat")
(tool-help "Concatenate input files (or standard input) to standard output")

(tool-main
 (command-line-arguments)
 (lambda (args)
   (for-each
    (lambda (f)
      (if numlines
	  (do ((i 1 (add1 i))
	       (lns (read-lines f) (cdr lns)) )
	      ((null? lns))
	    (format #t "~6d\t~a~%" i (car lns)) )
	  (display (read-all f)) ) )
    (if (null? args)
	(list (current-input-port))
	args) ) ) )

Authors

felix winkelmann

License

Copyright (c) 2007, Felix L. Winkelmann
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
conditions are met:
  Redistributions of source code must retain the above copyright notice, this list of conditions and the following
    disclaimer. 
  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
    disclaimer in the documentation and/or other materials provided with the distribution. 
  Neither the name of the author nor the names of its contributors may be used to endorse or promote
    products derived from this software without specific prior written permission. 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

Version History

0.1
initial release