source: trunk/gui/scripts/getopts.tcl @ 2035

Last change on this file since 2035 was 1914, checked in by dkearney, 14 years ago

updating getopts to handle cases where you have extra -'d arguments after a list argument.

Example:
in your tcl file if you specify an flags like:

proc fxn {args} {

Rappture::getopts args params {

list -tests "all"
list -dirs "."

}

...

and call your function like this:

fxn -tests a b c -dirs d e

in previouse versions of getopts, $params(-tests) would have the list
a b c -dirs d e
and $params(-dirs) would have the default value "."

in the new version of getopts, $params(-tests) should have the list
a b c
and $params(-dirs) should have the list
d e

this feature is used in hubchecki::runTests

File size: 5.4 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: getopts - simple argument parser
3#
4#  This utility makes it easy to process arguments for various
5#  commands.  You give a description of arguments, and it will
6#  parse and return the values.
7#
8#    getopts args params {
9#        value -foo foo_default
10#        flag group -bar default
11#        flag group -baz
12#    }
13#
14#  Note that both args and params are passed by name, not by
15#  value (not $args or $params).  This function initializes the
16#  params variable according to the values in the spec list.
17#  It then loops through all args, matching as many as possible
18#  from the list.  It throws an error on the first error
19#  encountered.  If there are extra arguments that don't match
20#  the flags and don't start with -, they are left in args, and
21#  processing stops.
22#
23# ======================================================================
24#  AUTHOR:  Michael McLennan, Purdue University
25#  Copyright (c) 2004-2005  Purdue Research Foundation
26#
27#  See the file "license.terms" for information on usage and
28#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
29# ======================================================================
30namespace eval Rappture { # forward declaration }
31
32# ----------------------------------------------------------------------
33# USAGE: getopts <listvar> <returnvar> <spec>
34#
35# Processes options in <listvar>, storing results in <returnvar>.
36# Throws an exception if an error is encountered.  Leaves any remaining
37# arguments (after flags) in <listvar>.
38# ----------------------------------------------------------------------
39proc Rappture::getopts {listVar returnVar spec} {
40    upvar $listVar args
41    upvar $returnVar params
42    catch {unset params}
43    set opts ""
44
45    #
46    # Pick apart the info in the <spec> and set up flags/params
47    #
48    foreach line [split $spec \n] {
49        if {[llength $line] == 0} {
50            continue  ;# ignore blank lines
51        }
52
53        set type [lindex $line 0]
54        switch -- $type {
55            value {
56                if {[llength $line] < 3} {
57                    error "bad value spec \"$line\": should be \"value -flag default\""
58                }
59                set name [lindex $line 1]
60                set flags($name) $type
61                set params($name) [lindex $line 2]
62                lappend opts $name
63            }
64            flag {
65                if {[llength $line] < 3 || [llength $line] > 4} {
66                    error "bad value spec \"$line\": should be \"flag group -flag ?default?\""
67                }
68                set group [lindex $line 1]
69                set name [lindex $line 2]
70                set flags($name) [list $type $group]
71                if {[llength $line] > 3} {
72                    set params($group) $name
73                    set params($name) 1
74                } else {
75                    if {![info exists params($group)]} {
76                        set params($group) ""
77                    }
78                    set params($name) 0
79                }
80                lappend opts $name
81            }
82            list {
83                if {[llength $line] < 3} {
84                    error "bad value spec \"$line\": should be \"list -flag default\""
85                }
86                set name [lindex $line 1]
87                set flags($name) $type
88                set params($name) [lindex $line 2]
89                lappend opts $name
90            }
91            default {
92                error "bad arg type \"$type\": should be flag or value"
93            }
94        }
95    }
96
97    #
98    # Now, walk through the values in $args and extract parameters.
99    #
100    while {[llength $args] > 0} {
101        set first [lindex $args 0]
102        if {[string index $first 0] != "-"} {
103            break
104        }
105        if {"--" == $first} {
106            set args [lrange $args 1 end]
107            break
108        }
109        if {![info exists params($first)]} {
110            error "bad option \"$first\": should be [join [lsort $opts] {, }]"
111        }
112        switch -- [lindex $flags($first) 0] {
113            value {
114                if {[llength $args] < 2} {
115                    error "missing value for option $first"
116                }
117                set params($first) [lindex $args 1]
118                set args [lrange $args 2 end]
119            }
120            flag {
121                set group [lindex $flags($first) 1]
122                set params($group) $first
123                set params($first) 1
124                set args [lrange $args 1 end]
125            }
126            list {
127                if {[llength $args] < 2} {
128                    error "missing value for option $first"
129                }
130                foreach arg [lrange $args 1 end] {
131                    if {[string index $arg 0] == "-"} {
132                        break
133                    }
134                }
135                set idx [lsearch -exact $args $arg]
136                if {$idx == [expr [llength $args] - 1]} {
137                    # reached the end of the $args list
138                    # with no other -'d arguments
139                    set params($first) [lrange $args 1 end]
140                    set args ""
141                } else {
142                    # there are further -'d arguments to process
143                    set params($first) [lrange $args 1 [expr $idx-1]]
144                    set args [lrange $args $idx end]
145                }
146            }
147        }
148    }
149    return ""
150}
Note: See TracBrowser for help on using the repository browser.