Source Edit

This module provides the standard Nim command line parser. It supports one convenience iterator over all command line options and some lower-level features.

Supported Syntax

The following syntax is supported when arguments for the shortNoVal and longNoVal parameters, which are described later, are not provided:

  1. Short options: -abcd, -e:5, -e=5
  2. Long options: --foo:bar, --foo=bar, --foo
  3. Arguments: everything that does not start with a -

These three kinds of tokens are enumerated in the CmdLineKind enum.

When option values begin with ‘:’ or ‘=’, they need to be doubled up (as in --delim::) or alternated (as in --delim=:).

The -- option, commonly used to denote that every token that follows is an argument, is interpreted as a long option, and its name is the empty string.

Parsing

Use an OptParser to parse command line options. It can be created with initOptParser, and next advances the parser by one token.

For each token, the parser’s kind, key, and val fields give information about that token. If the token is a long or short option, key is the option’s name, and val is either the option’s value, if provided, or the empty string. For arguments, the key field contains the argument itself, and val is unused. To check if the end of the command line has been reached, check if kind is equal to cmdEnd.

Here is an example:

  1. import std/parseopt
  2. var p = initOptParser("-ab -e:5 --foo --bar=20 file.txt")
  3. while true:
  4. p.next()
  5. case p.kind
  6. of cmdEnd: break
  7. of cmdShortOption, cmdLongOption:
  8. if p.val == "":
  9. echo "Option: ", p.key
  10. else:
  11. echo "Option and value: ", p.key, ", ", p.val
  12. of cmdArgument:
  13. echo "Argument: ", p.key
  14. # Output:
  15. # Option: a
  16. # Option: b
  17. # Option and value: e, 5
  18. # Option: foo
  19. # Option and value: bar, 20
  20. # Argument: file.txt

The getopt iterator, which is provided for convenience, can be used to iterate through all command line options as well.

To set a default value for a variable assigned through getopt and accept arguments from the cmd line. Assign the default value to a variable before parsing. Then set the variable to the new value while parsing.

Here is an example: .. code-block:: import std/parseopt

var varName: string = “defaultValue”

for kind, key, val in getopt(): case kind of cmdArgument: discard of cmdLongOption, cmdShortOption: case key: of “varName”: # —varName:<value> in the console when executing varName = val # do input sanitization in production systems of cmdEnd: discard

shortNoVal and longNoVal

The optional shortNoVal and longNoVal parameters present in initOptParser are for specifying which short and long options do not accept values.

When shortNoVal is non-empty, users are not required to separate short options and their values with a ‘:’ or ‘=’ since the parser knows which options accept values and which ones do not. This behavior also applies for long options if longNoVal is non-empty. For short options, -j4 becomes supported syntax, and for long options, --foo bar becomes supported. This is in addition to the previously mentioned syntax. Users can still separate options and their values with ‘:’ or ‘=’, but that becomes optional.

As more options which do not accept values are added to your program, remember to amend shortNoVal and longNoVal accordingly.

The following example illustrates the difference between having an empty shortNoVal and longNoVal, which is the default, and providing arguments for those two parameters:

  1. import std/parseopt
  2. proc printToken(kind: CmdLineKind, key: string, val: string) =
  3. case kind
  4. of cmdEnd: doAssert(false) # Doesn't happen with getopt()
  5. of cmdShortOption, cmdLongOption:
  6. if val == "":
  7. echo "Option: ", key
  8. else:
  9. echo "Option and value: ", key, ", ", val
  10. of cmdArgument:
  11. echo "Argument: ", key
  12. let cmdLine = "-j4 --first bar"
  13. var emptyNoVal = initOptParser(cmdLine)
  14. for kind, key, val in emptyNoVal.getopt():
  15. printToken(kind, key, val)
  16. # Output:
  17. # Option: j
  18. # Option: 4
  19. # Option: first
  20. # Argument: bar
  21. var withNoVal = initOptParser(cmdLine, shortNoVal = {'c'},
  22. longNoVal = @["second"])
  23. for kind, key, val in withNoVal.getopt():
  24. printToken(kind, key, val)
  25. # Output:
  26. # Option and value: j, 4
  27. # Option and value: first, bar

See also

Imports

os

Types

  1. CmdLineKind = enum
  2. cmdEnd, ## End of command line reached
  3. cmdArgument, ## An argument such as a filename
  4. cmdLongOption, ## A long option such as --option
  5. cmdShortOption ## A short option such as -c

The detected command line token. Source Edit

  1. OptParser = object of RootObj
  2. kind*: CmdLineKind ## The detected command line token
  3. key*, val*: string ## Key and value pair; the key is the option
  4. ## or the argument, and the value is not "" if
  5. ## the option was given a value

Implementation of the command line parser.

To initialize it, use the initOptParser proc.

Source Edit

Procs

  1. proc cmdLineRest(p: OptParser): string {....gcsafe, extern: "npo$1", raises: [],
  2. tags: [], forbids: [].}

Retrieves the rest of the command line that has not been parsed yet.

See also:

Examples:

  1. var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
  2. while true:
  3. p.next()
  4. if p.kind == cmdLongOption and p.key == "": # Look for "--"
  5. break
  6. doAssert p.cmdLineRest == "foo.txt bar.txt"

Source Edit

  1. proc initOptParser(cmdline = ""; shortNoVal: set[char] = {};
  2. longNoVal: seq[string] = @[];
  3. allowWhitespaceAfterColon = true): OptParser {....raises: [],
  4. tags: [ReadIOEffect], forbids: [].}

Initializes the command line parser.

If cmdline == “”, the real command line as provided by the os module is retrieved instead if it is available. If the command line is not available, a ValueError will be raised.

shortNoVal and longNoVal are used to specify which options do not take values. See the documentation about these parameters for more information on how this affects parsing.

This does not provide a way of passing default values to arguments.

See also:

Example:

  1. var p = initOptParser()
  2. p = initOptParser("--left --debug:3 -l -r:2")
  3. p = initOptParser("--left --debug:3 -l -r:2",
  4. shortNoVal = {'l'}, longNoVal = @["left"])

Source Edit

  1. proc initOptParser(cmdline: seq[string]; shortNoVal: set[char] = {};
  2. longNoVal: seq[string] = @[];
  3. allowWhitespaceAfterColon = true): OptParser {....raises: [],
  4. tags: [ReadIOEffect], forbids: [].}

Initializes the command line parser.

If cmdline.len == 0, the real command line as provided by the os module is retrieved instead if it is available. If the command line is not available, a ValueError will be raised. Behavior of the other parameters remains the same as in initOptParser(string, …).

See also:

Example:

  1. var p = initOptParser()
  2. p = initOptParser(@["--left", "--debug:3", "-l", "-r:2"])
  3. p = initOptParser(@["--left", "--debug:3", "-l", "-r:2"],
  4. shortNoVal = {'l'}, longNoVal = @["left"])

Source Edit

  1. proc next(p: var OptParser) {....gcsafe, extern: "npo$1", raises: [], tags: [],
  2. forbids: [].}

Parses the next token.

p.kind describes what kind of token has been parsed. p.key and p.val are set accordingly.

Example:

  1. var p = initOptParser("--left -r:2 file.txt")
  2. p.next()
  3. doAssert p.kind == cmdLongOption and p.key == "left"
  4. p.next()
  5. doAssert p.kind == cmdShortOption and p.key == "r" and p.val == "2"
  6. p.next()
  7. doAssert p.kind == cmdArgument and p.key == "file.txt"
  8. p.next()
  9. doAssert p.kind == cmdEnd

Source Edit

  1. proc remainingArgs(p: OptParser): seq[string] {....gcsafe, extern: "npo$1",
  2. raises: [], tags: [], forbids: [].}

Retrieves a sequence of the arguments that have not been parsed yet.

See also:

Examples:

  1. var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
  2. while true:
  3. p.next()
  4. if p.kind == cmdLongOption and p.key == "": # Look for "--"
  5. break
  6. doAssert p.remainingArgs == @["foo.txt", "bar.txt"]

Source Edit

Iterators

  1. iterator getopt(cmdline: seq[string] = @[]; shortNoVal: set[char] = {};
  2. longNoVal: seq[string] = @[]): tuple[kind: CmdLineKind,
  3. key, val: string] {....raises: [], tags: [ReadIOEffect], forbids: [].}

Convenience iterator for iterating over command line arguments.

This creates a new OptParser. If no command line arguments are provided, the real command line as provided by the os module is retrieved instead.

shortNoVal and longNoVal are used to specify which options do not take values. See the documentation about these parameters for more information on how this affects parsing.

There is no need to check for cmdEnd while iterating. If using getopt with case switching, checking for cmdEnd is required.

See also:

Examples:

  1. # these are placeholders, of course
  2. proc writeHelp() = discard
  3. proc writeVersion() = discard
  4. var filename: string
  5. let params = @["--left", "--debug:3", "-l", "-r:2"]
  6. for kind, key, val in getopt(params):
  7. case kind
  8. of cmdArgument:
  9. filename = key
  10. of cmdLongOption, cmdShortOption:
  11. case key
  12. of "help", "h": writeHelp()
  13. of "version", "v": writeVersion()
  14. of cmdEnd: assert(false) # cannot happen
  15. if filename == "":
  16. # no filename has been written, so we show the help
  17. writeHelp()

Source Edit

  1. iterator getopt(p: var OptParser): tuple[kind: CmdLineKind, key, val: string] {.
  2. ...raises: [], tags: [], forbids: [].}

Convenience iterator for iterating over the given OptParser.

There is no need to check for cmdEnd while iterating. If using getopt with case switching, checking for cmdEnd is required.

See also:

Examples:

  1. # these are placeholders, of course
  2. proc writeHelp() = discard
  3. proc writeVersion() = discard
  4. var filename: string
  5. var p = initOptParser("--left --debug:3 -l -r:2")
  6. for kind, key, val in p.getopt():
  7. case kind
  8. of cmdArgument:
  9. filename = key
  10. of cmdLongOption, cmdShortOption:
  11. case key
  12. of "help", "h": writeHelp()
  13. of "version", "v": writeVersion()
  14. of cmdEnd: assert(false) # cannot happen
  15. if filename == "":
  16. # no filename has been given, so we show the help
  17. writeHelp()

Source Edit