Skip to content

Take command of your command line in Nim

License

Notifications You must be signed in to change notification settings

tomekwojcik/commandant

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

74 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Commandant

Commandant is a simple to use library for parsing command line arguments. Commandant is ideal for writing terminal applications. All variables are defined right way, and are immediately accessable to your program. Some of the highlight features also include:

  • subcommands
  • options
  • flags
  • exit options (for custom help and version messages)
  • custom error messages
  • required arguments

This library is a fork of Guillaume Viger's Commandeer.

Usage


example1.nim

import commandant, strformat

commandline:
  argument(value, int)
  flag(selfDestruct, "destroy", "d")
  option(timer, float, "time", "t", 12.0) # last parameter is a default value

  # if you define an argument, then you are REQUIRED to always provide a value.
  #     commandant will terminate the program if an argument is missing.
  # conversely, flags are optional and the program will run whether they are 
  #     provided or not.
  # options are also optional

if selfDestruct:
  echo fmt"Using {value} volts, the computer will go to sleep in {timer} minutes"  
else:
  echo fmt"I will continue to perform my duties, running at {value} Hz"

terminal:

./example1 -d -t:5.2 1000

output:

Using 1000 volts, the computer will go to sleep in 5.2 minutes

example2.nim

import ../commandant, strformat

const myProgramVersion = "0.5.4"

proc helpMessage(): string =
  result = """
  pico-nim project template builder
  Usage: example2 <subcommand> <subcommand options> <sillyArg>
  Available subcommands: 
    {...}
  """

commandline:
  argument(sillyArg, float) 
  exitoption("help", "h", helpMessage())
  exitoption("version", "v", myProgramVersion)
  errormsg("you have made some kind of mistake")
  subcommand init, "init", "i":
    argument(name, string)
    flag(override, "override", "O")
    option(sdk, string, "sdk", "s")
    option(nimbase, string, "nimbase", "h")
    exitoption("help", "h", "I wish i could help you, but I can't")
  subcommand build, "build", "b":
    argument(mainProgram, string)
    option(output, string,"output", "o", "source/build")
  
if init:
  echo fmt"creating a new project directory, {name}. One second..."
elif build:
  echo fmt"writing {name}.uf2 to {output}..."
else:
  echo "please use either the 'init' or 'build' subcommand..."
  echo helpMessage()

Installation

There are 2 ways to install commandant:

nimble

Install nimble. Then do:

$ nimble install commandant

This will install the latest tagged version of commandant.

raw

Copy the commandant.nim file to your project and import it.

When I go this way for Nim libraries, I like to create a libs/ folder in my project and put third-party files in it. I then add the line path = "libs" to my nim.cfg file so that the libs/ directory is looked into at compile time.

Documentation

commandline

commandline is used to delimit the space where you define the command line arguments and options you expect. All other commandant constructs (described below) are placed under it. They are all optional - although you probably want to use at least one, right?

subcommand(identifier, name, [ alias1, alias2...])

subcommand declares identifier to be a variable of type bool that is true if the first command line argument passed is name or one of the aliases (alias1, alias2, etc.) and is false otherwise. Under it, you define the subcommand arguments and options you expect. All other commandant constructs (described below) can be placed under it.


argument(identifier, type)

argument declares a variable named identifier of type type initialized with the value of the corresponding command line argument converted to type type.

Correspondence works as follows: the first occurrence of argument corresponds to the first argument, the second to the second argument and so on. Note that if a subcommand is declared then 1) any top-level occurrence of argument is ignored, 2) the first subcommand argument corresponds to the first command line argument after the subcommand, the second to the second argument after the subcommand and so on.


arguments(identifier, type , atLeast1)

arguments declares a variable named identifier of type seq[type] initialized with the value of the sequential command line arguments that can be converted to type type. By default atLeast1 is true which means there must be at least one argument of type type or else an error is thrown. Passing false there allows for 0 or more arguments of the same type to be stored at identifier.

Warning: arguments myListOfStrings, string will eat all arguments on the command line. The same applies to other situations where one type is a supertype of another type in terms of conversion e.g., floats eat ints.


flag(identifier,long name, short name)

functionally, flags are just options (defined below) that have a pre-defined boolean type and a default value set to false.


option(identifier, type, long name, short name , default)

option declares a variable named identifier of type type initialized with the value of the corresponding command line option --long name or -short name converted to type type if it is present. The -- and - are added by commandant for your convenience. If the option is not present, identifier is initialized to its default type value or the passed default value.

The command line option syntax follows Nim's one and adds space (!) i.e., --times=3, --times:3, -t=3, -t:3, --times 3 and -t 3 are all valid.

Syntactic sugar is provided for boolean options such that only the presence of the option is needed to give a true value.


exitoption(long name, short name, exit message)

exitoption declares a long and short option string for which the application will immediately output exit message and exit. This can be used for subcommand specific exit messages too:

This is mostly used for printing the version or the help message.


errormsg(custom error message)

errormsg sets a string custom error message that will be displayed after the other error messages if the command line arguments or options are invalid.


Valid types for type are:

  • int, float, string, bool, char

Design

  • Keep as much logic out of the module and into the hands of the developer as possible
  • No magical variables should be made implicitly available. All created variables should be explicitly chosen by the developer.
  • Keep it simple and streamlined. Command line parsers can do a lot for you, but I prefer to be in adequate control.
  • Test in context. Tests are run on the installed package because that is what people get.

Tests

Run the test suite:

nimble test

TODO and Contribution

Version 0.16.0

  • Add help= string variable to all argument types, which will store a description of the argument
  • Create default --help command that outputs a typical help message

Version 0.17.0

  • Create an html AND markdown version of the help message

Version 1.0.0

  • Improve error handling and update tests to reflect this

About

Take command of your command line in Nim

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Nim 100.0%