Compare commits

...

2 Commits

  1. 8
      src/modules/#modpod-zipper-999999.0a1.0/zipper-999999.0a1.0.tm
  2. 13
      src/modules/punk-0.1.tm
  3. 4
      src/modules/punk/ansi-999999.0a1.0.tm
  4. 44
      src/modules/punk/basictelnet-999999.0a1.0.tm
  5. 2
      src/modules/punk/cap/handlers/templates-999999.0a1.0.tm
  6. 2
      src/modules/punk/char-999999.0a1.0.tm
  7. 2
      src/modules/punk/config-0.1.tm
  8. 4
      src/modules/punk/console-999999.0a1.0.tm
  9. 13
      src/modules/punk/fileline-999999.0a1.0.tm
  10. 30
      src/modules/punk/icomm-999999.0a1.0.tm
  11. 26
      src/modules/punk/lib-999999.0a1.0.tm
  12. 24
      src/modules/punk/repl-999999.0a1.0.tm
  13. 4
      src/modules/punk/sshrun-999999.0a1.0.tm
  14. 395
      src/modules/punk/timeinterval-999999.0a1.0.tm
  15. 14
      src/modules/punk/winrun-999999.0a1.0.tm
  16. 2
      src/modules/punkcheck-0.1.0.tm
  17. 11
      src/modules/shellrun-0.1.1.tm
  18. 12
      src/modules/shellthread-1.6.1.tm
  19. 6
      src/modules/textblock-999999.0a1.0.tm
  20. 152
      src/modules/winlibreoffice-999999.0a1.0.tm

8
src/modules/#modpod-zipper-999999.0a1.0/zipper-999999.0a1.0.tm

@ -31,8 +31,8 @@ namespace eval zipper {
set v::fd $fd
set v::base [tell $fd]
set v::toc {}
#fconfigure $fd -translation binary -encoding binary
fconfigure $fd -translation binary -encoding iso8859-1
#chan configure $fd -translation binary -encoding binary
chan configure $fd -translation binary -encoding iso8859-1
}
proc emit {s} {
@ -150,7 +150,7 @@ namespace eval zipper {
set len [expr {$cd_end_pos - $cd_start_pos}]
#incr pos -$v::base
set cdr_offset_pos [expr $cd_start_pos -$v::base] ;#review
set cdr_offset_pos [expr {$cd_start_pos -$v::base}] ;#review
#EOCD signature PK\5\6 = 0x06054b50
emit [binary format a2c2ssssiis PK {5 6} 0 0 $ntoc $ntoc $len $cdr_offset_pos 0]
@ -178,7 +178,7 @@ if {[info exists argv0] && [string match zipper-* [file tail $argv0]]} {
if {[file isfile $f]} {
regsub {^\./} $f {} f
set fd [open $f]
fconfigure $fd -translation binary -encoding binary
chan configure $fd -translation binary -encoding binary
zipper::addentry $f [read $fd] [file mtime $f]
close $fd
} elseif {[file isdir $f]} {

13
src/modules/punk-0.1.tm

@ -1234,7 +1234,7 @@ namespace eval punk {
break
}
#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)} {
set action ?mismatch-list-index-out-of-range
break
@ -3690,7 +3690,8 @@ namespace eval punk {
#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
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]
foreach v $var_names {
if {$v eq ""} {
@ -3699,7 +3700,9 @@ namespace eval punk {
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"
append msg "Unmatched\n"
append msg "Cannot match right hand side to pattern $multivar\n"
@ -5304,6 +5307,8 @@ namespace eval punk {
##if {$body ni $existing} {
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.
#tclint-disable-next-line
proc ::unknown {args} [string map [list @c@ $cond @b@ $body @scr@ $scr] {
#---------------------------------------
if {![catch {expr {@c@}} res] && $res} {
@ -5368,7 +5373,7 @@ namespace eval punk {
#for var="val {a b c}"
#proc ::punk::val {{v {}}} {tailcall lindex $v}
#proc ::punk::val {{v {}}} {return $v} ;#2023 - approx 2x faster than the tailcall lindex version
#tclint-disable-next-line
proc ::punk::val [list [list v [purelist]]] {return $v}
#----------------

4
src/modules/punk/ansi-999999.0a1.0.tm

@ -7569,11 +7569,11 @@ namespace eval punk::ansi::colour {
}
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)}]
} elseif {$T($c) < 0.5} {
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}]
} else {
set T($c) $P

44
src/modules/punk/basictelnet-999999.0a1.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 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 debug_width 80
@ -412,12 +412,12 @@ namespace eval punk::basictelnet {
#puts -nonewline [punk::ansi::cursor_off]
#use non cursorsave version - slower - but less likely to interfere with cursor operations in data
set existing_input_handler [fileevent $inputchannel readable] ;#stdin
fileevent $inputchannel readable {}
set existing_input_handler [chan event $inputchannel readable] ;#stdin
chan event $inputchannel readable {}
if {[string length $outputchannel]} {
set existing_output_handler [fileevent $outputchannel readable] ;#sock
fileevent $outputchannel readable {}
set existing_output_handler [chan event $outputchannel readable] ;#sock
chan event $outputchannel readable {}
}
if {[catch {
@ -434,9 +434,9 @@ namespace eval punk::basictelnet {
#todo - try? finally?
set writing_debug_frame 0
fileevent $inputchannel readable $existing_input_handler
chan event $inputchannel readable $existing_input_handler
if {[string length $outputchannel]} {
fileevent $outputchannel readable $existing_output_handler
chan event $outputchannel readable $existing_output_handler
}
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
reset_option_states
set sock [socket $server $port]
#fconfigure $sock -buffering none -blocking 0 -encoding binary -translation crlf -eofchar {}
#fconfigure $sock -buffering none -blocking 0 -encoding binary -translation binary -eofchar {}
fconfigure $sock -buffering none -blocking 0 -encoding iso8859-1 -translation binary -eofchar {}
fconfigure stdout -buffering none
fileevent $sock readable [list [namespace current]::fromServer $sock]
#chan configure $sock -buffering none -blocking 0 -encoding binary -translation crlf -eofchar {}
#chan configure $sock -buffering none -blocking 0 -encoding binary -translation binary -eofchar {}
chan configure $sock -buffering none -blocking 0 -encoding iso8859-1 -translation binary -eofchar {}
chan configure stdout -buffering none
chan event $sock readable [list [namespace current]::fromServer $sock]
chan configure stdin -blocking 0
fileevent stdin readable [list [namespace current]::toServer $sock]
chan event stdin readable [list [namespace current]::toServer $sock]
variable closed
vwait ::punk::basictelnet::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]
}
fileevent stdin readable {}
chan event stdin readable {}
if {$nextwaiting eq ""} {
set chunk [read stdin]
} else {
@ -616,13 +616,13 @@ namespace eval punk::basictelnet {
#Re-enable channel read handler only if no waiting chunks - must process in order
##################################################################################
if {![llength $input_chunks_waiting(stdin)]} {
fileevent stdin readable [list [namespace current]::toServer $sock]
chan event stdin readable [list [namespace current]::toServer $sock]
} else {
#after idle [list [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 {
disconnect sock
}
@ -642,7 +642,7 @@ namespace eval punk::basictelnet {
variable encoding_guess
variable debug
variable fromserver_unprocessed
fileevent $sock readable {}
chan event $sock readable {}
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.
#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]} {
#review - by throwing to another loop without waiting for readable event - we could spin on same data...?
#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 {
fileevent $sock readable [list [namespace current]::fromServer $sock]
chan event $sock readable [list [namespace current]::fromServer $sock]
}
}
proc disconnect {sock} {
variable closed
puts stdout "local disconnect"
catch {fileevent $sock readable {}}
catch {chan event $sock readable {}}
catch {close $sock}
set closed($sock) 1
fileevent stdin readable {}
chan event stdin readable {}
}
proc write string {

2
src/modules/punk/cap/handlers/templates-999999.0a1.0.tm

@ -95,7 +95,7 @@ namespace eval punk::cap::handlers::templates {
} else {
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"
flush stderr
return 0

2
src/modules/punk/char-999999.0a1.0.tm

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

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

@ -32,7 +32,7 @@ tcl::namespace::eval punk::config {
if {$exename ne ""} {
set exefolder [file dirname $exename]
#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 apps $exefolder/../../punkapps

4
src/modules/punk/console-999999.0a1.0.tm

@ -814,7 +814,7 @@ namespace eval punk::console {
#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)
#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
}
puts -nonewline stdout \033\[6n ;flush stdout
fconfigure stdin -blocking 0
chan configure stdin -blocking 0
set info [read stdin 20] ;#
after 1
if {[string first "R" $info] <=0} {

13
src/modules/punk/fileline-999999.0a1.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] datachunk should be passed with the file data including line-endings as-is for full functionality. ie use something like:
#[example_begin]
# fconfigure $fd -translation binary
# chan configure $fd -translation binary
# set chunkdata [lb]read $fd[rb]]
#or
# set chunkdata [lb]fileutil::cat <filename> -translation binary[rb]
@ -1221,8 +1221,11 @@ namespace eval punk::fileline::class {
#o_linemap
set oldsize [string length $o_chunk]
set newchunk ""
#review - what was the intention here?
puts stderr "regenerate_chunk -warning code incomplete"
dict for {idx lineinfo} $o_linemap {
set
#???
#set
}
@ -1287,7 +1290,7 @@ namespace eval punk::fileline {
if {$opt_file ne ""} {
set filename $opt_file
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
set rawchunk [read $fd]
close $fd
@ -1360,7 +1363,7 @@ namespace eval punk::fileline {
set bomenc "binary" ;# utf-8???
set startdata 3
} 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"
set bomenc cp936
} else {
@ -1485,7 +1488,7 @@ namespace eval punk::fileline {
proc file_boundary_display {filename startbyte endbyte chunksize args} {
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]
close $fd
set textobj [class::textinfo new $rawfiledata]

30
src/modules/punk/icomm-999999.0a1.0.tm

@ -875,9 +875,9 @@ namespace eval ::punk::icomm {
![string equal $encoding $comm($chan,encoding)]} {
# This should not be entered yet
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,*] {
fconfigure $sock -encoding $encoding
chan configure $sock -encoding $encoding
}
}
@ -935,10 +935,10 @@ namespace eval ::punk::icomm {
set nport [incr comm(lastport)]
}
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
set comm($chan,port) [lindex [fconfigure $ret -sockname] 2]
set comm($chan,port) [lindex [chan configure $ret -sockname] 2]
return ""
}
@ -1089,8 +1089,8 @@ namespace eval ::punk::icomm {
# coroutines to hide the CSP and properly handle everything
# event based.
fconfigure $fid -blocking 0
fileevent $fid readable [list ::punk::icomm::commIncomingOffered $chan $fid $addr $remport]
chan configure $fid -blocking 0
chan event $fid readable [list ::punk::icomm::commIncomingOffered $chan $fid $addr $remport]
return
}
@ -1111,8 +1111,8 @@ namespace eval ::punk::icomm {
# Protocol version line has been received, disable event handling
# again.
fileevent $fid readable {}
fconfigure $fid -blocking 1
chan event $fid readable {}
chan configure $fid -blocking 1
# a list of offered proto versions is the first word of first line
# remote id is the second word of first line
@ -1143,7 +1143,7 @@ namespace eval ::punk::icomm {
if {[dict exists $chanconf -sockname]} {
# If the remote host addr isn't our local host addr,
# 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
} else {
set id [list $remid $addr]
@ -1215,8 +1215,8 @@ namespace eval ::punk::icomm {
set comm($chan,peers,$id) $fid
}
set comm($chan,fids,$fid) $id
fconfigure $fid -translation lf -encoding $comm($chan,encoding) -blocking 0
fileevent $fid readable [list ::punk::icomm::commCollect $chan $fid]
chan configure $fid -translation lf -encoding $comm($chan,encoding) -blocking 0
chan event $fid readable [list ::punk::icomm::commCollect $chan $fid]
}
# ::punk::icomm::commLostConn --
@ -1324,7 +1324,7 @@ namespace eval ::punk::icomm {
# ::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
# command, which we then invoke.
#
@ -1343,9 +1343,9 @@ namespace eval ::punk::icomm {
if {[catch {read $fid} nbuf] || [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 [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"
return
}
@ -1995,7 +1995,7 @@ proc ::punk::icomm::initlocal {{tcpport 0}} {
if {[string equal macintosh $::tcl_platform(platform)]} {
::punk::icomm::comm new ::punk::icomm::comm -port 0 -local 0 -listen 1
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
} else {
::punk::icomm::comm new ::punk::icomm::comm -port 0 -local 1 -listen 1

26
src/modules/punk/lib-999999.0a1.0.tm

@ -477,7 +477,7 @@ namespace eval punk::lib {
set asegs [split [string map {:: \uFFFF} $abs] \uFFFF]
set acount [llength $asegs]
#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 {[string match $glob [lindex $asegs end]]} {
#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]
puts stdout $question
flush stdout
set stdin_state [fconfigure stdin]
set stdin_state [chan configure stdin]
if {[catch {
package require punk::console
set console_raw [tsv::get console is_raw]
@ -2769,7 +2769,7 @@ namespace eval punk::lib {
set console_raw 0
}
try {
fconfigure stdin -blocking 1
chan configure stdin -blocking 1
if {$console_raw} {
punk::console::disableRaw
set answer [gets stdin]
@ -2778,7 +2778,7 @@ namespace eval punk::lib {
set answer [gets stdin]
}
} finally {
fconfigure stdin -blocking [tcl::dict::get $stdin_state -blocking]
chan configure stdin -blocking [tcl::dict::get $stdin_state -blocking]
}
return $answer
}
@ -3629,8 +3629,8 @@ namespace eval punk::lib {
set s2 [expr {$s2 + (($time-$average)*($time-$average) / ($iters-1))}]
}
set sigma [expr {int(sqrt($s2))}]
set average [expr int($average)]
set sigma [expr {int(sqrt($s2))}]
set average [expr {int($average)}]
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
set point [string last "." $number];
if {$point >= 0} {
set PostDecimal [string range $number [expr $point + 1] end];
set PostDecimal [string range $number $point+1 end];
set PostDecimalP 1;
} else {
set point [expr [string length $number] + 1]
set point [expr {[string length $number] + 1}]
set PostDecimal "";
set PostDecimalP 0;
}
@ -3834,16 +3834,16 @@ namespace eval punk::lib {
incr ind;
}
set FirstNonSpace $ind;
set LastSpace [expr $FirstNonSpace - 1];
set LastSpace [expr {$FirstNonSpace - 1}];
set LeadingSpaces [string range $number 0 $LastSpace];
# 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.
set Length [string length $MainNumber];
set Phase [expr $Length % $GroupSize]
set PhaseMinusOne [expr $Phase -1];
set Phase [expr {$Length % $GroupSize}]
set PhaseMinusOne [expr {$Phase -1}];
set DelimitedMain "";
#First we deal with the extra stuff.
@ -3851,7 +3851,7 @@ namespace eval punk::lib {
append DelimitedMain [string range $MainNumber 0 $PhaseMinusOne];
}
set FirstInGroup $Phase;
set LastInGroup [expr $FirstInGroup + $GroupSize -1];
set LastInGroup [expr {$FirstInGroup + $GroupSize -1}];
while {$LastInGroup < $Length} {
if {$FirstInGroup > 0} {
append DelimitedMain $delim;

24
src/modules/punk/repl-999999.0a1.0.tm

@ -127,7 +127,7 @@ namespace eval punk::repl {
puts stderr "\n*> repl background error: '$message'"
#puts stderr "*> [set ::errorInfo]"
puts stderr "*> errorinfo: [dict get $errdict -errorinfo]"
set stdinreader [fileevent stdin readable]
set stdinreader [chan event stdin readable]
if {![string length $stdinreader]} {
puts stderr "*> stdin reader inactive"
} else {
@ -420,14 +420,14 @@ proc repl::start {inchan args} {
puts stderr "-->repl::start active on $inchan $args replthread:[thread::id] codethread:$codethread"
set prompt_config [punk::repl::get_prompt_config]
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
#catch {
# set punk::console::tabwidth [punk::console::get_tabstop_apparent_width]
#}
vwait [namespace current]::done
fileevent $inchan readable {}
chan event $inchan readable {}
#puts stderr "-->start done = $::repl::done"
@ -1327,7 +1327,7 @@ proc repl::repl_handler {inputchan prompt_config} {
set prompt_reset_flag 0
}
fileevent $inputchan readable {}
chan event $inputchan readable {}
upvar ::punk::console::input_chunks_waiting input_chunks_waiting
#note -inputmode not available in Tcl 8.6 for chan configure!
#According to DKF - -buffering option doesn't affect input channels
@ -1542,14 +1542,14 @@ proc repl::repl_handler {inputchan prompt_config} {
#Re-enable channel read handler only if no waiting chunks - must process in order
##################################################################################
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 {
after idle [list ::repl::repl_handler $inputchan $prompt_config]
}
####################################################
} else {
#repl_handler_checkchannel $inputchan
fileevent $inputchan readable {}
chan event $inputchan readable {}
set reading 0
thread::send -async $::repl::codethread {set ::punk::repl::codethread::running 0}
if {$::tcl_interactive} {
@ -1757,7 +1757,7 @@ proc repl::repl_process_data {inputchan chunktype chunk stdinlines prompt_config
# #review
# rputs stderr "->0byte read stdin"
# if {[chan eof $inputchan]} {
# fileevent $inputchan readable {}
# chan event $inputchan readable {}
# set reading 0
# #set running 0
# if {$::tcl_interactive} {
@ -1973,7 +1973,7 @@ proc repl::repl_process_data {inputchan chunktype chunk stdinlines prompt_config
rputs stderr "-------------"
rputs stderr "$::errorInfo"
rputs stderr "-------------"
set stdinreader [fileevent $inputchan readable]
set stdinreader [chan event $inputchan readable]
if {![string length $stdinreader]} {
rputs stderr "*> $inputchan reader inactive"
} else {
@ -2185,7 +2185,7 @@ proc repl::repl_process_data {inputchan chunktype chunk stdinlines prompt_config
#chan configure stdout -buffering none
#JMN
fileevent $inputchan readable {}
chan event $inputchan readable {}
set reading 0
#don't let unknown use 'args' to convert commandstr to list
#===============================================================================
@ -2529,7 +2529,7 @@ proc repl::repl_process_data {inputchan chunktype chunk stdinlines prompt_config
#append commandstr \n
if {$::punk::repl::signal_control_c} {
set ::punk::repl::signal_control_c 0
fileevent $inputchan readable {}
chan event $inputchan readable {}
rputs stderr "* console_control: control-c"
flush stderr
set c [a yellow bold]
@ -2578,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]"}
@ -2590,7 +2590,7 @@ proc repl::repl_process_data {inputchan chunktype chunk stdinlines prompt_config
rputs stderr "-------------"
rputs stderr "$::errorInfo"
rputs stderr "-------------"
set stdinreader [fileevent $inputchan readable]
set stdinreader [chan event $inputchan readable]
if {![string length $stdinreader]} {
rputs stderr "*> $inputchan reader inactive"
} else {

4
src/modules/punk/sshrun-999999.0a1.0.tm

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

395
src/modules/punk/timeinterval-999999.0a1.0.tm

@ -27,17 +27,23 @@
#
namespace eval punk::timeinterval {
proc clock_scan_interval { seconds delta units } {
# clock_scan_interval formats $seconds to a string for processing by clock scan
# then returns new timestamp in seconds
set stamp [clock format $seconds -format "%Y%m%dT%H%M%S"]
if { $delta < 0 } {
append stamp " - " [expr { abs( $delta ) } ] " " $units
} else {
append stamp " + " $delta " " $units
}
return [clock scan $stamp]
}
#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
#proc clock_scan_interval { seconds delta units } {
# # clock_scan_interval formats $seconds to a string for processing by clock scan
# # then returns new timestamp in seconds
# set stamp [clock format $seconds -format "%Y%m%dT%H%M%S"]
# if { $delta < 0 } {
# append stamp " - " [expr { abs( $delta ) } ] " " $units
# } else {
# append stamp " + " $delta " " $units
# }
# return [clock scan $stamp]
#}
#proc clock_scan_interval { seconds delta units } {
# #8.6+
# clock add $seconds $delta $units
#}
namespace export difference
#wrap in dict
@ -46,21 +52,36 @@ namespace eval punk::timeinterval {
lassign [interval_ymdhs $s1 $s2] Y M D h m s
return [dict create years $Y months $M days $D hours $h minutes $m seconds $s]
}
proc interval_ymdhs { s1 s2 } {
# interval_ymdhs calculates the interval of time between
# the earliest date and the last date
# by starting to count at the earliest date.
lappend PUNKARGS [list {
@id -id "::punk::timeinterval::interval_ymdhs"
@cmd -name "punk::timeinterval::interval_ymdhs" -help\
"interval_ymdhs calculates the interval of time between
the earliest date and the last date
by starting to count at the earliest date."
@opts
-maxunit -default years -choices {years months days hours minutes seconds}
-timezone -default ""
@values -min 2 -max 2
s1
s2
}]
proc interval_ymdhs {args} {
set argd [punk::args::parse $args withid ::punk::timeinterval::interval_ymdhs]
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
# attempt to correct and report any discrepancies it finds.
# if s1 and s2 aren't in seconds, convert to seconds.
if { ![string is integer -strict $s1] } {
set s1 [clock scan $s1]
set s1 [clock scan $s1 -timezone $timezone]
}
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.
@ -77,64 +98,82 @@ namespace eval punk::timeinterval {
# Calculate years from s1_p0 to s2
set y_count 0
set s1_p0 $s1
set s2_y_check $s1_p0
while { $s2_y_check <= $s2 } {
set s1_p1 $s2_y_check
set y $y_count
incr y_count
set s2_y_check [clock_scan_interval $s1_p0 $y_count years]
}
# interval s1_p0 to s1_p1 counted in y years
if {$maxunit eq "years"} {
set s2_y_check $s1_p0
while { $s2_y_check <= $s2 } {
set s1_p1 $s2_y_check
set y $y_count
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
# is the base offset incremented one too much?
set s2_y_check [clock_scan_interval $s1 $y years]
if { $s2_y_check > $s2 } {
set y [expr { $y - 1 } ]
set s2_y_check [clock_scan_interval $s1 $y years]
}
# increment s1 (s1_p0) forward y years to s1_p1
if { $y == 0 } {
set s1_p1 $s1
# is the base offset incremented one too much?
set s2_y_check [clock add $s1 $y years -timezone $timezone]
if { $s2_y_check > $s2 } {
set y [expr { $y - 1 } ]
set s2_y_check [clock add $s1 $y years -timezone $timezone]
}
# increment s1 (s1_p0) forward y years to s1_p1
if { $y == 0 } {
set s1_p1 $s1
} else {
set s1_p1 [clock add $s1 $y years -timezone $timezone]
}
} 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
# Calculate months from s1_p1 to s2
set m_count 0
set s2_m_check $s1_p1
while { $s2_m_check <= $s2 } {
set s1_p2 $s2_m_check
set m $m_count
incr m_count
set s2_m_check [clock_scan_interval $s1_p1 $m_count months]
set s1_p2 $s1_p1 ;#?
set m 0
if {$maxunit in {years months}} {
while { $s2_m_check <= $s2 } {
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
# Calculate interval s1_p2 to s2 in days
# day_in_sec [expr { 60 * 60 * 24 } ]
# 86400
# Since length of month is not relative, use math.
# Clip any fractional part.
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
set d 0
set s1_p3 $s1_p2
if {$maxunit in {years months days}} {
# Calculate interval s1_p2 to s2 in days
# day_in_sec [expr { 60 * 60 * 24 } ]
# 86400
# Since length of month is not relative, use math.
# Clip any fractional part.
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
# Calculate interval s1_p3 to s2 in hours
# hour_in_sec [expr { 60 * 60 } ]
# 3600
set h [expr { int( ( $s2 - $s1_p3 ) / 3600. ) } ]
# Move interval from s1_p3 to s1_p4
set s1_p4 [clock_scan_interval $s1_p3 $h hours]
# s1_p4 is less than an hour from s2
set h 0
set s1_p4 $s1_p3
if {$maxunit in {years months days hours}} {
# Calculate interval s1_p3 to s2 in hours
# hour_in_sec [expr { 60 * 60 } ]
# 3600
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!
@ -148,7 +187,7 @@ namespace eval punk::timeinterval {
# 43 years 9 mons 27 days
# (1 row)
# 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
# So, let's ignore the Postgresql irregularity for now.
# Here's more background:
@ -156,68 +195,84 @@ namespace eval punk::timeinterval {
# http://www.postgresql.org/message-id/200707060844.l668i89w097496@wwwmaster.postgresql.org
# So, Postgres had a bug..
# Sanity check: if over 24 or 48 hours, push it up to a day unit
set h_in_days [expr { int( $h / 24. ) } ]
if { $h >= 1 } {
# adjust hours to less than a day
set h [expr { $h - ( 24 * $h_in_days ) } ]
incr d $h_in_days
set h_correction_p 1
} else {
set h_correction_p 0
if {$maxunit in {years months days}} {
# Sanity check: if over 24 or 48 hours, push it up to a day unit
set h_in_days [expr { int( $h / 24. ) } ]
if { $h >= 1 } {
# adjust hours to less than a day
set h [expr { $h - ( 24 * $h_in_days ) } ]
incr d $h_in_days
set h_correction_p 1
} 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
if { $mm >= 60 } {
# adjust 60 minutes to 1 hour
# puts "interval_ymdhs: debug info mm - 60, h + 1"
set mm [expr { $mm - 60 } ]
incr h
set mm_correction_p 1
} else {
set mm_correction_p 0
set mm 0
set s1_p5 $s1_p4
if {$maxunit in {years months days hours minutes}} {
# 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 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 "interval_ymdhs: 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
set s [expr { int( $s2 - $s1_p5 ) } ]
# Sanity check: if 60 seconds, push it up to one minute unit
if { $s >= 60 } {
# adjust 60 minutes to 1 hour
set s [expr { $s - 60 } ]
incr mm
set s_correction_p 1
} else {
set s_correction_p 0
if {$maxunit in {years months days hours minutes}} {
# Sanity check: if 60 seconds, push it up to one minute unit
if { $s >= 60 } {
# adjust 60 minutes to 1 hour
set s [expr { $s - 60 } ]
incr mm
set s_correction_p 1
} else {
set s_correction_p 0
}
}
set return_list [list $y $m $d $h $mm $s]
# 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 s1_test [clock format $s1 -format "%Y%m%dT%H%M%S"]
set signs_inconsistent_p 0
set diffterms [list]
foreach unit {years months days hours minutes seconds} {
set t_term [lindex $return_list $i]
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 {
append s1_test " - [expr { abs( $t_term ) } ] $unit"
#append s1_test " -[expr { abs( $t_term ) } ] $unit"
lappend diffterms -[expr { abs( $t_term ) }] $unit
set signs_inconsistent_p 1
}
}
incr i
}
set s2_test [clock scan $s1_test]
#set s2_test [clock scan $s1_test]
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 } {
@ -263,19 +318,23 @@ namespace eval punk::timeinterval {
# 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 s1_test [clock format $s1 -format "%Y%m%dT%H%M%S"]
set diffterms [list]
foreach unit {years months days hours minutes seconds} {
set t_term [lindex $return_list $i]
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 {
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
}
set s2_test [clock scan $s1_test]
#set s2_test [clock scan $s1_test]
set s2_test [clock add $s1 {*}$diffterms -timezone $timezone]
incr counter
}
if { ( $counter > 0 || $signs_inconsistent_p ) && ( $h_correction_p || $mm_correction_p || $s_correction_p ) } {
@ -342,7 +401,7 @@ namespace eval punk::timeinterval {
set s1_p1 $s2_y_check
set y $y_count
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
@ -354,7 +413,7 @@ namespace eval punk::timeinterval {
set s1_p2 $s2_m_check
set m $m_count
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
@ -371,7 +430,7 @@ namespace eval punk::timeinterval {
}
# 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
@ -380,7 +439,7 @@ namespace eval punk::timeinterval {
# 3600
set h [expr { int( ceil( ( $s2 - $s1_p3 ) / 3600. ) ) } ]
# 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
# Sanity check: if over 24 or 48 hours, push it up to a day unit
@ -399,7 +458,7 @@ namespace eval punk::timeinterval {
# 60
set mm [expr { int( ceil( ( $s2 - $s1_p4 ) / 60. ) ) } ]
# 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
if { $mm <= -60 } {
@ -430,21 +489,25 @@ namespace eval punk::timeinterval {
# 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 s1_test [clock format $s1 -format "%Y%m%dT%H%M%S"]
set signs_inconsistent_p 0
set diffterms [list]
foreach unit {years months days hours minutes seconds} {
set t_term [lindex $return_list $i]
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
} 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
}
set s2_test [clock scan $s1_test]
#set s2_test [clock scan $s1_test]
set s2_test [clock add $s1 {*}$diffterms]
set counter 0
while { $s2 ne $s2_test && $counter < 3 } {
@ -490,19 +553,23 @@ namespace eval punk::timeinterval {
# 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 s1_test [clock format $s1 -format "%Y%m%dT%H%M%S"]
set diffterms [list]
foreach unit {years months days hours minutes seconds} {
set t_term [lindex $return_list $i]
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 {
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
}
set s2_test [clock scan $s1_test]
#set s2_test [clock scan $s1_test]
set s2_test [clock add $s1 {*}$diffterms]
incr counter
}
if { ( $counter > 0 || $signs_inconsistent_p ) && ( $h_correction_p || $mm_correction_p || $s_correction_p ) } {
@ -526,7 +593,7 @@ namespace eval punk::timeinterval {
proc interval_remains_ymdhs_w_units { t1 t2 } {
# interval_remains_ymdhs_w_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 a ""
foreach f {years months days hours minutes seconds} {
@ -543,7 +610,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/modules/punk/winrun-999999.0a1.0.tm

@ -37,7 +37,7 @@ namespace eval punk::winrun {
}
proc readchild_handler {chan hpid} {
#fileevent $chan readable {}
#chan event $chan readable {}
set data [read $chan 4096]
while {![chan blocked $chan] && ![eof $chan]} {
append data [read $chan 4096]
@ -46,19 +46,19 @@ namespace eval punk::winrun {
flush stdout
if {![eof $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 {
#puts "eof: waiting exit process"
set punk::winrun::waitresult [twapi::wait_on_handle $hpid -wait -1]
}
}
proc readchilderr_handler {chan} {
fileevent $chan readable {}
chan event $chan readable {}
set data [read $chan]
puts stderr "err: $data"
flush stderr
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
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 $writein "puts stdout blah;"
flush $writein
@ -106,8 +106,8 @@ namespace eval punk::winrun {
if {$waitresult eq "timeout"} {
puts stderr "tw_run: timeout waiting for process"
}
fileevent $readout readable {}
fileevent $readerr readable {}
chan event $readout readable {}
chan event $readerr readable {}
set code [twapi::get_process_exit_code $hpid]
twapi::close_handle $htid

2
src/modules/punkcheck-0.1.0.tm

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

11
src/modules/shellrun-0.1.1.tm

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

12
src/modules/shellthread-1.6.1.tm

@ -209,10 +209,10 @@ namespace eval shellthread::worker {
variable sysloghost_port
variable sock
if {[string length $sysloghost_port]} {
if {[catch {fconfigure $sock} state]} {
if {[catch {chan configure $sock} state]} {
set sock [udp_open]
fconfigure $sock -buffering none -translation binary
fconfigure $sock -remote $sysloghost_port
chan configure $sock -buffering none -translation binary
chan configure $sock -remote $sysloghost_port
}
}
}
@ -220,7 +220,7 @@ namespace eval shellthread::worker {
variable sock
catch {close $sock}
_initsock
return [fconfigure $sock]
return [chan configure $sock]
}
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.
# 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.
# 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.
# 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'
@ -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.
if {[llength $ts_end_list]} {
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
dict set workers $source ts_end_list $ts_end_list
} else {

6
src/modules/textblock-999999.0a1.0.tm

@ -663,7 +663,7 @@ tcl::namespace::eval textblock {
switch -- $k {
-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 ansi_codes [list] ;
set ansi_codes [list]
foreach {pt code} $parts {
if {$pt ne ""} {
#we don't expect plaintext in an ansibase
@ -1109,7 +1109,7 @@ tcl::namespace::eval textblock {
}
-ansibase {
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 {
if {$pt ne ""} {
#we don't expect plaintext in an ansibase
@ -7852,7 +7852,7 @@ tcl::namespace::eval textblock {
foreach {k v} $optlist {
set k2 [tcl::prefix::match -error "" $optnames $k]
switch -- $k2 {
-etabs - -type - -boxlimits - -boxmap - -joins
-etabs - -type - -boxlimits - -boxmap - -join
- -title - -titlealign - -subtitle - -subtitlealign - -width - -height
- -ansiborder - -ansibase
- -blockalign - -textalign - -ellipsis

152
src/modules/winlibreoffice-999999.0a1.0.tm

@ -28,13 +28,14 @@ if {"windows" eq $::tcl_platform(platform)} {
puts stderr "Minimal functionality - only some utils may work"
}
} 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"
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval winlibreoffice {
namespace export from_libre_date to_libre_date
#---
#todo: investigate tcluno package http://sf.net/projects/tcluno
#CPlusPlus - platforms?
@ -212,31 +213,132 @@ namespace eval winlibreoffice {
#ULTRABOLD 175.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 since 1899-12-30.
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
set tbase [clock scan $datebase]
set tbase [clock scan $datebase -timezone $tz]
package require punk::timeinterval
set diff [punk::timeinterval::difference $tbase $cs]
set info [punk::timeinterval::interval_ymdhs -maxunit days -timezone $tz $tbase $ts]
lassign $info Y m days h m s
set Y [dict get $diff years]
set M [dict get $diff months]
set D [dict get $diff days]
set yeardays [expr 365.25 * $Y]
set monthdays [expr 30.437 * $M]
return [expr {$days + ((($h *3600) + ($m * 60) + $s)/86400.0)}]
}
lappend PUNKARGS [list {
@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.
return [expr int($yeardays + $monthdays + $D)]
set cs [clock add $tbase +$intdays days +$wholesecs seconds -timezone $tz]
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
@ -265,13 +367,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
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++

Loading…
Cancel
Save