For Development HEAD DRAFTSearch (procedure/syntax/module):

11.10 srfi.37 - args-fold: a program argument processor

Module: srfi.37

This module implements args-fold, yet another procedure to process command-line arguments, defined in SRFI-37.

Unlike gauche.parseopt (see gauche.parseopt - Parsing command-line options), args-fold provides functional interface, i.e. the user’s states are explicitly passed via parser’s argument and return values, and also follows POSIX and GNU getopt guidelines, including long options.

Function: args-fold args options unrecognized-proc operand-proc :rest seeds

[SRFI-37]{srfi.37} Processes program options args from left to right, according to given option specification options, and two procedures unrecognized-proc and operand-proc.

Options is a list of option objects, explained below. Each option object keeps the name(s) of the option, a flag to specify whether the option takes an argument or not, and a procedure to process that option (we’ll call it option procedure).

Args-fold recognizes both single-character options (short options) and long options. A short option must begin with single hyphen (e.g. -a), while long option must begin with double hyphens (e.g. --help). Short options can be concatenated, e.g. -abc or -a -b -c. Both a short option and a long option can take required or optional arguments. Required short-option argument can appear with or without space after the option, e.g. -afoo or -a foo. Long-option argument can appear after character ’=’ or space, e.g. --long=foo or --long foo.

When args-fold encounters a command-line argument that cannot be an option argument, and doesn’t begin with hyphen, the argument is treated as an operand. Args-fold allows operands and options to be interleaved. However, if args-fold encounters ’--’, the rest of arguments are treated as operands, regardless of beginning with hyphen or not.

When the given option matches one of option object in options, the option procedure is called as follows:

(option-proc option name arg seed ...)

where option is the matched option object, name is the string actually used to specify the option, arg is the option argument (or #f if there’s none), and seed … is the user’s state information. Option-proc must return as many arguments as seeds.

When args-fold encounters an option that doesn’t match any of the option objects, it creates a new option object for the option and calls unrecognized-proc with the same arguments as option-proc.

When args-fold finds an operand, operand-proc is called as follows:

(operand-proc operand seed ...)

Operand-proc must return as many arguments as seeds.

The caller’s state should be explicitly passed around seed arguments and return values. The initial seed values are seeds given to args-fold. The values returned from option procedure, unrecognized-proc and operand-proc are used as the seed arguments of next invocation of those procedures. The values returned from the last call to the procedures are returned from args-fold.

Function: option names require-arg? optional-arg? processor

[SRFI-37]{srfi.37} Creates an option object with the passed properties.

Names is a list of characters and/or strings. A character is used for a short option, and a string is used for a long option.

Two flags, require-arg? and optional-arg? indicates whether the option should take an option argument, or may take an option argument.

Processor is the option processor procedure.

Note that, if an option argument is passed using ’=’ character, it is passed to the option procedure even if the option has #f in both require-arg? and optional-arg?. It is up to the option procedure to deal with the argument.

It should also be noted that the optional option argument for a short option is only recognized if it is given without whitespace after the short option. That is, if a short option ’d’ is marked to take optional option argument, then ’-dfoo’ is interpreted as ’-d’ with argument ’foo’, but ’-d foo’ is interpreted as ’-d’ without argument and an operand foo. If ’d’ is marked to take required option argument, however, both are interpreted as ’-d’ with argument ’foo’.

Function: option? obj

[SRFI-37]{srfi.37} Returns #t if obj is an option object, #f otherwise.

Function: option-names option
Function: option-required-arg? option
Function: option-optional-arg? option
Function: option-processor

[SRFI-37]{srfi.37} Returns the properties of an option object option.

A simple example:

(use srfi.37)

(define options
 (list (option '(#\d "debug") #f #t
               (lambda (option name arg debug batch paths files)
                 (values (or arg "2") batch paths files)))
       (option '(#\b "batch") #f #f
               (lambda (option name arg debug batch paths files)
                 (values debug #t paths files)))
       (option '(#\I "include") #t #f
               (lambda (option name arg debug batch paths files)
                 (values debug batch (cons arg paths) files)))))

(define (main args)
  (receive (debug-level batch-mode include-paths files)
    (args-fold (cdr args)
               options
               (lambda (option name arg . seeds)         ; unrecognized
                 (error "Unrecognized option:" name))
               (lambda (operand debug batch paths files) ; operand
                 (values debug batch paths (cons operand files)))
               0      ; default value of debug level
               #f     ; default value of batch mode
               '()    ; initial value of include paths
               '()    ; initial value of files
               )
     (print "debug level = " debug-level)
     (print "batch mode = " batch-mode)
     (print "include paths = " (reverse include-paths))
     (print "files = " (reverse files))
     0))


For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT