Browse Source

update bootsupport,vfs,project_layouts

master
Julian Noble 2 months ago
parent
commit
24d6f6e149
  1. 4
      src/bootsupport/modules/punk/ansi-0.1.1.tm
  2. 2
      src/bootsupport/modules/punk/cap/handlers/templates-0.1.0.tm
  3. 2
      src/bootsupport/modules/punk/char-0.1.0.tm
  4. 2
      src/bootsupport/modules/punk/config-0.1.tm
  5. 6
      src/bootsupport/modules/punk/console-0.1.1.tm
  6. 13
      src/bootsupport/modules/punk/fileline-0.1.0.tm
  7. 30
      src/bootsupport/modules/punk/lib-0.1.1.tm
  8. 2
      src/bootsupport/modules/punkcheck-0.1.0.tm
  9. 6
      src/bootsupport/modules/textblock-0.1.3.tm
  10. BIN
      src/bootsupport/modules/zipper-0.12.tm
  11. 4
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/ansi-0.1.1.tm
  12. 2
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/cap/handlers/templates-0.1.0.tm
  13. 2
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/char-0.1.0.tm
  14. 2
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/config-0.1.tm
  15. 6
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/console-0.1.1.tm
  16. 13
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/fileline-0.1.0.tm
  17. 30
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/lib-0.1.1.tm
  18. 2
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punkcheck-0.1.0.tm
  19. 6
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/textblock-0.1.3.tm
  20. BIN
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/zipper-0.12.tm
  21. 4
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/ansi-0.1.1.tm
  22. 2
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/cap/handlers/templates-0.1.0.tm
  23. 2
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/char-0.1.0.tm
  24. 2
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/config-0.1.tm
  25. 6
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/console-0.1.1.tm
  26. 13
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/fileline-0.1.0.tm
  27. 30
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/lib-0.1.1.tm
  28. 2
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punkcheck-0.1.0.tm
  29. 6
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/textblock-0.1.3.tm
  30. BIN
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/zipper-0.12.tm
  31. 642
      src/vfs/_vfscommon.vfs/modules/picalc-0.1.0.tm
  32. 36
      src/vfs/_vfscommon.vfs/modules/punk-0.1.tm
  33. 7672
      src/vfs/_vfscommon.vfs/modules/punk-0.1.tm.txt
  34. 4
      src/vfs/_vfscommon.vfs/modules/punk/ansi-0.1.1.tm
  35. 44
      src/vfs/_vfscommon.vfs/modules/punk/basictelnet-0.1.0.tm
  36. 2
      src/vfs/_vfscommon.vfs/modules/punk/cap/handlers/templates-0.1.0.tm
  37. 2
      src/vfs/_vfscommon.vfs/modules/punk/char-0.1.0.tm
  38. 2
      src/vfs/_vfscommon.vfs/modules/punk/config-0.1.tm
  39. 6
      src/vfs/_vfscommon.vfs/modules/punk/console-0.1.1.tm
  40. 13
      src/vfs/_vfscommon.vfs/modules/punk/fileline-0.1.0.tm
  41. 31
      src/vfs/_vfscommon.vfs/modules/punk/icomm-0.1.0.tm
  42. 57
      src/vfs/_vfscommon.vfs/modules/punk/imap4-0.9.tm
  43. 1
      src/vfs/_vfscommon.vfs/modules/punk/jtest.tcl
  44. 30
      src/vfs/_vfscommon.vfs/modules/punk/lib-0.1.1.tm
  45. 25
      src/vfs/_vfscommon.vfs/modules/punk/repl-0.1.1.tm
  46. 4
      src/vfs/_vfscommon.vfs/modules/punk/sshrun-0.1.0.tm
  47. 478
      src/vfs/_vfscommon.vfs/modules/punk/timeinterval-0.1.0.tm
  48. 14
      src/vfs/_vfscommon.vfs/modules/punk/winrun-0.1.0.tm
  49. 2
      src/vfs/_vfscommon.vfs/modules/punkcheck-0.1.0.tm
  50. 11
      src/vfs/_vfscommon.vfs/modules/shellrun-0.1.1.tm
  51. 12
      src/vfs/_vfscommon.vfs/modules/shellthread-1.6.1.tm
  52. 6
      src/vfs/_vfscommon.vfs/modules/textblock-0.1.3.tm
  53. 153
      src/vfs/_vfscommon.vfs/modules/winlibreoffice-0.1.0.tm
  54. BIN
      src/vfs/_vfscommon.vfs/modules/zipper-0.12.tm

4
src/bootsupport/modules/punk/ansi-0.1.1.tm

@ -7569,11 +7569,11 @@ namespace eval punk::ansi::colour {
} }
foreach c {R G B} { foreach c {R G B} {
if {$T($c) < [expr {1.0/6.0}]} { if {$T($c) < (1.0/6.0)} {
set T($c) [expr {$P+($Q-$P)*6.0*$T($c)}] set T($c) [expr {$P+($Q-$P)*6.0*$T($c)}]
} elseif {$T($c) < 0.5} { } elseif {$T($c) < 0.5} {
set T($c) $Q set T($c) $Q
} elseif {$T($c) < [expr {2.0/3.0}]} { } elseif {$T($c) < (2.0/3.0)} {
set T($c) [expr {$P+($Q-$P)*(2.0/3.0-$T($c))*6.0}] set T($c) [expr {$P+($Q-$P)*(2.0/3.0-$T($c))*6.0}]
} else { } else {
set T($c) $P set T($c) $P

2
src/bootsupport/modules/punk/cap/handlers/templates-0.1.0.tm

@ -95,7 +95,7 @@ namespace eval punk::cap::handlers::templates {
} else { } else {
set tm_exists [file exists $tmfile] set tm_exists [file exists $tmfile]
} }
if {![file exists $tmfile]} { if {!$tm_exists} {
puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - unable to determine base folder for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability" puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - unable to determine base folder for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability"
flush stderr flush stderr
return 0 return 0

2
src/bootsupport/modules/punk/char-0.1.0.tm

@ -1181,7 +1181,7 @@ tcl::namespace::eval punk::char {
} }
puts "ok.. loading" puts "ok.. loading"
set fd [open $file r] set fd [open $file r]
fconfigure $fd -translation binary chan configure $fd -translation binary
set data [read $fd] set data [read $fd]
close $fd close $fd
set block_count 0 set block_count 0

2
src/bootsupport/modules/punk/config-0.1.tm

@ -32,7 +32,7 @@ tcl::namespace::eval punk::config {
if {$exename ne ""} { if {$exename ne ""} {
set exefolder [file dirname $exename] set exefolder [file dirname $exename]
#default file logs to logs folder at same level as exe if writable, or empty string #default file logs to logs folder at same level as exe if writable, or empty string
set log_folder [file normalize $exefolder/../logs] set log_folder [file normalize $exefolder/../logs] ;#~2ms
#tcl::dict::set startup scriptlib $exefolder/scriptlib #tcl::dict::set startup scriptlib $exefolder/scriptlib
#tcl::dict::set startup apps $exefolder/../../punkapps #tcl::dict::set startup apps $exefolder/../../punkapps

6
src/bootsupport/modules/punk/console-0.1.1.tm

@ -777,7 +777,7 @@ namespace eval punk::console {
set extension [lindex [split $waitvar($callid) -] 1] set extension [lindex [split $waitvar($callid) -] 1]
if {$extension eq ""} { if {$extension eq ""} {
puts "blank extension $waitvar($callid)" puts "blank extension $waitvar($callid)"
puts "->[set $waitvar($callid]<-" puts "->[set $waitvar($callid)]<-"
} }
puts stderr "get_ansi_response_payload Extending timeout by $extension" puts stderr "get_ansi_response_payload Extending timeout by $extension"
after cancel $timeoutid($callid) after cancel $timeoutid($callid)
@ -814,7 +814,7 @@ namespace eval punk::console {
#it *might* be ok to restore entire state on an input channel #it *might* be ok to restore entire state on an input channel
#(it's not always on all channels - e.g stdout has -winsize which is read-only) #(it's not always on all channels - e.g stdout has -winsize which is read-only)
#Safest to only restore what we think we've modified. #Safest to only restore what we think we've modified.
fconfigure $input -blocking [dict get $previous_input_state -blocking] chan configure $input -blocking [dict get $previous_input_state -blocking]
@ -1947,7 +1947,7 @@ namespace eval punk::console {
set was_raw 1 set was_raw 1
} }
puts -nonewline stdout \033\[6n ;flush stdout puts -nonewline stdout \033\[6n ;flush stdout
fconfigure stdin -blocking 0 chan configure stdin -blocking 0
set info [read stdin 20] ;# set info [read stdin 20] ;#
after 1 after 1
if {[string first "R" $info] <=0} { if {[string first "R" $info] <=0} {

13
src/bootsupport/modules/punk/fileline-0.1.0.tm

@ -158,7 +158,7 @@ namespace eval punk::fileline::class {
#[para] Constructor for textinfo object which represents a chunk or all of a file #[para] Constructor for textinfo object which represents a chunk or all of a file
#[para] datachunk should be passed with the file data including line-endings as-is for full functionality. ie use something like: #[para] datachunk should be passed with the file data including line-endings as-is for full functionality. ie use something like:
#[example_begin] #[example_begin]
# fconfigure $fd -translation binary # chan configure $fd -translation binary
# set chunkdata [lb]read $fd[rb]] # set chunkdata [lb]read $fd[rb]]
#or #or
# set chunkdata [lb]fileutil::cat <filename> -translation binary[rb] # set chunkdata [lb]fileutil::cat <filename> -translation binary[rb]
@ -1221,8 +1221,11 @@ namespace eval punk::fileline::class {
#o_linemap #o_linemap
set oldsize [string length $o_chunk] set oldsize [string length $o_chunk]
set newchunk "" set newchunk ""
#review - what was the intention here?
puts stderr "regenerate_chunk -warning code incomplete"
dict for {idx lineinfo} $o_linemap { dict for {idx lineinfo} $o_linemap {
set #???
#set
} }
@ -1287,7 +1290,7 @@ namespace eval punk::fileline {
if {$opt_file ne ""} { if {$opt_file ne ""} {
set filename $opt_file set filename $opt_file
set fd [open $filename r] set fd [open $filename r]
fconfigure $fd -translation binary -encoding $opt_translation;#should use translation binary to get actual line-endings - but we allow caller to override chan configure $fd -translation binary -encoding $opt_translation;#should use translation binary to get actual line-endings - but we allow caller to override
#Always read encoding in binary - check for bom below and/or apply chosen opt_encoding #Always read encoding in binary - check for bom below and/or apply chosen opt_encoding
set rawchunk [read $fd] set rawchunk [read $fd]
close $fd close $fd
@ -1360,7 +1363,7 @@ namespace eval punk::fileline {
set bomenc "binary" ;# utf-8??? set bomenc "binary" ;# utf-8???
set startdata 3 set startdata 3
} elseif {$maybe_bom eq "84319533"} { } elseif {$maybe_bom eq "84319533"} {
if {![dict exists [punk::char::page_names_dict gb18030]]} { if {![dict exists [punk::char::page_names_dict gb18030] gb18030]} {
puts stderr "WARNING - no direct support for GB18030 (chinese) - falling back to cp936/gbk" puts stderr "WARNING - no direct support for GB18030 (chinese) - falling back to cp936/gbk"
set bomenc cp936 set bomenc cp936
} else { } else {
@ -1485,7 +1488,7 @@ namespace eval punk::fileline {
proc file_boundary_display {filename startbyte endbyte chunksize args} { proc file_boundary_display {filename startbyte endbyte chunksize args} {
set fd [open $filename r] ;#use default error if file not readable set fd [open $filename r] ;#use default error if file not readable
fconfigure $fd -translation binary chan configure $fd -translation binary
set rawfiledata [read $fd] set rawfiledata [read $fd]
close $fd close $fd
set textobj [class::textinfo new $rawfiledata] set textobj [class::textinfo new $rawfiledata]

30
src/bootsupport/modules/punk/lib-0.1.1.tm

@ -477,7 +477,7 @@ namespace eval punk::lib {
set asegs [split [string map {:: \uFFFF} $abs] \uFFFF] set asegs [split [string map {:: \uFFFF} $abs] \uFFFF]
set acount [llength $asegs] set acount [llength $asegs]
#puts "alias $abs acount:$acount asegs:$asegs segcount:$segcount segments: $segments" #puts "alias $abs acount:$acount asegs:$asegs segcount:$segcount segments: $segments"
if {[expr {$acount - 1}] == $segcount} { if {($acount - 1) == $segcount} {
if {[lrange $asegs 0 end-1] eq $segments} { if {[lrange $asegs 0 end-1] eq $segments} {
if {[string match $glob [lindex $asegs end]]} { if {[string match $glob [lindex $asegs end]]} {
#report this alias in the current namespace - even though there may be no matching command #report this alias in the current namespace - even though there may be no matching command
@ -2760,7 +2760,7 @@ namespace eval punk::lib {
#[example_end] #[example_end]
puts stdout $question puts stdout $question
flush stdout flush stdout
set stdin_state [fconfigure stdin] set stdin_state [chan configure stdin]
if {[catch { if {[catch {
package require punk::console package require punk::console
set console_raw [tsv::get console is_raw] set console_raw [tsv::get console is_raw]
@ -2769,7 +2769,7 @@ namespace eval punk::lib {
set console_raw 0 set console_raw 0
} }
try { try {
fconfigure stdin -blocking 1 chan configure stdin -blocking 1
if {$console_raw} { if {$console_raw} {
punk::console::disableRaw punk::console::disableRaw
set answer [gets stdin] set answer [gets stdin]
@ -2778,7 +2778,7 @@ namespace eval punk::lib {
set answer [gets stdin] set answer [gets stdin]
} }
} finally { } finally {
fconfigure stdin -blocking [tcl::dict::get $stdin_state -blocking] chan configure stdin -blocking [tcl::dict::get $stdin_state -blocking]
} }
return $answer return $answer
} }
@ -3629,8 +3629,8 @@ namespace eval punk::lib {
set s2 [expr {$s2 + (($time-$average)*($time-$average) / ($iters-1))}] set s2 [expr {$s2 + (($time-$average)*($time-$average) / ($iters-1))}]
} }
set sigma [expr {int(sqrt($s2))}] set sigma [expr {int(sqrt($s2))}]
set average [expr int($average)] set average [expr {int($average)}]
return "$average +/- $sigma microseconds per iteration" return "$average +/- $sigma microseconds per iteration"
} }
@ -3820,10 +3820,10 @@ namespace eval punk::lib {
# First, extract right hand part of number, up to and including decimal point # First, extract right hand part of number, up to and including decimal point
set point [string last "." $number]; set point [string last "." $number];
if {$point >= 0} { if {$point >= 0} {
set PostDecimal [string range $number [expr $point + 1] end]; set PostDecimal [string range $number $point+1 end];
set PostDecimalP 1; set PostDecimalP 1;
} else { } else {
set point [expr [string length $number] + 1] set point [expr {[string length $number] + 1}]
set PostDecimal ""; set PostDecimal "";
set PostDecimalP 0; set PostDecimalP 0;
} }
@ -3834,16 +3834,16 @@ namespace eval punk::lib {
incr ind; incr ind;
} }
set FirstNonSpace $ind; set FirstNonSpace $ind;
set LastSpace [expr $FirstNonSpace - 1]; set LastSpace [expr {$FirstNonSpace - 1}];
set LeadingSpaces [string range $number 0 $LastSpace]; set LeadingSpaces [string range $number 0 $LastSpace];
# Now extract the non-fractional part of the number, omitting leading spaces. # Now extract the non-fractional part of the number, omitting leading spaces.
set MainNumber [string range $number $FirstNonSpace [expr $point -1]]; set MainNumber [string range $number $FirstNonSpace $point-1];
# Insert commas into the non-fractional part. # Insert commas into the non-fractional part.
set Length [string length $MainNumber]; set Length [string length $MainNumber];
set Phase [expr $Length % $GroupSize] set Phase [expr {$Length % $GroupSize}]
set PhaseMinusOne [expr $Phase -1]; set PhaseMinusOne [expr {$Phase -1}];
set DelimitedMain ""; set DelimitedMain "";
#First we deal with the extra stuff. #First we deal with the extra stuff.
@ -3851,7 +3851,7 @@ namespace eval punk::lib {
append DelimitedMain [string range $MainNumber 0 $PhaseMinusOne]; append DelimitedMain [string range $MainNumber 0 $PhaseMinusOne];
} }
set FirstInGroup $Phase; set FirstInGroup $Phase;
set LastInGroup [expr $FirstInGroup + $GroupSize -1]; set LastInGroup [expr {$FirstInGroup + $GroupSize -1}];
while {$LastInGroup < $Length} { while {$LastInGroup < $Length} {
if {$FirstInGroup > 0} { if {$FirstInGroup > 0} {
append DelimitedMain $delim; append DelimitedMain $delim;
@ -3958,8 +3958,12 @@ tcl::namespace::eval punk::lib::flatgrid {
} }
} }
tcl::namespace::eval punk::lib::test {
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#todo - way to generate 'internal' docs separately? #todo - way to generate 'internal' docs separately?
#*** !doctools #*** !doctools

2
src/bootsupport/modules/punkcheck-0.1.0.tm

@ -86,7 +86,7 @@ namespace eval punkcheck {
set linecount [llength [split $newtdl \n]] set linecount [llength [split $newtdl \n]]
#puts stdout $newtdl #puts stdout $newtdl
set fd [open $punkcheck_file w] set fd [open $punkcheck_file w]
fconfigure $fd -translation binary chan configure $fd -translation binary
puts -nonewline $fd $newtdl puts -nonewline $fd $newtdl
close $fd close $fd
return [list recordcount [llength $recordlist] linecount $linecount] return [list recordcount [llength $recordlist] linecount $linecount]

6
src/bootsupport/modules/textblock-0.1.3.tm

@ -663,7 +663,7 @@ tcl::namespace::eval textblock {
switch -- $k { switch -- $k {
-ansibase_header - -ansibase_body - -ansiborder_header - -ansiborder-body - -ansiborder_footer { -ansibase_header - -ansibase_body - -ansiborder_header - -ansiborder-body - -ansiborder_footer {
set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]" set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]"
set ansi_codes [list] ; set ansi_codes [list]
foreach {pt code} $parts { foreach {pt code} $parts {
if {$pt ne ""} { if {$pt ne ""} {
#we don't expect plaintext in an ansibase #we don't expect plaintext in an ansibase
@ -1109,7 +1109,7 @@ tcl::namespace::eval textblock {
} }
-ansibase { -ansibase {
set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]" set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]"
set col_ansibase_items [list] ; set col_ansibase_items [list]
foreach {pt code} $parts { foreach {pt code} $parts {
if {$pt ne ""} { if {$pt ne ""} {
#we don't expect plaintext in an ansibase #we don't expect plaintext in an ansibase
@ -7852,7 +7852,7 @@ tcl::namespace::eval textblock {
foreach {k v} $optlist { foreach {k v} $optlist {
set k2 [tcl::prefix::match -error "" $optnames $k] set k2 [tcl::prefix::match -error "" $optnames $k]
switch -- $k2 { switch -- $k2 {
-etabs - -type - -boxlimits - -boxmap - -joins -etabs - -type - -boxlimits - -boxmap - -join
- -title - -titlealign - -subtitle - -subtitlealign - -width - -height - -title - -titlealign - -subtitle - -subtitlealign - -width - -height
- -ansiborder - -ansibase - -ansiborder - -ansibase
- -blockalign - -textalign - -ellipsis - -blockalign - -textalign - -ellipsis

BIN
src/bootsupport/modules/zipper-0.12.tm

Binary file not shown.

4
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/ansi-0.1.1.tm

@ -7569,11 +7569,11 @@ namespace eval punk::ansi::colour {
} }
foreach c {R G B} { foreach c {R G B} {
if {$T($c) < [expr {1.0/6.0}]} { if {$T($c) < (1.0/6.0)} {
set T($c) [expr {$P+($Q-$P)*6.0*$T($c)}] set T($c) [expr {$P+($Q-$P)*6.0*$T($c)}]
} elseif {$T($c) < 0.5} { } elseif {$T($c) < 0.5} {
set T($c) $Q set T($c) $Q
} elseif {$T($c) < [expr {2.0/3.0}]} { } elseif {$T($c) < (2.0/3.0)} {
set T($c) [expr {$P+($Q-$P)*(2.0/3.0-$T($c))*6.0}] set T($c) [expr {$P+($Q-$P)*(2.0/3.0-$T($c))*6.0}]
} else { } else {
set T($c) $P set T($c) $P

2
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/cap/handlers/templates-0.1.0.tm

@ -95,7 +95,7 @@ namespace eval punk::cap::handlers::templates {
} else { } else {
set tm_exists [file exists $tmfile] set tm_exists [file exists $tmfile]
} }
if {![file exists $tmfile]} { if {!$tm_exists} {
puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - unable to determine base folder for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability" puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - unable to determine base folder for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability"
flush stderr flush stderr
return 0 return 0

2
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/char-0.1.0.tm

@ -1181,7 +1181,7 @@ tcl::namespace::eval punk::char {
} }
puts "ok.. loading" puts "ok.. loading"
set fd [open $file r] set fd [open $file r]
fconfigure $fd -translation binary chan configure $fd -translation binary
set data [read $fd] set data [read $fd]
close $fd close $fd
set block_count 0 set block_count 0

2
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/config-0.1.tm

@ -32,7 +32,7 @@ tcl::namespace::eval punk::config {
if {$exename ne ""} { if {$exename ne ""} {
set exefolder [file dirname $exename] set exefolder [file dirname $exename]
#default file logs to logs folder at same level as exe if writable, or empty string #default file logs to logs folder at same level as exe if writable, or empty string
set log_folder [file normalize $exefolder/../logs] set log_folder [file normalize $exefolder/../logs] ;#~2ms
#tcl::dict::set startup scriptlib $exefolder/scriptlib #tcl::dict::set startup scriptlib $exefolder/scriptlib
#tcl::dict::set startup apps $exefolder/../../punkapps #tcl::dict::set startup apps $exefolder/../../punkapps

6
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/console-0.1.1.tm

@ -777,7 +777,7 @@ namespace eval punk::console {
set extension [lindex [split $waitvar($callid) -] 1] set extension [lindex [split $waitvar($callid) -] 1]
if {$extension eq ""} { if {$extension eq ""} {
puts "blank extension $waitvar($callid)" puts "blank extension $waitvar($callid)"
puts "->[set $waitvar($callid]<-" puts "->[set $waitvar($callid)]<-"
} }
puts stderr "get_ansi_response_payload Extending timeout by $extension" puts stderr "get_ansi_response_payload Extending timeout by $extension"
after cancel $timeoutid($callid) after cancel $timeoutid($callid)
@ -814,7 +814,7 @@ namespace eval punk::console {
#it *might* be ok to restore entire state on an input channel #it *might* be ok to restore entire state on an input channel
#(it's not always on all channels - e.g stdout has -winsize which is read-only) #(it's not always on all channels - e.g stdout has -winsize which is read-only)
#Safest to only restore what we think we've modified. #Safest to only restore what we think we've modified.
fconfigure $input -blocking [dict get $previous_input_state -blocking] chan configure $input -blocking [dict get $previous_input_state -blocking]
@ -1947,7 +1947,7 @@ namespace eval punk::console {
set was_raw 1 set was_raw 1
} }
puts -nonewline stdout \033\[6n ;flush stdout puts -nonewline stdout \033\[6n ;flush stdout
fconfigure stdin -blocking 0 chan configure stdin -blocking 0
set info [read stdin 20] ;# set info [read stdin 20] ;#
after 1 after 1
if {[string first "R" $info] <=0} { if {[string first "R" $info] <=0} {

13
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/fileline-0.1.0.tm

@ -158,7 +158,7 @@ namespace eval punk::fileline::class {
#[para] Constructor for textinfo object which represents a chunk or all of a file #[para] Constructor for textinfo object which represents a chunk or all of a file
#[para] datachunk should be passed with the file data including line-endings as-is for full functionality. ie use something like: #[para] datachunk should be passed with the file data including line-endings as-is for full functionality. ie use something like:
#[example_begin] #[example_begin]
# fconfigure $fd -translation binary # chan configure $fd -translation binary
# set chunkdata [lb]read $fd[rb]] # set chunkdata [lb]read $fd[rb]]
#or #or
# set chunkdata [lb]fileutil::cat <filename> -translation binary[rb] # set chunkdata [lb]fileutil::cat <filename> -translation binary[rb]
@ -1221,8 +1221,11 @@ namespace eval punk::fileline::class {
#o_linemap #o_linemap
set oldsize [string length $o_chunk] set oldsize [string length $o_chunk]
set newchunk "" set newchunk ""
#review - what was the intention here?
puts stderr "regenerate_chunk -warning code incomplete"
dict for {idx lineinfo} $o_linemap { dict for {idx lineinfo} $o_linemap {
set #???
#set
} }
@ -1287,7 +1290,7 @@ namespace eval punk::fileline {
if {$opt_file ne ""} { if {$opt_file ne ""} {
set filename $opt_file set filename $opt_file
set fd [open $filename r] set fd [open $filename r]
fconfigure $fd -translation binary -encoding $opt_translation;#should use translation binary to get actual line-endings - but we allow caller to override chan configure $fd -translation binary -encoding $opt_translation;#should use translation binary to get actual line-endings - but we allow caller to override
#Always read encoding in binary - check for bom below and/or apply chosen opt_encoding #Always read encoding in binary - check for bom below and/or apply chosen opt_encoding
set rawchunk [read $fd] set rawchunk [read $fd]
close $fd close $fd
@ -1360,7 +1363,7 @@ namespace eval punk::fileline {
set bomenc "binary" ;# utf-8??? set bomenc "binary" ;# utf-8???
set startdata 3 set startdata 3
} elseif {$maybe_bom eq "84319533"} { } elseif {$maybe_bom eq "84319533"} {
if {![dict exists [punk::char::page_names_dict gb18030]]} { if {![dict exists [punk::char::page_names_dict gb18030] gb18030]} {
puts stderr "WARNING - no direct support for GB18030 (chinese) - falling back to cp936/gbk" puts stderr "WARNING - no direct support for GB18030 (chinese) - falling back to cp936/gbk"
set bomenc cp936 set bomenc cp936
} else { } else {
@ -1485,7 +1488,7 @@ namespace eval punk::fileline {
proc file_boundary_display {filename startbyte endbyte chunksize args} { proc file_boundary_display {filename startbyte endbyte chunksize args} {
set fd [open $filename r] ;#use default error if file not readable set fd [open $filename r] ;#use default error if file not readable
fconfigure $fd -translation binary chan configure $fd -translation binary
set rawfiledata [read $fd] set rawfiledata [read $fd]
close $fd close $fd
set textobj [class::textinfo new $rawfiledata] set textobj [class::textinfo new $rawfiledata]

30
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/lib-0.1.1.tm

@ -477,7 +477,7 @@ namespace eval punk::lib {
set asegs [split [string map {:: \uFFFF} $abs] \uFFFF] set asegs [split [string map {:: \uFFFF} $abs] \uFFFF]
set acount [llength $asegs] set acount [llength $asegs]
#puts "alias $abs acount:$acount asegs:$asegs segcount:$segcount segments: $segments" #puts "alias $abs acount:$acount asegs:$asegs segcount:$segcount segments: $segments"
if {[expr {$acount - 1}] == $segcount} { if {($acount - 1) == $segcount} {
if {[lrange $asegs 0 end-1] eq $segments} { if {[lrange $asegs 0 end-1] eq $segments} {
if {[string match $glob [lindex $asegs end]]} { if {[string match $glob [lindex $asegs end]]} {
#report this alias in the current namespace - even though there may be no matching command #report this alias in the current namespace - even though there may be no matching command
@ -2760,7 +2760,7 @@ namespace eval punk::lib {
#[example_end] #[example_end]
puts stdout $question puts stdout $question
flush stdout flush stdout
set stdin_state [fconfigure stdin] set stdin_state [chan configure stdin]
if {[catch { if {[catch {
package require punk::console package require punk::console
set console_raw [tsv::get console is_raw] set console_raw [tsv::get console is_raw]
@ -2769,7 +2769,7 @@ namespace eval punk::lib {
set console_raw 0 set console_raw 0
} }
try { try {
fconfigure stdin -blocking 1 chan configure stdin -blocking 1
if {$console_raw} { if {$console_raw} {
punk::console::disableRaw punk::console::disableRaw
set answer [gets stdin] set answer [gets stdin]
@ -2778,7 +2778,7 @@ namespace eval punk::lib {
set answer [gets stdin] set answer [gets stdin]
} }
} finally { } finally {
fconfigure stdin -blocking [tcl::dict::get $stdin_state -blocking] chan configure stdin -blocking [tcl::dict::get $stdin_state -blocking]
} }
return $answer return $answer
} }
@ -3629,8 +3629,8 @@ namespace eval punk::lib {
set s2 [expr {$s2 + (($time-$average)*($time-$average) / ($iters-1))}] set s2 [expr {$s2 + (($time-$average)*($time-$average) / ($iters-1))}]
} }
set sigma [expr {int(sqrt($s2))}] set sigma [expr {int(sqrt($s2))}]
set average [expr int($average)] set average [expr {int($average)}]
return "$average +/- $sigma microseconds per iteration" return "$average +/- $sigma microseconds per iteration"
} }
@ -3820,10 +3820,10 @@ namespace eval punk::lib {
# First, extract right hand part of number, up to and including decimal point # First, extract right hand part of number, up to and including decimal point
set point [string last "." $number]; set point [string last "." $number];
if {$point >= 0} { if {$point >= 0} {
set PostDecimal [string range $number [expr $point + 1] end]; set PostDecimal [string range $number $point+1 end];
set PostDecimalP 1; set PostDecimalP 1;
} else { } else {
set point [expr [string length $number] + 1] set point [expr {[string length $number] + 1}]
set PostDecimal ""; set PostDecimal "";
set PostDecimalP 0; set PostDecimalP 0;
} }
@ -3834,16 +3834,16 @@ namespace eval punk::lib {
incr ind; incr ind;
} }
set FirstNonSpace $ind; set FirstNonSpace $ind;
set LastSpace [expr $FirstNonSpace - 1]; set LastSpace [expr {$FirstNonSpace - 1}];
set LeadingSpaces [string range $number 0 $LastSpace]; set LeadingSpaces [string range $number 0 $LastSpace];
# Now extract the non-fractional part of the number, omitting leading spaces. # Now extract the non-fractional part of the number, omitting leading spaces.
set MainNumber [string range $number $FirstNonSpace [expr $point -1]]; set MainNumber [string range $number $FirstNonSpace $point-1];
# Insert commas into the non-fractional part. # Insert commas into the non-fractional part.
set Length [string length $MainNumber]; set Length [string length $MainNumber];
set Phase [expr $Length % $GroupSize] set Phase [expr {$Length % $GroupSize}]
set PhaseMinusOne [expr $Phase -1]; set PhaseMinusOne [expr {$Phase -1}];
set DelimitedMain ""; set DelimitedMain "";
#First we deal with the extra stuff. #First we deal with the extra stuff.
@ -3851,7 +3851,7 @@ namespace eval punk::lib {
append DelimitedMain [string range $MainNumber 0 $PhaseMinusOne]; append DelimitedMain [string range $MainNumber 0 $PhaseMinusOne];
} }
set FirstInGroup $Phase; set FirstInGroup $Phase;
set LastInGroup [expr $FirstInGroup + $GroupSize -1]; set LastInGroup [expr {$FirstInGroup + $GroupSize -1}];
while {$LastInGroup < $Length} { while {$LastInGroup < $Length} {
if {$FirstInGroup > 0} { if {$FirstInGroup > 0} {
append DelimitedMain $delim; append DelimitedMain $delim;
@ -3958,8 +3958,12 @@ tcl::namespace::eval punk::lib::flatgrid {
} }
} }
tcl::namespace::eval punk::lib::test {
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#todo - way to generate 'internal' docs separately? #todo - way to generate 'internal' docs separately?
#*** !doctools #*** !doctools

2
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punkcheck-0.1.0.tm

@ -86,7 +86,7 @@ namespace eval punkcheck {
set linecount [llength [split $newtdl \n]] set linecount [llength [split $newtdl \n]]
#puts stdout $newtdl #puts stdout $newtdl
set fd [open $punkcheck_file w] set fd [open $punkcheck_file w]
fconfigure $fd -translation binary chan configure $fd -translation binary
puts -nonewline $fd $newtdl puts -nonewline $fd $newtdl
close $fd close $fd
return [list recordcount [llength $recordlist] linecount $linecount] return [list recordcount [llength $recordlist] linecount $linecount]

6
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/textblock-0.1.3.tm

@ -663,7 +663,7 @@ tcl::namespace::eval textblock {
switch -- $k { switch -- $k {
-ansibase_header - -ansibase_body - -ansiborder_header - -ansiborder-body - -ansiborder_footer { -ansibase_header - -ansibase_body - -ansiborder_header - -ansiborder-body - -ansiborder_footer {
set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]" set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]"
set ansi_codes [list] ; set ansi_codes [list]
foreach {pt code} $parts { foreach {pt code} $parts {
if {$pt ne ""} { if {$pt ne ""} {
#we don't expect plaintext in an ansibase #we don't expect plaintext in an ansibase
@ -1109,7 +1109,7 @@ tcl::namespace::eval textblock {
} }
-ansibase { -ansibase {
set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]" set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]"
set col_ansibase_items [list] ; set col_ansibase_items [list]
foreach {pt code} $parts { foreach {pt code} $parts {
if {$pt ne ""} { if {$pt ne ""} {
#we don't expect plaintext in an ansibase #we don't expect plaintext in an ansibase
@ -7852,7 +7852,7 @@ tcl::namespace::eval textblock {
foreach {k v} $optlist { foreach {k v} $optlist {
set k2 [tcl::prefix::match -error "" $optnames $k] set k2 [tcl::prefix::match -error "" $optnames $k]
switch -- $k2 { switch -- $k2 {
-etabs - -type - -boxlimits - -boxmap - -joins -etabs - -type - -boxlimits - -boxmap - -join
- -title - -titlealign - -subtitle - -subtitlealign - -width - -height - -title - -titlealign - -subtitle - -subtitlealign - -width - -height
- -ansiborder - -ansibase - -ansiborder - -ansibase
- -blockalign - -textalign - -ellipsis - -blockalign - -textalign - -ellipsis

BIN
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/zipper-0.12.tm

Binary file not shown.

4
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/ansi-0.1.1.tm

@ -7569,11 +7569,11 @@ namespace eval punk::ansi::colour {
} }
foreach c {R G B} { foreach c {R G B} {
if {$T($c) < [expr {1.0/6.0}]} { if {$T($c) < (1.0/6.0)} {
set T($c) [expr {$P+($Q-$P)*6.0*$T($c)}] set T($c) [expr {$P+($Q-$P)*6.0*$T($c)}]
} elseif {$T($c) < 0.5} { } elseif {$T($c) < 0.5} {
set T($c) $Q set T($c) $Q
} elseif {$T($c) < [expr {2.0/3.0}]} { } elseif {$T($c) < (2.0/3.0)} {
set T($c) [expr {$P+($Q-$P)*(2.0/3.0-$T($c))*6.0}] set T($c) [expr {$P+($Q-$P)*(2.0/3.0-$T($c))*6.0}]
} else { } else {
set T($c) $P set T($c) $P

2
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/cap/handlers/templates-0.1.0.tm

@ -95,7 +95,7 @@ namespace eval punk::cap::handlers::templates {
} else { } else {
set tm_exists [file exists $tmfile] set tm_exists [file exists $tmfile]
} }
if {![file exists $tmfile]} { if {!$tm_exists} {
puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - unable to determine base folder for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability" puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - unable to determine base folder for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability"
flush stderr flush stderr
return 0 return 0

2
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/char-0.1.0.tm

@ -1181,7 +1181,7 @@ tcl::namespace::eval punk::char {
} }
puts "ok.. loading" puts "ok.. loading"
set fd [open $file r] set fd [open $file r]
fconfigure $fd -translation binary chan configure $fd -translation binary
set data [read $fd] set data [read $fd]
close $fd close $fd
set block_count 0 set block_count 0

2
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/config-0.1.tm

@ -32,7 +32,7 @@ tcl::namespace::eval punk::config {
if {$exename ne ""} { if {$exename ne ""} {
set exefolder [file dirname $exename] set exefolder [file dirname $exename]
#default file logs to logs folder at same level as exe if writable, or empty string #default file logs to logs folder at same level as exe if writable, or empty string
set log_folder [file normalize $exefolder/../logs] set log_folder [file normalize $exefolder/../logs] ;#~2ms
#tcl::dict::set startup scriptlib $exefolder/scriptlib #tcl::dict::set startup scriptlib $exefolder/scriptlib
#tcl::dict::set startup apps $exefolder/../../punkapps #tcl::dict::set startup apps $exefolder/../../punkapps

6
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/console-0.1.1.tm

@ -777,7 +777,7 @@ namespace eval punk::console {
set extension [lindex [split $waitvar($callid) -] 1] set extension [lindex [split $waitvar($callid) -] 1]
if {$extension eq ""} { if {$extension eq ""} {
puts "blank extension $waitvar($callid)" puts "blank extension $waitvar($callid)"
puts "->[set $waitvar($callid]<-" puts "->[set $waitvar($callid)]<-"
} }
puts stderr "get_ansi_response_payload Extending timeout by $extension" puts stderr "get_ansi_response_payload Extending timeout by $extension"
after cancel $timeoutid($callid) after cancel $timeoutid($callid)
@ -814,7 +814,7 @@ namespace eval punk::console {
#it *might* be ok to restore entire state on an input channel #it *might* be ok to restore entire state on an input channel
#(it's not always on all channels - e.g stdout has -winsize which is read-only) #(it's not always on all channels - e.g stdout has -winsize which is read-only)
#Safest to only restore what we think we've modified. #Safest to only restore what we think we've modified.
fconfigure $input -blocking [dict get $previous_input_state -blocking] chan configure $input -blocking [dict get $previous_input_state -blocking]
@ -1947,7 +1947,7 @@ namespace eval punk::console {
set was_raw 1 set was_raw 1
} }
puts -nonewline stdout \033\[6n ;flush stdout puts -nonewline stdout \033\[6n ;flush stdout
fconfigure stdin -blocking 0 chan configure stdin -blocking 0
set info [read stdin 20] ;# set info [read stdin 20] ;#
after 1 after 1
if {[string first "R" $info] <=0} { if {[string first "R" $info] <=0} {

13
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/fileline-0.1.0.tm

@ -158,7 +158,7 @@ namespace eval punk::fileline::class {
#[para] Constructor for textinfo object which represents a chunk or all of a file #[para] Constructor for textinfo object which represents a chunk or all of a file
#[para] datachunk should be passed with the file data including line-endings as-is for full functionality. ie use something like: #[para] datachunk should be passed with the file data including line-endings as-is for full functionality. ie use something like:
#[example_begin] #[example_begin]
# fconfigure $fd -translation binary # chan configure $fd -translation binary
# set chunkdata [lb]read $fd[rb]] # set chunkdata [lb]read $fd[rb]]
#or #or
# set chunkdata [lb]fileutil::cat <filename> -translation binary[rb] # set chunkdata [lb]fileutil::cat <filename> -translation binary[rb]
@ -1221,8 +1221,11 @@ namespace eval punk::fileline::class {
#o_linemap #o_linemap
set oldsize [string length $o_chunk] set oldsize [string length $o_chunk]
set newchunk "" set newchunk ""
#review - what was the intention here?
puts stderr "regenerate_chunk -warning code incomplete"
dict for {idx lineinfo} $o_linemap { dict for {idx lineinfo} $o_linemap {
set #???
#set
} }
@ -1287,7 +1290,7 @@ namespace eval punk::fileline {
if {$opt_file ne ""} { if {$opt_file ne ""} {
set filename $opt_file set filename $opt_file
set fd [open $filename r] set fd [open $filename r]
fconfigure $fd -translation binary -encoding $opt_translation;#should use translation binary to get actual line-endings - but we allow caller to override chan configure $fd -translation binary -encoding $opt_translation;#should use translation binary to get actual line-endings - but we allow caller to override
#Always read encoding in binary - check for bom below and/or apply chosen opt_encoding #Always read encoding in binary - check for bom below and/or apply chosen opt_encoding
set rawchunk [read $fd] set rawchunk [read $fd]
close $fd close $fd
@ -1360,7 +1363,7 @@ namespace eval punk::fileline {
set bomenc "binary" ;# utf-8??? set bomenc "binary" ;# utf-8???
set startdata 3 set startdata 3
} elseif {$maybe_bom eq "84319533"} { } elseif {$maybe_bom eq "84319533"} {
if {![dict exists [punk::char::page_names_dict gb18030]]} { if {![dict exists [punk::char::page_names_dict gb18030] gb18030]} {
puts stderr "WARNING - no direct support for GB18030 (chinese) - falling back to cp936/gbk" puts stderr "WARNING - no direct support for GB18030 (chinese) - falling back to cp936/gbk"
set bomenc cp936 set bomenc cp936
} else { } else {
@ -1485,7 +1488,7 @@ namespace eval punk::fileline {
proc file_boundary_display {filename startbyte endbyte chunksize args} { proc file_boundary_display {filename startbyte endbyte chunksize args} {
set fd [open $filename r] ;#use default error if file not readable set fd [open $filename r] ;#use default error if file not readable
fconfigure $fd -translation binary chan configure $fd -translation binary
set rawfiledata [read $fd] set rawfiledata [read $fd]
close $fd close $fd
set textobj [class::textinfo new $rawfiledata] set textobj [class::textinfo new $rawfiledata]

30
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/lib-0.1.1.tm

@ -477,7 +477,7 @@ namespace eval punk::lib {
set asegs [split [string map {:: \uFFFF} $abs] \uFFFF] set asegs [split [string map {:: \uFFFF} $abs] \uFFFF]
set acount [llength $asegs] set acount [llength $asegs]
#puts "alias $abs acount:$acount asegs:$asegs segcount:$segcount segments: $segments" #puts "alias $abs acount:$acount asegs:$asegs segcount:$segcount segments: $segments"
if {[expr {$acount - 1}] == $segcount} { if {($acount - 1) == $segcount} {
if {[lrange $asegs 0 end-1] eq $segments} { if {[lrange $asegs 0 end-1] eq $segments} {
if {[string match $glob [lindex $asegs end]]} { if {[string match $glob [lindex $asegs end]]} {
#report this alias in the current namespace - even though there may be no matching command #report this alias in the current namespace - even though there may be no matching command
@ -2760,7 +2760,7 @@ namespace eval punk::lib {
#[example_end] #[example_end]
puts stdout $question puts stdout $question
flush stdout flush stdout
set stdin_state [fconfigure stdin] set stdin_state [chan configure stdin]
if {[catch { if {[catch {
package require punk::console package require punk::console
set console_raw [tsv::get console is_raw] set console_raw [tsv::get console is_raw]
@ -2769,7 +2769,7 @@ namespace eval punk::lib {
set console_raw 0 set console_raw 0
} }
try { try {
fconfigure stdin -blocking 1 chan configure stdin -blocking 1
if {$console_raw} { if {$console_raw} {
punk::console::disableRaw punk::console::disableRaw
set answer [gets stdin] set answer [gets stdin]
@ -2778,7 +2778,7 @@ namespace eval punk::lib {
set answer [gets stdin] set answer [gets stdin]
} }
} finally { } finally {
fconfigure stdin -blocking [tcl::dict::get $stdin_state -blocking] chan configure stdin -blocking [tcl::dict::get $stdin_state -blocking]
} }
return $answer return $answer
} }
@ -3629,8 +3629,8 @@ namespace eval punk::lib {
set s2 [expr {$s2 + (($time-$average)*($time-$average) / ($iters-1))}] set s2 [expr {$s2 + (($time-$average)*($time-$average) / ($iters-1))}]
} }
set sigma [expr {int(sqrt($s2))}] set sigma [expr {int(sqrt($s2))}]
set average [expr int($average)] set average [expr {int($average)}]
return "$average +/- $sigma microseconds per iteration" return "$average +/- $sigma microseconds per iteration"
} }
@ -3820,10 +3820,10 @@ namespace eval punk::lib {
# First, extract right hand part of number, up to and including decimal point # First, extract right hand part of number, up to and including decimal point
set point [string last "." $number]; set point [string last "." $number];
if {$point >= 0} { if {$point >= 0} {
set PostDecimal [string range $number [expr $point + 1] end]; set PostDecimal [string range $number $point+1 end];
set PostDecimalP 1; set PostDecimalP 1;
} else { } else {
set point [expr [string length $number] + 1] set point [expr {[string length $number] + 1}]
set PostDecimal ""; set PostDecimal "";
set PostDecimalP 0; set PostDecimalP 0;
} }
@ -3834,16 +3834,16 @@ namespace eval punk::lib {
incr ind; incr ind;
} }
set FirstNonSpace $ind; set FirstNonSpace $ind;
set LastSpace [expr $FirstNonSpace - 1]; set LastSpace [expr {$FirstNonSpace - 1}];
set LeadingSpaces [string range $number 0 $LastSpace]; set LeadingSpaces [string range $number 0 $LastSpace];
# Now extract the non-fractional part of the number, omitting leading spaces. # Now extract the non-fractional part of the number, omitting leading spaces.
set MainNumber [string range $number $FirstNonSpace [expr $point -1]]; set MainNumber [string range $number $FirstNonSpace $point-1];
# Insert commas into the non-fractional part. # Insert commas into the non-fractional part.
set Length [string length $MainNumber]; set Length [string length $MainNumber];
set Phase [expr $Length % $GroupSize] set Phase [expr {$Length % $GroupSize}]
set PhaseMinusOne [expr $Phase -1]; set PhaseMinusOne [expr {$Phase -1}];
set DelimitedMain ""; set DelimitedMain "";
#First we deal with the extra stuff. #First we deal with the extra stuff.
@ -3851,7 +3851,7 @@ namespace eval punk::lib {
append DelimitedMain [string range $MainNumber 0 $PhaseMinusOne]; append DelimitedMain [string range $MainNumber 0 $PhaseMinusOne];
} }
set FirstInGroup $Phase; set FirstInGroup $Phase;
set LastInGroup [expr $FirstInGroup + $GroupSize -1]; set LastInGroup [expr {$FirstInGroup + $GroupSize -1}];
while {$LastInGroup < $Length} { while {$LastInGroup < $Length} {
if {$FirstInGroup > 0} { if {$FirstInGroup > 0} {
append DelimitedMain $delim; append DelimitedMain $delim;
@ -3958,8 +3958,12 @@ tcl::namespace::eval punk::lib::flatgrid {
} }
} }
tcl::namespace::eval punk::lib::test {
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#todo - way to generate 'internal' docs separately? #todo - way to generate 'internal' docs separately?
#*** !doctools #*** !doctools

2
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punkcheck-0.1.0.tm

@ -86,7 +86,7 @@ namespace eval punkcheck {
set linecount [llength [split $newtdl \n]] set linecount [llength [split $newtdl \n]]
#puts stdout $newtdl #puts stdout $newtdl
set fd [open $punkcheck_file w] set fd [open $punkcheck_file w]
fconfigure $fd -translation binary chan configure $fd -translation binary
puts -nonewline $fd $newtdl puts -nonewline $fd $newtdl
close $fd close $fd
return [list recordcount [llength $recordlist] linecount $linecount] return [list recordcount [llength $recordlist] linecount $linecount]

6
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/textblock-0.1.3.tm

@ -663,7 +663,7 @@ tcl::namespace::eval textblock {
switch -- $k { switch -- $k {
-ansibase_header - -ansibase_body - -ansiborder_header - -ansiborder-body - -ansiborder_footer { -ansibase_header - -ansibase_body - -ansiborder_header - -ansiborder-body - -ansiborder_footer {
set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]" set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]"
set ansi_codes [list] ; set ansi_codes [list]
foreach {pt code} $parts { foreach {pt code} $parts {
if {$pt ne ""} { if {$pt ne ""} {
#we don't expect plaintext in an ansibase #we don't expect plaintext in an ansibase
@ -1109,7 +1109,7 @@ tcl::namespace::eval textblock {
} }
-ansibase { -ansibase {
set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]" set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]"
set col_ansibase_items [list] ; set col_ansibase_items [list]
foreach {pt code} $parts { foreach {pt code} $parts {
if {$pt ne ""} { if {$pt ne ""} {
#we don't expect plaintext in an ansibase #we don't expect plaintext in an ansibase
@ -7852,7 +7852,7 @@ tcl::namespace::eval textblock {
foreach {k v} $optlist { foreach {k v} $optlist {
set k2 [tcl::prefix::match -error "" $optnames $k] set k2 [tcl::prefix::match -error "" $optnames $k]
switch -- $k2 { switch -- $k2 {
-etabs - -type - -boxlimits - -boxmap - -joins -etabs - -type - -boxlimits - -boxmap - -join
- -title - -titlealign - -subtitle - -subtitlealign - -width - -height - -title - -titlealign - -subtitle - -subtitlealign - -width - -height
- -ansiborder - -ansibase - -ansiborder - -ansibase
- -blockalign - -textalign - -ellipsis - -blockalign - -textalign - -ellipsis

BIN
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/zipper-0.12.tm

Binary file not shown.

642
src/vfs/_vfscommon.vfs/modules/picalc-0.1.0.tm

@ -0,0 +1,642 @@
# -*- tcl -*-
# Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'dev make' or bin/punkmake to update from <pkg>-buildversion.txt
# module template: shellspy/src/decktemplates/vendor/punk/modules/template_module-0.0.3.tm
#
# Please consider using a BSD or MIT style license for greatest compatibility with the Tcl ecosystem.
# Code using preferred Tcl licenses can be eligible for inclusion in Tcllib, Tklib and the punk package repository.
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# (C) 2025
#
# @@ Meta Begin
# Application picalc 0.1.0
# Meta platform tcl
# Meta license MIT
# @@ Meta End
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[manpage_begin shellspy_module_picalc 0 0.1.0]
#[copyright "2025"]
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}]
#[moddesc {-}] [comment {-- Description at end of page heading --}]
#[require picalc]
#[keywords module]
#[description]
#[para] -
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Overview]
#[para] overview of picalc
#[subsection Concepts]
#[para] -
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Requirements
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[subsection dependencies]
#[para] packages used by picalc
#[list_begin itemized]
package require Tcl 8.6-
package require punk::lib
package require punk::args
#*** !doctools
#[item] [package {Tcl 8.6}]
#[item] [package {punk::lib}]
#[item] [package {punk::args}]
# #package require frobz
# #*** !doctools
# #[item] [package {frobz}]
#*** !doctools
#[list_end]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# oo::class namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#tcl::namespace::eval picalc::class {
#*** !doctools
#[subsection {Namespace picalc::class}]
#[para] class definitions
#if {[tcl::info::commands [tcl::namespace::current]::interface_sample1] eq ""} {
#*** !doctools
#[list_begin enumerated]
# oo::class create interface_sample1 {
# #*** !doctools
# #[enum] CLASS [class interface_sample1]
# #[list_begin definitions]
# method test {arg1} {
# #*** !doctools
# #[call class::interface_sample1 [method test] [arg arg1]]
# #[para] test method
# puts "test: $arg1"
# }
# #*** !doctools
# #[list_end] [comment {-- end definitions interface_sample1}]
# }
#*** !doctools
#[list_end] [comment {--- end class enumeration ---}]
#}
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval picalc {
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Base namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[subsection {Namespace picalc}]
#[para] Core API functions for picalc
#[list_begin definitions]
variable PUNKARGS
#proc sample1 {p1 n args} {
# #*** !doctools
# #[call [fun sample1] [arg p1] [arg n] [opt {option value...}]]
# #[para]Description of sample1
# #[para] Arguments:
# # [list_begin arguments]
# # [arg_def tring p1] A description of string argument p1.
# # [arg_def integer n] A description of integer argument n.
# # [list_end]
# return "ok"
#}
#a known value for the _test functions
variable pifrac [string map {" " ""} "1415926535 8979323846 2643383279 5028841971"]
#10k approx 2s
#20k approx 18s
#100k approx 1519s (25+minutes)
proc fast {dp} {
package require math::bigfloat
#math::bigfloat calculates using 'precision'
# --------------
#Faster for large values - but timing variable on same values!!
#After running on large values becomes - slower than calc and spigot for small values (somewhere around <1k)
catch {unset ::math::bigfloat::_pi0}
#this is due to the caching mechanism - for the purposes of comparison/testing and consistent results, we'll 'wreck' that caching here.
# --------------
set answer [math::bigfloat::tostr [math::bigfloat::pi [expr {$dp+3}]]] ;#we need to calculate with +3 precision to avoid rounding at the tail of chosen number of dp in all cases
return [string range $answer 0 end-2]
}
proc fast_test {max} {
variable pifrac
set pi 3.$pifrac
set result ""
set k 0
while {$k <= $max} {
set answer [fast $k]
set lcp [punk::lib::longestCommonPrefix [list $pi $answer]]
set lcplen [string length $lcp]
set tail [string range $answer $lcplen end]
set greenanswer [a+ green]$lcp[a]$tail
package require overtype ;#can't use 'format' for ANSI coloured strings
set col1 [string repeat " " [expr {$max + 3}]]
append result "[format %3s $k]-> [overtype::left $col1 $greenanswer]" \n
incr k
}
return $result
}
lappend PUNKARGS [list {
@id -id ::picalc::spigot
@cmd -name picalc::spigot -help\
"Return digits of pi to dp decimal places.
'classic' Rabinowitz and Wagon spigot algorithm.
https://www.cs.williams.edu/~heeringa/classes/cs135/s15/readings/spigot.pdf
relatively straight port from pascal algorithm
This algorithm for generating digits of pi uses a long list relative to the number of required digits
Performance doesn't seem to be spectacular,
(seems to be around 7-8secs for 1000 digits
93s for 10K digits)
The 'fast' (math::bigfloat based) function is much faster,
but also becomes extremely slow at a few 10's of thousands of digits.
"
@leaders -min 0 -max 0
@opts
-channel -choices {none stdout stderr} -default none -choicerestricted 0 -choicelabels {
none\
" Return as result string"
}
@values -min 0 -max 1
dp -type int -default 32 -help\
"Number of decimal places
(final digit is not rounded)"
}]
# 5K approx 25s
#10K approx 93s
proc spigot_emit {c chan countvar dp} {
upvar $countvar count
incr count
if {$chan eq "none"} {
upvar result r
append r $c ;#leave chars beyond dp to be trimmed by caller
return
} else {
if {$count > 2} {
if {$count <= $dp + 2} {
puts -nonewline $chan $c
}
} else {
if {$count == 1} {
puts -nonewline $chan 3
} else {
puts -nonewline $chan "."
}
}
}
}
proc spigot {args} {
set argd [punk::args::parse $args withid ::picalc::spigot]
lassign [dict values $argd] leaders opts values received
set dp [dict get $values dp]
set channel [dict get $opts -channel]
if {$dp < 1} {return 3}
set n [expr {$dp +2}] ;#dp +1 can get rounding errors
set len [expr {(10 * $n) / 3}]
set a [lrepeat [expr {$len+1}] 2]
set nines 0
set predigit 0
set result ""
set countvar 0
if {$channel eq "none"} {
set dpextra 2
} else {
set dpextra 2
}
for {set j 1} {$j <= $len} {incr j} {
set q 0
for {set i $len} {$i > 0} {incr i -1} {
set ai [lindex $a $i]
set x [expr {(10 * $ai) + ($q * $i)}]
lset a $i [expr {$x % (2*$i-1)}]
set q [expr {$x / (2*$i-1)}]
}
lset a 1 [expr {$q % 10}]
set q [expr {$q / 10}]
if {$q == 9} {
incr nines
} else {
if {$q == 10} {
#append result [expr {$predigit + 1}]
spigot_emit [expr {$predigit + 1}] $channel countvar $dp
if {$countvar == $dp +$dpextra} {
break
}
for {set k 1} {$k <= $nines} {incr k} {
#append result 0
spigot_emit 0 $channel countvar $dp
if {$countvar == $dp +$dpextra} {
break
}
}
if {$countvar == $dp +$dpextra} {
break
}
set predigit 0
set nines 0
} else {
#append result $predigit
spigot_emit $predigit $channel countvar $dp
if {$countvar == $dp +$dpextra} {
#+2 for leading 03
break
}
set predigit $q
if {$nines != 0} {
for {set k 1} {$k <= $nines} {incr k} {
#append result 9
spigot_emit 9 $channel countvar $dp
if {$countvar == $dp +$dpextra} {
break
}
}
if {$countvar == $dp +$dpextra} {
break
}
set nines 0
}
}
}
}
#append result $predigit
spigot_emit $predigit $channel countvar $dp
#eg result 0314159
if {$channel eq "none"} {
set result 3.[string range $result 2 $dp+1] ;#always trim to dp+1 (= $dp+2-1) - longer answer can have erroneous digits
#set result 3.[string range $result 2 end]
return $result
} else {
flush $channel
#review
return "emitted $countvar chars to channel $channel"
}
}
proc spigot_test {max} {
variable pifrac
set pi 3.$pifrac
set result ""
set k 0
while {$k <= $max} {
set answer [spigot $k]
set lcp [punk::lib::longestCommonPrefix [list $pi $answer]]
set lcplen [string length $lcp]
set tail [string range $answer $lcplen end]
set greenanswer [a+ green]$lcp[a]$tail
package require overtype ;#can't use 'format' for ANSI coloured strings
set col1 [string repeat " " [expr {$max + 3}]]
append result "[format %3s $k]-> [overtype::left $col1 $greenanswer]" \n
incr k
}
return $result
}
#def f(n):
# numerator, denominator = 1, 1
# # i/(2i + 1) = n/(2n + 1), ..., 3/7, 2/5, 1/3
# for i in range(n, 0, -1):
# # multiply by i/(2i + 1)
# numerator *= i
# denominator *= 2 * i + 1
# # add 1 (p/q -> (p + q)/q = p/q + q/q = p/q + 1)
# numerator += denominator
# return 2 * numerator, denominator
#for n in range(20):
# p, q = f(n)
# print(Fraction(p, q))
#an approx of pi that rapidly creates a fraction too big to calculate with standard Tcl doubles..
proc fraction {dp} {
if {$dp < 1} {return 3}
#determine an n big enough to give dp valid digits
set n [expr {$dp +1}]
set n [expr {(10 * $n) / 3}]
return [fraction_iteration $n]
}
# 5k approx 27s
# 10k approx 127s
proc calc {dp} {
if {$dp < 1} {return 3}
set n [expr {$dp +1}]
set n [expr {(10 * $n) / 3}]
package require math::bigfloat
lassign [fraction_iteration $n] a b
set bigfloat [math::bigfloat::div [math::bigfloat::int2float $a] [math::bigfloat::int2float $b]]
set answer [math::bigfloat::tostr $bigfloat]
#10*$d/3 == $n
#set trustdigits [expr {(3*$n)/10}] ;#??
return [string range $answer 0 $dp+1] ;#= +2-1
return $answer
}
proc calc_test {max} {
variable pifrac
set pi 3.$pifrac
set k 0
set result ""
set last_lcplen 0
set got ""
while {$k <= $max} {
set answer [calc $k]
set lcp [punk::lib::longestCommonPrefix [list $pi $answer]]
set lcplen [string length $lcp]
if {$lcplen > $last_lcplen} {
set last_lcplen $lcplen
set got [string index $lcp end]
set c red
} else {
set c yellow
}
set tail [string range $answer $lcplen end]
set greenanswer [a+ green]$lcp[a]$tail
package require overtype
set col1 [string repeat " " [expr {$max + 3}]]
append result "[overtype::left " " [a+ $c $got]] [format %3s $k]-> [overtype::left $col1 $greenanswer]" \n
incr k
}
return $result
}
proc fraction_iteration {n} {
set numerator 1; set denominator 1
for {set i $n} {$i > 0} {incr i -1} {
set numerator [expr {$numerator * $i}]
set denominator [expr {$denominator * (2 * $i + 1)}]
incr numerator $denominator
}
return [list [expr {$numerator * 2}] $denominator]
}
proc fraction_iteration_test {max} {
variable pifrac
set pi 3.$pifrac
set k 0
set result ""
set last_lcplen 0
set got ""
package require math::bigfloat
while {$k <= $max} {
set s [fraction_iteration $k]
lassign $s a b
#set answer [expr {$a / double($b)}] ;limited range
set bigfloat [math::bigfloat::div [math::bigfloat::int2float $a] [math::bigfloat::int2float $b]]
set answer [math::bigfloat::tostr $bigfloat]
set lcp [punk::lib::longestCommonPrefix [list $pi $answer]]
set lcplen [string length $lcp]
if {$lcplen > $last_lcplen} {
set last_lcplen $lcplen
set got [string index $lcp end]
set c red
} else {
set c yellow
}
set tail [string range $answer $lcplen end]
set greenanswer [a+ green]$lcp[a]$tail
#math::numtheory::gcd
#set gcd [punk::lib::gcd {*}$s]
#if {$gcd > 1} {
# set a [expr {$a/$gcd}]
# set b [expr {$b/$gcd}]
#}
set ax [string map [list $got [a+ $c]$got[a]] $a]
set bx [string map [list $got [a+ $c]$got[a]] $b]
set m [expr {$a % $b}]
set mx [string map [list $got [a+ $c]$got[a]] $m]
package require overtype
set sp40 [string repeat " " 40]
set sp60 [string repeat " " 60]
append result "[format %1s $got] [format %3s $k]-> [overtype::left $sp40 $greenanswer] [overtype::left $sp60 $ax] [overtype::left $sp60 $bx] [overtype::left $sp60 $mx]" \n
incr k
}
return $result
}
#an experiment
proc slow_approx {{m 1000}} {
set pi 0
set d [expr {1.0}]
for {set i 1} {$i <= $m} {incr i} {
set a [expr {2 * ($i % 2) - 1}]
set pi [expr {$pi + ($a * 4 / $d)}]
set d [expr {$d + 2.0}]
}
return $pi
}
#*** !doctools
#[list_end] [comment {--- end definitions namespace picalc ---}]
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Secondary API namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval picalc::lib {
tcl::namespace::export {[a-z]*} ;# Convention: export all lowercase
tcl::namespace::path [tcl::namespace::parent]
#*** !doctools
#[subsection {Namespace picalc::lib}]
#[para] Secondary functions that are part of the API
#[list_begin definitions]
#proc utility1 {p1 args} {
# #*** !doctools
# #[call lib::[fun utility1] [arg p1] [opt {?option value...?}]]
# #[para]Description of utility1
# return 1
#}
#*** !doctools
#[list_end] [comment {--- end definitions namespace picalc::lib ---}]
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Internal]
#tcl::namespace::eval picalc::system {
#*** !doctools
#[subsection {Namespace picalc::system}]
#[para] Internal functions that are not part of the API
#}
# == === === === === === === === === === === === === === ===
# Sample 'about' function with punk::args documentation
# == === === === === === === === === === === === === === ===
tcl::namespace::eval picalc {
tcl::namespace::export {[a-z]*} ;# Convention: export all lowercase
variable PUNKARGS
variable PUNKARGS_aliases
lappend PUNKARGS [list {
@id -id "(package)picalc"
@package -name "picalc" -help\
"Package
Description"
}]
namespace eval argdoc {
#namespace for custom argument documentation
proc package_name {} {
return picalc
}
proc about_topics {} {
#info commands results are returned in an arbitrary order (like array keys)
set topic_funs [info commands [namespace current]::get_topic_*]
set about_topics [list]
foreach f $topic_funs {
set tail [namespace tail $f]
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]
}
proc default_topics {} {return [list Description *]}
# -------------------------------------------------------------
# get_topic_ functions add more to auto-include in about topics
# -------------------------------------------------------------
proc get_topic_Description {} {
punk::args::lib::tstr [string trim {
package picalc
experiments in calculating pi in Tcl
} \n]
}
proc get_topic_License {} {
return "MIT"
}
proc get_topic_Version {} {
return "$::picalc::version"
}
proc get_topic_Contributors {} {
set authors {<unspecified>}
set contributors ""
foreach a $authors {
append contributors $a \n
}
if {[string index $contributors end] eq "\n"} {
set contributors [string range $contributors 0 end-1]
}
return $contributors
}
proc get_topic_notes {} {
punk::args::lib::tstr -return string {
A playground for evaluating performance and testing methods to calculate
the digits pi in Tcl.
A precalculated value of enough precision for almost any
usecase is available at $::math::constants::pi after loading
the math::constants package.
Note that this package is focused on calculating the digits of pi so
there is no rounding of the final digit.
For large values of pi using the mathematical concept of 'precision'
rather than decimal places - consider math::bigfloat::pi
}
}
# -------------------------------------------------------------
}
# we re-use the argument definition from punk::args::standard_about and override some items
set overrides [dict create]
dict set overrides @id -id "::picalc::about"
dict set overrides @cmd -name "picalc::about"
dict set overrides @cmd -help [string trim [punk::args::lib::tstr {
Experiments in calculating the digits of pi
}] \n]
dict set overrides topic -choices [list {*}[picalc::argdoc::about_topics] *]
dict set overrides topic -choicerestricted 1
dict set overrides topic -default [picalc::argdoc::default_topics] ;#if -default is present 'topic' will always appear in parsed 'values' dict
set newdef [punk::args::resolved_def -antiglobs -package_about_namespace -override $overrides ::punk::args::package::standard_about *]
lappend PUNKARGS [list $newdef]
proc about {args} {
package require punk::args
#standard_about accepts additional choices for topic - but we need to normalize any abbreviations to full topic name before passing on
set argd [punk::args::parse $args withid ::picalc::about]
lassign [dict values $argd] _leaders opts values _received
punk::args::package::standard_about -package_about_namespace ::picalc::argdoc {*}$opts {*}[dict get $values topic]
}
}
# end of sample 'about' function
# == === === === === === === === === === === === === === ===
# -----------------------------------------------------------------------------
# register namespace(s) to have PUNKARGS,PUNKARGS_aliases variables checked
# -----------------------------------------------------------------------------
# variable PUNKARGS
# variable PUNKARGS_aliases
namespace eval ::punk::args::register {
#use fully qualified so 8.6 doesn't find existing var in global namespace
lappend ::punk::args::register::NAMESPACES ::picalc
}
# -----------------------------------------------------------------------------
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Ready
package provide picalc [tcl::namespace::eval picalc {
variable pkg picalc
variable version
set version 0.1.0
}]
return
#*** !doctools
#[manpage_end]

36
src/vfs/_vfscommon.vfs/modules/punk-0.1.tm

@ -1234,7 +1234,7 @@ namespace eval punk {
break break
} }
#leave the - from the end- as part of the offset #leave the - from the end- as part of the offset
set offset [expr $endspec] ;#don't brace! set offset [expr $endspec] ;#don't brace! (consider: set x --34;puts expr $j;puts expr {$j} )
if {$do_bounds_check && ($offset > 0 || abs($offset) >= $len)} { if {$do_bounds_check && ($offset > 0 || abs($offset) >= $len)} {
set action ?mismatch-list-index-out-of-range set action ?mismatch-list-index-out-of-range
break break
@ -1583,7 +1583,7 @@ namespace eval punk {
} }
%# { %# {
set active_key_type "string" set active_key_type "string"
if $get_not { if {$get_not} {
error "!%# not string length is not supported" error "!%# not string length is not supported"
} }
#string length - REVIEW - #string length - REVIEW -
@ -1595,7 +1595,7 @@ namespace eval punk {
%%# { %%# {
#experimental #experimental
set active_key_type "string" set active_key_type "string"
if $get_not { if {$get_not} {
error "!%%# not string length is not supported" error "!%%# not string length is not supported"
} }
#string length - REVIEW - #string length - REVIEW -
@ -1606,7 +1606,7 @@ namespace eval punk {
} }
%str { %str {
set active_key_type "string" set active_key_type "string"
if $get_not { if {$get_not} {
error "!%str - not string-get is not supported" error "!%str - not string-get is not supported"
} }
lappend INDEX_OPERATIONS string-get lappend INDEX_OPERATIONS string-get
@ -1617,7 +1617,7 @@ namespace eval punk {
%sp { %sp {
#experimental #experimental
set active_key_type "string" set active_key_type "string"
if $get_not { if {$get_not} {
error "!%sp - not string-space is not supported" error "!%sp - not string-space is not supported"
} }
lappend INDEX_OPERATIONS string-space lappend INDEX_OPERATIONS string-space
@ -1628,7 +1628,7 @@ namespace eval punk {
%empty { %empty {
#experimental #experimental
set active_key_type "string" set active_key_type "string"
if $get_not { if {$get_not} {
error "!%empty - not string-empty is not supported" error "!%empty - not string-empty is not supported"
} }
lappend INDEX_OPERATIONS string-empty lappend INDEX_OPERATIONS string-empty
@ -1638,7 +1638,7 @@ namespace eval punk {
} }
@words { @words {
set active_key_type "string" set active_key_type "string"
if $get_not { if {$get_not} {
error "!%words - not list-words-from-string is not supported" error "!%words - not list-words-from-string is not supported"
} }
lappend INDEX_OPERATIONS list-words-from-string lappend INDEX_OPERATIONS list-words-from-string
@ -1650,7 +1650,7 @@ namespace eval punk {
#experimental - leading character based on result not input(?) #experimental - leading character based on result not input(?)
#input type is string - but output is list #input type is string - but output is list
set active_key_type "list" set active_key_type "list"
if $get_not { if {$get_not} {
error "!%chars - not list-chars-from-string is not supported" error "!%chars - not list-chars-from-string is not supported"
} }
lappend INDEX_OPERATIONS list-from_chars lappend INDEX_OPERATIONS list-from_chars
@ -1662,7 +1662,7 @@ namespace eval punk {
#experimental - flatten one level of list #experimental - flatten one level of list
#join without arg - output is list #join without arg - output is list
set active_key_type "string" set active_key_type "string"
if $get_not { if {$get_not} {
error "!@join - not list-join-list is not supported" error "!@join - not list-join-list is not supported"
} }
lappend INDEX_OPERATIONS list-join-list lappend INDEX_OPERATIONS list-join-list
@ -1674,7 +1674,7 @@ namespace eval punk {
#experimental #experimental
#input type is list - but output is string #input type is list - but output is string
set active_key_type "string" set active_key_type "string"
if $get_not { if {$get_not} {
error "!%join - not string-join-list is not supported" error "!%join - not string-join-list is not supported"
} }
lappend INDEX_OPERATIONS string-join-list lappend INDEX_OPERATIONS string-join-list
@ -1684,7 +1684,7 @@ namespace eval punk {
} }
%ansiview { %ansiview {
set active_key_type "string" set active_key_type "string"
if $get_not { if {$get_not} {
error "!%# not string-ansiview is not supported" error "!%# not string-ansiview is not supported"
} }
lappend INDEX_OPERATIONS string-ansiview lappend INDEX_OPERATIONS string-ansiview
@ -1694,7 +1694,7 @@ namespace eval punk {
} }
%ansiviewstyle { %ansiviewstyle {
set active_key_type "string" set active_key_type "string"
if $get_not { if {$get_not} {
error "!%# not string-ansiviewstyle is not supported" error "!%# not string-ansiviewstyle is not supported"
} }
lappend INDEX_OPERATIONS string-ansiviewstyle lappend INDEX_OPERATIONS string-ansiviewstyle
@ -3690,7 +3690,8 @@ namespace eval punk {
#todo - some way to restrict mismatch info to simple "mismatch" and avoid overhead of verbose message #todo - some way to restrict mismatch info to simple "mismatch" and avoid overhead of verbose message
#e.g for within pipeswitch block where mismatches are expected and the reasons are less important than moving on quickly #e.g for within pipeswitch block where mismatches are expected and the reasons are less important than moving on quickly
set vidx 0 set vidx 0
set mismatches [lmap m $match_state v $var_names {expr {$m == 0} ? {[list mismatch $v]} : {[list match $v]}}] #set mismatches [lmap m $match_state v $var_names {expr {$m == 0} ? {[list mismatch $v]} : {[list match $v]}}]
set mismatches [lmap m $match_state v $var_names {expr {$m == 0 ? [list mismatch $v] : [list match $v]}}]
set var_display_names [list] set var_display_names [list]
foreach v $var_names { foreach v $var_names {
if {$v eq ""} { if {$v eq ""} {
@ -3699,7 +3700,9 @@ namespace eval punk {
lappend var_display_names $v lappend var_display_names $v
} }
} }
set mismatches_display [lmap m $match_state v $var_display_names {expr {$m == 0} ? {$v} : {[expr {$m eq "?"} ? {"?[string repeat { } [expr [string length $v] -1]]"} : {[string repeat " " [string length $v]]} ]}}] #REVIEW 2025
#set mismatches_display [lmap m $match_state v $var_display_names {expr {$m == 0} ? {$v} : {[expr {$m eq "?"} ? {"?[string repeat { } [expr [string length $v] -1]]"} : {[string repeat " " [string length $v]]} ]}}]
set mismatches_display [lmap m $match_state v $var_display_names {expr {$m == 0 ? $v : [expr {$m eq "?" ? "?[string repeat { } [expr {[string length $v] -1}]]" : [string repeat " " [string length $v]] }]}}]
set msg "\n" set msg "\n"
append msg "Unmatched\n" append msg "Unmatched\n"
append msg "Cannot match right hand side to pattern $multivar\n" append msg "Cannot match right hand side to pattern $multivar\n"
@ -5304,6 +5307,8 @@ namespace eval punk {
##if {$body ni $existing} { ##if {$body ni $existing} {
set scr [base64::encode -maxlen 0 $cond] ;#will only be decoded if the debug is triggered set scr [base64::encode -maxlen 0 $cond] ;#will only be decoded if the debug is triggered
#tcllib has some double-substitution going on.. base64 seems easiest and will not impact the speed of normal execution when debug off. #tcllib has some double-substitution going on.. base64 seems easiest and will not impact the speed of normal execution when debug off.
#tclint-disable-next-line
proc ::unknown {args} [string map [list @c@ $cond @b@ $body @scr@ $scr] { proc ::unknown {args} [string map [list @c@ $cond @b@ $body @scr@ $scr] {
#--------------------------------------- #---------------------------------------
if {![catch {expr {@c@}} res] && $res} { if {![catch {expr {@c@}} res] && $res} {
@ -5368,6 +5373,7 @@ namespace eval punk {
#for var="val {a b c}" #for var="val {a b c}"
#proc ::punk::val {{v {}}} {tailcall lindex $v} #proc ::punk::val {{v {}}} {tailcall lindex $v}
#proc ::punk::val {{v {}}} {return $v} ;#2023 - approx 2x faster than the tailcall lindex version #proc ::punk::val {{v {}}} {return $v} ;#2023 - approx 2x faster than the tailcall lindex version
proc ::punk::val [list [list v [purelist]]] {return $v} proc ::punk::val [list [list v [purelist]]] {return $v}
#---------------- #----------------
@ -7437,7 +7443,7 @@ namespace eval punk {
foreach v $known_punk { foreach v $known_punk {
set c1 [overtype::left $col1 $v] set c1 [overtype::left $col1 $v]
if {[info exists ::env($v)]} { if {[info exists ::env($v)]} {
set c2 [overtype::left $col2 [set ::env($v)] set c2 [overtype::left $col2 [set ::env($v)]]
} else { } else {
set c2 [overtype::right $col2 "(NOT SET)"] set c2 [overtype::right $col2 "(NOT SET)"]
} }

7672
src/vfs/_vfscommon.vfs/modules/punk-0.1.tm.txt

File diff suppressed because it is too large Load Diff

4
src/vfs/_vfscommon.vfs/modules/punk/ansi-0.1.1.tm

@ -7569,11 +7569,11 @@ namespace eval punk::ansi::colour {
} }
foreach c {R G B} { foreach c {R G B} {
if {$T($c) < [expr {1.0/6.0}]} { if {$T($c) < (1.0/6.0)} {
set T($c) [expr {$P+($Q-$P)*6.0*$T($c)}] set T($c) [expr {$P+($Q-$P)*6.0*$T($c)}]
} elseif {$T($c) < 0.5} { } elseif {$T($c) < 0.5} {
set T($c) $Q set T($c) $Q
} elseif {$T($c) < [expr {2.0/3.0}]} { } elseif {$T($c) < (2.0/3.0)} {
set T($c) [expr {$P+($Q-$P)*(2.0/3.0-$T($c))*6.0}] set T($c) [expr {$P+($Q-$P)*(2.0/3.0-$T($c))*6.0}]
} else { } else {
set T($c) $P set T($c) $P

44
src/vfs/_vfscommon.vfs/modules/punk/basictelnet-0.1.0.tm

@ -402,7 +402,7 @@ namespace eval punk::basictelnet {
set client_declined "CLI-WONT:[a+ red bold][get_client_option_declined_summary][a]" set client_declined "CLI-WONT:[a+ red bold][get_client_option_declined_summary][a]"
set info $server_summary\n$client_summary\n$client_declined\n$info set info $server_summary\n$client_summary\n$client_declined\n$info
#set existing_handler [fileevent stdin readable] #set existing_handler [chan event stdin readable]
set RST "\x1b\[m" set RST "\x1b\[m"
set debug_width 80 set debug_width 80
@ -412,12 +412,12 @@ namespace eval punk::basictelnet {
#puts -nonewline [punk::ansi::cursor_off] #puts -nonewline [punk::ansi::cursor_off]
#use non cursorsave version - slower - but less likely to interfere with cursor operations in data #use non cursorsave version - slower - but less likely to interfere with cursor operations in data
set existing_input_handler [fileevent $inputchannel readable] ;#stdin set existing_input_handler [chan event $inputchannel readable] ;#stdin
fileevent $inputchannel readable {} chan event $inputchannel readable {}
if {[string length $outputchannel]} { if {[string length $outputchannel]} {
set existing_output_handler [fileevent $outputchannel readable] ;#sock set existing_output_handler [chan event $outputchannel readable] ;#sock
fileevent $outputchannel readable {} chan event $outputchannel readable {}
} }
if {[catch { if {[catch {
@ -434,9 +434,9 @@ namespace eval punk::basictelnet {
#todo - try? finally? #todo - try? finally?
set writing_debug_frame 0 set writing_debug_frame 0
fileevent $inputchannel readable $existing_input_handler chan event $inputchannel readable $existing_input_handler
if {[string length $outputchannel]} { if {[string length $outputchannel]} {
fileevent $outputchannel readable $existing_output_handler chan event $outputchannel readable $existing_output_handler
} }
return return
} }
@ -529,13 +529,13 @@ namespace eval punk::basictelnet {
#todo - allow telnet with channels other than stdin/stdout - and multiple sessions - per session option_states #todo - allow telnet with channels other than stdin/stdout - and multiple sessions - per session option_states
reset_option_states reset_option_states
set sock [socket $server $port] set sock [socket $server $port]
#fconfigure $sock -buffering none -blocking 0 -encoding binary -translation crlf -eofchar {} #chan configure $sock -buffering none -blocking 0 -encoding binary -translation crlf -eofchar {}
#fconfigure $sock -buffering none -blocking 0 -encoding binary -translation binary -eofchar {} #chan configure $sock -buffering none -blocking 0 -encoding binary -translation binary -eofchar {}
fconfigure $sock -buffering none -blocking 0 -encoding iso8859-1 -translation binary -eofchar {} chan configure $sock -buffering none -blocking 0 -encoding iso8859-1 -translation binary -eofchar {}
fconfigure stdout -buffering none chan configure stdout -buffering none
fileevent $sock readable [list [namespace current]::fromServer $sock] chan event $sock readable [list [namespace current]::fromServer $sock]
chan configure stdin -blocking 0 chan configure stdin -blocking 0
fileevent stdin readable [list [namespace current]::toServer $sock] chan event stdin readable [list [namespace current]::toServer $sock]
variable closed variable closed
vwait ::punk::basictelnet::closed($sock) vwait ::punk::basictelnet::closed($sock)
unset closed($sock) unset closed($sock)
@ -568,7 +568,7 @@ namespace eval punk::basictelnet {
set input_chunks_waiting(stdin) [lrange $input_chunks_waiting(stdin) 1 end] set input_chunks_waiting(stdin) [lrange $input_chunks_waiting(stdin) 1 end]
} }
fileevent stdin readable {} chan event stdin readable {}
if {$nextwaiting eq ""} { if {$nextwaiting eq ""} {
set chunk [read stdin] set chunk [read stdin]
} else { } else {
@ -616,13 +616,13 @@ namespace eval punk::basictelnet {
#Re-enable channel read handler only if no waiting chunks - must process in order #Re-enable channel read handler only if no waiting chunks - must process in order
################################################################################## ##################################################################################
if {![llength $input_chunks_waiting(stdin)]} { if {![llength $input_chunks_waiting(stdin)]} {
fileevent stdin readable [list [namespace current]::toServer $sock] chan event stdin readable [list [namespace current]::toServer $sock]
} else { } else {
#after idle [list [namespace current]::toServer $sock] #after idle [list [namespace current]::toServer $sock]
tailcall [namespace current]::toServer $sock tailcall [namespace current]::toServer $sock
} }
#################################################### ####################################################
#fileevent stdin readable [list [namespace current]::toServer $sock] #chan event stdin readable [list [namespace current]::toServer $sock]
} else { } else {
disconnect sock disconnect sock
} }
@ -642,7 +642,7 @@ namespace eval punk::basictelnet {
variable encoding_guess variable encoding_guess
variable debug variable debug
variable fromserver_unprocessed variable fromserver_unprocessed
fileevent $sock readable {} chan event $sock readable {}
variable in_sb variable in_sb
set chunksize 4096 ;#No choice of chunksize can avoid the possibility of splitting a token such as a Telnet protocol command or an ANSI sequence. set chunksize 4096 ;#No choice of chunksize can avoid the possibility of splitting a token such as a Telnet protocol command or an ANSI sequence.
#in theory, a split ANSI sequence won't cause a problem - except if we have debug on which could emit a request on stdout (e.g get_cursor_pos) #in theory, a split ANSI sequence won't cause a problem - except if we have debug on which could emit a request on stdout (e.g get_cursor_pos)
@ -872,24 +872,24 @@ namespace eval punk::basictelnet {
#after idle [list fileevent $sock readable [list [namespace current]::fromServer $sock]] #after idle [list chan event $sock readable [list [namespace current]::fromServer $sock]]
if {[string length $fromserver_unprocessed]} { if {[string length $fromserver_unprocessed]} {
#review - by throwing to another loop without waiting for readable event - we could spin on same data...? #review - by throwing to another loop without waiting for readable event - we could spin on same data...?
#after idle [list [namespace current]::fromServer $sock] #after idle [list [namespace current]::fromServer $sock]
fileevent $sock readable [list [namespace current]::fromServer $sock] chan event $sock readable [list [namespace current]::fromServer $sock]
} else { } else {
fileevent $sock readable [list [namespace current]::fromServer $sock] chan event $sock readable [list [namespace current]::fromServer $sock]
} }
} }
proc disconnect {sock} { proc disconnect {sock} {
variable closed variable closed
puts stdout "local disconnect" puts stdout "local disconnect"
catch {fileevent $sock readable {}} catch {chan event $sock readable {}}
catch {close $sock} catch {close $sock}
set closed($sock) 1 set closed($sock) 1
fileevent stdin readable {} chan event stdin readable {}
} }
proc write string { proc write string {

2
src/vfs/_vfscommon.vfs/modules/punk/cap/handlers/templates-0.1.0.tm

@ -95,7 +95,7 @@ namespace eval punk::cap::handlers::templates {
} else { } else {
set tm_exists [file exists $tmfile] set tm_exists [file exists $tmfile]
} }
if {![file exists $tmfile]} { if {!$tm_exists} {
puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - unable to determine base folder for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability" puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - unable to determine base folder for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability"
flush stderr flush stderr
return 0 return 0

2
src/vfs/_vfscommon.vfs/modules/punk/char-0.1.0.tm

@ -1181,7 +1181,7 @@ tcl::namespace::eval punk::char {
} }
puts "ok.. loading" puts "ok.. loading"
set fd [open $file r] set fd [open $file r]
fconfigure $fd -translation binary chan configure $fd -translation binary
set data [read $fd] set data [read $fd]
close $fd close $fd
set block_count 0 set block_count 0

2
src/vfs/_vfscommon.vfs/modules/punk/config-0.1.tm

@ -32,7 +32,7 @@ tcl::namespace::eval punk::config {
if {$exename ne ""} { if {$exename ne ""} {
set exefolder [file dirname $exename] set exefolder [file dirname $exename]
#default file logs to logs folder at same level as exe if writable, or empty string #default file logs to logs folder at same level as exe if writable, or empty string
set log_folder [file normalize $exefolder/../logs] set log_folder [file normalize $exefolder/../logs] ;#~2ms
#tcl::dict::set startup scriptlib $exefolder/scriptlib #tcl::dict::set startup scriptlib $exefolder/scriptlib
#tcl::dict::set startup apps $exefolder/../../punkapps #tcl::dict::set startup apps $exefolder/../../punkapps

6
src/vfs/_vfscommon.vfs/modules/punk/console-0.1.1.tm

@ -777,7 +777,7 @@ namespace eval punk::console {
set extension [lindex [split $waitvar($callid) -] 1] set extension [lindex [split $waitvar($callid) -] 1]
if {$extension eq ""} { if {$extension eq ""} {
puts "blank extension $waitvar($callid)" puts "blank extension $waitvar($callid)"
puts "->[set $waitvar($callid]<-" puts "->[set $waitvar($callid)]<-"
} }
puts stderr "get_ansi_response_payload Extending timeout by $extension" puts stderr "get_ansi_response_payload Extending timeout by $extension"
after cancel $timeoutid($callid) after cancel $timeoutid($callid)
@ -814,7 +814,7 @@ namespace eval punk::console {
#it *might* be ok to restore entire state on an input channel #it *might* be ok to restore entire state on an input channel
#(it's not always on all channels - e.g stdout has -winsize which is read-only) #(it's not always on all channels - e.g stdout has -winsize which is read-only)
#Safest to only restore what we think we've modified. #Safest to only restore what we think we've modified.
fconfigure $input -blocking [dict get $previous_input_state -blocking] chan configure $input -blocking [dict get $previous_input_state -blocking]
@ -1947,7 +1947,7 @@ namespace eval punk::console {
set was_raw 1 set was_raw 1
} }
puts -nonewline stdout \033\[6n ;flush stdout puts -nonewline stdout \033\[6n ;flush stdout
fconfigure stdin -blocking 0 chan configure stdin -blocking 0
set info [read stdin 20] ;# set info [read stdin 20] ;#
after 1 after 1
if {[string first "R" $info] <=0} { if {[string first "R" $info] <=0} {

13
src/vfs/_vfscommon.vfs/modules/punk/fileline-0.1.0.tm

@ -158,7 +158,7 @@ namespace eval punk::fileline::class {
#[para] Constructor for textinfo object which represents a chunk or all of a file #[para] Constructor for textinfo object which represents a chunk or all of a file
#[para] datachunk should be passed with the file data including line-endings as-is for full functionality. ie use something like: #[para] datachunk should be passed with the file data including line-endings as-is for full functionality. ie use something like:
#[example_begin] #[example_begin]
# fconfigure $fd -translation binary # chan configure $fd -translation binary
# set chunkdata [lb]read $fd[rb]] # set chunkdata [lb]read $fd[rb]]
#or #or
# set chunkdata [lb]fileutil::cat <filename> -translation binary[rb] # set chunkdata [lb]fileutil::cat <filename> -translation binary[rb]
@ -1221,8 +1221,11 @@ namespace eval punk::fileline::class {
#o_linemap #o_linemap
set oldsize [string length $o_chunk] set oldsize [string length $o_chunk]
set newchunk "" set newchunk ""
#review - what was the intention here?
puts stderr "regenerate_chunk -warning code incomplete"
dict for {idx lineinfo} $o_linemap { dict for {idx lineinfo} $o_linemap {
set #???
#set
} }
@ -1287,7 +1290,7 @@ namespace eval punk::fileline {
if {$opt_file ne ""} { if {$opt_file ne ""} {
set filename $opt_file set filename $opt_file
set fd [open $filename r] set fd [open $filename r]
fconfigure $fd -translation binary -encoding $opt_translation;#should use translation binary to get actual line-endings - but we allow caller to override chan configure $fd -translation binary -encoding $opt_translation;#should use translation binary to get actual line-endings - but we allow caller to override
#Always read encoding in binary - check for bom below and/or apply chosen opt_encoding #Always read encoding in binary - check for bom below and/or apply chosen opt_encoding
set rawchunk [read $fd] set rawchunk [read $fd]
close $fd close $fd
@ -1360,7 +1363,7 @@ namespace eval punk::fileline {
set bomenc "binary" ;# utf-8??? set bomenc "binary" ;# utf-8???
set startdata 3 set startdata 3
} elseif {$maybe_bom eq "84319533"} { } elseif {$maybe_bom eq "84319533"} {
if {![dict exists [punk::char::page_names_dict gb18030]]} { if {![dict exists [punk::char::page_names_dict gb18030] gb18030]} {
puts stderr "WARNING - no direct support for GB18030 (chinese) - falling back to cp936/gbk" puts stderr "WARNING - no direct support for GB18030 (chinese) - falling back to cp936/gbk"
set bomenc cp936 set bomenc cp936
} else { } else {
@ -1485,7 +1488,7 @@ namespace eval punk::fileline {
proc file_boundary_display {filename startbyte endbyte chunksize args} { proc file_boundary_display {filename startbyte endbyte chunksize args} {
set fd [open $filename r] ;#use default error if file not readable set fd [open $filename r] ;#use default error if file not readable
fconfigure $fd -translation binary chan configure $fd -translation binary
set rawfiledata [read $fd] set rawfiledata [read $fd]
close $fd close $fd
set textobj [class::textinfo new $rawfiledata] set textobj [class::textinfo new $rawfiledata]

31
src/vfs/_vfscommon.vfs/modules/punk/icomm-0.1.0.tm

@ -711,7 +711,6 @@ namespace eval ::punk::icomm {
# #
# Results: # Results:
# None. # None.
proc commConfigure {chan {force 0} args} { proc commConfigure {chan {force 0} args} {
variable comm variable comm
@ -876,9 +875,9 @@ namespace eval ::punk::icomm {
![string equal $encoding $comm($chan,encoding)]} { ![string equal $encoding $comm($chan,encoding)]} {
# This should not be entered yet # This should not be entered yet
set comm($chan,encoding) $encoding set comm($chan,encoding) $encoding
fconfigure $comm($chan,socket) -encoding $encoding chan configure $comm($chan,socket) -encoding $encoding
foreach {i sock} [array get comm $chan,peers,*] { foreach {i sock} [array get comm $chan,peers,*] {
fconfigure $sock -encoding $encoding chan configure $sock -encoding $encoding
} }
} }
@ -936,10 +935,10 @@ namespace eval ::punk::icomm {
set nport [incr comm(lastport)] set nport [incr comm(lastport)]
} }
set comm($chan,socket) $ret set comm($chan,socket) $ret
fconfigure $ret -translation lf -encoding $comm($chan,encoding) chan configure $ret -translation lf -encoding $comm($chan,encoding)
# If port was 0, system allocated it for us # If port was 0, system allocated it for us
set comm($chan,port) [lindex [fconfigure $ret -sockname] 2] set comm($chan,port) [lindex [chan configure $ret -sockname] 2]
return "" return ""
} }
@ -1090,8 +1089,8 @@ namespace eval ::punk::icomm {
# coroutines to hide the CSP and properly handle everything # coroutines to hide the CSP and properly handle everything
# event based. # event based.
fconfigure $fid -blocking 0 chan configure $fid -blocking 0
fileevent $fid readable [list ::punk::icomm::commIncomingOffered $chan $fid $addr $remport] chan event $fid readable [list ::punk::icomm::commIncomingOffered $chan $fid $addr $remport]
return return
} }
@ -1112,8 +1111,8 @@ namespace eval ::punk::icomm {
# Protocol version line has been received, disable event handling # Protocol version line has been received, disable event handling
# again. # again.
fileevent $fid readable {} chan event $fid readable {}
fconfigure $fid -blocking 1 chan configure $fid -blocking 1
# a list of offered proto versions is the first word of first line # a list of offered proto versions is the first word of first line
# remote id is the second word of first line # remote id is the second word of first line
@ -1144,7 +1143,7 @@ namespace eval ::punk::icomm {
if {[dict exists $chanconf -sockname]} { if {[dict exists $chanconf -sockname]} {
# If the remote host addr isn't our local host addr, # If the remote host addr isn't our local host addr,
# then add it to the remote id. # then add it to the remote id.
if {[string equal [lindex [fconfigure $fid -sockname] 0] $addr]} { if {[string equal [lindex [chan configure $fid -sockname] 0] $addr]} {
set id $remid set id $remid
} else { } else {
set id [list $remid $addr] set id [list $remid $addr]
@ -1216,8 +1215,8 @@ namespace eval ::punk::icomm {
set comm($chan,peers,$id) $fid set comm($chan,peers,$id) $fid
} }
set comm($chan,fids,$fid) $id set comm($chan,fids,$fid) $id
fconfigure $fid -translation lf -encoding $comm($chan,encoding) -blocking 0 chan configure $fid -translation lf -encoding $comm($chan,encoding) -blocking 0
fileevent $fid readable [list ::punk::icomm::commCollect $chan $fid] chan event $fid readable [list ::punk::icomm::commCollect $chan $fid]
} }
# ::punk::icomm::commLostConn -- # ::punk::icomm::commLostConn --
@ -1325,7 +1324,7 @@ namespace eval ::punk::icomm {
# ::punk::icomm::commCollect -- # ::punk::icomm::commCollect --
# #
# Internal command. Called from the fileevent to read from fid # Internal command. Called from the chan event to read from fid
# and append to the buffer. This continues until we get a whole # and append to the buffer. This continues until we get a whole
# command, which we then invoke. # command, which we then invoke.
# #
@ -1344,9 +1343,9 @@ namespace eval ::punk::icomm {
if {[catch {read $fid} nbuf] || [eof $fid]} { if {[catch {read $fid} nbuf] || [eof $fid]} {
commDebug {puts stderr "<$chan> collect/lost eof $fid = [eof $fid]"} commDebug {puts stderr "<$chan> collect/lost eof $fid = [eof $fid]"}
commDebug {puts stderr "<$chan> collect/lost nbuf = <$nbuf>"} commDebug {puts stderr "<$chan> collect/lost nbuf = <$nbuf>"}
commDebug {puts stderr "<$chan> collect/lost [fconfigure $fid]"} commDebug {puts stderr "<$chan> collect/lost [chan configure $fid]"}
fileevent $fid readable {} ;# be safe chan event $fid readable {} ;# be safe
commLostConn $chan $fid "target application died or connection lost" commLostConn $chan $fid "target application died or connection lost"
return return
} }
@ -1996,7 +1995,7 @@ proc ::punk::icomm::initlocal {{tcpport 0}} {
if {[string equal macintosh $::tcl_platform(platform)]} { if {[string equal macintosh $::tcl_platform(platform)]} {
::punk::icomm::comm new ::punk::icomm::comm -port 0 -local 0 -listen 1 ::punk::icomm::comm new ::punk::icomm::comm -port 0 -local 0 -listen 1
set ::punk::icomm::comm(localhost) \ set ::punk::icomm::comm(localhost) \
[lindex [fconfigure $::punk::icomm::comm(::punk::icomm::comm,socket) -sockname] 0] [lindex [chan configure $::punk::icomm::comm(::punk::icomm::comm,socket) -sockname] 0]
::punk::icomm::comm config -local 1 ::punk::icomm::comm config -local 1
} else { } else {
::punk::icomm::comm new ::punk::icomm::comm -port 0 -local 1 -listen 1 ::punk::icomm::comm new ::punk::icomm::comm -port 0 -local 1 -listen 1

57
src/vfs/_vfscommon.vfs/modules/punk/imap4-0.9.tm

@ -2744,6 +2744,61 @@ tcl::namespace::eval punk::imap4 {
} }
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval punk::imap4::admin {
tcl::namespace::export {[a-zA-Z]*} ;# Convention: export all lowercase
variable PUNKARGS
variable PUNKARGS_aliases
lappend PUNKARGS [list {
@id -id "::punk::imap4::admin::GETQUOTA"
@cmd -name "punk::imap4::::admin::GETQUOTA" -help\
"Get quota information"
@leaders -min 1 -max 1
chan
@opts
@values -min 1 -max 1
mailbox -help\
"e.g user/account.test"
}]
proc GETQUOTA {args} {
set argd [punk::args::parse $args withid ::punk::imap4::admin::GETQUOTA]
lassign [dict values $argd] leaders opts values received
set chan [dict get $leaders chan]
set mailbox [dict get $values mailbox]
punk::imap4::proto::simplecmd $chan GETQUOTA {AUTH SELECT} $mailbox
}
lappend PUNKARGS [list {
@id -id "::punk::imap4::admin::SETQUOTARESOURCE"
@cmd -name "punk::imap4::admin::SETQUOTARESOURCE" -help\
"Set quota for a resource"
@leaders -min 1 -max 1
chan
@opts
-resource -default STORAGE -help\
"This interface only allows setting of a single resource
at a time."
@values -min 2 -max 2
mailbox -help\
"e.g user/account.test"
quota -type integer -minsize 0 -help\
"Number of 1024 Byte blocks
(KB)"
}]
proc SETQUOTARESOURCE {args} {
set argd [punk::args::parse $args withid ::punk::imap4::admin::SETQUOTARESOURCE]
lassign [dict values $argd] leaders opts values received
set chan [dict get $leaders chan]
set mailbox [dict get $values mailbox]
set resource [dict get $opts -resource]
set quota [dict get $values quota]
punk::imap4::proto::simplecmd $chan SETQUOTA {AUTH SELECT} $mailbox "($resource $quota)"
}
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Secondary API namespace # Secondary API namespace
@ -3294,7 +3349,7 @@ tcl::namespace::eval punk::imap4 {
# variable PUNKARGS_aliases # variable PUNKARGS_aliases
namespace eval ::punk::args::register { namespace eval ::punk::args::register {
#use fully qualified so 8.6 doesn't find existing var in global namespace #use fully qualified so 8.6 doesn't find existing var in global namespace
lappend ::punk::args::register::NAMESPACES ::punk::imap4 ::punk::imap4::proto lappend ::punk::args::register::NAMESPACES ::punk::imap4 ::punk::imap4::admin ::punk::imap4::proto
} }
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------

1
src/vfs/_vfscommon.vfs/modules/punk/jtest.tcl

@ -42,3 +42,4 @@
} }
#test #test
set x blah set x blah

30
src/vfs/_vfscommon.vfs/modules/punk/lib-0.1.1.tm

@ -477,7 +477,7 @@ namespace eval punk::lib {
set asegs [split [string map {:: \uFFFF} $abs] \uFFFF] set asegs [split [string map {:: \uFFFF} $abs] \uFFFF]
set acount [llength $asegs] set acount [llength $asegs]
#puts "alias $abs acount:$acount asegs:$asegs segcount:$segcount segments: $segments" #puts "alias $abs acount:$acount asegs:$asegs segcount:$segcount segments: $segments"
if {[expr {$acount - 1}] == $segcount} { if {($acount - 1) == $segcount} {
if {[lrange $asegs 0 end-1] eq $segments} { if {[lrange $asegs 0 end-1] eq $segments} {
if {[string match $glob [lindex $asegs end]]} { if {[string match $glob [lindex $asegs end]]} {
#report this alias in the current namespace - even though there may be no matching command #report this alias in the current namespace - even though there may be no matching command
@ -2760,7 +2760,7 @@ namespace eval punk::lib {
#[example_end] #[example_end]
puts stdout $question puts stdout $question
flush stdout flush stdout
set stdin_state [fconfigure stdin] set stdin_state [chan configure stdin]
if {[catch { if {[catch {
package require punk::console package require punk::console
set console_raw [tsv::get console is_raw] set console_raw [tsv::get console is_raw]
@ -2769,7 +2769,7 @@ namespace eval punk::lib {
set console_raw 0 set console_raw 0
} }
try { try {
fconfigure stdin -blocking 1 chan configure stdin -blocking 1
if {$console_raw} { if {$console_raw} {
punk::console::disableRaw punk::console::disableRaw
set answer [gets stdin] set answer [gets stdin]
@ -2778,7 +2778,7 @@ namespace eval punk::lib {
set answer [gets stdin] set answer [gets stdin]
} }
} finally { } finally {
fconfigure stdin -blocking [tcl::dict::get $stdin_state -blocking] chan configure stdin -blocking [tcl::dict::get $stdin_state -blocking]
} }
return $answer return $answer
} }
@ -3629,8 +3629,8 @@ namespace eval punk::lib {
set s2 [expr {$s2 + (($time-$average)*($time-$average) / ($iters-1))}] set s2 [expr {$s2 + (($time-$average)*($time-$average) / ($iters-1))}]
} }
set sigma [expr {int(sqrt($s2))}] set sigma [expr {int(sqrt($s2))}]
set average [expr int($average)] set average [expr {int($average)}]
return "$average +/- $sigma microseconds per iteration" return "$average +/- $sigma microseconds per iteration"
} }
@ -3820,10 +3820,10 @@ namespace eval punk::lib {
# First, extract right hand part of number, up to and including decimal point # First, extract right hand part of number, up to and including decimal point
set point [string last "." $number]; set point [string last "." $number];
if {$point >= 0} { if {$point >= 0} {
set PostDecimal [string range $number [expr $point + 1] end]; set PostDecimal [string range $number $point+1 end];
set PostDecimalP 1; set PostDecimalP 1;
} else { } else {
set point [expr [string length $number] + 1] set point [expr {[string length $number] + 1}]
set PostDecimal ""; set PostDecimal "";
set PostDecimalP 0; set PostDecimalP 0;
} }
@ -3834,16 +3834,16 @@ namespace eval punk::lib {
incr ind; incr ind;
} }
set FirstNonSpace $ind; set FirstNonSpace $ind;
set LastSpace [expr $FirstNonSpace - 1]; set LastSpace [expr {$FirstNonSpace - 1}];
set LeadingSpaces [string range $number 0 $LastSpace]; set LeadingSpaces [string range $number 0 $LastSpace];
# Now extract the non-fractional part of the number, omitting leading spaces. # Now extract the non-fractional part of the number, omitting leading spaces.
set MainNumber [string range $number $FirstNonSpace [expr $point -1]]; set MainNumber [string range $number $FirstNonSpace $point-1];
# Insert commas into the non-fractional part. # Insert commas into the non-fractional part.
set Length [string length $MainNumber]; set Length [string length $MainNumber];
set Phase [expr $Length % $GroupSize] set Phase [expr {$Length % $GroupSize}]
set PhaseMinusOne [expr $Phase -1]; set PhaseMinusOne [expr {$Phase -1}];
set DelimitedMain ""; set DelimitedMain "";
#First we deal with the extra stuff. #First we deal with the extra stuff.
@ -3851,7 +3851,7 @@ namespace eval punk::lib {
append DelimitedMain [string range $MainNumber 0 $PhaseMinusOne]; append DelimitedMain [string range $MainNumber 0 $PhaseMinusOne];
} }
set FirstInGroup $Phase; set FirstInGroup $Phase;
set LastInGroup [expr $FirstInGroup + $GroupSize -1]; set LastInGroup [expr {$FirstInGroup + $GroupSize -1}];
while {$LastInGroup < $Length} { while {$LastInGroup < $Length} {
if {$FirstInGroup > 0} { if {$FirstInGroup > 0} {
append DelimitedMain $delim; append DelimitedMain $delim;
@ -3958,8 +3958,12 @@ tcl::namespace::eval punk::lib::flatgrid {
} }
} }
tcl::namespace::eval punk::lib::test {
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#todo - way to generate 'internal' docs separately? #todo - way to generate 'internal' docs separately?
#*** !doctools #*** !doctools

25
src/vfs/_vfscommon.vfs/modules/punk/repl-0.1.1.tm

@ -127,7 +127,7 @@ namespace eval punk::repl {
puts stderr "\n*> repl background error: '$message'" puts stderr "\n*> repl background error: '$message'"
#puts stderr "*> [set ::errorInfo]" #puts stderr "*> [set ::errorInfo]"
puts stderr "*> errorinfo: [dict get $errdict -errorinfo]" puts stderr "*> errorinfo: [dict get $errdict -errorinfo]"
set stdinreader [fileevent stdin readable] set stdinreader [chan event stdin readable]
if {![string length $stdinreader]} { if {![string length $stdinreader]} {
puts stderr "*> stdin reader inactive" puts stderr "*> stdin reader inactive"
} else { } else {
@ -420,14 +420,14 @@ proc repl::start {inchan args} {
puts stderr "-->repl::start active on $inchan $args replthread:[thread::id] codethread:$codethread" puts stderr "-->repl::start active on $inchan $args replthread:[thread::id] codethread:$codethread"
set prompt_config [punk::repl::get_prompt_config] set prompt_config [punk::repl::get_prompt_config]
doprompt "P% " doprompt "P% "
fileevent $inchan readable [list [namespace current]::repl_handler $inchan $prompt_config] chan event $inchan readable [list [namespace current]::repl_handler $inchan $prompt_config]
set reading 1 set reading 1
#catch { #catch {
# set punk::console::tabwidth [punk::console::get_tabstop_apparent_width] # set punk::console::tabwidth [punk::console::get_tabstop_apparent_width]
#} #}
vwait [namespace current]::done vwait [namespace current]::done
fileevent $inchan readable {} chan event $inchan readable {}
#puts stderr "-->start done = $::repl::done" #puts stderr "-->start done = $::repl::done"
@ -1044,7 +1044,6 @@ namespace eval punk::repl::class {
incr i incr i
} }
} }
method add_rendered_chunk {rchunk} { method add_rendered_chunk {rchunk} {
#split only on lf newlines - movement codes and \b \v \r not expected #split only on lf newlines - movement codes and \b \v \r not expected
@ -1328,7 +1327,7 @@ proc repl::repl_handler {inputchan prompt_config} {
set prompt_reset_flag 0 set prompt_reset_flag 0
} }
fileevent $inputchan readable {} chan event $inputchan readable {}
upvar ::punk::console::input_chunks_waiting input_chunks_waiting upvar ::punk::console::input_chunks_waiting input_chunks_waiting
#note -inputmode not available in Tcl 8.6 for chan configure! #note -inputmode not available in Tcl 8.6 for chan configure!
#According to DKF - -buffering option doesn't affect input channels #According to DKF - -buffering option doesn't affect input channels
@ -1543,14 +1542,14 @@ proc repl::repl_handler {inputchan prompt_config} {
#Re-enable channel read handler only if no waiting chunks - must process in order #Re-enable channel read handler only if no waiting chunks - must process in order
################################################################################## ##################################################################################
if {![llength $input_chunks_waiting($inputchan)]} { if {![llength $input_chunks_waiting($inputchan)]} {
fileevent $inputchan readable [list ::repl::repl_handler $inputchan $prompt_config] chan event $inputchan readable [list ::repl::repl_handler $inputchan $prompt_config]
} else { } else {
after idle [list ::repl::repl_handler $inputchan $prompt_config] after idle [list ::repl::repl_handler $inputchan $prompt_config]
} }
#################################################### ####################################################
} else { } else {
#repl_handler_checkchannel $inputchan #repl_handler_checkchannel $inputchan
fileevent $inputchan readable {} chan event $inputchan readable {}
set reading 0 set reading 0
thread::send -async $::repl::codethread {set ::punk::repl::codethread::running 0} thread::send -async $::repl::codethread {set ::punk::repl::codethread::running 0}
if {$::tcl_interactive} { if {$::tcl_interactive} {
@ -1758,7 +1757,7 @@ proc repl::repl_process_data {inputchan chunktype chunk stdinlines prompt_config
# #review # #review
# rputs stderr "->0byte read stdin" # rputs stderr "->0byte read stdin"
# if {[chan eof $inputchan]} { # if {[chan eof $inputchan]} {
# fileevent $inputchan readable {} # chan event $inputchan readable {}
# set reading 0 # set reading 0
# #set running 0 # #set running 0
# if {$::tcl_interactive} { # if {$::tcl_interactive} {
@ -1974,7 +1973,7 @@ proc repl::repl_process_data {inputchan chunktype chunk stdinlines prompt_config
rputs stderr "-------------" rputs stderr "-------------"
rputs stderr "$::errorInfo" rputs stderr "$::errorInfo"
rputs stderr "-------------" rputs stderr "-------------"
set stdinreader [fileevent $inputchan readable] set stdinreader [chan event $inputchan readable]
if {![string length $stdinreader]} { if {![string length $stdinreader]} {
rputs stderr "*> $inputchan reader inactive" rputs stderr "*> $inputchan reader inactive"
} else { } else {
@ -2186,7 +2185,7 @@ proc repl::repl_process_data {inputchan chunktype chunk stdinlines prompt_config
#chan configure stdout -buffering none #chan configure stdout -buffering none
#JMN #JMN
fileevent $inputchan readable {} chan event $inputchan readable {}
set reading 0 set reading 0
#don't let unknown use 'args' to convert commandstr to list #don't let unknown use 'args' to convert commandstr to list
#=============================================================================== #===============================================================================
@ -2530,7 +2529,7 @@ proc repl::repl_process_data {inputchan chunktype chunk stdinlines prompt_config
#append commandstr \n #append commandstr \n
if {$::punk::repl::signal_control_c} { if {$::punk::repl::signal_control_c} {
set ::punk::repl::signal_control_c 0 set ::punk::repl::signal_control_c 0
fileevent $inputchan readable {} chan event $inputchan readable {}
rputs stderr "* console_control: control-c" rputs stderr "* console_control: control-c"
flush stderr flush stderr
set c [a yellow bold] set c [a yellow bold]
@ -2579,7 +2578,7 @@ proc repl::repl_process_data {inputchan chunktype chunk stdinlines prompt_config
} }
#fileevent $inputchan readable [list repl::repl_handler $inputchan $prompt_config] #chan event $inputchan readable [list repl::repl_handler $inputchan $prompt_config]
#catch {puts stderr "zend--->[rep $::arglej]"} #catch {puts stderr "zend--->[rep $::arglej]"}
@ -2591,7 +2590,7 @@ proc repl::repl_process_data {inputchan chunktype chunk stdinlines prompt_config
rputs stderr "-------------" rputs stderr "-------------"
rputs stderr "$::errorInfo" rputs stderr "$::errorInfo"
rputs stderr "-------------" rputs stderr "-------------"
set stdinreader [fileevent $inputchan readable] set stdinreader [chan event $inputchan readable]
if {![string length $stdinreader]} { if {![string length $stdinreader]} {
rputs stderr "*> $inputchan reader inactive" rputs stderr "*> $inputchan reader inactive"
} else { } else {

4
src/vfs/_vfscommon.vfs/modules/punk/sshrun-0.1.0.tm

@ -306,7 +306,7 @@ namespace eval punk::sshrun {
# }] # }]
variable ssh; variable ssh;
system::_verify_connection $host; system::_verify_connection $host;
fileevent $ssh($host,F) $readable_writable $script; chan event $ssh($host,F) $readable_writable $script;
} }
proc hfconfigure {host args} { proc hfconfigure {host args} {
@ -314,7 +314,7 @@ namespace eval punk::sshrun {
# [call hconfigure [arg host] [arg args]] # [call hconfigure [arg host] [arg args]]
variable ssh; variable ssh;
system::_verify_connection $host; system::_verify_connection $host;
eval fconfigure $ssh($host,F) $args; eval chan configure $ssh($host,F) $args;
} }
proc rexec {host script output_varname} { proc rexec {host script output_varname} {

478
src/vfs/_vfscommon.vfs/modules/punk/timeinterval-0.1.0.tm

@ -16,7 +16,7 @@
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Requirements ## Requirements
##e.g package require frobz package require punk::args
@ -27,40 +27,65 @@
# #
namespace eval punk::timeinterval { namespace eval punk::timeinterval {
proc clock_scan_interval { seconds delta units } { #The free-form 'clock scan' is deprecated. It worked in 8.4 to 8.6/8.7 (and earlier?) - but doesn't work in tcl9
# clock_scan_interval formats $seconds to a string for processing by clock scan #proc clock_scan_interval { seconds delta units } {
# then returns new timestamp in seconds # # clock_scan_interval formats $seconds to a string for processing by clock scan
set stamp [clock format $seconds -format "%Y%m%dT%H%M%S"] # # then returns new timestamp in seconds
if { $delta < 0 } { # set stamp [clock format $seconds -format "%Y%m%dT%H%M%S"]
append stamp " - " [expr { abs( $delta ) } ] " " $units # if { $delta < 0 } {
} else { # append stamp " - " [expr { abs( $delta ) } ] " " $units
append stamp " + " $delta " " $units # } else {
} # append stamp " + " $delta " " $units
return [clock scan $stamp] # }
} # return [clock scan $stamp]
#}
#proc clock_scan_interval { seconds delta units } {
# #8.6+
# clock add $seconds $delta $units
#}
namespace export difference namespace export difference
#wrap in dict
proc difference {s1 s2} { lappend PUNKARGS [list {
lassign [interval_ymdhs $s1 $s2] Y M D h m s @id -id "::punk::timeinterval::difference"
return [dict create years $Y months $M days $D hours $h minutes $m seconds $s] @cmd -name "punk::timeinterval::difference" -help\
} "difference calculates the interval of time between
the earliest date and the last date
proc interval_ymdhs { s1 s2 } { by starting to count at the earliest date.
# interval_ymdhs calculates the interval of time between It returns a dictionary with keys:
# the earliest date and the last date years months days hours minutes seconds"
# by starting to count at the earliest date. @opts
-maxunit -default years -choices {years months days hours minutes seconds} -help\
"If maxunit is specified, the resulting dict will still contain all keys,
but keys for larger units will be zero.
e.g when -maxunit is months, years will be zero but months could be
something like 36.
"
-timezone -default "" -help\
"If unspecified, the timezone will be the
current time zone on the system"
@values -min 2 -max 2
s1
s2
}]
proc difference {args} {
set argd [punk::args::parse $args withid ::punk::timeinterval::difference]
lassign [dict values $argd] leaders opts values received
set maxunit [dict get $opts -maxunit]
set timezone [dict get $opts -timezone]
set s1 [dict get $values s1]
set s2 [dict get $values s2]
# This proc has audit features. It will automatically # This proc has audit features. It will automatically
# attempt to correct and report any discrepancies it finds. # attempt to correct and report any discrepancies it finds.
# if s1 and s2 aren't in seconds, convert to seconds. # if s1 and s2 aren't in seconds, convert to seconds.
if { ![string is integer -strict $s1] } { if { ![string is integer -strict $s1] } {
set s1 [clock scan $s1] set s1 [clock scan $s1 -timezone $timezone]
} }
if { ![string is integer -strict $s2] } { if { ![string is integer -strict $s2] } {
set s2 [clock scan $s2] set s2 [clock scan $s2 -timezone $timezone]
} }
# postgreSQL intervals determine month length based on earliest date in interval calculations. # postgreSQL intervals determine month length based on earliest date in interval calculations.
@ -77,69 +102,87 @@ namespace eval punk::timeinterval {
# Calculate years from s1_p0 to s2 # Calculate years from s1_p0 to s2
set y_count 0 set y_count 0
set s1_p0 $s1 set s1_p0 $s1
set s2_y_check $s1_p0 if {$maxunit eq "years"} {
while { $s2_y_check <= $s2 } { set s2_y_check $s1_p0
set s1_p1 $s2_y_check while { $s2_y_check <= $s2 } {
set y $y_count set s1_p1 $s2_y_check
incr y_count set y $y_count
set s2_y_check [clock_scan_interval $s1_p0 $y_count years] incr y_count
} set s2_y_check [clock add $s1_p0 $y_count years -timezone $timezone]
# interval s1_p0 to s1_p1 counted in y years }
# interval s1_p0 to s1_p1 counted in y years
# is the base offset incremented one too much? # is the base offset incremented one too much?
set s2_y_check [clock_scan_interval $s1 $y years] set s2_y_check [clock add $s1 $y years -timezone $timezone]
if { $s2_y_check > $s2 } { if { $s2_y_check > $s2 } {
set y [expr { $y - 1 } ] set y [expr { $y - 1 } ]
set s2_y_check [clock_scan_interval $s1 $y years] set s2_y_check [clock add $s1 $y years -timezone $timezone]
} }
# increment s1 (s1_p0) forward y years to s1_p1 # increment s1 (s1_p0) forward y years to s1_p1
if { $y == 0 } { if { $y == 0 } {
set s1_p1 $s1 set s1_p1 $s1
} else {
set s1_p1 [clock add $s1 $y years -timezone $timezone]
}
} else { } else {
set s1_p1 [clock_scan_interval $s1 $y years] set y 0
set s1_p1 $s1
} }
# interval s1 to s1_p1 counted in y years # interval s1 to s1_p1 counted in y years
# Calculate months from s1_p1 to s2 # Calculate months from s1_p1 to s2
set m_count 0 set m_count 0
set s2_m_check $s1_p1 set s2_m_check $s1_p1
while { $s2_m_check <= $s2 } { set s1_p2 $s1_p1 ;#?
set s1_p2 $s2_m_check set m 0
set m $m_count if {$maxunit in {years months}} {
incr m_count while { $s2_m_check <= $s2 } {
set s2_m_check [clock_scan_interval $s1_p1 $m_count months] set s1_p2 $s2_m_check
set m $m_count
incr m_count
set s2_m_check [clock add $s1_p1 $m_count months -timezone $timezone]
}
} }
# interval s1_p1 to s1_p2 counted in m months # interval s1_p1 to s1_p2 counted in m months
# Calculate interval s1_p2 to s2 in days
# day_in_sec [expr { 60 * 60 * 24 } ] set d 0
# 86400 set s1_p3 $s1_p2
# Since length of month is not relative, use math. if {$maxunit in {years months days}} {
# Clip any fractional part. # Calculate interval s1_p2 to s2 in days
set d [expr { int( ( $s2 - $s1_p2 ) / 86400. ) } ] # day_in_sec [expr { 60 * 60 * 24 } ]
# Ideally, this should always be true, but daylight savings.. # 86400
# so, go backward one day and make hourly steps for last day. # Since length of month is not relative, use math.
if { $d > 0 } { # Clip any fractional part.
incr d -1 set d [expr { int( ( $s2 - $s1_p2 ) / 86400. ) } ]
# Ideally, this should always be true, but daylight savings..
# so, go backward one day and make hourly steps for last day.
if { $d > 0 } {
incr d -1
}
# Move interval from s1_p2 to s1_p3
set s1_p3 [clock add $s1_p2 $d days -timezone $timezone]
} }
# Move interval from s1_p2 to s1_p3
set s1_p3 [clock_scan_interval $s1_p2 $d days]
# s1_p3 is less than a day from s2 # s1_p3 is less than a day from s2
# Calculate interval s1_p3 to s2 in hours set h 0
# hour_in_sec [expr { 60 * 60 } ] set s1_p4 $s1_p3
# 3600 if {$maxunit in {years months days hours}} {
set h [expr { int( ( $s2 - $s1_p3 ) / 3600. ) } ] # Calculate interval s1_p3 to s2 in hours
# Move interval from s1_p3 to s1_p4 # hour_in_sec [expr { 60 * 60 } ]
set s1_p4 [clock_scan_interval $s1_p3 $h hours] # 3600
# s1_p4 is less than an hour from s2 set h [expr { int( ( $s2 - $s1_p3 ) / 3600. ) } ]
# Move interval from s1_p3 to s1_p4
set s1_p4 [clock add $s1_p3 $h hours -timezone $timezone]
# s1_p4 is less than an hour from s2
}
# Sometimes h = 24, yet is already included as a day! # Sometimes h = 24, yet is already included as a day!
# For example, this case: # For example, this case:
# interval_ymdhs 20010410T000000 19570613T000000 # difference 20010410T000000 19570613T000000
# from Age() example in PostgreSQL documentation: # from Age() example in PostgreSQL documentation:
# http://www.postgresql.org/docs/9.1/static/functions-datetime.html # http://www.postgresql.org/docs/9.1/static/functions-datetime.html
# psql test=# select age(timestamp '2001-04-10', timestamp '1957-06-13'); # psql test=# select age(timestamp '2001-04-10', timestamp '1957-06-13');
@ -148,7 +191,7 @@ namespace eval punk::timeinterval {
# 43 years 9 mons 27 days # 43 years 9 mons 27 days
# (1 row) # (1 row)
# According to LibreCalc, the difference is 16007 days # According to LibreCalc, the difference is 16007 days
#puts "s2=s1+16007days? [clock format [clock_scan_interval $s1 16007 days] -format %Y%m%dT%H%M%S]" #puts "s2=s1+16007days? [clock format [clock add $s1 16007 days] -format %Y%m%dT%H%M%S]"
# ^ this calc is consistent with 16007 days # ^ this calc is consistent with 16007 days
# So, let's ignore the Postgresql irregularity for now. # So, let's ignore the Postgresql irregularity for now.
# Here's more background: # Here's more background:
@ -156,133 +199,143 @@ namespace eval punk::timeinterval {
# http://www.postgresql.org/message-id/200707060844.l668i89w097496@wwwmaster.postgresql.org # http://www.postgresql.org/message-id/200707060844.l668i89w097496@wwwmaster.postgresql.org
# So, Postgres had a bug.. # So, Postgres had a bug..
# Sanity check: if over 24 or 48 hours, push it up to a day unit if {$maxunit in {years months days}} {
set h_in_days [expr { int( $h / 24. ) } ] # Sanity check: if over 24 or 48 hours, push it up to a day unit
if { $h >= 1 } { set h_in_days [expr { int( $h / 24. ) } ]
# adjust hours to less than a day if { $h >= 1 } {
set h [expr { $h - ( 24 * $h_in_days ) } ] # adjust hours to less than a day
incr d $h_in_days set h [expr { $h - ( 24 * $h_in_days ) } ]
set h_correction_p 1 incr d $h_in_days
} else { set h_correction_p 1
set h_correction_p 0 } else {
set h_correction_p 0
}
} }
# Calculate interval s1_p4 to s2 in minutes
# minute_in_sec [expr { 60 } ]
# 60
set mm [expr { int( ( $s2 - $s1_p4 ) / 60. ) } ]
# Move interval from s1_p4 to s1_p5
set s1_p5 [clock_scan_interval $s1_p4 $mm minutes]
# Sanity check: if 60 minutes, push it up to an hour unit set mm 0
if { $mm >= 60 } { set s1_p5 $s1_p4
# adjust 60 minutes to 1 hour if {$maxunit in {years months days hours minutes}} {
# puts "interval_ymdhs: debug info mm - 60, h + 1" # Calculate interval s1_p4 to s2 in minutes
set mm [expr { $mm - 60 } ] # minute_in_sec [expr { 60 } ]
incr h # 60
set mm_correction_p 1 set mm [expr { int( ( $s2 - $s1_p4 ) / 60. ) } ]
} else { # Move interval from s1_p4 to s1_p5
set mm_correction_p 0 set s1_p5 [clock add $s1_p4 $mm minutes -timezone $timezone]
}
if {$maxunit in {years months days hours}} {
# Sanity check: if 60 minutes, push it up to an hour unit
if { $mm >= 60 } {
# adjust 60 minutes to 1 hour
# puts "difference: debug info mm - 60, h + 1"
set mm [expr { $mm - 60 } ]
incr h
set mm_correction_p 1
} else {
set mm_correction_p 0
}
} }
# Calculate interval s1_p5 to s2 in seconds # Calculate interval s1_p5 to s2 in seconds
set s [expr { int( $s2 - $s1_p5 ) } ] set s [expr { int( $s2 - $s1_p5 ) } ]
# Sanity check: if 60 seconds, push it up to one minute unit if {$maxunit in {years months days hours minutes}} {
if { $s >= 60 } { # Sanity check: if 60 seconds, push it up to one minute unit
# adjust 60 minutes to 1 hour if { $s >= 60 } {
set s [expr { $s - 60 } ] # adjust 60 minutes to 1 hour
incr mm set s [expr { $s - 60 } ]
set s_correction_p 1 incr mm
} else { set s_correction_p 1
set s_correction_p 0 } else {
set s_correction_p 0
}
} }
set return_list [list $y $m $d $h $mm $s] #set return_list [list $y $m $d $h $mm $s]
set return_list [dict create years $y months $m days $d hours $h minutes $mm seconds $s]
# test results by adding difference to s1 to get s2: # test results by adding difference to s1 to get s2:
set i 0
set s1_test [clock format $s1 -format "%Y%m%dT%H%M%S"]
set signs_inconsistent_p 0 set signs_inconsistent_p 0
foreach unit {years months days hours minutes seconds} { set diffterms [list]
set t_term [lindex $return_list $i] dict for {unit t_term} $return_list {
if { $t_term != 0 } { if {$t_term != 0} {
if { $t_term > 0 } { if { $t_term > 0 } {
append s1_test " + $t_term $unit" lappend diffterms +$t_term $unit
} else { } else {
append s1_test " - [expr { abs( $t_term ) } ] $unit" lappend diffterms -[expr { abs( $t_term ) }] $unit
set signs_inconsistent_p 1 set signs_inconsistent_p 1
} }
} }
incr i
} }
set s2_test [clock scan $s1_test]
# puts "test s2 '$s2_test' from: '$s1_test'" #set s2_test [clock scan $s1_test]
set counter 0 set s2_test [clock add $s1 {*}$diffterms -timezone $timezone]
# puts "test s2 '$s2_test' from: '$s1_test'"
set counter 0
while { $s2 ne $s2_test && $counter < 30 } { while { $s2 ne $s2_test && $counter < 30 } {
set s2_diff [expr { $s2_test - $s2 } ] set s2_diff [expr { $s2_test - $s2 } ]
puts "\ninterval_ymdhs: debug s1 $s1 s2 $s2 y $y m $m d $d h $h s $s s2_diff $s2_diff" puts "difference: debug s1 $s1 s2 $s2 y $y m $m d $d h $h s $s s2_diff $s2_diff"
set absdiff [expr {abs($s2_diff)}] set absdiff [expr {abs($s2_diff)}]
if { $absdiff > 86399 } { if { $absdiff > 86399 } {
if { $s2_diff > 0 } { if { $s2_diff > 0 } {
incr d -1 incr d -1
puts "interval_ymdhs: debug, audit adjustment. decreasing 1 day to $d" puts "difference: debug, audit adjustment. decreasing 1 day to $d"
} else { } else {
incr d incr d
puts "interval_ymdhs: debug, audit adjustment. increasing 1 day to $d" puts "difference: debug, audit adjustment. increasing 1 day to $d"
} }
} elseif { $absdiff > 3599 } { } elseif { $absdiff > 3599 } {
if { $s2_diff > 0 } { if { $s2_diff > 0 } {
incr h -1 incr h -1
puts "interval_ymdhs: debug, audit adjustment. decreasing 1 hour to $h" puts "difference: debug, audit adjustment. decreasing 1 hour to $h"
} else { } else {
incr h incr h
puts "interval_ymdhs: debug, audit adjustment. increasing 1 hour to $h" puts "difference: debug, audit adjustment. increasing 1 hour to $h"
} }
} elseif { $absdiff > 59 } { } elseif { $absdiff > 59 } {
if { $s2_diff > 0 } { if { $s2_diff > 0 } {
incr mm -1 incr mm -1
puts "interval_ymdhs: debug, audit adjustment. decreasing 1 minute to $mm" puts "difference: debug, audit adjustment. decreasing 1 minute to $mm"
} else { } else {
incr mm incr mm
puts "interval_ymdhs: debug, audit adjustment. increasing 1 minute to $mm" puts "difference: debug, audit adjustment. increasing 1 minute to $mm"
} }
} elseif { $absdiff > 0 } { } elseif { $absdiff > 0 } {
if { $s2_diff > 0 } { if { $s2_diff > 0 } {
incr s -1 incr s -1
puts "interval_ymdhs: debug, audit adjustment. decreasing 1 second to $s" puts "difference: debug, audit adjustment. decreasing 1 second to $s"
} else { } else {
incr s incr s
puts "interval_ymdhs: debug, audit adjustment. increasing 1 second to $s" puts "difference: debug, audit adjustment. increasing 1 second to $s"
} }
} }
set return_list [list $y $m $d $h $mm $s] set return_list [dict create years $y months $m days $d hours $h minutes $mm seconds $s]
# set return_list [list [expr { abs($y) } ] [expr { abs($m) } ] [expr { abs($d) } ] [expr { abs($h) } ] [expr { abs($mm) } ] [expr { abs($s) } ]] # set return_list [list [expr { abs($y) } ] [expr { abs($m) } ] [expr { abs($d) } ] [expr { abs($h) } ] [expr { abs($mm) } ] [expr { abs($s) } ]]
# test results by adding difference to s1 to get s2: # test results by adding difference to s1 to get s2:
set i 0 set diffterms [list]
set s1_test [clock format $s1 -format "%Y%m%dT%H%M%S"] dict for {unit t_term} $return_list {
foreach unit {years months days hours minutes seconds} {
set t_term [lindex $return_list $i]
if { $t_term != 0 } { if { $t_term != 0 } {
if { $t_term > 0 } { if { $t_term > 0 } {
append s1_test " + $t_term $unit" lappend diffterms +$t_term $unit
} else { } else {
append s1_test " - [expr { abs( $t_term ) } ] $unit" lappend diffterms -[expr { abs( $t_term ) }] $unit
} }
} }
incr i
} }
set s2_test [clock scan $s1_test] set s2_test [clock add $s1 {*}$diffterms -timezone $timezone]
incr counter incr counter
} }
if { ( $counter > 0 || $signs_inconsistent_p ) && ( $h_correction_p || $mm_correction_p || $s_correction_p ) } { #if { ( $counter > 0 || $signs_inconsistent_p ) && ( $h_correction_p || $mm_correction_p || $s_correction_p ) } {
# puts "interval_ymdhs: Corrections in the main calculation were applied: h ${h_correction_p}, mm ${mm_correction_p}, s ${s_correction_p}" # puts "difference: Corrections in the main calculation were applied: h ${h_correction_p}, mm ${mm_correction_p}, s ${s_correction_p}"
} #}
if { $signs_inconsistent_p } { if { $signs_inconsistent_p } {
puts "\ninterval_ymdhs: signs inconsistent y $y m $m d $d h $h mm $mm s $s" puts "\punk::timeinterval::difference - signs inconsistent y $y m $m d $d h $h mm $mm s $s"
} }
if { $s2 eq $s2_test } { if { $s2 eq $s2_test } {
return $return_list return $return_list
@ -290,23 +343,19 @@ namespace eval punk::timeinterval {
set s2_diff [expr { $s2_test - $s2 } ] set s2_diff [expr { $s2_test - $s2 } ]
puts "debug s1 $s1 s1_p1 $s1_p1 s1_p2 $s1_p2 s1_p3 $s1_p3 s1_p4 $s1_p4" puts "debug s1 $s1 s1_p1 $s1_p1 s1_p2 $s1_p2 s1_p3 $s1_p3 s1_p4 $s1_p4"
puts "debug y $y m $m d $d h $h mm $mm s $s" puts "debug y $y m $m d $d h $h mm $mm s $s"
puts "interval_ymdhs error: s2 is '$s2' but s2_test is '$s2_test' a difference of ${s2_diff} from s1 '$s1_test'." puts "punk::timeinterval::difference - error: s2 is '$s2' but s2_test is '$s2_test' a difference of ${s2_diff} from s1 '$s1_test'."
# error "result audit fails" "error: s2 is $s2 but s2_test is '$s2_test' a difference of ${s2_diff} from: '$s1_test'." error "punk::timeinterval::difference result audit fail" "error: s2 is $s2 but s2_test is '$s2_test' a difference of ${s2_diff} from: '$s1_test'."
} }
} }
proc interval_ymdhs_w_units { t1 t2 } {
# interval_ymdhs_w_units }
# returns interval_ymdhs values with units
set v_list [interval_ymdhs $t2 $t1] tcl::namespace::eval punk::timeinterval::experimental {
set i 0 #The interval_remains.. functions were part of the original code from the wiki
set a "" #Updated to use clock add etc - but the result seems to be off by one for the value of days - review
foreach f {years months days hours minutes seconds} { #The original purpose of these functions isn't clearly understood - perhaps it was just a different
append a "[lindex $v_list $i] $f \n" #mechanism to calculate the interval as a crosscheck?
incr i
}
return $a
}
proc interval_remains_ymdhs { s1 s2 } { proc interval_remains_ymdhs { s1 s2 } {
@ -342,7 +391,7 @@ namespace eval punk::timeinterval {
set s1_p1 $s2_y_check set s1_p1 $s2_y_check
set y $y_count set y $y_count
incr y_count -1 incr y_count -1
set s2_y_check [clock_scan_interval $s1_p0 $y_count years] set s2_y_check [clock add $s1_p0 $y_count years]
} }
# interval s1_p0 to s1_p1 counted in y years # interval s1_p0 to s1_p1 counted in y years
@ -354,7 +403,7 @@ namespace eval punk::timeinterval {
set s1_p2 $s2_m_check set s1_p2 $s2_m_check
set m $m_count set m $m_count
incr m_count -1 incr m_count -1
set s2_m_check [clock_scan_interval $s1_p1 $m_count months] set s2_m_check [clock add $s1_p1 $m_count months]
} }
# interval s1_p1 to s1_p2 counted in m months # interval s1_p1 to s1_p2 counted in m months
@ -371,7 +420,7 @@ namespace eval punk::timeinterval {
} }
# Move interval from s1_p2 to s1_p3 # Move interval from s1_p2 to s1_p3
set s1_p3 [clock_scan_interval $s1_p2 $d days] set s1_p3 [clock add $s1_p2 $d days]
# s1_p3 is less than a day from s2 # s1_p3 is less than a day from s2
@ -380,7 +429,7 @@ namespace eval punk::timeinterval {
# 3600 # 3600
set h [expr { int( ceil( ( $s2 - $s1_p3 ) / 3600. ) ) } ] set h [expr { int( ceil( ( $s2 - $s1_p3 ) / 3600. ) ) } ]
# Move interval from s1_p3 to s1_p4 # Move interval from s1_p3 to s1_p4
set s1_p4 [clock_scan_interval $s1_p3 $h hours] set s1_p4 [clock add $s1_p3 $h hours]
# s1_p4 is less than an hour from s2 # s1_p4 is less than an hour from s2
# Sanity check: if over 24 or 48 hours, push it up to a day unit # Sanity check: if over 24 or 48 hours, push it up to a day unit
@ -399,7 +448,7 @@ namespace eval punk::timeinterval {
# 60 # 60
set mm [expr { int( ceil( ( $s2 - $s1_p4 ) / 60. ) ) } ] set mm [expr { int( ceil( ( $s2 - $s1_p4 ) / 60. ) ) } ]
# Move interval from s1_p4 to s1_p5 # Move interval from s1_p4 to s1_p5
set s1_p5 [clock_scan_interval $s1_p4 $mm minutes] set s1_p5 [clock add $s1_p4 $mm minutes]
# Sanity check: if 60 minutes, push it up to an hour unit # Sanity check: if 60 minutes, push it up to an hour unit
if { $mm <= -60 } { if { $mm <= -60 } {
@ -430,21 +479,25 @@ namespace eval punk::timeinterval {
# test results by adding difference to s1 to get s2: # test results by adding difference to s1 to get s2:
set i 0 set i 0
set s1_test [clock format $s1 -format "%Y%m%dT%H%M%S"] #set s1_test [clock format $s1 -format "%Y%m%dT%H%M%S"]
set signs_inconsistent_p 0 set signs_inconsistent_p 0
set diffterms [list]
foreach unit {years months days hours minutes seconds} { foreach unit {years months days hours minutes seconds} {
set t_term [lindex $return_list $i] set t_term [lindex $return_list $i]
if { $t_term != 0 } { if { $t_term != 0 } {
if { $t_term > 0 } { if { $t_term > 0 } {
append s1_test " + $t_term $unit" #append s1_test " + $t_term $unit"
lappend diffterms +$t_term $unit
set signs_inconsistent_p 1 set signs_inconsistent_p 1
} else { } else {
append s1_test " - [expr { abs( $t_term ) } ] $unit" #append s1_test " - [expr { abs( $t_term ) } ] $unit"
lappend diffterms -[expr { abs( $t_term ) } ] $unit
} }
} }
incr i incr i
} }
set s2_test [clock scan $s1_test] #set s2_test [clock scan $s1_test]
set s2_test [clock add $s1 {*}$diffterms]
set counter 0 set counter 0
while { $s2 ne $s2_test && $counter < 3 } { while { $s2 ne $s2_test && $counter < 3 } {
@ -490,19 +543,23 @@ namespace eval punk::timeinterval {
# test results by adding difference to s1 to get s2: # test results by adding difference to s1 to get s2:
set i 0 set i 0
set s1_test [clock format $s1 -format "%Y%m%dT%H%M%S"] #set s1_test [clock format $s1 -format "%Y%m%dT%H%M%S"]
set diffterms [list]
foreach unit {years months days hours minutes seconds} { foreach unit {years months days hours minutes seconds} {
set t_term [lindex $return_list $i] set t_term [lindex $return_list $i]
if { $t_term != 0 } { if { $t_term != 0 } {
if { $t_term > 0 } { if { $t_term > 0 } {
append s1_test " + $t_term $unit" #append s1_test " + $t_term $unit"
lappend diffterms +$t_term $unit
} else { } else {
append s1_test " - [expr { abs( $t_term ) } ] $unit" #append s1_test " - [expr { abs( $t_term ) } ] $unit"
lappend diffterms -[expr { abs( $t_term ) } ] $unit
} }
} }
incr i incr i
} }
set s2_test [clock scan $s1_test] #set s2_test [clock scan $s1_test]
set s2_test [clock add $s1 {*}$diffterms]
incr counter incr counter
} }
if { ( $counter > 0 || $signs_inconsistent_p ) && ( $h_correction_p || $mm_correction_p || $s_correction_p ) } { if { ( $counter > 0 || $signs_inconsistent_p ) && ( $h_correction_p || $mm_correction_p || $s_correction_p ) } {
@ -523,10 +580,11 @@ namespace eval punk::timeinterval {
} }
proc interval_remains_ymdhs_w_units { t1 t2 } { proc interval_remains_ymdhs_w_units { t1 t2 } {
# interval_remains_ymdhs_w_units # interval_remains_ymdhs_w_units
# returns interval_remains_ymdhs values with units # returns interval_remains_ymdhs values with units
set v_list [interval_ymdhs $t2 $t1] set v_list [interval_remains_ymdhs $t2 $t1]
set i 0 set i 0
set a "" set a ""
foreach f {years months days hours minutes seconds} { foreach f {years months days hours minutes seconds} {
@ -541,9 +599,105 @@ namespace eval punk::timeinterval {
# == === === === === === === === === === === === === === ===
# Sample 'about' function with punk::args documentation
# == === === === === === === === === === === === === === ===
tcl::namespace::eval punk::timeinterval {
tcl::namespace::export {[a-zA-Z]*} ;# Convention: export all lowercase
variable PUNKARGS
variable PUNKARGS_aliases
lappend PUNKARGS [list {
@id -id "(package)punk::timeinterval"
@package -name "punk::timeinterval" -help\
"time interval from wiki"
}]
namespace eval argdoc {
#namespace for custom argument documentation
proc package_name {} {
return punk::timeinterval
}
proc about_topics {} {
#info commands results are returned in an arbitrary order (like array keys)
set topic_funs [info commands [namespace current]::get_topic_*]
set about_topics [list]
foreach f $topic_funs {
set tail [namespace tail $f]
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]
}
proc default_topics {} {return [list Description *]}
# -------------------------------------------------------------
# get_topic_ functions add more to auto-include in about topics
# -------------------------------------------------------------
proc get_topic_Description {} {
punk::args::lib::tstr [string trim {
package punk::timeinterval
basic time interval calculations
} \n]
}
proc get_topic_License {} {
return "X11"
}
proc get_topic_Version {} {
return "$::punk::timeinterval::version"
}
proc get_topic_Contributors {} {
set authors {{various "https://wiki.tcl-lang.org/page/Measuring+time+intervals+%28between+two+timestamps%29+with+months+etc"} {Julian Noble <julian@precisium.com.au>}}
set contributors ""
foreach a $authors {
append contributors $a \n
}
if {[string index $contributors end] eq "\n"} {
set contributors [string range $contributors 0 end-1]
}
return $contributors
}
proc get_topic_notes {} {
punk::args::lib::tstr -return string {
X11 license - is MIT with additional clause regarding use of contributor names.
}
}
# -------------------------------------------------------------
}
# we re-use the argument definition from punk::args::standard_about and override some items
set overrides [dict create]
dict set overrides @id -id "::punk::timeinterval::about"
dict set overrides @cmd -name "punk::timeinterval::about"
dict set overrides @cmd -help [string trim [punk::args::lib::tstr {
About punk::timeinterval
}] \n]
dict set overrides topic -choices [list {*}[punk::timeinterval::argdoc::about_topics] *]
dict set overrides topic -choicerestricted 1
dict set overrides topic -default [punk::timeinterval::argdoc::default_topics] ;#if -default is present 'topic' will always appear in parsed 'values' dict
set newdef [punk::args::resolved_def -antiglobs -package_about_namespace -override $overrides ::punk::args::package::standard_about *]
lappend PUNKARGS [list $newdef]
proc about {args} {
package require punk::args
#standard_about accepts additional choices for topic - but we need to normalize any abbreviations to full topic name before passing on
set argd [punk::args::parse $args withid ::punk::timeinterval::about]
lassign [dict values $argd] _leaders opts values _received
punk::args::package::standard_about -package_about_namespace ::punk::timeinterval::argdoc {*}$opts {*}[dict get $values topic]
}
}
# end of sample 'about' function
# == === === === === === === === === === === === === === ===
# -----------------------------------------------------------------------------
# register namespace(s) to have PUNKARGS,PUNKARGS_aliases variables checked
# -----------------------------------------------------------------------------
# variable PUNKARGS
# variable PUNKARGS_aliases
namespace eval ::punk::args::register {
#use fully qualified so 8.6 doesn't find existing var in global namespace
lappend ::punk::args::register::NAMESPACES ::punk::timeinterval
}

14
src/vfs/_vfscommon.vfs/modules/punk/winrun-0.1.0.tm

@ -37,7 +37,7 @@ namespace eval punk::winrun {
} }
proc readchild_handler {chan hpid} { proc readchild_handler {chan hpid} {
#fileevent $chan readable {} #chan event $chan readable {}
set data [read $chan 4096] set data [read $chan 4096]
while {![chan blocked $chan] && ![eof $chan]} { while {![chan blocked $chan] && ![eof $chan]} {
append data [read $chan 4096] append data [read $chan 4096]
@ -46,19 +46,19 @@ namespace eval punk::winrun {
flush stdout flush stdout
if {![eof $chan]} { if {![eof $chan]} {
puts stdout "not eof $chan [fconfigure $chan] chan blocked:[chan blocked $chan]" puts stdout "not eof $chan [fconfigure $chan] chan blocked:[chan blocked $chan]"
#fileevent $chan readable [list punk::winrun::readchild_handler $chan $hpid] #chan event $chan readable [list punk::winrun::readchild_handler $chan $hpid]
} else { } else {
#puts "eof: waiting exit process" #puts "eof: waiting exit process"
set punk::winrun::waitresult [twapi::wait_on_handle $hpid -wait -1] set punk::winrun::waitresult [twapi::wait_on_handle $hpid -wait -1]
} }
} }
proc readchilderr_handler {chan} { proc readchilderr_handler {chan} {
fileevent $chan readable {} chan event $chan readable {}
set data [read $chan] set data [read $chan]
puts stderr "err: $data" puts stderr "err: $data"
flush stderr flush stderr
if {![eof $chan]} { if {![eof $chan]} {
fileevent $chan readable [list punk::winrun::readchild_handler $chan] chan event $chan readable [list punk::winrun::readchild_handler $chan]
} }
} }
@ -81,7 +81,7 @@ namespace eval punk::winrun {
#after 1000 #after 1000
chan configure $readout -blocking 0 chan configure $readout -blocking 0
fileevent $readout readable [list readchild_handler $readout $hpid] chan event $readout readable [list readchild_handler $readout $hpid]
puts stdout "input: [chan configure $writein]" puts stdout "input: [chan configure $writein]"
puts $writein "puts stdout blah;" puts $writein "puts stdout blah;"
flush $writein flush $writein
@ -106,8 +106,8 @@ namespace eval punk::winrun {
if {$waitresult eq "timeout"} { if {$waitresult eq "timeout"} {
puts stderr "tw_run: timeout waiting for process" puts stderr "tw_run: timeout waiting for process"
} }
fileevent $readout readable {} chan event $readout readable {}
fileevent $readerr readable {} chan event $readerr readable {}
set code [twapi::get_process_exit_code $hpid] set code [twapi::get_process_exit_code $hpid]
twapi::close_handle $htid twapi::close_handle $htid

2
src/vfs/_vfscommon.vfs/modules/punkcheck-0.1.0.tm

@ -86,7 +86,7 @@ namespace eval punkcheck {
set linecount [llength [split $newtdl \n]] set linecount [llength [split $newtdl \n]]
#puts stdout $newtdl #puts stdout $newtdl
set fd [open $punkcheck_file w] set fd [open $punkcheck_file w]
fconfigure $fd -translation binary chan configure $fd -translation binary
puts -nonewline $fd $newtdl puts -nonewline $fd $newtdl
close $fd close $fd
return [list recordcount [llength $recordlist] linecount $linecount] return [list recordcount [llength $recordlist] linecount $linecount]

11
src/vfs/_vfscommon.vfs/modules/shellrun-0.1.1.tm

@ -283,7 +283,8 @@ namespace eval shellrun {
#exitcode not part of return value for runout - colourcode appropriately #exitcode not part of return value for runout - colourcode appropriately
set n $RST set n $RST
set c "" set c ""
if [dict exists $exitinfo exitcode] {
if {[dict exists $exitinfo exitcode]} {
set code [dict get $exitinfo exitcode] set code [dict get $exitinfo exitcode]
if {$code == 0} { if {$code == 0} {
set c [a+ green] set c [a+ green]
@ -291,7 +292,7 @@ namespace eval shellrun {
set c [a+ white bold] set c [a+ white bold]
} }
lappend chunklist [list "info" "$c$exitinfo$n"] lappend chunklist [list "info" "$c$exitinfo$n"]
} elseif [dict exists $exitinfo error] { } elseif {[dict exists $exitinfo error]} {
set c [a+ yellow bold] set c [a+ yellow bold]
lappend chunklist [list "info" "${c}error [dict get $exitinfo error]$n"] lappend chunklist [list "info" "${c}error [dict get $exitinfo error]$n"]
lappend chunklist [list "info" "errorCode [dict get $exitinfo errorCode]"] lappend chunklist [list "info" "errorCode [dict get $exitinfo errorCode]"]
@ -398,17 +399,15 @@ namespace eval shellrun {
set n [a] set n [a]
set c "" set c ""
if [dict exists $exitinfo exitcode] { if {[dict exists $exitinfo exitcode]} {
set code [dict get $exitinfo exitcode] set code [dict get $exitinfo exitcode]
if {$code == 0} { if {$code == 0} {
set c [a+ green] set c [a+ green]
} else { } else {
set c [a+ white bold] set c [a+ white bold]
} }
lappend chunklist [list "info" "$c$exitinfo$n"] lappend chunklist [list "info" "$c$exitinfo$n"]
} elseif {[dict exists $exitinfo error]} {
} elseif [dict exists $exitinfo error] {
set c [a+ yellow bold] set c [a+ yellow bold]
lappend chunklist [list "info" "error [dict get $exitinfo error]"] lappend chunklist [list "info" "error [dict get $exitinfo error]"]
lappend chunklist [list "info" "errorCode [dict get $exitinfo errorCode]"] lappend chunklist [list "info" "errorCode [dict get $exitinfo errorCode]"]

12
src/vfs/_vfscommon.vfs/modules/shellthread-1.6.1.tm

@ -209,10 +209,10 @@ namespace eval shellthread::worker {
variable sysloghost_port variable sysloghost_port
variable sock variable sock
if {[string length $sysloghost_port]} { if {[string length $sysloghost_port]} {
if {[catch {fconfigure $sock} state]} { if {[catch {chan configure $sock} state]} {
set sock [udp_open] set sock [udp_open]
fconfigure $sock -buffering none -translation binary chan configure $sock -buffering none -translation binary
fconfigure $sock -remote $sysloghost_port chan configure $sock -remote $sysloghost_port
} }
} }
} }
@ -220,7 +220,7 @@ namespace eval shellthread::worker {
variable sock variable sock
catch {close $sock} catch {close $sock}
_initsock _initsock
return [fconfigure $sock] return [chan configure $sock]
} }
proc send_info {client_tid ts_sent source msg} { proc send_info {client_tid ts_sent source msg} {
@ -436,7 +436,7 @@ namespace eval shellthread::manager {
# todo - some protection mechanism for case where target is a file to stop creation of multiple worker threads writing to same file. # todo - some protection mechanism for case where target is a file to stop creation of multiple worker threads writing to same file.
# Even if we use open fd,close fd wrapped around writes.. it is probably undesirable to have multiple threads with same target # Even if we use open fd,close fd wrapped around writes.. it is probably undesirable to have multiple threads with same target
# On the other hand socket targets such as UDP can happily be written to by multiple threads. # On the other hand socket targets such as UDP can happily be written to by multiple threads.
# For now the mechanism is that a call to new_worker (rename to open_worker?) will join the same thread if a sourcetag matches.. # For now the mechanism is that a call to new_worker (rename to open_worker?) will join the same thread if a sourcetag matches.
# but, as sourcetags can get removed(unsubbed via leave_worker) this doesn't guarantee two threads with same -file settings won't fight. # but, as sourcetags can get removed(unsubbed via leave_worker) this doesn't guarantee two threads with same -file settings won't fight.
# Also.. the settingsdict is ignored when joining with a tag that exists.. this is problematic.. e.g logrotation where previous file still being written by existing worker # Also.. the settingsdict is ignored when joining with a tag that exists.. this is problematic.. e.g logrotation where previous file still being written by existing worker
# todo - rename 'sourcetag' concept to 'targettag' ?? the concept is a mixture of both.. it is somewhat analagous to a syslog 'facility' # todo - rename 'sourcetag' concept to 'targettag' ?? the concept is a mixture of both.. it is somewhat analagous to a syslog 'facility'
@ -751,7 +751,7 @@ namespace eval shellthread::manager {
set ts_end_list [dict get $workers $source ts_end_list] ;#ts_end_list is just a list of timestamps of closing calls for this source - only one is needed to close, but they may all come in a flurry. set ts_end_list [dict get $workers $source ts_end_list] ;#ts_end_list is just a list of timestamps of closing calls for this source - only one is needed to close, but they may all come in a flurry.
if {[llength $ts_end_list]} { if {[llength $ts_end_list]} {
set last_end_ts [lindex $ts_end_list end] set last_end_ts [lindex $ts_end_list end]
if {[expr {(($tsnow - $last_end_ts) / 1000) >= $timeout}]} { if {(($tsnow - $last_end_ts) / 1000) >= $timeout} {
lappend ts_end_list $ts_now lappend ts_end_list $ts_now
dict set workers $source ts_end_list $ts_end_list dict set workers $source ts_end_list $ts_end_list
} else { } else {

6
src/vfs/_vfscommon.vfs/modules/textblock-0.1.3.tm

@ -663,7 +663,7 @@ tcl::namespace::eval textblock {
switch -- $k { switch -- $k {
-ansibase_header - -ansibase_body - -ansiborder_header - -ansiborder-body - -ansiborder_footer { -ansibase_header - -ansibase_body - -ansiborder_header - -ansiborder-body - -ansiborder_footer {
set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]" set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]"
set ansi_codes [list] ; set ansi_codes [list]
foreach {pt code} $parts { foreach {pt code} $parts {
if {$pt ne ""} { if {$pt ne ""} {
#we don't expect plaintext in an ansibase #we don't expect plaintext in an ansibase
@ -1109,7 +1109,7 @@ tcl::namespace::eval textblock {
} }
-ansibase { -ansibase {
set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]" set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]"
set col_ansibase_items [list] ; set col_ansibase_items [list]
foreach {pt code} $parts { foreach {pt code} $parts {
if {$pt ne ""} { if {$pt ne ""} {
#we don't expect plaintext in an ansibase #we don't expect plaintext in an ansibase
@ -7852,7 +7852,7 @@ tcl::namespace::eval textblock {
foreach {k v} $optlist { foreach {k v} $optlist {
set k2 [tcl::prefix::match -error "" $optnames $k] set k2 [tcl::prefix::match -error "" $optnames $k]
switch -- $k2 { switch -- $k2 {
-etabs - -type - -boxlimits - -boxmap - -joins -etabs - -type - -boxlimits - -boxmap - -join
- -title - -titlealign - -subtitle - -subtitlealign - -width - -height - -title - -titlealign - -subtitle - -subtitlealign - -width - -height
- -ansiborder - -ansibase - -ansiborder - -ansibase
- -blockalign - -textalign - -ellipsis - -blockalign - -textalign - -ellipsis

153
src/vfs/_vfscommon.vfs/modules/winlibreoffice-0.1.0.tm

@ -28,13 +28,14 @@ if {"windows" eq $::tcl_platform(platform)} {
puts stderr "Minimal functionality - only some utils may work" puts stderr "Minimal functionality - only some utils may work"
} }
} else { } else {
puts stderr "Package requires twapi. No current equivalent on non-windows platform. Try tcluno http://sf.net/projets/tcluno " puts stderr "Package requires twapi. No current equivalent on non-windows platform. Try tcluno http://sf.net/projets/tcluno"
puts stderr "Minimal functionality - only some utils may work" puts stderr "Minimal functionality - only some utils may work"
} }
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval winlibreoffice { namespace eval winlibreoffice {
namespace export from_libre_date to_libre_date
#--- #---
#todo: investigate tcluno package http://sf.net/projects/tcluno #todo: investigate tcluno package http://sf.net/projects/tcluno
#CPlusPlus - platforms? #CPlusPlus - platforms?
@ -212,31 +213,133 @@ namespace eval winlibreoffice {
#ULTRABOLD 175.0 #ULTRABOLD 175.0
#BLACK 200.0 #BLACK 200.0
lappend PUNKARGS [list {
@id -id ::winlibreoffice::to_libre_date
@cmd -name winlibreoffice::to_libre_date -help\
"Return an internal Libre Office date/time floating point
number representing the number of days between 1899-12-30
and the supplied time.
e.g
% to_libre_date 2025-02-28T060000
45716.25
% to_libre_date 2025-01-01T060101
45658.250706018516
"
@opts
-timezone -default "" -help\
"If unspecified, the timezone will be the
current time zone on the system"
@values -min 1 -max 1
time -type string -help\
"A unix timestamp as output by 'clock seconds'
or a text timestamp such as 2025-01-03T000000
parseable by 'clock scan'"
}]
proc to_libre_date {args} {
package require punk::args
set argd [punk::args::parse $args withid ::winlibreoffice::to_libre_date]
lassign [dict values $argd] leaders opts values received
set tz [dict get $opts -timezone]
set time [dict get $values time]
if {![string is integer -strict $time]} {
set ts [clock scan $time -timezone $tz]
} else {
set ts $time
}
#a hack
#return libreoffice date in days since 1899..
proc date_from_clockseconds_approx {cs} {
variable datebase variable datebase
set tbase [clock scan $datebase] set tbase [clock scan $datebase -timezone $tz]
package require punk::timeinterval package require punk::timeinterval
set diff [punk::timeinterval::difference $tbase $cs] set info [punk::timeinterval::difference -maxunit days -timezone $tz $tbase $ts]
lassign [dict values $info] _Y _m days h m s
set Y [dict get $diff years] return [expr {$days + ((($h *3600) + ($m * 60) + $s)/86400.0)}]
set M [dict get $diff months] }
set D [dict get $diff days]
set yeardays [expr 365.25 * $Y] lappend PUNKARGS [list {
set monthdays [expr 30.437 * $M] @id -id ::winlibreoffice::from_libre_date
@cmd -name winlibreoffice::from_libre_date -help\
"Convert an internal Libre Office date floating point value
representing the number of days since 1899-12-30 to a format
understood by Tcl such as 'clock seconds', 'clock milliseconds'
as specified in the -format option.
"
@opts
-format -default "clockseconds" -choices {clockseconds clockmillis ISO8601} -choicerestricted 0 -help\
"Aside from the special values listed -format accepts a format string
as accepted by the Tcl 'clock format' command's -format option."
-timezone -default "" -help\
"If unspecified, the timezone will be the
current time zone on the system"
@values -min 1 -max 1
libredatetime -type float -help\
"Floating point number representing the number of
days since 1899-12-30."
}]
#review - we don't expect sci notation for any float values here
#but we could easily get them.. e.g 0.000000001 * 86400.0 => 8.64e-5
#todo - clockmicros ?
proc from_libre_date {args} {
package require punk::args
set argd [punk::args::parse $args withid ::winlibreoffice::from_libre_date]
lassign [dict values $argd] leaders opts values received
set format [dict get $opts -format]
set tz [dict get $opts -timezone]
set libredatetime [dict get $values libredatetime]
variable datebase
set tbase [clock scan $datebase -timezone $tz]
set intdays [expr {int($libredatetime)}]
set fracdays [lindex [split $libredatetime .] 1]
if {$fracdays ne ""} {
set fracdays "0.$fracdays"
set floatsecs [expr {$fracdays * 86400.0}] ;#assuming not a leap-second day
if {$format eq "clockmillis"} {
set wholesecs [expr {int($floatsecs)}]
set msfrac [lindex [split $floatsecs .] 1]
if {$msfrac ne ""} {
set msfrac "0.$msfrac" ;#could also be something like 0.64e-5 which should still work
set ms [expr {round(1000 * $msfrac)}]
if {$ms == 1000} {
set ms 0
incr wholesecs
}
} else {
set ms 0
}
} else {
set wholesecs [expr {round($floatsecs)}]
set ms 0
}
} else {
set wholesecs 0
set ms 0
}
#yes.. this is horrible.. just a test really - but gets in the ballpark. set cs [clock add $tbase +$intdays days +$wholesecs seconds -timezone $tz]
return [expr int($yeardays + $monthdays + $D)] switch -- $format {
clockseconds {
return $cs
}
clockmillis {
return [expr {($cs * 1000) + $ms}]
}
ISO8601 {
set format "%Y%m%dT%H%M%S"
}
}
return [clock format $cs -format $format]
} }
#time is represented on a scale of 0 to 1 6:00am = 0.25 (24/4)
#time is represented on a scale of 0 to 1 6:00am = 0.25 (24/4)
proc date_from_clockseconds {cs} {
puts stderr "unimplemented"
#return libreoffice date as a floating point number of days since 1899.. (1899-12-30)
proc to_libre_date_from_clockseconds_gmt {cs} {
return [expr {($cs/86400.0) + 25569}]
} }
#see also: https://wiki.tcl-lang.org/page/Tcom+examples+for+Microsoft+Outlook #see also: https://wiki.tcl-lang.org/page/Tcom+examples+for+Microsoft+Outlook
@ -265,13 +368,15 @@ namespace eval winlibreoffice {
# -----------------------------------------------------------------------------
# register namespace(s) to have PUNKARGS,PUNKARGS_aliases variables checked
# -----------------------------------------------------------------------------
# variable PUNKARGS
# variable PUNKARGS_aliases
namespace eval ::punk::args::register {
#use fully qualified so 8.6 doesn't find existing var in global namespace
lappend ::punk::args::register::NAMESPACES ::winlibreoffice
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++

BIN
src/vfs/_vfscommon.vfs/modules/zipper-0.12.tm

Binary file not shown.
Loading…
Cancel
Save