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

Last change on this file since 3582 was 3330, checked in by gah, 12 years ago

merge (by hand) with Rappture1.2 branch

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