expandOpts

## ******************************************************** 
##
## Name: expandOpts 
##
## Description:
## Expands procedure options.  See example and test cases
## below.
##
## Comments:
## Ambiguous options throw exception.

proc expandOpts {{opts "opts"}} {
    set options {}
    set matches {}
    set inputs [uplevel set args]
    regsub -all -- {\n\s+} $inputs { } inputs
    regexp {^\{(.+)\}$} $inputs -> inputs
    ;## get defaults
    set defaults [uplevel subst \$$opts]
    regsub -all -- {\n\s+} $defaults { } defaults
     
    foreach {opt def} $defaults {
        set opt [string trim $opt]
        set def [string trim $def] 
        
        set matched 0

        foreach {name val} $inputs {
            set name [string trim $name]
            regsub -- {[-]+} $name "-" name
            set val [string trim $val]
           
            if {[regexp -nocase -- $name $opt]} {
                ;## next test fails if ambiguous item is last
                ;## option on command line...
                if {[lsearch -exact $matches $name] > -1} {
                    return -code error "ambiguous option: $name"
                }
              
                lappend matches $name
                set options [concat $options [list $opt $val]]
                set matched 1
                break
            }
        }
        if {$matched == 0} {
            set options [concat $options [list $opt $def]]
        }
    }   
    return $options
}
## ******************************************************** 
## ******************************************************** 
##
## Usage example and test function

proc test { args } {
    set opts {
        -this "$something"
        -that "hostname: $::env(HOST)"
        -those { 0.1 2.0 -1.2 12-43 }
        -them  {}
        -these "foo*!{}icky-blat xx -1"
        -the-others .......
    }
    set something foo!
    array set foo [ expandOpts ]
    puts [ array get foo ]
}
## ******************************************************** 

test -that "whaaaa?? {} foo x-m" -them "1 2 -3" -the-o {}
test -them "1 2 -3" -that "whaaaa?? {} foo x-m" -the oops! -the-o {}