append errmsg "(additional error in punk::args::arg_error when attempting to display usage)" \n
append errmsg "$errM" \n
append errmsg "$::errorInfo"
}
} else {
#todo - something boring
}
error $errmsg
}
#generally we expect values to contain leading dashes only if -- specified. Otherwise no reliable way determine difference between bad flags and values
#If no eopts (--) specified we stop looking for opts at the first nondash encountered in a position we'd expect a dash - so without eopt, values could contain dashes - but not in first position after flags.
#we can't treat as first positional arg - as it comes before the eopt indicator --
arg_error "punk::args::get_dict bad options for [Get_caller]. Expected flag (leading -) at position $i got:$rawargs" $argspecs
}
#TODO!
if {[tcl::dict::get $arg_info $a -type] ne "none"} {
if {[incr i] > $maxidx} {
arg_error "punk::args::get_dict bad options for [Get_caller]. No value supplied for last option $a which is not marked with -solo 1" $argspecs $a
if {![catch {tcl::prefix match -message "options for %caller%. Unexpected option" $opt_names $a } fullopt]} {
if {[tcl::dict::get $arg_info $fullopt -type] ne "none"} {
#non-solo
set flagval [lindex $arglist $i+1]
if {[dict get $arg_info $fullopt -multiple]} {
#don't lappend to default - we need to replace if there is a default
#review - what if user sets first value that happens to match a default?
if {$fullopt ni $flagsreceived && [tcl::dict::exists $opt_defaults $fullopt] && ([tcl::dict::get $opt_defaults $fullopt] eq [tcl::dict::get $opts $fullopt])} {
#first occurrence of this flag, whilst stored value matches default
tcl::dict::set opts $fullopt $flagval
} else {
tcl::dict::lappend opts $fullopt $flagval
}
} else {
tcl::dict::set opts $fullopt $flagval
}
#incr i to skip flagval
if {[incr i] > $maxidx} {
arg_error "punk::args::get_dict bad options for [Get_caller]. No value supplied for last option $fullopt at index [expr {$i-1}] which is not marked with -type none" $argspecs $fullopt
}
} else {
#type none (solo-flag)
if {[tcl::dict::get $arg_info $fullopt -multiple]} {
if {[tcl::dict::get $opts $fullopt] == 0} {
#review - what if default at time opt was specified is not zero? we will end up with more items in the list than the number of times the flag was specified
tcl::dict::set opts $fullopt 1
} else {
tcl::dict::lappend opts $fullopt 1
}
} else {
tcl::dict::set opts $fullopt 1
}
}
lappend flagsreceived $fullopt ;#dups ok
} else {
if {$opt_any} {
set newval [lindex $arglist $i+1]
#opt was unspecified but is allowed due to *opt -any 1 - 'adhoc/passthrough' option
tcl::dict::set arg_info $a $optspec_defaults ;#use default settings for unspecified opt
tcl::dict::set arg_checks $a $opt_checks_defaults
if {[tcl::dict::get $arg_info $a -type] ne "none"} {
if {[tcl::dict::get $arg_info $a -multiple]} {
tcl::dict::lappend opts $a $newval
} else {
tcl::dict::set opts $a $newval
}
lappend flagsreceived $a ;#adhoc flag as supplied
if {[incr i] > $maxidx} {
arg_error "punk::args::get_dict bad options for [Get_caller]. No value supplied for last adhoc option $a at index [expr {$i-1}] which is not marked with -type none" $argspecs $a
}
} else {
#review -we can't provide a way to allow unspecified -type none flags through reliably/unambiguously unless all remaining unspecified options are -type none
if {[tcl::dict::get $arg_info $a -multiple]} {
if {![tcl::dict::exists $opts $a]} {
tcl::dict::set opts $a 1
} else {
tcl::dict::lappend opts $a 1
}
} else {
tcl::dict::set opts $a 1
}
}
} else {
#delay Get_caller so only called in the unhappy path
set errmsg [tcl::string::map [list %caller% [Get_caller]] $fullopt]
#we want defaults to pass through - even if they don't pass the checks that would be required for a specified value
#If the caller manually specified a value that happens to match the default - we don't detect that as any different from an unspecified value - Review.
#arguments that are at their default are not subject to type and other checks
set globsearches [dict get $argd values globsearches]; #note that in this case our globsearch won't reduce the machine's effort in scannning the filesystem - as we need to search on the renamed results