Defines functions to simplify handling of command line arguments.
Command line argument parsing is a basic component of all command line tools. This module simplifies the creation of such tools.
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〉
]
〈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
〈parse-arguments' locals〉 ≡
help-text arguments keywords result action value default-value env-name var-name keyword
type