@ -979,7 +979,9 @@ tcl::namespace::eval punk::args {
# -arg -choices {${$DYN_CHOICES}} -help "${$RED}important info${$RST}"
#}
if {$defspace ne ""} {
set optionspecs [namespace eval $defspace [list punk::args::lib::tstr -return string -eval 1 -allowcommands $optionspecs]]
#set optionspecs [namespace eval $defspace [list punk::args::lib::tstr -return string -eval 1 -allowcommands $optionspecs]]
#JJJ - review
set optionspecs [namespace eval $defspace [list punk::args::lib::tstr -return string -eval 1 -allowcommands -paramindents none $optionspecs]]
}
#REVIEW - join also serves to unescape things such as \$\{$x\} \$\{[cmd]\} without subst'ing or evaling (?)
if {[string first \$\{ $optionspecs] > 0} {
@ -2017,6 +2019,8 @@ tcl::namespace::eval punk::args {
}
ansi - ansistring {set normtype ansistring}
string - globstring {set normtype $lc_firstword}
packageversion {set normtype packageversion}
packagerequirement {set normtype packagerequirement}
literal {
#value was split out by _split_type_expression
set normtype literal([lindex $alt 1])
@ -2390,8 +2394,13 @@ tcl::namespace::eval punk::args {
as these arguments are already fully spec'd. The defaults from the
source can be removed by adding @leaders, @opts @values to the
-antiglobs list, but again - this won't affect the existing arguments.
Each argument can have members of its spec overridden using the
-override dictionary.
-override dictionary The members of each override sub dictionary are
usually options beginning with a dash. The key 'name' can be used to
override the name of the leader/option/value itself.
e.g
punk::args::resolved_def -types values -override {version {name version1 -optional 0}} (shared)::package version
"
@leaders -min 0 -max 0
@opts
@ -2608,8 +2617,9 @@ tcl::namespace::eval punk::args {
if {[dict get $argspec -ARGTYPE] eq $tp} {
set argspec [dict remove $argspec -ARGTYPE]
if {[dict exists $opt_override $m]} {
append result \n "\"$m\" [dict merge $argspec [dict get $opt_override $m]]"
dict set resultdict $m [dict merge $argspec [dict get $opt_override $m]]
set overdict [dict get $opt_override $m]
append result \n "\"$m\" [dict merge $argspec $overdict]"
dict set resultdict $m [dict merge $argspec $overdict]
} else {
append result \n "\"$m\" $argspec"
dict set resultdict $m $argspec
@ -2670,8 +2680,19 @@ tcl::namespace::eval punk::args {
if {[dict get $argspec -ARGTYPE] eq [dict get $argtypes $type]} {
set argspec [dict remove $argspec -ARGTYPE]
if {[dict exists $opt_override $m]} {
append result \n "\"$m\" [dict merge $argspec [dict get $opt_override $m]]"
dict set resultdict $m [dict merge $argspec [dict get $opt_override $m]]
set overdict [dict get $opt_override $m]
if {[dict exists $opt_override $m name]} {
#special override for name of argument itself
#e.g
#punk::args::resolved_def -types values -override {version {name version1 -optional 1}} (shared)::package version
set newname [dict get $opt_override $m name]
dict unset overdict name
append result \n "\"$newname\" [dict merge $argspec $overdict]"
dict set resultdict $newname [dict merge $argspec $overdict]
} else {
append result \n "\"$m\" [dict merge $argspec $overdict]"
dict set resultdict $m [dict merge $argspec $overdict]
}
} else {
append result \n "\"$m\" $argspec"
dict set resultdict $m $argspec
@ -3501,6 +3522,9 @@ tcl::namespace::eval punk::args {
set docname [Dict_getdef $spec_dict doc_info -name "Manual:"]
set docurl [Dict_getdef $spec_dict doc_info -url ""]
#set example [Dict_getdef $spec_dict examples_info -help ""]
set has_example [dict exists $spec_dict examples_info -help]
#review - when can there be more than one selected form?
set argdisplay_header ""
set argdisplay_body ""
@ -3546,6 +3570,12 @@ tcl::namespace::eval punk::args {
} else {
set docurl_display ""
}
if {$has_example} {
lappend blank_header_col ""
set example_display "[a+ white]eg [dict get $spec_dict id]$RST"
} else {
set example_display ""
}
#synopsis
set synopsis "# [Dict_getdef $spec_dict cmd_info -summary {}]\n"
set form_info [dict get $spec_dict form_info]
@ -3624,6 +3654,14 @@ tcl::namespace::eval punk::args {
}
incr h
}
if {$has_example} {
if {$use_table} {
$t configure_header $h -colspans $arg_colspans -values [list Example: $example_display]
} else {
lappend errlines "Example: $docurl_display"
}
incr h
}
if {$synopsis ne ""} {
if {$use_table} {
$t configure_header $h -colspans $arg_colspans -values [list Synopsis: [punk::ansi::ansiwrap brightwhite $synopsis]]
@ -5807,6 +5845,49 @@ tcl::namespace::eval punk::args {
break
}
}
packageversion {
if {[catch {::package vsatisfies $e_check $e_check}]} {
set msg "$argclass $argname for %caller% requires type packageversion. A package version number as understood by 'package vsatifies'. Received: '$e_check'"
lset clause_results $c_idx $a_idx [list errorcode [list PUNKARGS VALIDATION [list typemismatch $type] -badarg $argname -argspecs $argspecs] msg $msg]
} else {
lset clause_results $c_idx $a_idx 1
break
}
}
packagerequirement {
set parts [split $e_check -]
if {[llength $parts] > 2} {
set msg "$argclass $argname for %caller% requires type packagerequirement. (form min min- or min-max) Received: '$e_check'"
lset clause_results $c_idx $a_idx [list errorcode [list PUNKARGS VALIDATION [list typemismatch $type] -badarg $argname -argspecs $argspecs] msg $msg]
continue
}
set vchecklist [list]
if {[llength $parts] == 1} {
lappend vchecklist [lindex $parts 0]
} else {
lassign $parts vmin vmax
if {$vmax eq ""} {
#empty vmax allowed - ignore
lappend vchecklist $vmin
} else {
lappend vchecklist $vmin $vmax
}
}
#we have either just the min, or min and max
set v_ok 1 ;#default assumption
foreach vcheck $vchecklist {
if {[catch {::package vsatisfies $vcheck $vcheck}]} {
set msg "$argclass $argname for %caller% requires type packagerequirement. (from min min- or min-max) . Received: '$e_check'"
lset clause_results $c_idx $a_idx [list errorcode [list PUNKARGS VALIDATION [list typemismatch $type] -badarg $argname -argspecs $argspecs] msg $msg]
set v_ok 0
break ;#inner loop
}
}
if {$v_ok} {
lset clause_results $c_idx $a_idx 1
break
}
}
string - ansistring - globstring {
#we may commonly want exceptions that ignore validation rules - most commonly probably the empty string
#we possibly don't want to always have to regex on things that don't pass the other more basic checks
@ -9167,6 +9248,7 @@ tcl::namespace::eval punk::args {
append syn " $display"
dict set ARGD type [dict get $arginfo -type]
dict set ARGD optional [dict get $arginfo -optional]
dict set ARGD multiple [dict get $arginfo -multiple]
dict set ARGD display $display
#dict lappend SYND $f $ARGD
@ -9300,6 +9382,7 @@ tcl::namespace::eval punk::args {
append syn " $display"
dict set ARGD type [dict get $arginfo -type]
dict set ARGD optional [dict get $arginfo -optional]
dict set ARGD multiple [dict get $arginfo -multiple]
dict set ARGD display $display
#dict lappend SYND $f $ARGD
lappend FORMARGS $ARGD
@ -9417,10 +9500,23 @@ tcl::namespace::eval punk::args {
append syn " $display"
dict set ARGD type [dict get $arginfo -type]
dict set ARGD optional [dict get $arginfo -optional]
dict set ARGD multiple [dict get $arginfo -multiple]
dict set ARGD display $display
#dict lappend SYND $f $ARGD
lappend FORMARGS $ARGD
}
#accepts unnamed extra arguments e.g toplevel docid for ensembles and ensemble-like commands
if {[dict get $forminfo VAL_UNNAMED]} {
set display "?<unnamed>...?"
append syn " $display"
set ARGD [dict create argname "" class value]
dict set ARGD type any
dict set ARGD optional 1
dict set ARGD multiple 1
dict set ARGD display $display
lappend FORMARGS $ARGD
}
append syn \n
dict set SYND FORMS $f $FORMARGS
}
@ -9640,7 +9736,8 @@ tcl::namespace::eval punk::args {
dict for {g members} $opt_groupdict {
lappend allgrouped {*}$members
}
set choiceinfodict [dict create]
set choiceinfodict [dict create]
set choicelabelsdict [dict create]
foreach {sc cmd} $subdict {
if {$sc ni $allgrouped} {
if {$sc ni $others} {
@ -9669,20 +9766,43 @@ tcl::namespace::eval punk::args {
}
}
#could be more than one punk::args id - choose a precedence by how we order the id_exists checks.
if {[punk::args::id_exists [list $ensemble $sc]]} {
dict lappend choiceinfodict $sc {doctype punkargs}
dict lappend choiceinfodict $sc [list subhelp {*}$ensemble $sc]
} elseif {[punk::args::id_exists $cmd]} {
dict lappend choiceinfodict $sc {doctype punkargs}
dict lappend choiceinfodict $sc [list subhelp {*}$cmd]
} elseif {[punk::args::id_exists [dict get $cinfo origin]]} {
dict lappend choiceinfodict $sc {doctype punkargs}
dict lappend choiceinfodict $sc [list subhelp {*}[dict get $cinfo origin]]
} else {
#puts stderr "ensemble_subcommands_definition--- NO doc for [list $ensemble $sc] or $cmd or [dict get $cinfo origin]"
set id_checks [list\
"$ensemble $sc"\
$cmd\
[dict get $cinfo origin]\
]
foreach checkid $id_checks {
if {[punk::args::id_exists $checkid]} {
dict lappend choiceinfodict $sc {doctype punkargs}
dict lappend choiceinfodict $sc [list subhelp {*}$checkid]
dict set choicelabelsdict $sc [punk::ansi::a+ normal][punk::ns::synopsis $checkid][punk::ansi::a]
break
}
}
#if {[punk::args::id_exists [list $ensemble $sc]]} {
# dict lappend choiceinfodict $sc {doctype punkargs}
# dict lappend choiceinfodict $sc [list subhelp {*}$ensemble $sc]
#} elseif {[punk::args::id_exists $cmd]} {
# dict lappend choiceinfodict $sc {doctype punkargs}
# dict lappend choiceinfodict $sc [list subhelp {*}$cmd]
#} elseif {[punk::args::id_exists [dict get $cinfo origin]]} {
# dict lappend choiceinfodict $sc {doctype punkargs}
# dict lappend choiceinfodict $sc [list subhelp {*}[dict get $cinfo origin]]
#}
#foreach id [punk::args::get_ids "::package *"] {
# if {[llength $id] == 2} {
# lassign $id _ sub
# dict set PACKAGE_CHOICEINFO $sub {{doctype native} {doctype punkargs}}
# #override manual synopsis entry
# dict set PACKAGE_CHOICELABELS $sub [punk::ns::synopsis "::package $sub"]
# }
#}
#if {[punk::args::id_exists [dict get $cinfo origin]] || [punk::args::id_exists [list $ensemble $sc]]} {
# dict lappend choiceinfodict $sc {doctype punkargs}
#}
@ -9694,7 +9814,7 @@ tcl::namespace::eval punk::args {
dict for {g members} $opt_groupdict {
append argdef " \"$g\" \{$members\}" \n
}
append argdef " \} -choicecolumns $opt_columns -choiceinfo {$choiceinfodict}" \n
append argdef " \} -choicecolumns $opt_columns -choicelabels {$choicelabelsdict} -choice info {$choiceinfodict}" \n
#todo -choicelabels
#detect subcommand further info available e.g if oo or ensemble or punk::args id exists..