'''command options''' are ever-present in Tcl scripts. This page presents various approaches to processing them. ** See Also ** [category Argument Processing]: [Syntax parsing in Tcl]: [Tcl syntax]: [Argument Parsing, a discussion]: ** Description ** suggests several distinct topics: * tclsh and wish arguments * command-line options (as seen through $::argv) of Tcl-coded applications * idioms for parsing variable (args) arguments seen by pure-Tcl [proc]s. Certain considerations are common to all these, and are convenient to treat here in a unified way. ** Option Parsing for Tcl Commands ** [http://openacs.org/api-doc/proc-view?proc=ad_proc%|%ad_proc]: [alternative getopt]: by [sbron] [argument processing for Tcl (Lehenbauer)]: Tk-like argument processing for Tcl procs. [argument parsing with defaults (Wagner)]: Only available by contacting the author directly. see [theObjects] for a C version, which is available for download [argument processing (Zimmer)]: [aqtools]: includes an ... [[?]] package for argument parsing [argp]: simple and flexible arg parsing for Tcl [Better getopt]: Compatible with getopt_long_only(3) [http://wi-fizzle.com/clig/%|%clig]: written in Tcl, generates interpreters for both standalone programs and Tcl commands [cmdline] in [tcllib]: probably the most standard and widely-used of these packages [http://core.tcl.tk/akupries/cmdr/index%|%cmdr], by [AK]: a framework for command-line parsing and dispatch. Presented at the [Twentieth Annual Tcl/Tk Conference (2013)] [ftp://ftp.lehigh.edu/pub/evap/Announce%|%Evaluate Parameters 2.4]: for [C], [Perl], and [Tcl] [Extral]'s args_parse, cmd_parse, and so on: [getopt], by [RS]: light-weight, of course [GetOpt-ish] by [FF]: getopt-like tool [http://groups.google.com/d/msg/comp.lang.tcl/4YPkcMyFgy4/KcrGjaFviD0J%|%groom: a simple getopt: calling Tcl procs with options], Doug Simpson, 2001-09-04: [init], by [Larry Smith]: parses a command's arguments and also initialises local variables. [Matthias Hoffmann - Tcl-Code-Snippets - misc routines - command line parsing]: another simple command line parsing routine in a few lines of tcl, with integrated help support [mkextensions], by [Michael Kraus]: includes mkGeneric::options, a simple but efficient option-processing routine. [Named arguments], by [RS]: [named parameters]: A simple approach that allows positional arguments followed by key-value pairs. [Octopus package for parsing command line options for procedures/scripts]: [opt]: deprecated [optparse], by [Laurent Demailly]: deprecated ''optional arguments'', in [Tcl Gems]: illustrates the use of [Arrays / Hash Maps%|%arrays] to do simple argument parsing [Options and Arguments], by [aspect]: [option parsing using ensemble], by [Lars H]: uses the [namespace ensemble] mechanism to to handle options [ParseArgs], circa 1996: Utility library for parsing command line arguments in various languages (including Tcl) and on various hardware platforms [parse_args]: A fast C-based argument parser from [RubyLane]. [procargs], by [JBR]: [http://jazimmer.com/tclbook/tcl/examples/html/zproc_usage.html%|%Procedure for Extracting Options and Switches], by J Adrian Zimmer, 1988: [Simple way to parse command options], by [FabricioRocha%|%Fabricio Rocha]: provides '''optionscheck''', which verifies the formatting of a traditional options list like `-option1 value1 -option2 value2 ...`. Intended for being used in megawidgets and customized commands, the procedure finds unknown options, values without preceding options, options without a value assigned to them. It returns a dict containing all those cases above along with the valid option/value pairs, and can generate errors in such cases or work silently. [SNTL], by [Sam Shen]: contains code for command line argument processing as well as many other items. [ftp://ftp.tcl.tk/pub/tcl/all/t/tclGetOpts/1.1/tclGetOpts1.1.tar.gz%|%TclGetOpts]: mildly buggy Tcl_ParseArgsObjv: parsing of C implemented Tcl commands using the object interface. (See example below.) [tepam], or ''Tcl's Enhanced Procedure Argument Manager'': a component of [tcllib] [Option Parsing for Tcl Commands - tgetopt]: [TWAPI]: provides [http://twapi.sourceforge.net/misc.html#parseargs%|%parseargs] for flexible argument parsing. This is implemented in C and is therefore fast enough to be used for argument parsing in any proc. Some of the Tcl based parsers are slow enough that they impose a significant performance penalty if used for general proc arg processing as opposed to just dealing with command line options where performance of course does not matter. [The Simple Development Library]: includes both [http://simpledevlib.sourceforge.net/SimpleProc.html%|%SimpleProc], a package for command arguments handling including typed arguments, with optional run-time checking, and options [http://simpledevlib.sourceforge.net/SimpleOption.html%|%SimpleOption], a very powerful command options parser with too many features to list here [yaap - Yet Another Argument Parsing utility]: a template-based argument parsing utility inspired by `XtGetApplicationResources()` `[ycl] proc checkargs`: Like [tepam], but weaves documentation and code together in a [Literate Programming] style, providing a versatile argument specification system as well as argument validation and inter-argument validation. Both positional and key-value arguments can be fully specified and processed. Additional features include a docstring-like characteristic, default argument values, configurable collector variable for unrecognized values, inline argument transformers, specifcation of mandatory vs optional arguments, configurable end-of-arguments indicator, ability to specify whether multiple occurrences of an argument are collected into a list or simply replace earlier values, as well as minimum and maximimum limits on the number of occurrences of each argument. It's also possible to reuse all or part of the argument specifications of other procs, mixing and matching as required. It's urrently somewhat slow, but its performance should improve over time. ** System Command Line ** [ftp://ftp.lehigh.edu/pub/evap/Announce%|%Evaluate Parameters 2.4]: for [C], [Perl], and [Tcl] ** A "Standard" Template ** The following example can be used as a template for processing arguments in the way that is fairly standard for [Tcl Commands%|%built-in] commands: ====== # If this script was executed, and not just "source"'d, handle argv if {[info exists argv0] && [ file dirname [file normalize [info script]/...]] eq [ file dirname [file normalize $argv0/...]]} { while {[llength $argv]} { puts [list ooo $argv] set argv [lassign $argv[set argv {}] flag] switch -glob $flag { -bool { set bool 1 } -option { set argv [lassign $argv[set argv {}] value] } -- break -* { return -code error [list {unknown option} $flag] } default { set argv [list $flag {*}$argv] break } } } } foreach file $argv { puts [format "file: %s" $file] } ====== ---- PT writes: I like to use code similar to the above example for option processing. However, we want to avoid 'shimmering' the args list into a string and back into a list. Plus I find it repetitive to keep writing the same two lines for setting the option value. Here is my current example: ====== # ------------------------------------------------------------------------- # Description: # Pop the nth element off a list. Used in options processing. # proc dns::Pop {varname {nth 0}} { upvar $varname args set r [lindex $args $nth] set args [lreplace $args $nth $nth] return $r } # --------------------------------------------------------------------- # Now the option processing loop. Eats the arguments once handled and stops at '--' # setup the defaults. array set opts {-a 1 -b 0} while {[string match -* [lindex $args 0]]} { switch -glob [lindex $args 0] { -A* -a* { set opts(-a) [Pop args 1] } -b* { set opts(-b) [Pop args 1] } -- { Pop args ; break } default { set opts [join [lsort [array names state -*]] ", "] return -code error "bad option [lindex $args 0]: \ must be one of $opts" } } Pop args } puts "Options now [array get opts] and the remaining args: $args" ====== [PYK] 2016-02-04: As far as I can tell, neither the original code, nor the modified version I'm providing with this edit, cause `$argv` to shimmer, so I plan to delete the portion of the statement above, by [PT], to that effect. ---- [SB] 2003-05-21: For many of my tcl utilities I have only vanilla tclsh but still need to parse command line options. As I mostly use the tools myself I don't need too much fancy error detection. For a small application, I need a couple of switches, one with an argument and then the file to process. Nothing fancy, but it is written in a matter of seconds, and it is fairly easy to extend with more switches. ====== set arglen [llength $argv] set index 0 while {$index < $arglen} { set arg [lindex $argv $index] switch -exact $arg { -s { set args($arg) [lindex $argv [incr index]] } -l { set args($arg) . } default { set filename [lindex $argv $index] } } incr index } if {[info exists args(-l)]} { puts "-l switch set" ... code what happens for -l } if {[info exists args(-s)]} { puts "-s switch set with arg $args(-s)" ... code what happens for -s and its arg } ====== ** The Key/Value Approach ** See [named parameters] ** Discussion ** <> Question: In C, for Tcl, using the newer objc, objv API, how do I parse options? I would have thought people would need to do this all the time, but I can't find anything. Needs to handle args, options, required optional etc. Speed is high on the priority list... If you can use the Tk library, try `Tk_SetOptions` and its assorted support functions. It would be nice if something like this were in the Tcl library, for those times when one doesn't have Tk around. A pure-Tcl solution might be to do the option handling in Tcl, passing a fixed number of arguments to the C code, but that might not meet your speed requirements. [SPB]: I've modified the `Tk_ParseArgv()` routine in tkArg.[[hc] to handle this case. Also, to make it even more useful, I added a `Tcl_ParseArgsObjv` for parsing a bunch of arguments passed to a C-implemented Tcl command. For example, you can do something like: ======c #include #include #include #include #include int mycoolcommand(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int mytoggle=0; int myint=-2; Tcl_ArgvInfo argTable[] = { {"-toggle",TCL_ARGV_CONSTANT,(void*)1,&mytoggle,"turn toggle on"}, {"-theint",TCL_ARGV_INT,NULL,&myint,"set myint"}, {(char*)NULL,TCL_ARGV_END,NULL,NULL,(char*)NULL} }; Tcl_Obj **private_objv=(Tcl_Obj**)calloc(objc+1,sizeof(Tcl_Obj*)); int i; for (i=0;iargstest.tcl "KEY ValueKey1" "KEY2 ValueKey2" ;# typed on command line {KEY1 ValueKey1} {KEY2 ValueKey2} ;# argv as received by the tcl script {{KEY1 ValueKey1} {KEY2 ValueKey2}} ;# argv as received by proc parseargs ValueKey1 ;# value of the key KEY1 ====== [PYK] 2015-10-20: That approach bundles a key and a value into a single argument, which can lead to quoting issues between the system shell and the Tcl interpreter. Better to treat `$argv` as a sequence of key-value pairs: ====== proc main {$argv0 $argv} { dict update $argv KEY KEY KEY2 KEY2 {} ... } main $argv0 $argv ====== ---- '''[tarzan] - 2017-05-04 08:31:38''' TclArgv on https://github.com/sbromle/TclArgv%|%github%|% <> Argument Processing | Arts and crafts of Tcl-Tk programming