simple_parseopt

    Dark Mode
Search:
Group by:

Nim module which provides clean, zero-effort command line parsing.

Basic Use

This module gives you two ways to parse the command line: get_options and get_options_and_supplied

get_options

At its simplest, declare a block like this:

# foo.nim

let options = get_options:
    name          = "Default Name"
    active        = false
    letter_one    = 'a'
    age           = 1
    hello:string
    big:float64   = 1.1
    small:float   = 2.2
    flat:uint     = 2
    arguments:seq[string]

echo options.name & " is " & options.age.repr & " years old!"

Notice it follows the same syntax as a var block.

In the example foo.nim above, the variable options will be set to an object with fields as described in the get_options block. Each field will also be set up as a command-line parameter for the user running the program to use; bools will toggle, while other fields will take a value argument.

foo -name "J. Random" -active -big 1011121.121498 -letter-one z

This will set the name string to "J. Random", toggle the active bool to true, set the big float64 to 1011121.121498, and set letter_one to z (notice the underscore in the field becomes a hyphen at the command line).

You may use any basic type: bool, string, int, float, uint, char, and the sized variants thereof, as well as seqs of those types: seq[string], seq[int], seq[float], etc. (You may not use seq[bool])

The last seq[string] will automatically be used to store any arguments set without a parameter name (you can disable this behaviour with no_implicit_bare())

Details

The code above will translate into the equivalent of:

type Options = object
    name:string
    active:bool
    letter_one:char
    age:int
    hello:string
    big:float64
    small:float
    flat:uint
    arguments:seq[string]

options = Options(name: "Default Name", active: false, letter_one: 'a', age: 1, big: 1.1, small: 2.2, flat: 2)

parse_command_line_into(options)

Where parse_command_line_into is some hypothetical procedure which parses the user-supplied command line and sets fields in options appropriately.

get_options_and_supplied

Using a get_options_and_supplied block will behave just like get_options, except it will return a tuple of two objects. The first is as detailed above. The second object will have identical field names, but all its fields will be of type bool.

Any field which the user has supplied on the command line will have its bool in the second object set to true.

# foo.nim

let (options, supplied) = get_options_and_supplied:
    name          = "Default Name"
    active        = false
    letter        = 'a'
    age           = 1
    big:float64   = 1.1
    small:float   = 2.2
    flat:uint     = 2
    hello:string

if supplied.name and supplied.age:
    echo options.name & " is " & options.age.repr & " years old!"

Default command-line syntax

By default, each named parameter may be set on the command line by the user prefixing it with a - or a /. For bool fields, this will toggle the field. For other fields, the next argument on the command line is used to set the field.

All of these will work:

foo -name "Joe Random" -active
foo /active /flat 100
foo /hello Greetings! -big 100 /small 20

Extra Parameter Info: Pragmas

You may also add pragmas to the end of any line to modify parameter behaviour. Each pragma has a more verbose alias, if you prefer that style of code.

  • {. info("text") .} or {. description("text") .}

    Description of the parameter which will be shown in help text.

  • {. aka("a", "b", ...) .} or {. alias("a", "b", ...) .}

    Aliases for the parameter - user may use these as parameters; they will write to the field.

  • {. bare .} or {. positional .}

    Accepts a bare, positional argument (an argument which has not been prefixed with a parameter name). User will not be able to refer to the argument with its parameter name.

  • {. need .} or .{ required .}

    Parameter must be supplied by user or an error is shown.

  • {. len(i) .} or .{ count(i) .}

    Place on a seq field to require that many values be supplied to it. For example:

    position:seq[float] {. len(3) .} # x y z

    Note that this does not set a limit on the total length of the seq, only on how many values the user must specify. Using len in conjunction with the allow_repetition setting, you can accept multiple batches of values (see normalize.nim example)

Settings

You may tailor the parser with the following calls:

  • no_dash()

    Disable parameter being identified by prefixing with -

  • no_slash()

    Disable parameter being identified by prefixing with /

  • dash_dash_parameters()

    Require that parameters which have more than one character in their name be prefixed with -- instead of -. Single-character parameters may then be entered grouped together under one -

  • dash_dash_separator()

    -- on its own in the command line will disable parameter names on every argument after it; they will all be treated as bare

  • value_after_colon()

    Allow the user to specify parameter & value together, separated by a :

    e.g. -param:value

    Note this will not play nicely with quoted string values.

  • value_after_equals()

    Allow the user to specify parameter & value together, separated by a =

    e.g. -param=value

    Note this will not play nicely with quoted string values.

  • allow_repetition()

    Allow the user to specify the same parameter more than once without reporting an error.

  • allow_errors()

    Allow program execution to continue after erroneous input.

  • no_implicit_bare()

    Do not automatically use the last seq[string] parameter to gather any bare parameters the user enters (they become erroneous instead)

  • can_name_bare()

    Allows user to set bare parameters by name.

  • manual_help()

    Disable automatic generation of help message when user enters -?, -h or -help (when you do not include them as parameters)

  • command_name(name: string)

    Set the name of the executable, for use in the auto-generated help-message when the user enters -?, -h, or -help.

    Note: command_name may not be included in a config: chain

  • help_text(text: string, footer = "")

    Set the text which is included in the auto-generated help-message when the user enters -?, -h, or -help.

    • text is displayed at the top, before the parameters.
    • footer is displayed at the bottom, after them.

    Note: help_text may not be included in a config: chain

  • config:

    A helper macro which allows you to specify the above options (except help_text and command_name) as a call chain. For example:

    simple_parseopt.config: no_slash.dash_dash_parameters.allow_repetition

Procs

proc no_dash() {...}{.raises: [], tags: [].}
Disable parameter being identified by prefixing with -   Source Edit
proc no_slash() {...}{.raises: [], tags: [].}
Disable parameter being identified by prefixing with /   Source Edit
proc dash_dash_parameters() {...}{.raises: [], tags: [].}

Require that parameters which have more than one character in their name be prefixed with -- instead of -.

Single-character parameters may then be entered grouped together under one -

  Source Edit
proc dash_dash_separator() {...}{.raises: [], tags: [].}
-- on its own in the command line will disable parameter names on every argument after it; they will all be treated as bare.   Source Edit
proc value_after_colon() {...}{.raises: [], tags: [].}

Allow the user to specify parameter & value together, separated by a :

e.g. -param:value

Note this will not play nicely with quoted string values.

  Source Edit
proc value_after_equals() {...}{.raises: [], tags: [].}

Allow the user to specify parameter & value together, separated by a =

e.g. -param=value

Note this will not play nicely with quoted string values.

  Source Edit
proc allow_repetition() {...}{.raises: [], tags: [].}
Allow the user to specify the same parameter more than once without reporting an error.   Source Edit
proc allow_errors() {...}{.raises: [], tags: [].}
Allow program execution to continue after erroneous input.   Source Edit
proc no_implicit_bare() {...}{.raises: [], tags: [].}
Do not automatically use the last seq[string] parameter to gather any bare parameters the user enters (instead they become erroneous)   Source Edit
proc can_name_bare() {...}{.raises: [], tags: [].}
Allows user to set bare parameters by name.   Source Edit
proc manual_help() {...}{.raises: [], tags: [].}
Disable automatic generation of help message when user enters -?, -h or -help (when you do not include them as parameters)   Source Edit
proc command_name(name: string) {...}{.raises: [], tags: [].}

Set the name of the executable, for use in the auto-generated help-message when the user enters -?, -h, or -help.

Note: command_name may not be included in a config: chain

  Source Edit
proc help_text(text, footer = "") {...}{.raises: [], tags: [].}

Set the text which is included in the auto-generated help-message when the user enters -?, -h, or -help.

text is displayed at the top, before the parameters. footer is displayed at the bottom, after them.

Note: help_text may not be included in a config: chain

  Source Edit

Macros

macro config(body: untyped): untyped

Helper macro to let you easily specify several config options.

Example:

simple_parseopt.config: no_slash.dash_dash_parameters.allow_repetition

  Source Edit
macro get_options_and_supplied(body: untyped): untyped

Parses the command-line arguments provided by the user, using it and the code block to fill out an object's fields.

Returns a tuple of two objects: the first as detailed by the code block, the second a mirror of it, but all of type bool. For any parameters which the user has supplied on the command line, the field on the second object will be set to true.

All basic intrinsic types are supported: string, char, bool, int, uint, float (and all size variants: int16, float32, etc.)

The block is written as if it were a var, i.e. all of these are valid:

x = 0
x:int32
x:int = 20
You may also use any seq of the above: seq[string], seq[int], seq[float], etc. These may not be initialized to a default value, however: they must be empty.

args: seq[string]
If you do not explicitly specify a {. bare .} seq[string], but do have one or more seq[string], then the last one will be used to store all bare arguments. (i.e. will be treated as if it had an implicit {. bare .} pragma.) This may be disabled with the no_implicit_bare setting.

You may also add pragmas to the end of any line to modify parameter behaviour. Each pragma has a more verbose alias, if you prefer that style of code.

{. info("text") .} or {. description("text") .}
Description of the parameter shown in help text.
{. aka("a", "b", ...) .} or {. alias("a", "b", ...) .}
Aliases for the parameter - user may use these as parameters; they will write to the variable.
{. bare .} or {. positional .}
Accepts a bare, positional argument (an argument which has not been prefixed with a parameter name). User will not be able to refer to the argument with its parameter name.
{. need .} or .{ required .}
Parameter must be supplied by user or an error is shown.
{. len(i) .} or .{ count(i) .}

Place on a seq field to require that many values be supplied to it. For example: position:seq[float] {. len(3) .} # x y z

Note that this does not set a limit on the total length of the seq, only on how many values the user must specify. Using len in conjunction with the allow_repetition setting, you can accept multiple batches of values (see normalize.nim example)

Example:

let options, supplied = get_options_and_supplied:
    teenager = "Joe Random" {. aka("name", "n") .}
    age[int8] = 13
    nin:string              {. info("National Insurance Number") .}
    arguments:seq[string]

if not supplied.nin:
    report "Must supply NIN"
    quit(1)

if options.age < 13 or options.age > 19:
    report "Not a teenager!"
    quit(1)

  Source Edit
macro get_options(body: untyped): untyped

Parses the command-line arguments provided by the user, using it and the code block to fill out an object's fields.

Returns an object whose fields are detailed by the code block.

All basic intrinsic types are supported: string, char, bool, int, uint, float (and all size variants: int16, float32, etc.)

The block is written as if it were a var, i.e. all of these are valid:

x = 0
x:int32
x:int = 20
You may also use any seq of the above: seq[string], seq[int], seq[float], etc. These may not be initialized to a default value, however: they must be empty.

args: seq[string]
If you do not explicitly specify a {. bare .} seq[string], but do have one or more seq[string], then the last one will be used to store all bare arguments. (i.e. will be treated as if it had an implicit {. bare .} pragma.) This may be disabled with the no_implicit_bare setting.

You may also add pragmas to the end of any line to modify parameter behaviour. Each pragma has a more verbose alias, if you prefer that style of code.

{. info("text") .} or {. description("text") .}
Description of the parameter shown in help text.
{. aka("a", "b", ...) .} or {. alias("a", "b", ...) .}
Aliases for the parameter - user may use these as parameters; they will write to the variable.
{. bare .} or {. positional .}
Accepts a bare, positional argument (an argument which has not been prefixed with a parameter name). User will not be able to refer to the argument with its parameter name.
{. need .} or .{ required .}
Parameter must be supplied by user or an error is shown.
{. len(i) .} or .{ count(i) .}

Place on a seq field to require that many values be supplied to it. For example: position:seq[float] {. len(3) .} # x y z

Note that this does not set a limit on the total length of the seq, only on how many values the user must specify. Using len in conjunction with the allow_repetition setting, you can accept multiple batches of values (see normalize.nim example)

Example:

let options = get_options:
    teenager = "Joe Random" {. alias("name", "n") .}
    age[int8] = 13
    nin:string              {. info("National Insurance Number") .}

if options.nin.len != 9:
    report "Must supply valid NIN"
    quit(1)

if options.age < 13 or options.age > 19:
    report "Not a teenager!"
    quit(1)

  Source Edit