Contents:

1. Introduction

Command line argument parsing is a basic component of all command line tools. This module simplifies the creation of such tools.

2. Overview

We take a very simple approach. Other features will be added as needed.

The arguments spec is a block with the grammar:

opt ['title string!] ; program title to use when displaying help
any [
 string! word! opt type opt ['default skip] opt ['help string!]
 ; argument keyword, argument name, optional argument type,
 ; optional default value, optional help string
 |
 word! type opt ['default skip] opt ['help string!]
 ; argument name, argument type, optional default value, optional help string
]

With type being one of integer!, file! or string!.

For example, a spec like:

title "IMAP proxy daemon"
port-number integer! default 1025 help "Port number to listen to"
"config" config-file file! default %.conf help "Specify alternate configuration file name"
"pid" pid-file file! default %.pid help "Specify alternate PID file name"

specifies three variables that can be set via command line arguments: port-number, config-file and pid-file. The former must be an integer, and does not require any keywords. The other two are converted using to-rebol-file, and introduced by a keyword.

If the /env refinement is used, the default values for arguments can be overridden with environment variables. The spec block specifies the variable names, with the grammar:

any [
 word! string!
 ; argument name, environment variable name
]

There is a special keyword, "help", which causes the function to print the command usage help and quit. (So, you must be prepared for this function just calling quit.)

Overview

parse-arguments: func [
 "Parse command line arguments, return an object"
 spec [block!] "Arguments spec"
 /env env-spec [block!] "Environment variables spec"

 /local parse-arguments' locals
] [
 Parse command line arguments according to spec
]

3. Parse command line arguments according to spec

Parse command line arguments according to spec

unless env [env-spec: [ ]]
help-text: clear ""
keywords: [
 "help" (print help-text quit)
]
arguments: [
 keywords
]
result: clear [ ]
type-rule: [
 'integer! (
  type: 'integer!
  action: to paren! compose/deep [
   if value: attempt [to integer! value] [
    set in result (to lit-word! var-name) value
   ]
  ]
 )
 |
 'file! (
  type: 'file!
  action: to paren! compose [set in result (to lit-word! var-name) to-rebol-file value]
 )
 |
 (type: 'string! action: to paren! compose [set in result (to lit-word! var-name) value])
 'string!
]
default-rule: [
 'default set default-value skip
 |
 (default-value: none)
]
get-env*: [
 if all [
  env-name: select env-spec var-name
  value: get-env env-name
 ] [
  default-value: switch type [
   file! [to-rebol-file value]
   integer! [attempt [to integer! value]]
   string! [value]
  ]
 ]
]
help-rule: [
 'help set value string! (repend help-text [" - " value])
]
finish-help: [
 if default-value [
  repend help-text [
   " (default: "
   either file? default-value [to-local-file default-value] [default-value]
   #")"
  ]
 ]
 append help-text newline
 if env-name [
  repend help-text [
   "^-^-Default can be set with the variable " env-name newline
  ]
 ]
 repend result [to set-word! var-name default-value]
]
parse spec [
 [
  'title set value string! (insert insert tail help-text value "^/Usage:^/^/")
  |
  (append help-text "Usage:^/^/")
 ]
 any [
  set keyword string! set var-name word!
  opt type-rule
  default-rule (
   do get-env*
   repend help-text [
    #"^-" keyword " <" var-name #">"
   ]
  )
  opt help-rule (
   do finish-help
   repend keywords [
    '|
    keyword 'set 'value 'string! action
   ]
  )
  |
  set var-name word!
  type-rule
  default-rule
  (
   do get-env*
   repend help-text [
    "^-<" var-name #">"
   ]
  )
  opt help-rule (
   do finish-help
   repend arguments [
    '|
    'set 'value 'string! action
   ]
  )
 ]
]
result: context result
if system/options/args [parse system/options/args [any arguments]]
result

3.1 parse-arguments' locals

parse-arguments' locals

help-text arguments keywords result action value default-value env-name var-name keyword
type