#[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]Important caveat:
#[para] When text is a tcl list made from splitting (or lappending) some ansi string - individual elements may be braced or have certain chars escaped. (one example is if a list element contains an unbalanced brace)
#[para] This can cause square brackets that form part of the ansi being backslash escaped - and the regexp can fail to match
regexp <re> $text
regexp <re> $text
}]
}]
#can be used on dicts - but will check keys too. keys could also contain ansi and have escapes
set opt_keysorttype [dict get $argd opts -keysorttype]
set opt_keysorttype [dict get $argd opts -keysorttype]
set opt_keysortdirection [dict get $argd opts -keysortdirection]
set opt_keysortdirection [dict get $argd opts -keysortdirection]
set opt_trimright [dict get $argd opts -trimright]
set opt_trimright [dict get $argd opts -trimright]
set opt_ansibase_key [dict get $argd opts -ansibase_keys]
set opt_ansibase_value [dict get $argd opts -ansibase_values]
set opt_return [dict get $argd opts -return]
set dval [dict get $argd values dictvalue]
set dval [dict get $argd values dictvalue]
set patterns [dict get $argd values patterns]
set patterns [dict get $argd values patterns]
@ -456,10 +465,37 @@ namespace eval punk::lib {
#simple use of 'format' won't cut it for more complex dict keys/values
#simple use of 'format' won't cut it for more complex dict keys/values
#use block::width or our columns won't align in some cases
#use block::width or our columns won't align in some cases
set maxl [::tcl::mathfunc::max {*}[lmap v $filtered_keys {textblock::width $v}]]
set maxl [::tcl::mathfunc::max {*}[lmap v $filtered_keys {textblock::width $v}]]
set RST [a]
switch -- $opt_return {
"tailtohead" {
#last line of key is side by side (possibly with separator) with first line of value
#This is more intelligible when terminal wrapping occurs - and is closer to what happens with parray multiline keys and values
#we still pad the key to max width so that the separator appears in the same column - which in the case of wide keys could cause that to wrap for all entries
lassign [textblock::size [dict get $dval $key]] _vw vwidth _vh vheight
set totalheight [expr {$kheight + $vheight -1}]
set blanks_above [string repeat \n [expr {$kheight -1}]]
set blanks_below [string repeat \n [expr {$vheight -1}]]
set sepwidth [textblock::width $opt_sep]
#append result [textblock::pad $opt_ansibase_key$key$RST -width $maxl] $opt_sep $opt_ansibase_value[dict get $dval $key]$RST \n
set kblock [textblock::pad $opt_ansibase_key$key$RST$blanks_below -width $maxl]
set sblock [textblock::pad $blanks_above$opt_sep$blanks_below -width $sepwidth]
set vblock $blanks_above$opt_ansibase_value[dict get $dval $key]$RST
#only vblock is ragged - we can do a basic join because we don't care about rhs whitespace
append result [textblock::join_basic $kblock $sblock $vblock] \n
}
}
"sidebyside" {
#This is nice for multiline keys and values of reasonable length, will produce unintuitive results when line-wrapping occurs.
#use ansibase_key etc to make the output more comprehensible in that situation.
#This is why it is not the default. (review - terminal width detection and wrapping?)
foreach key $filtered_keys {
foreach key $filtered_keys {
#append result [format "%-*s = %s" $maxl $key [dict get $dval $key]] \n
#append result [format "%-*s = %s" $maxl $key [dict get $dval $key]] \n
#differing height blocks (ie ragged) so we need a full textblock::join rather than join_basic
#differing height blocks (ie ragged) so we need a full textblock::join rather than join_basic
append result [textblock::join -- [textblock::pad $key -width $maxl] $opt_sep [dict get $dval $key]] \n
append result [textblock::join -- [textblock::pad $opt_ansibase_key$key$RST -width $maxl] $opt_sep "$opt_ansibase_value[dict get $dval $key]$RST"] \n
}
}
}
}
}
}
if {$opt_trimright} {
if {$opt_trimright} {
@ -1659,7 +1695,11 @@ namespace eval punk::lib {
set replaycodes $RST ;#todo - default?
set replaycodes $RST ;#todo - default?
set transformed [list]
set transformed [list]
#shortcircuit common case of no ansi
#shortcircuit common case of no ansi
if {![punk::ansi::ta::detect $linelist]} {
#NOTE: running ta::detect on a list (or dict) as a whole can be problematic if items in the have backslash escapes due to Tcl list quoting and escaping behaviour.
#This commonly happens if there is an unbalanced brace (which is a normal occurrence and needs to be handled)
#ta::detect on a list of ansi-containing string may appear to work for some simple inputs but is not reliable
#detect_in_list will check at first level. (not intended for detecting ansi in deeper structures)
if {![punk::ansi::ta::detect_in_list $linelist]} {