#[para]Return a boolean indicating whether Ansi codes were detected in text
#[para]Return a boolean indicating whether Ansi codes were detected in text
#[para]
#[para]
regexp <re> $text
}]
#note - micro optimisation of inlining <re> gives us *almost* nothing extra.
#left in place for detect as it's a common call that should be made as fast as possible as it's used to avoid more expensive operations such as split_...
# in general the technique doesn't seem worthwhile for this set of functions.
#the performance is dominated by the complexity of the regexp
#micro optimisations on split_codes to avoid function calls and make re var local tend to yield very little benefit (sub uS diff on calls that commonly take 10s/100s of uSeconds)
#like split_codes - but each ansi-escape is split out separately (with empty string of plaintext between codes so odd/even plain ansi still holds)
#like split_codes - but each ansi-escape is split out separately (with empty string of plaintext between codes so odd/even plain ansi still holds)
#- the slightly simpler regex than split_codes means that it will be slightly faster than keeping the codes grouped.
ef [list name EOR code 239 meaning "End-of-Record"]\
f0 [list name SE code 240 meaning "End of subnegotiation parameters"]\
f1 [list name NOP code 241 meaning "no-op"]\
f2 [list name "Data Mark" code 242 meaning "The data stream portion of a Synch"]\
f3 [list name "Break" code 243 meaning "NVT character BRK"]\
f4 [list name "Interrupt Process" code 244 meaning "The function IP"]\
f5 [list name "Abort Output" code 245 meaning "The function AO"]\
f6 [list name "Are You There" code 246 meaning "The function AYT"]\
f7 [list name "Erase Character" code 247 meaning "The function EC"]\
f8 [list name "Erase Line" code 248 meaning "The function EL"]\
f9 [list name "Go Ahead" code 249 meaning "The GA signal"]\
fa [list name "SB" code 250 meaning "Indicates that what follows is subnegotiation of the indicated option"]\
fb [list name "WILL" code 251 meaning "Indicates the desire to begin performing, or confimation that you are now performing, the indicated option"]\
fc [list name "WON'T" code 252 meaning "Indicates the refusal to peform or continue performing, the indicated option"]\
fd [list name "DO" code 253 meaning "Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option"]\
fe [list name "DON'T" code 254 meaning "Indicates the demand that the other party stop performaing, or confirmation that you are no longer expecting the other party to perform, the indicated option"]\
]
proc cmd_info {cmd} {
proc cmd_info {cmd} {
variable cmdmap
#ef - extension to rfc-854
#ef - extension to rfc-854
set cmdmap [dict create\
ef [list name EOR code 239 meaning "End-of-Record"]\
f0 [list name SE code 240 meaning "End of subnegotiation parameters"]\
f1 [list name NOP code 241 meaning "no-op"]\
f2 [list name "Data Mark" code 242 meaning "The data stream portion of a Synch"]\
f3 [list name "Break" code 243 meaning "NVT character BRK"]\
f4 [list name "Interrupt Process" code 244 meaning "The function IP"]\
f5 [list name "Abort Output" code 245 meaning "The function AO"]\
f6 [list name "Are You There" code 246 meaning "The function AYT"]\
f7 [list name "Erase Character" code 247 meaning "The function EC"]\
f8 [list name "Erase Line" code 248 meaning "The function EL"]\
f9 [list name "Go Ahead" code 249 meaning "The GA signal"]\
fa [list name "SB" code 250 meaning "Indicates that what follows is subnegotiation of the indicated option"]\
fb [list name "WILL" code 251 meaning "Indicates the desire to begin performing, or confimation that you are now performing, the indicated option"]\
fc [list name "WON'T" code 252 meaning "Indicates the refusal to peform or continue performing, the indicated option"]\
fd [list name "DO" code 253 meaning "Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option"]\
fe [list name "DON'T" code 254 meaning "Indicates the demand that the other party stop performaing, or confirmation that you are no longer expecting the other party to perform, the indicated option"]\
#not just used by cksum_path. used by caller (e.g fill_relativecksums_from_base_and_relativepathdict via cksum_filter_opts) to determine what opt names passed through
#not just used by cksum_path. used by caller (e.g fill_relativecksums_from_base_and_relativepathdict via cksum_filter_opts) to determine what opt names passed through
variable cksum_default_opts
set cksum_default_opts [dict create -cksum_content 1 -cksum_meta auto -cksum_acls 0 -cksum_usetar auto -cksum_algorithm sha1]
proc cksum_default_opts {} {
proc cksum_default_opts {} {
return [dict create -cksum_content 1 -cksum_meta auto -cksum_acls 0 -cksum_usetar auto -cksum_algorithm sha1]
variable cksum_default_opts
return $cksum_default_opts
}
}
#crc::cksum is extremely slow in tcllib as at 2023 e.g 20x slower (no c implementation?)
#crc::cksum is extremely slow in tcllib as at 2023 e.g 20x slower (no c implementation?)
#review - we should probably provide a more narrow filter than only strips color - and one that strips most(?)
#review - we should probably provide a more narrow filter than only strips color - and one that strips most(?)
# - but does it ever really make sense to strip things like "esc(0" and "esc(B" which flip to the G0 G1 characters? (once stripped - things like box-lines become ordinary letters - unlikely to be desired?)
# - but does it ever really make sense to strip things like "esc(0" and "esc(B" which flip to the G0 G1 characters? (once stripped - things like box-lines become ordinary letters - unlikely to be desired?)
#punk::ansi::stripansi converts at least some of the box drawing G0 chars to unicode - todo - more complete conversion
#punk::ansi::stripansi converts at least some of the box drawing G0 chars to unicode - todo - more complete conversion
#assumes line-buffering. a more advanced filter required if ansicodes can arrive split accross separate read or write operations!
#assumes line-buffering. a more advanced filter required if ansicodes can arrive split across separate read or write operations!
#this isn't a particularly nice thing to do to a stream - especially if someone isn't expecting ansi codes sprinkled through it.
#this isn't a particularly nice thing to do to a stream - especially if someone isn't expecting ansi codes sprinkled through it.
#It can be useful for test/debugging
#It can be useful for test/debugging
#Due to chunking at random breaks - we have to check if an ansi code in the underlying stream has been split - otherwise our wrapping will break the existing ansi
set o_columndata [tcl::dict::create] ;#we store data by column even though it is often added row by row
set o_columndata [tcl::dict::create] ;#we store data by column even though it is often added row by row
set o_columnstates [tcl::dict::create] ;#store the maxwidthbodyseen etc as we add rows and maxwidthheaderseen etc as we add headers - it is needed often and expensive to calculate repeatedly
set o_columnstates [tcl::dict::create] ;#store the maxwidthbodyseen etc as we add rows and maxwidthheaderseen etc as we add headers - it is needed often and expensive to calculate repeatedly
set o_headerstates [tcl::dict::create]
set o_headerstates [tcl::dict::create]
set o_rowdefs [tcl::dict::create] ;#user requested row data e.g -minheight -maxheight
set o_rowdefs [tcl::dict::create] ;#user requested row data e.g -minheight -maxheight
set o_rowstates [tcl::dict::create] ;#actual row data such as -minheight and -maxheight detected from supplied row data
set o_rowstates [tcl::dict::create] ;#actual row data such as -minheight and -maxheight detected from supplied row data
set TSUB \uF111 ;#should be BMP PUA code to show as either replacement char or nerdfont glyph. See FSUB for comments regarding choices.
set TSUB \uF111 ;#should be BMP PUA code to show as either replacement char or nerdfont glyph. See FSUB for comments regarding choices.
#todo - allow zero values to hide/collapse rows as is possible with columns
if {![tcl::string::is integer $opt_minh] || ($opt_maxh ne "" && ![tcl::string::is integer -strict $opt_maxh])} {
if {![tcl::string::is integer $opt_minh] || ($opt_maxh ne "" && ![tcl::string::is integer -strict $opt_maxh])} {
error "[tcl::namespace::current]::table::add_row error -minheight '$opt_minh' and -maxheight '$opt_maxh' must be integers greater than or equal to 1"
error "[tcl::namespace::current]::table::configure_row error -minheight '$opt_minh' and -maxheight '$opt_maxh' must be integers greater than or equal to 1 (for now)"
}
}
if {$opt_minh < 1 || ($opt_maxh ne "" && $opt_maxh < 1)} {
if {$opt_minh < 1 || ($opt_maxh ne "" && $opt_maxh < 1)} {
error "[tcl::namespace::current]::table::add_row error -minheight '$opt_minh' and -maxheight '$opt_maxh' must both be 1 or greater"
error "[tcl::namespace::current]::table::configure_row error -minheight '$opt_minh' and -maxheight '$opt_maxh' must both be 1 or greater (for now)"
}
}
if {$opt_maxh ne "" && $opt_maxh < $opt_minh} {
if {$opt_maxh ne "" && $opt_maxh < $opt_minh} {
error "[tcl::namespace::current]::table::add_row error -maxheight '$opt_maxh' must greater than -minheight '$opt_minh'"
error "[tcl::namespace::current]::table::configure_row error -maxheight '$opt_maxh' must greater than -minheight '$opt_minh'"
error "[tcl::namespace::current]::table::get_column_by_index error invalid value '$opt_posn' for -position. Valid values: $valid_positions"
error "[tcl::namespace::current]::table::get_column_by_index error invalid value '$opt_posn' for -position. Valid values: [list left inner right solo]"
#options before content argument - which is allowed to be absent
#options before content argument - which is allowed to be absent
#frame performance (noticeable with complex tables even of modest size) is improved significantly by frame_cache - but is still (2024) a fairly expensive operation.
#frame performance (noticeable with complex tables even of modest size) is improved significantly by frame_cache - but is still (2024) a fairly expensive operation.