[sbron] 7-Dec-2008: There are several pieces of code available (on the wiki, in [tcllib]) for parsing command lines, but they all feel a little awkward to me. For that reason I came up with the code below. It allows the user to specify the allowed command line options in a similar fashion as the [switch] command. Only in this case there's an implied loop that repeats as long as command line options are available. The switch patterns also serve as the specification of which command line options exist. Command line options can have two forms: long options and short options. Long options start with -- and may be specified as an unambiguous prefix. Short options start with just a single -. Multiple short options without arguments may be specified as a single string of option characters prefixed with a -. If one of the characters represents an option that requires an argument, the rest of the string is taken as the argument. At the end the ''arglist'' branch is executed with the arguments remaining after all options have been processed. It will do this even if there are no remaining arguments. Two other special branches are available for handling invalid options: ''missing'' and ''unknown''. An example of how this proc can be used: getopt flag arg $argv { -h? - --help { # The user wants some help help } -v { # Increase the verbosity level incr verbosity } --verbose: { # Set the verbosity level set verbosity $arg } --version { # Report the version of the program puts "Version: $version" exit 0 } -ptrb:g: { # Various other options set option($flag) $arg } missing { puts stderr "option requires argument: $arg" exit 2 } unknown { puts stderr "unknown or ambiguous option: $arg" exit 2 } arglist { set files $arg } } In the above example, if an option --ver is passed it will be flagged as ambiguous. But --vers will report the version of the program. And here's the code: proc getopt {optvar argvar list body} { upvar 1 $optvar option $argvar value set arg(missing) [dict create pattern missing argument 0] set arg(unknown) [dict create pattern unknown argument 0] foreach {pat code} $body { switch -glob -- $pat { -- {# end-of-options option} --?*: {# long option requiring an argument set arg([string range $pat 0 end-1]) \ [dict create pattern $pat argument 1] } --?* {# long option without an argument set arg($pat) [dict create pattern $pat argument 0] } -?* {# short options set last ""; foreach c [split [string range $pat 1 end] ""] { if {$c eq ":" && $last ne ""} { dict set arg($last) argument 1 set last "" } else { set arg(-$c) [dict create pattern $pat argument 0] set last -$c } } } } } while {[llength $list]} { set rest [lassign $list opt] # Does it look like an option? if {$opt eq "-" || [string index $opt 0] ne "-"} break # Is it the end-of-options option? if {$opt eq "--"} {set list $rest; break} set option [string range $opt 0 1] set value 1 if {$option eq "--"} { # Long format option if {[info exists arg($opt)]} { set option $opt } elseif {[llength [set match [array names arg $opt*]]] == 1} { set option [lindex $match 0] } else { # Unknown or ambiguous option set value $opt set option unknown } if {[dict get $arg($option) argument]} { if {[llength $rest]} { set rest [lassign $rest value] } else { set value $option set option missing } } } elseif {![info exists arg($option)]} { set value $option set option unknown if {[string length $opt] > 2} { set rest [lreplace $list 0 0 [string replace $opt 1 1]] } } elseif {[dict get $arg($option) argument]} { if {[string length $opt] > 2} { set value [string range $opt 2 end] } elseif {[llength $rest]} { set rest [lassign $rest value] } else { set value $option set option missing } } elseif {[string length $opt] > 2} { set rest [lreplace $list 0 0 [string replace $opt 1 1]] } uplevel 1 [list switch -- [dict get $arg($option) pattern] $body] set list $rest } set option arglist set value $list uplevel 1 [list switch -- arglist $body] } ---- !!!!!! %| enter categories here |% !!!!!!