Browse Source

punk::args example fixes, grepstr fixes, more tclcore docs

master
Julian Noble 3 months ago
parent
commit
cf62cebc8b
  1. 253
      src/modules/punk-0.1.tm
  2. 245
      src/modules/punk/args-999999.0a1.0.tm
  3. 2301
      src/modules/punk/args/moduledoc/tclcore-999999.0a1.0.tm
  4. 34
      src/modules/punk/args/moduledoc/tkcore-999999.0a1.0.tm
  5. 98
      src/modules/punk/imap4-999999.0a1.0.tm
  6. 3
      src/modules/punk/ns-999999.0a1.0.tm

253
src/modules/punk-0.1.tm

@ -564,14 +564,15 @@ namespace eval punk {
"Grep for regex pattern in plaintext of supplied (possibly ANSI) string."\
-help\
"The grepstr command can find strings in ANSI text even if there are interspersed
ANSI colour codes etc. Even if a word has different coloured/styled letters, the
ANSI colour codes etc. Even if a word has different coloured/styled letters, the
regex can match the plaintext. (Search is performed on ansistripped text, and then
the matched sections are highlighted and overlayed on the original styled/colourd
input.
If the input string has ANSI movement codes - the resultant text may not be directly
searchable because the parts of a word may be separated by various codes and other
plain text. To search such an input string, the string should first be 'rendered' to
a form where the ANSI only represents SGR styling (and perhaps other non-movement
a form where the ANSI only represents SGR styling (and perhaps other non-movement
codes) using something like overtype::renderline or overtype::rendertext."
@leaders -min 0 -max 0
@ -589,7 +590,7 @@ namespace eval punk {
except that when instead using -returnlines all with --line-number, the *
indicator after the linenumber will only be highlighted for lines with matches,
and the following matchcount will indicate zero for non-matching lines."
}
}
-B|--before-context= -parsekey "--before-context" -default 0 -type integer -typesynopsis num
-C|--context= -parsekey "--context" -default 0 -type integer -typesynopsis num -help\
"Print num lines of leading and trailing context surrounding each match."
@ -628,7 +629,10 @@ namespace eval punk {
-- -type none
@values
pattern -type string -help\
"regex pattern to match in plaintext portion of ANSI string"
"regex pattern to match in plaintext portion of ANSI string
The pattern may contain bracketed capturing groups, which
will be highlighted (todo) in the result. If there is no capturing
group, the entire match will be highlighted."
string -type string
}
proc grepstr {args} {
@ -670,40 +674,117 @@ namespace eval punk {
}
set data [string map {\r\n \n} $data]
if {![punk::ansi::ta::detect $data]} {
if {[punk::ansi::ta::detect $data]} {
set raw_has_ansi 1
set plain [punk::ansi::ansistrip $data]
} else {
set raw_has_ansi 0
set plain $data
}
set plainlines [split $plain \n]
set lines [split $data \n]
set matches [lsearch -all {*}$nocase -regexp $lines $pattern]
set result ""
set matched_line_indices [lsearch -all {*}$nocase -regexp $plainlines $pattern]
if {$opt_returnlines eq "all"} {
set returnlines [punk::lib::range 0 [llength $lines]-1]
} else {
#matches|breaksandmatches
set returnlines $matches
set returnlines $matched_line_indices
}
set max [lindex $returnlines end]
if {[string is integer -strict $max]} {
#if max index is 9 - linenum will be 10, (99->100 etc) - so add one in case we're on such a boundary.
incr max
}
set w1 [string length $max]
#lineindex is zero based - display of linenums is 1 based
set result ""
set placeholder \UFFEF ;#review
set resultlines [dict create]
foreach lineindex $returnlines {
set ln [lindex $lines $lineindex]
set col1 ""
if {$do_linenums} {
set col1 [format "%${w1}s " [expr {$lineindex+1}]]
set ln [lindex $lines $lineindex]
set col1 ""
if {$do_linenums} {
set col1 [format "%${w1}s " [expr {$lineindex+1}]]
}
if {$lineindex in $matched_line_indices} {
set plain_ln [lindex $plainlines $lineindex]
#first test the regexp with a single match to determine number of capturing groups
set matchparts [regexp {*}$nocase -inline -- $pattern $plain_ln] ;#get fullmatch capturegroup...
set numgroups [expr {[llength $matchparts] -1}]
set allparts [regexp -all {*}$nocase -indices -inline -- $pattern $plain_ln]
#allparts includes each full match as well as each capturing group
#early versions of tcl 8.6 still didn't support 'lsearch -stride' - avoid for now.
set matchcount [expr {[llength $allparts] / ($numgroups + 1)}]
#set matchcount [llength $allparts]
if {$matchcount == 0} {
#This probably can't happen (?)
#If it does.. it's more likely to be an issue with our line index than with regexp
puts stderr "Unexpected regex mismatch in grepstr (shouldn't happen) regex: $pattern lineindex: $lineindex"
set matchshow "??? $ln"
dict set resultlines $lineindex $matchshow
continue
}
if {$lineindex in $matches} {
set ln [regsub -all {*}$nocase -- $pattern $ln $H&$R] ;#n
set matchcount [regexp -all {*}$nocase -- $pattern $ln]
if {$do_linenums} {
append col1 $H*$R[format %03s $matchcount]
# ------------------------------------
if {$numgroups > 0} {
# restrict ourself to just the capture groups, excluding the full match (if there are capture groups)
set highlight_ranges [list]
set i 0
foreach range $allparts {
if {($i % ($numgroups+1)) != 0} {
lappend highlight_ranges $range
}
incr i
}
} else {
if {$do_linenums} {
append col1 "*000"
#No capture group in the regex, each index range is just a full match
set highlight_ranges $allparts
}
# ------------------------------------
#puts stderr "numgroups : $numgroups"
#puts stderr "grepstr pattern : $pattern"
#puts stderr "grepstr allparts: $allparts"
#puts stderr "highlight_ranges: $highlight_ranges"
if {$do_linenums} {
append col1 $H*$R[format %03s $matchcount]
}
if {$raw_has_ansi} {
set overlay ""
set i 0
foreach hrange $highlight_ranges {
lassign $hrange s e
set prelen [expr {$s - $i}]
#append overlay [string repeat $placeholder $prelen] $H[string range $plain_ln $s $e]$R
append overlay [string repeat $placeholder $prelen] $H[string range $plain_ln $s $e]
set i [expr {$e + 1}]
}
set tail [string range $plain_ln $e+1 end]
append overlay [string repeat $placeholder [string length $tail]]
#puts "$overlay"
#puts "$ln"
#set rendered [overtype::renderline -transparent $placeholder -insert_mode 0 $ln $overlay]
set rendered [overtype::renderspace -transparent $placeholder -insert_mode 0 $ln $overlay]
} else {
set rendered ""
set i 0
foreach hrange $highlight_ranges {
lassign $hrange s e
set prelen [expr {$s - $i}]
#append overlay [string repeat $placeholder $prelen] $H[string range $plain_ln $s $e]
append rendered [string range $plain_ln $i $s-1] $H [string range $plain_ln $s $e] $R
set i [expr {$e + 1}]
}
append rendered [string range $plain_ln $e+1 end]
}
if {$do_linenums} {
set matchshow "$col1 $rendered"
} else {
set matchshow $rendered
}
#---------------------------------------------------------------
set prelines [lrange $lines $lineindex-$beforecontext $lineindex-1]
set s [expr {$lineindex-$beforecontext-1}]
@ -721,12 +802,7 @@ namespace eval punk {
}
}
#---------------------------------------------------------------
if {$do_linenums} {
set show "$col1 $ln"
} else {
set show $ln
}
dict set resultlines $lineindex $show
dict set resultlines $lineindex $matchshow
#---------------------------------------------------------------
set postlines [lrange $lines $lineindex+1 $lineindex+$aftercontext]
set s $lineindex
@ -742,109 +818,16 @@ namespace eval punk {
}
}
#---------------------------------------------------------------
}
} else {
set plain [punk::ansi::ansistrip $data]
set plainlines [split $plain \n]
set lines [split $data \n]
set matches [lsearch -all {*}$nocase -regexp $plainlines $pattern]
if {$opt_returnlines eq "all"} {
set returnlines [punk::lib::range 0 [llength $lines]-1]
} else {
set returnlines $matches
}
set max [lindex $returnlines end]
if {[string is integer -strict $max]} {
#if max index is 9 - linenum will be 10, (99->100 etc) - so add one in case we're on such a boundary.
incr max
}
set w1 [string length $max]
set result ""
set placeholder \UFFEF ;#review
set resultlines [dict create]
foreach lineindex $returnlines {
set ln [lindex $lines $lineindex]
set col1 ""
if {$do_linenums} {
set col1 [format "%${w1}s " [expr {$lineindex+1}]]
}
if {$lineindex in $matches} {
set plain_ln [lindex $plainlines $lineindex]
set parts [regexp -all {*}$nocase -indices -inline -- $pattern $plain_ln]
set matchcount [llength $parts]
if {$do_linenums} {
append col1 $H*$R[format %03s $matchcount]
}
if {[llength $parts] == 0} {
#This probably can't happen (?)
#If it does.. it's more likely to be an issue with our line index than with regexp
puts stderr "Unexpected regex mismatch in grepstr - line marked with ??? (shouldn't happen)"
set matchshow "??? $ln"
#dict set resultlines $lineindex $show
} else {
set overlay ""
set i 0
foreach prange $parts {
lassign $prange s e
set prelen [expr {$s - $i}]
append overlay [string repeat $placeholder $prelen] $H[string range $plain_ln $s $e]$R
set i [expr {$e + 1}]
}
set tail [string range $plain_ln $e+1 end]
append overlay [string repeat $placeholder [string length $tail]]
#puts "$overlay"
#puts "$ln"
set rendered [overtype::renderline -transparent $placeholder -insert_mode 0 $ln $overlay]
if {$do_linenums} {
set matchshow "$col1 $rendered"
} else {
set matchshow $rendered
}
}
#---------------------------------------------------------------
set prelines [lrange $lines $lineindex-$beforecontext $lineindex-1]
set s [expr {$lineindex-$beforecontext-1}]
if {$s < -1} {set s -1}
foreach p $prelines {
incr s
#append result "[format %${w1}s [expr {$s+1}]]- " " " $p \n
if {![dict exists $resultlines $s]} {
if {$do_linenums} {
set show "[format "%${w1}s " [expr {$s+1}]]- $p"
} else {
set show $p
}
dict set resultlines $s $show
}
}
#---------------------------------------------------------------
dict set resultlines $lineindex $matchshow
#---------------------------------------------------------------
set postlines [lrange $lines $lineindex+1 $lineindex+$aftercontext]
set s $lineindex
foreach p $postlines {
incr s
if {![dict exists $resultlines $s]} {
if {$do_linenums} {
set show "[format "%${w1}s " [expr {$s+1}]]- $p"
} else {
set show $p
}
dict set resultlines $s $show
}
}
#---------------------------------------------------------------
append col1 "*000"
set show "$col1 $ln"
} else {
if {$do_linenums} {
append col1 "*000"
set show "$col1 $ln"
} else {
set show $ln
}
dict set resultlines $lineindex $show
set show $ln
}
dict set resultlines $lineindex $show
}
}
set ordered_resultlines [lsort -integer [dict keys $resultlines]]
set result ""
@ -7828,6 +7811,7 @@ namespace eval punk {
lappend cmdinfo [list help "?topics?" "This help. To see available subitems type: help topics"]
lappend cmdinfo [list i "cmd ?subcommand...?" "Show usage for a command or ensemble subcommand"]
lappend cmdinfo [list s "cmd ?subcommand...?" "Show synopsis for a command or ensemble subcommand"]
lappend cmdinfo [list eg "cmd ?subcommand...?" "Show example from manpage"]
lappend cmdinfo [list ./ "?subdir?" "view/change directory"]
lappend cmdinfo [list ../ "" "go up one directory"]
lappend cmdinfo [list ./new "subdir" "make new directory and switch to it"]
@ -7884,12 +7868,19 @@ namespace eval punk {
append warningblock "${indent}see [punk::ansi::hyperlink https://core.tcl-lang.org/tcl/tktview/1095bf7f75]"
append warningblock [a]
}
if {[punk::lib::check::has_tclbug_lsearch_strideallinline]} {
set indent " "
append warningblock \n "[a+ web-red]warning: punk::lib::check::has_tclbug_lsearch_strideallinline returned true!" \n
append warningblock "${indent}(lsearch using -stride -all -inline -subindices does not return values corresponding to subindex when a single -index value is used)" \n
append warningblock "${indent}see [punk::ansi::hyperlink https://core.tcl-lang.org/tcl/tktview/5a1aaa201d]"
append warningblock [a]
if {[catch {lsearch -stride 2 {a b} b}]} {
set indent " "
append warningblock \n "[a+ web-red]warning: lsearch does not seem to support -stride option" \n
append warningblock "${indent}(Consider upgrading to a late release of tcl 8.6 or tcl 9+ )" \n
append warningblock [a]
} else {
if {[punk::lib::check::has_tclbug_lsearch_strideallinline]} {
set indent " "
append warningblock \n "[a+ web-red]warning: punk::lib::check::has_tclbug_lsearch_strideallinline returned true!" \n
append warningblock "${indent}(lsearch using -stride -all -inline -subindices does not return values corresponding to subindex when a single -index value is used)" \n
append warningblock "${indent}see [punk::ansi::hyperlink https://core.tcl-lang.org/tcl/tktview/5a1aaa201d]"
append warningblock [a]
}
}
if {[punk::lib::check::has_tclbug_list_quoting_emptyjoin]} {
set indent " "

245
src/modules/punk/args-999999.0a1.0.tm

@ -270,6 +270,165 @@ tcl::namespace::eval punk::args::register {
tcl::namespace::eval ::punk::args {}
tcl::namespace::eval ::punk::args::helpers {
variable PUNKARGS
namespace export *
#proc B {} {return \x1b\[1m} ;#a+ bold
#proc N {} {return \x1b\[22m} ;#a+ normal
#proc I {} {return \x1b\[3m} ;#a+ italic
#proc NI {} {return \x1b\[23m} ;#a+ noitalic
proc I {} {punk::ansi::a+ italic}
proc B {} {punk::ansi::a+ bold}
proc N {} {punk::ansi::a+ normal}
proc NI {} {punk::ansi::a+ italic}
lappend PUNKARGS [list {
@id -id ::punk::args::helpers::example
@cmd -name punk::args::helpers::example\
-summary\
{Display formatting for argdoc example text}\
-help\
{Wrap }
@opts
-padright -type integer -default 2 -help\
{Number of padding spaces to add on RHS of text block}
-syntax -type string -default tcl -choices {none tcl} -choicelabels {
tcl\
" Very basic tcl syntax highlighting
of braces,square brackets and comments."
}
text -type string
}]
proc example {args} {
#only use punk::args::parse on the unhappy path
if {[llength $args] == 0} {
punk::args::parse $args withid ::punk::args::helpers::example
return
}
set str [lindex $args end]
set optlist [lrange $args 0 end-1]
if {[llength $optlist] %2 != 0} {
punk::args::parse $args withid ::punk::args::helpers::example
return
}
set defaults [dict create\
-padright 2\
-syntax tcl\
]
dict for {o v} $optlist {
switch -- $o {
-padright - -syntax {}
default {
punk::args::parse $args withid ::punk::args::helpers::example
return
}
}
}
set opts [dict merge $defaults $optlist]
set opt_padright [dict get $opts -padright]
set opt_syntax [dict get $opts -syntax]
if {[string index $str 0] eq "\n"} {
set str [string range $str 1 end]
}
if {[string index $str end] eq "\n"} {
set str [string range $str 0 end-1]
}
#example is intended to run from a source doc that has already been dedented appropriately based on context
# - we don't want to further undent, hence -undent 0
set str [uplevel 1 [list punk::lib::tstr -undent 0 -return string -eval 1 -allowcommands $str]]
#puts stderr -------------------
#puts $str
#puts stderr -------------------
if {$opt_padright > 0} {
set str [textblock::join -- $str [string repeat " " $opt_padright]]
}
set str [punk::ansi::ansiwrap Web-gray [textblock::frame -ansibase [a+ Web-gray white] -ansiborder [a+ black White] -boxlimits {hl} -type block $str]]
#puts stderr -------------------
#puts $str
#puts stderr -------------------
#rudimentary colourising (not full tcl syntax parsing)
#highlight comments first - so that we can also highlight braces within comments to help with detecting unbalanced braces/square brackets in comments
switch -- $opt_syntax {
tcl {
#result lines often indicated in examples by \u2192 →
#however - it's not present on each line of output, instead indents are used - so we can't so easily highlight all appropriate rows(?)
set str [punk::grepstr -return all -highlight {Web-gray term-darkgreen} {^\s*#.*} $str] ;#Note, will not highlight comments at end of line - like this one
set str [punk::grepstr -return all -highlight {Web-gray term-darkgreen} {;\s*(#.*)} $str]
#TODO - fix grepstr highlighting (bg issues - why?)
set str [punk::grepstr -return all -highlight {Web-gray term-darkblue} {\{|\}} $str]
set str [punk::grepstr -return all -highlight {Web-gray term-orange1} {\[|\]} $str]
#puts stderr -------------------
#puts $str
#puts stderr -------------------
}
}
set result [textblock::bookend_lines $str [a] "[a defaultbg] [a]"]
return $result
}
lappend PUNKARGS [list {
@id -id ::punk::args::helpers::strip_nodisplay_comments
@cmd -name punk::args::helpers::strip_nodisplay_comments\
-summary\
"strip #<nodisplay> lines."\
-help\
"Strip lines beginning with #<nodisplay> from the supplied text.
Whitespace prior to #<nodisplay> is ignored, and ANSI is stripped
prior to examining each line for the #<nodisplay> tag."
@values -min 1 -max 1
text -optional 0 -help\
"punk::args::define scripts must have properly balanced braces etc
as per Tcl rules.
Sometimes it is desired to display help text or examples demonstrating
unbalanced braces etc, but without escaping it in a way that shows the
escaping backslash in the help text. This balancing requirement includes
curly braces in comments. eg
${[punk::args::helpers::example {
proc bad_syntax {args} {
#eg this is an unbalanced left curly brace {
#<nodisplay> balancing right curly brace }
return $args
}
}]}
There is a second comment line in the above proc which begins
with #<nodisplay> and contains the balancing right curly brace.
This shouldn't show in the example above.
The actual text is in a placeholder call to punk::args::helpers::example
to provide basic syntax highlighting and box background, and looks like
the following, but without the left-hand side pipe symbols.
${[punk::args::helpers::example -syntax none {
| proc bad_syntax {args} {
| #eg this is an unbalanced left curly brace {
| #<nodisplay> balancing right curly brace }
| return $args
| }
}]}
A #<nodisplay> comment can also be used just for commenting the help
source inline.
The ${[B]}strip_nodisplay_comments${[N]} function is called automatically
by the help text generators in punk::args, and generally shouldn't need
to be used directly, but nevertheless resides in in punk::args::helpers
alongside the ${[B]}example${[N]} function which is intended for writers
of punk::args::define scripts (command documentors) to use.
"
}]
proc strip_nodisplay_comments {text} {
set display ""
foreach ln [split $text \n] {
if {![string match "#<nodisplay>*" [string trimleft [punk::ansi::ansistrip $ln]]]} {
append display $ln \n
}
}
if {[string index $display end] eq "\n"} {
set display [string range $display 0 end-1]
}
return $display
}
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Base namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
@ -624,8 +783,15 @@ tcl::namespace::eval punk::args {
-maxsize (type dependant)
-range (type dependant - only valid if -type is a single item)
-typeranges (list with same number of elements as -type)
-help <string>
for the @cmd directive - this is the main multiline description.
For an argument is the multi-line help that displays in the Help
column.
For the @examples directive this is the text for examples as
displayed with 'eg <commandname>'
For cases where unbalanced braces, double quotes are to
be displayed to the user without visible backslash escapes,
see 'i ::punk::args::helpers::strip_nodisplay_comments'
"
-dynamic -type boolean -default 0 -help\
"If -dynamic is true, tstr interpolations of the form \$\{\$var\}
@ -649,7 +815,7 @@ tcl::namespace::eval punk::args {
from existing definitions (by id) for re-use of argument specifications and help text)
e.g the following definition passes 2 blocks as text arguments
${[punk::args::moduledoc::tclcore::argdoc::example {
${[punk::args::helpers::example {
punk::args::define {
@id -id ::myns::myfunc
@cmd -name myns::myfunc -help\
@ -955,6 +1121,8 @@ tcl::namespace::eval punk::args {
set LVL 2
if {!$is_dynamic} {
#todo - don't use cached version if 'colour off' vs 'colour on' different to when last resolved!
#(e.g example blocks will still have colour if previously resolved)
if {[tcl::dict::exists $argdata_cache $cache_key]} {
return [tcl::dict::get $argdata_cache $cache_key]
}
@ -1082,6 +1250,19 @@ tcl::namespace::eval punk::args {
set record_line 0 ;#incremented at each incomplete record, set to zero after processing a complete record
foreach rawline $linelist {
#puts stderr "$record_line $rawline"
#XXX
#set rawtrimmed [string trim $rawline]
#if {$in_record_continuation && $rawtrimmed ne "" && [string index $rawtrimmed 0] ni [list "\}" {"} "#"]} {
# regexp {(\s*).*} $rawline _ rawline_indent
# if {[string length $rawline_indent] <= [string length $record_base_indent]} {
# lappend records $linebuild
# set linebuild ""
# #prep for next record
# set in_record_continuation 0
# incr record_id
# set record_line 0
# }
#}
set record_so_far [tcl::string::cat $linebuild $rawline]
#ansi colours can stop info complete from working (contain square brackets)
#review - when exactly are ansi codes allowed/expected in record lines.
@ -1174,6 +1355,10 @@ tcl::namespace::eval punk::args {
set record_line 0
}
}
if {$in_record_continuation} {
puts stderr "punk::args::resolve incomplete record:"
puts stderr "$linebuild"
}
#puts stderr 1[lindex $records 1]
#puts stderr 4[lindex $records 4]
#puts stderr 5[lindex $records 5]
@ -1212,6 +1397,13 @@ tcl::namespace::eval punk::args {
"" - # {continue}
}
incr record_number
if {[catch {lassign $trimrec firstword}]} {
puts stdout "----------------------------------------------"
puts stderr "rec: $rec"
set ::testrecord $rec
puts "records: $records"
puts stdout "----------------------------------------------"
}
set record_values [lassign $trimrec firstword] ;#after first word, the remaining list elements up to the first newline that isn't inside a value, form a dict
if {[llength $record_values] % 2 != 0} {
#todo - avoid raising an error - store invalid defs keyed on id
@ -3671,6 +3863,7 @@ tcl::namespace::eval punk::args {
lappend blank_header_col ""
#set cmdhelp_display [a+ brightwhite]$cmdhelp[a]
#set cmdhelp_display [textblock::ansibase_lines $cmdhelp $CLR(linebase_header)]
set cmdhelp [punk::args::helpers::strip_nodisplay_comments $cmdhelp]
set cmdhelp_display [punk::ansi::ansiwrap_raw $CLR(linebase_header) "" "" $cmdhelp]
} else {
set cmdhelp_display ""
@ -4055,6 +4248,7 @@ tcl::namespace::eval punk::args {
}
set unindentedfields [Dict_getdef $arginfo -unindentedfields {}]
set help [Dict_getdef $arginfo -help ""]
set help [punk::args::helpers::strip_nodisplay_comments $help]
set allchoices_originalcase [list]
set choices [Dict_getdef $arginfo -choices {}]
set choicegroups [Dict_getdef $arginfo -choicegroups {}]
@ -4656,7 +4850,7 @@ tcl::namespace::eval punk::args {
lappend PUNKARGS [list {
@id -id ::punk::args::parse
@cmd -name punk::args::parse -help\
"parse and validate command arguments based on a definition.
{parse and validate command arguments based on a definition.
In the 'withid' form the definition is a pre-existing record that has been
created with ::punk::args::define, or indirectly by adding a definition to
@ -4673,23 +4867,25 @@ tcl::namespace::eval punk::args {
Returns a dict of information regarding the parsed arguments
example of basic usage for single option only:
punk::args::define {
@id -id ::myns::myfunc
@cmd -name myns::myfunc
@leaders -min 0 -max 0
@opts
-configfile -type existingfile
#type none makes it a solo flag
-verbose -type none
@values -min 0 -max 0
}
proc myfunc {args} {
set argd [punk::args::parse $args withid ::myns::myfunc]
lassign [dict values $argd] leaders opts values received solos
if {[dict exists $received] -configfile} {
puts \"have option for existing file [dict get $opts -configfile]\"
}
}
${[punk::args::helpers::example {
punk::args::define {
@id -id ::myns::myfunc
@cmd -name myns::myfunc
@leaders -min 0 -max 0
@opts
-configfile -type existingfile
#type none makes it a solo flag
-verbose -type none
@values -min 0 -max 0
}
proc myfunc {args} {
set argd [punk::args::parse $args withid ::myns::myfunc]
lassign [dict values $argd] leaders opts values received solos
if {[dict exists $received] -configfile} {
puts "have option for existing file [dict get $opts -configfile]"
}
}
}]}
The leaders, opts, values keys in the parse result dict are proper dicts.
The received key is dict-like but can have repeated keys for arguments than can
accept multiples. The value for each received element is the ordinal position.
@ -4698,7 +4894,7 @@ tcl::namespace::eval punk::args {
to another procedure which also requires solos, because the opts dict contains
solo flags with a 1 value or a list of 1's if it was a solo with -multiple true
specified.
"
}
@form -form {withid withdef}
@leaders -min 1 -max 1
arglist -type list -optional 0 -help\
@ -9152,7 +9348,8 @@ tcl::namespace::eval punk::args {
return
}
if {[dict exists $spec examples_info -help]} {
return [dict get $spec examples_info -help]
set egdata [dict get $spec examples_info -help]
return [punk::args::helpers::strip_nodisplay_comments $egdata]
} else {
return "no @examples defined for $id"
}
@ -10807,7 +11004,7 @@ tcl::namespace::eval punk::args::package {
# set PUNKARGS ""
#}
lappend ::punk::args::register::NAMESPACES ::punk::args::argdoc ::punk::args ::punk::args::lib ::punk::args::package
lappend ::punk::args::register::NAMESPACES ::punk::args::argdoc ::punk::args ::punk::args::lib ::punk::args::package ::punk::args::helpers
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools

2301
src/modules/punk/args/moduledoc/tclcore-999999.0a1.0.tm

File diff suppressed because it is too large Load Diff

34
src/modules/punk/args/moduledoc/tkcore-999999.0a1.0.tm

@ -21,7 +21,7 @@
#[manpage_begin punkshell_module_punk::args::moduledoc::tkcore 0 999999.0a1.0]
#[copyright "2025"]
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}]
#[moddesc {-}] [comment {-- Description at end of page heading --}]
#[moddesc {-}] [comment {-- Description at end of page heading --}]
#[require punk::args::moduledoc::tkcore]
#[keywords module]
#[description]
@ -112,13 +112,15 @@ tcl::namespace::eval punk::args::moduledoc::tkcore {
set B [a+ bold]
set N [a+ normal]
# -- --- --- --- ---
proc example {str} {
set str [string trimleft $str \n]
set block [punk::ansi::ansiwrap Web-gray [textblock::frame -ansibase [a+ Web-gray bold white] -ansiborder [a+ black White] -boxlimits {hl} -type block $str]]
set result [textblock::bookend_lines $block [a] "[a defaultbg] [a]"]
#puts $result
return $result
}
namespace import ::punk::args::helpers::*
#proc example {str} {
# #sample override of punk::args::helpers::example (without highlighting and inner placeholder processing)
# set str [string trimleft $str \n]
# set block [punk::ansi::ansiwrap Web-gray [textblock::frame -ansibase [a+ Web-gray bold white] -ansiborder [a+ black White] -boxlimits {hl} -type block $str]]
# set result [textblock::bookend_lines $block [a] "[a defaultbg] [a]"]
# return $result
#}
}
@ -459,15 +461,15 @@ tcl::namespace::eval punk::args::moduledoc::tkcore {
{
@examples -help {
This is the classic Tk “Hello, World!” demonstration:
${[punk::args::moduledoc::tclcore::argdoc::example {
button .b -text "Hello, World!" -command exit
${[example {
${$B}button${$N} .b -text "Hello, World!" -command exit
pack .b
}]}
This example demonstrates how to handle button accelerators:
${[punk::args::moduledoc::tclcore::argdoc::example {
button .b1 -text Hello -underline 0
button .b2 -text World -underline 0
${[example {
${$B}button${$N} .b1 -text Hello -underline 0
${$B}button .b2${$N} -text World -underline 0
bind . <Key-h> {.b1 flash; .b1 invoke}
bind . <Key-w> {.b2 flash; .b2 invoke}
pack .b1 .b2
@ -557,9 +559,9 @@ tcl::namespace::eval punk::args::moduledoc::tkcore::lib {
# == === === === === === === === === === === === === === ===
# == === === === === === === === === === === === === === ===
# Sample 'about' function with punk::args documentation
# == === === === === === === === === === === === === === ===
# == === === === === === === === === === === === === === ===
tcl::namespace::eval punk::args::moduledoc::tkcore {
tcl::namespace::export {[a-z]*} ;# Convention: export all lowercase
variable PUNKARGS
@ -582,7 +584,7 @@ tcl::namespace::eval punk::args::moduledoc::tkcore {
set about_topics [list]
foreach f $topic_funs {
set tail [namespace tail $f]
lappend about_topics [string range $tail [string length get_topic_] end]
lappend about_topics [string range $tail [string length get_topic_] end]
}
#Adjust this function or 'default_topics' if a different order is required
return [lsort $about_topics]

98
src/modules/punk/imap4-999999.0a1.0.tm

@ -1481,53 +1481,55 @@ tcl::namespace::eval punk::imap4 {
lappend PUNKARGS [list {
@id -id ::punk::imap4::CONNECT
@cmd -name punk::imap4::CONNECT -help\
"Open a new IMAP connection and initialise the handler.
Returns the Tcl channel to use in subsequent calls to
the API. Other API commands will return zero on success.
e.g
${[punk::args::moduledoc::tclcore::argdoc::example {
% set chan [CONNECT mail.example.com]
sock123aaa456789
% AUTH_PLAIN $chan user pass
0
... EXAMINE/CLOSE mailboxes, SEARCH, FETCH etc ...
% LOGOUT $chan
0}]}"
@leaders -min 0 -max 0
-debug -type boolean -default 0 -help\
"Display some of the cli/server interaction on stdout
during commands. This can be set or queried using
the 'debugchan $chan ?bool?' command."
-security -nocase 1 -choices {None TLS/SSL STARTTLS} -help\
"Connection security.
TLS/SSL is recommended (implicit TLS).
If port is 143 and -security is omitted, then it will
default to STARTTLS.
For any other port, or omitted port, the default for
-security is TLS/SSL.
ie if no channel security is wanted, then -security
should be explicitly set to None."
@values -min 1 -max 2
hostname -optional 0 -help\
"Host/IP Address of server.
port may optionally be specified at tail of hostname
after a colon, but not if the following optional port
argument to the command is also supplied and is non-zero.
e.g
server.example.com:143
[::1]::993
"
port -optional 1 -type integer -help\
"Port to connect to.
If port is omitted:
defaults to 143 when -security None or STARTTLS
defaults to 993 when -security TLS/SSL or -security is omitted."
}]
namespace eval argdoc {
lappend PUNKARGS [list {
@id -id ::punk::imap4::CONNECT
@cmd -name punk::imap4::CONNECT -help\
"Open a new IMAP connection and initialise the handler.
Returns the Tcl channel to use in subsequent calls to
the API. Other API commands will return zero on success.
e.g
${[example {
% set chan [${[B]}CONNECT${[N]} mail.example.com]
sock123aaa456789
% AUTH_PLAIN $chan user pass
0
# ... EXAMINE/CLOSE mailboxes, SEARCH, FETCH etc ...
% LOGOUT $chan
0
}]}"
@leaders -min 0 -max 0
-debug -type boolean -default 0 -help\
"Display some of the cli/server interaction on stdout
during commands. This can be set or queried using
the 'debugchan $chan ?bool?' command."
-security -nocase 1 -choices {None TLS/SSL STARTTLS} -help\
"Connection security.
TLS/SSL is recommended (implicit TLS).
If port is 143 and -security is omitted, then it will
default to STARTTLS.
For any other port, or omitted port, the default for
-security is TLS/SSL.
ie if no channel security is wanted, then -security
should be explicitly set to None."
@values -min 1 -max 2
hostname -optional 0 -help\
"Host/IP Address of server.
port may optionally be specified at tail of hostname
after a colon, but not if the following optional port
argument to the command is also supplied and is non-zero.
e.g
server.example.com:143
[::1]::993
"
port -optional 1 -type integer -help\
"Port to connect to.
If port is omitted:
defaults to 143 when -security None or STARTTLS
defaults to 993 when -security TLS/SSL or -security is omitted."
}]
}
proc CONNECT {args} {
set argd [punk::args::parse $args withid ::punk::imap4::CONNECT]
lassign [dict values $argd] leaders opts values received
@ -4231,6 +4233,8 @@ tcl::namespace::eval punk::imap4 {
namespace eval argdoc {
#namespace for custom argument documentation
namespace import ::punk::args::helpers::*
proc package_name {} {
return punk::imap4
}

3
src/modules/punk/ns-999999.0a1.0.tm

@ -5256,7 +5256,8 @@ tcl::namespace::eval punk::ns {
basic {
#rudimentary colourising only
set argl [punk::grepstr -return all -highlight tk-darkcyan {\{|\}} $argl]
set body [punk::grepstr -return all -highlight green {^\s*#.*} $body] ;#Note, will not highlight comments at end of line - like this one.
set body [punk::grepstr -return all -highlight green {^\s*#.*} $body] ;#Note, will not highlight comments at end of line - like this one.
set body [punk::grepstr -return all -highlight green {;\s*(#.*)} $body] ;#treat as tail comment only if preceeded by semicolon
set body [punk::grepstr -return all -highlight tk-darkcyan {\{|\}} $body]
set body [punk::grepstr -return all -highlight tk-orange {\[|\]} $body]
#ansi colourised items in list format may not always have desired string representation (list escaping can occur)

Loading…
Cancel
Save