how to create tcl proc with hyphen flag arguments

2020-02-06 10:45发布

问题:

Im searching all over the internet , i guess im searching not the right keywords i tried most of them :)

i want to create in tcl/bash a proc with hyphen flags to get arguments with flags from the user

ex.

proc_name -color red -somethingselse black

回答1:

It's very easy to do, actually. This code allows abbreviated option names, flag options (-quxwoo in the example) and the ability to stop reading options either with a -- token or with a non-option argument appearing. In the example, unknown option names raise errors. After passing the option-parsing loop, args contains the remaining command-line arguments (not including the -- token if it was used).

proc foo args {
    array set options {-bargle {} -bazout vampires -quxwoo 0}
    while {[llength $args]} {
        switch -glob -- [lindex $args 0] {
            -bar*   {set args [lassign $args - options(-bargle)]}
            -baz*   {set args [lassign $args - options(-bazout)]}
            -qux*   {set options(-quxwoo) 1 ; set args [lrange $args 1 end]}
            --      {set args [lrange $args 1 end] ; break}
            -*      {error "unknown option [lindex $args 0]"}
            default break
        }
    }
    puts "options: [array get options]"
    puts "other args: $args"
}

foo -barg 94 -quxwoo -- abc def
# => options: -quxwoo 1 -bazout vampires -bargle 94
# => other args: abc def

This is how it works. First set default values for the options:

array set options {-bargle {} -bazout vampires -quxwoo 0}

Then enter a loop that processes the arguments, if there are any (left).

while {[llength $args]} {

During each iteration, look at the first element in the argument list:

switch -glob -- [lindex $args 0] {

String-match ("glob") matching is used to make it possible to have abbreviated option names.

If a value option is found, use lassign to copy the value to the corresponding member of the options array and to remove the first two elements in the argument list.

-bar*   {set args [lassign $args - options(-bargle)]}

If a flag option is found, set the corresponding member of the options array to 1 and remove the first element in the argument list.

-qux*   {set options(-quxwoo) 1 ; set args [lrange $args 1 end]}

If the special -- token is found, remove it from the argument list and exit the option-processing loop.

--      {set args [lrange $args 1 end] ; break}

If an option name is found that hasn't already been dealt with, raise an error.

-*      {error "unknown option [lindex $args 0]"}

If the first argument doesn't match any of the above, we seem to have run out of option arguments: just exit the loop.

default break

Documentation: array, break, error, lassign, lindex, llength, proc, puts, set, switch, while



回答2:

With array set, we can assign the parameters and their values into an array.

proc getInfo {args} {
    # Assigning key-value pair into array
    # If odd number of arguments passed, then it should throw error
    if {[catch {array set aInfo $args} msg]} {
        return $msg
    }
    parray aInfo; # Just printing for your info
}


puts [getInfo -name Dinesh -age 25 -id 974155]

will produce the following output

aInfo(-age)  = 25
aInfo(-id)   = 974155
aInfo(-name) = Dinesh


回答3:

The usual way to handle this in Tcl is by slurping the values into an array or dictionary and then picking them out of that. It doesn't offer the greatest amount of error checking, but it's so easy to get working.

proc myExample args {
    # Set the defaults
    array set options {-foo 0 -bar "xyz"}
    # Read in the arguments
    array set options $args
    # Use them
    puts "the foo option is $options(-foo) and the bar option is $options(-bar)"
}

myExample -bar abc -foo [expr {1+2+3}]
# the foo option is 6 and the bar option is abc

Doing error checking takes more effort. Here's a simple version

proc myExample args {
    array set options {-foo 0 -bar "xyz"}
    if {[llength $args] & 1} {
        return -code error "must have even number of arguments in opt/val pairs"
    }
    foreach {opt val} $args {
        if {![info exist options($opt)]} {
            return -code error "unknown option \"$opt\""
        }
        set options($opt) $val
    }
    # As before...
    puts "the foo option is $options(-foo) and the bar option is $options(-bar)"
}

myExample -bar abc -foo [expr {1+2+3}]
# the foo option is 6 and the bar option is abc

# And here are the errors it spits out...
myExample -spregr sgkjfd
# unknown option "-spregr"
myExample -foo
# must have even number of arguments in opt/val pairs


标签: tcl