Executive Summary
A cross-platform command line library which can parse almost any of the standard command line formats in use today. It supports character types of ASCII, MBCS and Unicode. It is designed explicitly to be portable to any platform and has been tested on Windows and Linux.
A Bit More Detail
SimpleOpt is designed to just get the job done. It is feature complete and the only changes from now on will be for any necessary bugfixes.
SimpleOpt does do the following:
- separate the command line args into valid options and files
- notify the programmer of invalid options and missing arguments, but lets them decide how to handle them
- separates the programmer from the pain of parsing the argument list
- .... that's it.
It's basic but powerful. It has a simple API, it's easy to configure and use, and quick to add to your project (1 header file). It is all of the features that you need. It doesn't do any of the stuff that is best left to another layer, and which would just make the library more complex.
SimpleOpt does NOT do the following:
- It doesn't try to create usage help (you can write that better, and in the format you want)
- It doesn't try to enforce rules for ranges, types, or possible values (best left to program logic)
But wait!
Not only do you get all of that, but you also get the cross-platform command-line processing version of steak-knives! Included in the package is cross-platform implementation of glob() so that wildcards in command line arguments can be simply expanded for use by the program.
"But how much?" you ask. Nada. Zip. Zero. Released as open-source and free using the MIT licence. Use it with any open-source licence or in any commercial software.
Documentation
Full documentation of the interface is available in either online documentation or as a separate download.
Downloads
The current version of SimpleOpt is 3.6 (last updated: 9 Mar 2013)
Download simpleopt-3.6.zip (about 60Kb)
Download Doxygen documentation (about 130Kb)
Source Repository
Full source code, demo and test programs are included in the download. The homepage of the project is here, however the source repository is stored at google code.
Features
- MIT Licence allows free use in all software (including GPL and commercial)
- multi-platform (Windows 95/98/ME/NT/2K/XP, Linux, Unix)
- supports all types of options:
- switch character only (e.g. use stdin for input) -o short (single character) -long long (multiple character, single switch character) --longer long (multiple character, multiple switch characters) word special word construed as an option, no switch characters - supports all types of arguments for options:
--option short/long option flag (no argument) --option ARG short/long option with separate required argument --option=ARG short/long option with combined required argument --option[=ARG] short/long option with combined optional argument -oARG short option with combined required argument -o[ARG] short option with combined optional argument - supports options with multiple or variable numbers of arguments:
--multi ARG1 ARG2 Multiple arguments --multi N ARG-1 ARG-2 ... ARG-N Variable number of arguments - supports an unlimited number of command-line arguments
- supports case-insensitive option matching on short, long and/or word arguments
- supports clumping of multiple short options in a string
foo.exe -defgcFILE == foo.exe -d -e -f -g -cFILE - automatic recognition of a single slash as equivalent to a single hyphen on Windows
foo.exe /f FILE == foo.exe -f FILE - file arguments can appear anywhere in the argument list
foo.exe FILE1 -a arg FILE2 --flag FILE3 FILE4 - file arguments (and optionally unknown arguments) will be returned to the application in the same order they were supplied on the command line
FILE1 FILE2 FILE3 FILE4 - short-circuit option matching: "--man" will match "--mandate" (see the section on short-circuit option matching below for details)
- invalid options can be handled while continuing to parse the command line
- valid options list can be changed dynamically during command line processing, i.e. accept different options depending on an option supplied earlier in the command line.
- implemented with only a single C++ header file
- optionally uses no C runtime or OS functions
- char, wchar_t and Windows TCHAR in the same program
- complete working examples included
- compiles cleanly at warning level 4 (Windows/VC.NET 2003), warning level 3 (Windows/VC6) and -Wall (Linux/gcc)
SimpleOpt Usage
The SimpleOpt class is used by following these steps:
- include the SimpleOpt.h header file
#include "SimpleOpt.h"
- define an array of valid options for your program.
In this code, OPT_* are identifiers that I have created to uniquely identify an option. The text is the literal text of an option. The SO_* values are flags specifying whether that option has arguments or not and how they should be formatted. Note that OPT_HELP is used twice, meaning that either "-?" or "--help" can be used to specify that option.
enum { OPT_HELP, OPT_FOO, OPT_BAR, OPT_HOGE }; CSimpleOpt::SOption g_rgOptions[] = { // ID TEXT TYPE { OPT_FOO, _T("-a"), SO_NONE }, // "-a" { OPT_BAR, _T("-b"), SO_NONE }, // "-b" { OPT_HOGE, _T("-f"), SO_REQ_SEP }, // "-f ARG" { OPT_HELP, _T("-?"), SO_NONE }, // "-?" { OPT_HELP, _T("--help"), SO_NONE }, // "--help" SO_END_OF_OPTIONS // END };Note that all options must start with a hyphen even if the slash will be accepted. This is because the slash character is automatically converted into a hyphen to test against the list of options. For example, the following line matches both "-?" and "/?" (on Windows).
{ OPT_HELP, _T("-?"), SO_NONE }, // "-?" - instantiate a CSimpleOpt object supplying argc, argv and the option table
CSimpleOpt args(argc, argv, g_rgOptions);
- process the arguments by calling Next() until it returns false. On each call, first check for an error by calling LastError(), then either handle the error or process the argument.
while (args.Next()) { if (args.LastError() == SO_SUCCESS) { // handle option, for example... // * OptionId() gets the identifier (i.e. OPT_HOGE) // * OptionText() gets the option text (i.e. "-f") // * OptionArg() gets the option argument (i.e. "/tmp/file.o") } else { // handle error (see the error codes - enum ESOError) } } - process all non-option arguments with File(), Files() and FileCount()
ShowFiles(args.FileCount(), args.Files());
SimpleGlob Usage
The SimpleGlob class is used by following these steps:
- include the SimpleGlob.h header file
#include "SimpleGlob.h"
- instantiate a CSimpleGlob object supplying the appropriate flags (see the header file for details)
CSimpleGlob glob(SG_GLOB_NODOT|SG_GLOB_NOCHECK);
- adding file specs with Add()
if (SG_SUCCESS != glob.Add(argc, argv)) { // handle error } - extract the file names using FileCount() and Files()
for (int n = 0; n < glob.FileCount(); ++n) { printf("file %d: '%s'\n", n, glob.File(n)); }
Examples
Basic usage of the SimpleOpt and SimpleGlob library is illustrated by the following code sample (included in the download as basicSample.cpp). This shows simple command line processing including the use of SimpleGlob to expand wildcard filenames passed on the command line.
#include "SimpleOpt.h" #include "SimpleGlob.h" // define the ID values to indentify the option enum { OPT_HELP, OPT_FLAG, OPT_ARG }; // declare a table of CSimpleOpt::SOption structures. See the SimpleOpt.h header // for details of each entry in this structure. In summary they are: // 1. ID for this option. This will be returned from OptionId() during processing. // It may be anything >= 0 and may contain duplicates. // 2. Option as it should be written on the command line // 3. Type of the option. See the header file for details of all possible types. // The SO_REQ_SEP type means an argument is required and must be supplied // separately, e.g. "-f FILE" // 4. The last entry must be SO_END_OF_OPTIONS. // CSimpleOpt::SOption g_rgOptions[] = { { OPT_FLAG, _T("-a"), SO_NONE }, // "-a" { OPT_FLAG, _T("-b"), SO_NONE }, // "-b" { OPT_ARG, _T("-f"), SO_REQ_SEP }, // "-f ARG" { OPT_HELP, _T("-?"), SO_NONE }, // "-?" { OPT_HELP, _T("--help"), SO_NONE }, // "--help" SO_END_OF_OPTIONS // END }; // show the usage of this program void ShowUsage() { _tprintf(_T("Usage: basicSample [-a] [-b] [-f FILE] [-?] [--help] FILES\n")); } int _tmain(int argc, TCHAR * argv[]) { // declare our options parser, pass in the arguments from main // as well as our array of valid options. CSimpleOpt args(argc, argv, g_rgOptions); // while there are arguments left to process while (args.Next()) { if (args.LastError() == SO_SUCCESS) { if (args.OptionId() == OPT_HELP) { ShowUsage(); return 0; } _tprintf(_T("Option, ID: %d, Text: '%s', Argument: '%s'\n"), args.OptionId(), args.OptionText(), args.OptionArg() ? args.OptionArg() : ""); } else { _tprintf(_T("Invalid argument: %s\n"), args.OptionText()); return 1; } } // process any files that were passed to us on the command line. // send them to the globber so that all wildcards are expanded // into valid filenames (e.g. *.cpp -> a.cpp, b.cpp, c.cpp, etc) // See the SimpleGlob.h header file for details of the flags. CSimpleGlob glob(SG_GLOB_NODOT|SG_GLOB_NOCHECK); if (SG_SUCCESS != glob.Add(args.FileCount(), args.Files())) { _tprintf(_T("Error while globbing files\n")); return 1; } // dump all of the details, the script that was passed on the // command line and the expanded file names for (int n = 0; n < glob.FileCount(); ++n) { _tprintf(_T("file %d: '%s'\n"), n, glob.File(n)); } return 0; }
Another included example 'fullSample.cpp' implements the following command line. This demonstrates all of the different types of arguments which can be parsed by SimpleOpt.
Usage: fullSample [OPTIONS] [FILES] --exact Disallow partial matching of option names --noslash Disallow use of slash as an option marker on Windows --shortarg Permit arguments on single letter options with no equals sign --clump Permit single char options to be clumped as long string --noerr Do not generate any errors for invalid options --pedantic Generate an error for petty things -d -e -f -g -flag --flag Flag (no arg) -s ARG -sep ARG --sep ARG Separate required arg -cARG -c=ARG -com=ARG --com=ARG Combined required arg -o[ARG] -o[=ARG] -opt[=ARG] --opt[=ARG] Combined optional arg -man -mandy -mandate Shortcut matching tests --man --mandy --mandate Shortcut matching tests --multi0 --multi1 ARG --multi2 ARG1 ARG2 Multiple argument tests --multi N ARG-1 ARG-2 ... ARG-N Multiple argument tests open read write close zip unzip Special words -? -h -help --help Output this help. If a FILE is `-', read standard input.
A third included example 'globSample.cpp' implements the a test program to test all of the flags supported by SimpleGlob.
Short-Circuit Option Matching (SimpleOpt)
The short-circuit matching of the long option names is enabled by default. It can be disabled by passing SO_O_EXACT as one of the flags to Init(). When disabled, only exact matches are accepted for options. When enabled, matches are calculated in the following manner.
- an exact match takes precedence over a partial match
- equal partial matches returns an "
SO_OPT_MULTIPLE" error - a better partial match will return the matched option
For example, if the command line has the following valid options:
--main--mainline--mainlamp
The following matches would occur:
| Commandline | Result | Why |
|---|---|---|
--mai | SO_OPT_MULTIPLE | multiple patial matches |
--main | --main | exact match |
--mainl | SO_OPT_MULTIPLE | multiple patial matches |
--mainli | --mainline | single partial match |
--mainline | --mainline | exact match |
Change History
3.6 (9 Mar 2013)
- Fix for issue invalid clumped option isn't returned by OptionText()
3.5 (17 Mar 2011)
- Added support for ICU supported UChar interface to SimpleGlob
3.4 (21 Nov 2008)
- Add the Stop() method to stop processing the command line and return all remaining arguments as files.
3.3 (22 Sep 2008)
- Prevent copying with private copy constructor and operator=
3.2 (10 Jul 2008)
- Fix for gcc warning about using constant strings with a non-const variable pointer.
3.1 (24 Apr 2008)
- Minor update pulling together the latest changes to the build system into a release. No code changes to either SimpleOpt or SimpleGlob but makes the building on Linux/Unix better.
3.0 (8 Nov 2007)
- Can now process unlimited number of arguments (using malloc/free), or for C lib free compilation it still supports a fixed maximum. Default is now to use C lib and provide unlimited argc processing. Note: a stack array is still used for small numbers of argc (currently 50).
2.9 (6 Sep 2007)
- Added options for case-insensitive matching on short, long and word arguments
2.8 (23 June 2007) Note: re-uploaded version 2.8
- Fixed compile error with gcc 4
2.8 (21 June 2007)
- Fixed a warning with gcc 3.4.6 so that the '-fpermissive' compiler option is not required
- Added support for multiple and variable numbers of arguments per option (new argument type: SO_MULTI)
- Don't return an error when a combined argument is supplied for an argument marked as separated unless the SO_O_PEDANTIC flag is set
- Return an error when an argument to an option looks like an option itself (e.g. --option --not-argument). This can be disabled by using SO_O_NOERR flag.
- Added automated testing harness for regression testing (more tests are welcome)
2.7 (4 June 2007)
Fixed a number of bugs with SimpleOpt involving combined arguments. Added ability to combine clumped and short options with required combined args, e.g. "-defgcARG" == "-d -e -f -g -c=ARG"
2.6 (21 May 2007)
Fixed small bug in glob with reserved slots. Obviously no-one has been using the Unix version of glob as it was wildly broken but is now fully repaired and working.
2.5 (19 May 2007)
Fixed some bugs in glob in the new prefix code. General code cleanup.
2.4 (10 May 2007)
Fixed a bug in glob so that wildcards with a prefixed path will keep the path prefix when they are expanded. i.e. "../foo.*" will expand to "../foo.cpp" instead of "foo.cpp" which it was incorrectly returning previously.
2.3 (25 January 2007)
Replaced glob implementation on Unix with the same implementation as on Windows to ensure greater support and consistency between results. Fixed build warnings on VC2005 and gcc.
(14 August 2006) Re-released under the MIT Licence to simplify licence issues
2.2 (11 July 2006)
Add debug mode checking of the option array to ensure that there are no options using a slash for the option character (all options must be defined using a hyphen).
2.1 (25 May 2006)
Major rewrite with change in interface. Support general keywords without switch characters. Support long options without requiring double switch characters. Support processing of entire argv array. Support clumping of single character options together.
1.5 (22 May 2006)
Add support for slash options on Windows. Fix bug with fuzzy matching of long option strings.