Script Library: 1213 scripts
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Documentation for: args.r


REBOL

args.r reference documentation and example usage

Contents:

1. what is args.r?
1.1 how does it work
1.2 In the future...
2. A Quick Example
2.1 Argument Flags, briefly
2.2 Switch Flags, Briefly
2.3 Arguments, at a glance
3. Loading the module
3.1 Dependencies
3.2 Linking to the module
4. Module usage and details
4.1 construct-args() function
4.2 the args-ctx object!
4.3 Arguments
5. Flags
5.1 Different flag types
5.2 Argument flags
5.3 Switch flags
5.4 Toggle flags
6. Direct command-line values (without flags!)
7. The datatypes
7.1 integer!
7.2 decimal!
7.3 logic!
7.4 file!
7.5 string!
7.6 text!
7.7 planned data types
8. Noteworthy details and notes
8.1 Composing args default values
9. Error handling
9.1 template dialect errors
9.2 command line errors

1. what is args.r?

Args.r is a dialect which allows you to manage the command-line arguments sent to your application.

frequent updates in next few days...

These docs are an on-going process and will be updated and revised a few times in the following days. If you wish to get some specific help and documentation for something that's not yet detailed, you can reach the author on Rebol's altme private group, or you can also reach him on the rebol mailing list.

1.1 how does it work

Args.r allows you to define a command template, and then match it against the command line arguments which are supplied to your tool.

You can even use it to handle real-time interactive command-line based applications if you wish, because you supply the string to parse manually.

Internally, the args dialect builds up a parse rule on the fly which handles type validation, optional and default arguments, and neatly stores all of the default and user given values in a simple to use object.

1.2 In the future...

  • Create a help string automatically, which you can print out when the user calls a specific flag or when an error is detected.
  • Add other datatypes like date and time, but these will be included depending on my needs and user demand.
  • Change how template dialect error is reported... actually cause a rebol error.

2. A Quick Example

The following is a small template example which shows how you could template a frame cycling application.

Each dashed argument is called a flag, and any flag then supplies a block which defines its specification.

Most flags will be of the argument type (ex: -start, -end, -speed and -cycle), but we can also use a switch mode flag (ex: -reverse).

rebol []

do %vprint.r
do %args.r

args: construct-args system/script/args [
    -start [start integer!]
    -end [end integer!]
    -speed [fps integer!]
    -cycle [
        start integer! [#0]
        end integer! [#24]
        fps integer! decimal! [#24]
    ]
    -reverse [switch! reverse?]
    -clip [path file! [%sequence.*.jpg]]
]

probe args

ask ""

with this template, you could call your application like so:

> rebol.exe frame-cycler.r -start 1 -end 240 -speed 24

or

> rebol.exe frame-cycler.r -cycle 1 240 24

or

> rebol.exe frame-cycler.r -cycle 1 240

The application would receive the same information. Basically play back frames 1 to 240 at 24 frames a second, so it would load up a 10 second clip.

Here is the return value from the construct-args call which would result from the first command-line example above.

make object! [
    *supplied-flags: [-start -end -speed]
    *error: none
    start: #1
    end: #240
    fps: #24
    reverse?: false
    path: %sequence.*.jpg
]

2.1 Argument Flags, briefly

Flags are the basic elements of the template definition. They supply the names for the options you want to setup. Flags themselves are optional. supplying a flag means you want to alter how the application acts by default.

Within the template, they are spelled-out just like they'd be used on the command-line, with the dash, in order to make them easy to make out when reviewing your template.

2.1.1 In the above example:

Note that the -cycle flag has more than one argument.

Note that the -cycle flag's arguments have default values.

Note that the -clip flag's path argument may include spaces right on the command line without needing any quotes unless the path has a dash preceded by a space in its name.

flag names characters...

Note that not all REBOL word characters are valid for the flags names. Many characters which are valid for words in rebol are used for special tricks in most shells and command prompts.

2.2 Switch Flags, Briefly

Switch mode flags are really simple, they're usually used like toggles for application features or modes. For this reason, they aren't expected to supply any values on the command-line.

They only say if something was chosen or not. There is much more to the switch's specification though, its described in full below.

2.3 Arguments, at a glance

All flags allow you to specify one or more argument names which will receive the values which where given on the command-line or associated to a switch flag.

Arguments may have default values that can be any rebol value, even if different than the template. This allows you to detect if the value is supplied by default, or if the user actually supplied the default value manually.

You can reuse the same argument names in more than one flags (like the -cycle flag above).

3. Loading the module

3.1 Dependencies

Before you can use the args module, you must also download the vprint.r module from rebol.org

3.2 Linking to the module

Just 'DO vprint.r and args.r within the app which uses args.r .

example:

do %vprint.r
do %args.r

I advise you to place the modules relative to your application in order to increase its portability when distributing it.

4. Module usage and details

ARGS.r allows you to match user-supplied arguments to a template you specify using an easy to use dialect. Any user errors are detected and reported, so you may report them to the user.

If there is an error in the template itself, args.r will raise an error, since you should not allow your application to provide a faulty interface to your user... a descriptive error message is always printed to the command-line.

The engine parses your template and converts it into a parse rule that is used to load a string of command-line arguments.

Any flags present in the command-line will set appropriate values within an object that describes your whole template and which is returned by the 'CONSTRUCT-ARGS function.

4.1 construct-args() function

This is the only function you need to call within your application. When the module is linked to, this function will be defined globally.

here is its definition:

construct-args func [
    "returns an object with all fields filled and fully validated, according to spec, an error string otherwise."
    args [string! block!]
    spec [block!] 
][
    return [object!]
]

The args can be any string you give it, including interactive console menu sessions!

The block type args use is for internal use only, and should not be attempted.

4.2 the args-ctx object!

The args-ctx is what is returned by all calls to contsruct-args. Its a very simple object, which will include one attribute for every argument you specified in the template.

Note that any argument name that was specified more than once is shared within the args-ctx object, this allows you to supply differents setups for recurring arguments in different application modes or pre-defined argument setups.

make object! [
       *supplied-flags: [-flag1 -flag2 ...]
       *error: none
       arg1: none
       arg2: none
       ...
   ]

For example, you could have a set of flags which manage the console messaging of your application: -quiet, -verbose, -debug, -warnings, -errors. These would all preset a series of arguments such as 'verbose, 'debug-lvl, 'disk-log.

4.2 internal attributes

Note that two attributes in the args-ctx are prefixed with a '*' character, these are added by the system.

args-ctx/*supplied-flag is for remembering which flags where actually supplied on the command-line, note that the list is added in the order which the flags are encountered.

args-ctx/*error will store any error message you may want to report to the user which arised from the use of the library (described fully under error handling section below). === Template dialect basics

The template dialect is similar in nature to REBOL's native function dialect, but is structured differently.

At the root of the dialect, you may specify one of three things:

  • flag names
  • datatypes (to put values directly on the command line without flags)
  • sub-specifications for the above, in the form of a block.

depending on their specifications, flags and datatypes may take on different meanings or even work differently on the command-line. look at each of their own respective sections to get all the details.

note that there are no limit as to the number of flags which can be specified, and ALL flags are optional on the command-line.

4.3 Arguments

Before going into the specifics of defining the template, it is usefull to understand just what arguments are. You have already seen how arguments are returned to us via the args-ctx object!.

As part of their specification, all flags may assign the effect of their specification to "arguments".

Each argument represents one value within the whole application template that you want to manage.

Different flags may use the same argument name over and over, in which case, it really is the same argument being shared (i.e. the use of that argument in any of the options, switches, etc. will result in the same argument being set in args-ctx).

In most uses, args MUST be type casted in order to ensure data integrity on the command-line. If you do not care for type, simply use a text! type which loads up everything up to the next flag as a string, without any command-line syntax needed. Be carefull though, cause if the data itself includes or may include something interpreted as a flag, your command-line arguments will be invalid with the application.

5. Flags

Flags are a powerfull way to specify application options. On the command line, basically, you write a flag name and, depending on the flag's definition, may add some values which are related to that option.

The actual flag name must start with a dash ('-') followed by a letter and then any combination of letters, digits, dashes, or underscores ('_'). Flag names may not contain spaces. To be compatible with a flag variant on linux, you may also use two dashes at the start of the flag. note that single and double dashed flags are DIFFERENT flags.

here is a list of VALID flag names:

-flag
-a  
--a 
--flag
-layer1  
-layer2 
-layer-1 
-option_A 
-option-b 
-option-C

here is a list of INVALID flag names with the reason for each.

-1a            (flag name must start with a letter)
--1a           (flag name must start with a letter)
- flag         (cannot have spaces in flag names)
_flag          (flag name must start with a letter)
-_option       (flag name must start with a letter)
--_opt         (flag name must start with a letter)
-*flag         (invalid character)
-flag.opt      (invalid character)

Internally, flags are case insensitive. This makes it easier for users. Otherwise authors may use a mix of cases and this becomes confusing for others.

5.1 Different flag types

Flags may be used in one of three ways.

  • As options which enable you to specify values to send to your applications. We call them: "argument flags".
  • As switches, used as simple on/off boolean states. We call them: "switch flags".
  • As toggles, toggles between two values. We call them: "toggle flags".

Flags are easy to specify. Spell them out, and add a spec block just after, like so:

[
    -flag1 [ ... ]
    -flag2 [ ... ]
    --f1 [ ... ]
    ...
]

5.2 Argument flags

Argument flags explicitely define arguments and are the basis for most command lines.

In a single spec, you can define as many arguments as you want. Simply include all argument definitions, one after another. The engine will know how to split the block automatically.

Be carefull to properly type your datatypes or else it might think they are argument names.

5.3 Switch flags

By adding switch! to the begining of a flag spec, you change the role of the flag.

This is followed by an argument name which will store the result of the switch being set or not.

To make it a switch flag, you must either supply no default argument or explicitely one, when specifiying one, it must be a boolean value. The only real use of a single argument is to inverse the default flag state.

example:

here the flag will be false by default, thus verbosity is true when -verbose is used

-verbose [switch! verbosity]

here the flag will be true by default, thus verbosity is false when -quiet is used

-quiet [switch! verbosity [true]]

5.4 Toggle flags

To make a toggle flag, you add switch! just like for a switch flag, but instead, give exactly two default values.

These values become the selected and default values of the flag.

The specified values can be of any type, even different ones!

here the flag will toggle between two values. 'male when the flag is used, 'female otherwise.

-male [switch! sex [male female]]

6. Direct command-line values (without flags!)

unreliable feature at the moment...

This feature might not work as documented, especially if you use more than one direct argument of the same type, but the documentation is the intended usage. In a prior release this will be addressed explicitely.

Your feedback *will* raise the priority.

It is very convenient to have some values directly on the command-line as if a default flag was being activated.

We can add these by using the datatypes directly within the template, without any flag name. It is like if the datatype became the flag.

This allows simpler use of many tools, ex:

> rebol.exe frame-cycler.r image.****.png -cycle 1 100

In this case, we might always want the user to supply the frames to cycle, but start and end times could be set to the sequence's complete length by default. so we supply the image names explicitely all the time and add optional (flagged) cycle information.

Note that the engine is supposed to handle extra arguments before OR after the flags. This would also be valid:

> rebol.exe frame-cycler.r -cycle 1 100 image.****.png

There is some care to be taken by your users though, if placing the flag-less arguments after any flags. If the last flag defines some default arguments, and the type happens to be the same as those extra parameters, the engine WILL grab those arguments, send them to the flag and complain that its missing a value on the command-line.

This is why we recommend always supplying mandatory or optional flag-less values BEFORE the first flag.

You can also tailor your flags to make sure the situation does not present itself, but that can be almost impossible for larger applications.

7. The datatypes

not all types in ARGS.r actually represent an actual datatype in rebol. The scope is a bit wider. Types like text! are pseudo types, in that they are lexically different on the command-line but ultimately represent some internal data which rebol can express natively... in this case a string.

7.1 integer!

integers are in fact bignums, since they can be any length in characters. They are loaded within rebol as issues, so you may verify if the value is 32bit compatible.

The main reason integers are loaded this way is that on a command-line... numbers can represent something else than an actual value. It may be a serial number for example. Also, 32 bits is quite small nowadays for many file tasks, its simply not enough.

Note that when giving a default value, its best to supply an issue also, cause otherwise you will end up with a different datatype depending on if the data is default or user-supplied.

7.2 decimal!

Decimals are handled like BCD values since they never get loaded within an IEEE float value. as such they are infinite in precision and all digits are significant.

Like the integers, decimals are loaded as issues. The main reason is that, once again, there is nothing implicit about a decimal number needing to be used in arithmetics. If a simple value is usually rounded once loaded into float, then for some applications, the imprecision would render the decimal useless.

Note that when giving a default value, its best to supply an issue also, cause otherwise you will end up with a different datatype depending on if the data is default or user-supplied.

7.3 logic!

true false on off 0 1

7.4 file!

These are loaded as file! types within args-ctx.

you can use OS filenames OR rebol style filenames transparently. if your filepath is specified last on the command-line, it may include spaces. In may include spaces in any case, but flags may be missed in some circumstances.

in any case, you can surround the filename with single quotes as you do with strings. it will still be loaded as a file! type in rebol.

7.5 string!

a usual string, except that we use single quotes to specify the string boundaries. escape character is not '^\ but rather '\' as is normal for csh-style command-line usage.

I am testing the use of "" and {} as alternatives... but this doesn't seems to function yet

7.6 text!

This is a special pseudo type which simply tells ARGS.r to grab all the characters up to the next flag encountered. you can escape characters as usual, so you could include flags within the grabbed text, if you preceded them with a \.

This is very usefull to provide simple interfaces to non-technical users.

7.7 planned data types

  • float!: explicit IEEE value, loaded as a decimal, in REBOL.
  • number!: same as integer! but an explicit 32 bit signed integer value. gives overflow error if larger than +/- * 2^31 bits.
  • word!: a single word string any character allowed
  • alphanumeric: a single alphanumeric word (usefull for catalogues and pipeline stuff... kiss labels)
  • hex!: same as integer, loaded as an issue, but converted to decimal, beforehand.
  • time!, date!: self-explanatory
  • tuple!: loaded as an issue, any value size at each value.
  • 8bit-tuple!: loaded as tuple in rebol.
  • 16bit-tuple!: loaded into an issue.

8. Noteworthy details and notes

8.1 Composing args default values

Sometimes the default values must be linked to or simply generated at run time (they might be installation path relative, for example).

In this case, its best to use compose/deep to reduce only one value within your whole block.

Be carefull to use the /only refinement if needed and also keep in mind that the template block is not bound nor reduced internally by ARGS.r. so words like 'NONE, 'TRUE, 'FALSE, actually aren't loaded as values, they stay as words within the whole processing of the template.

If you need these to be values, then compose them, or use their molded form, ex: #[none] refers to a none VALUE explicitely.

9. Error handling

9.1 template dialect errors

Any error in template dialect usage is raised directly as an error. This is to prevent bad templates to proceed to users, and you distributing broken tools. The error is reported to you with an indication as to where the error occured.

9.2 command line errors

As of v0.1.9, error reporting for the command-line parsing has been added. Any error is stored within the args-ctx/*error as a string, and is ready to be printed.

Here in an example of an error report for the frame-cycle used at the begining of this documentation:

Command-line error in '-cycle' flag
Description: none
Location : -cycle 1 ee
                   __
MakeDoc2 by REBOL- 17-Dec-2008