Browse Source

textblock::class::table feature and ansi fixes

master
Julian Noble 5 months ago
parent
commit
7c6ca9b532
  1. 2
      src/bootsupport/include_modules.config
  2. 200
      src/bootsupport/modules/oolib-0.1.1.tm
  3. 63
      src/bootsupport/modules/punk/ansi-0.1.1.tm
  4. 17
      src/bootsupport/modules/punk/lib-0.1.1.tm
  5. 3076
      src/bootsupport/modules/textblock-0.1.1.tm
  6. 20
      src/embedded/man/files/punk/_module_lib-0.1.1.tm.n
  7. 122
      src/embedded/md/doc/files/punk/_module_lib-0.1.1.tm.md
  8. 108
      src/embedded/www/doc/files/punk/_module_lib-0.1.1.tm.html
  9. 63
      src/modules/punk/ansi-999999.0a1.0.tm
  10. 17
      src/modules/punk/lib-999999.0a1.0.tm
  11. 2084
      src/modules/textblock-999999.0a1.0.tm

2
src/bootsupport/include_modules.config

@ -53,6 +53,8 @@ set bootsupport_modules [list\
modules punk::repo\
modules punk::tdl\
modules punk::winpath\
modules textblock\
modules oolib\
]
#each entry - base subpath

200
src/bootsupport/modules/oolib-0.1.1.tm

@ -0,0 +1,200 @@
#JMN - api should be kept in sync with package patternlib where possible
#
package provide oolib [namespace eval oolib {
variable version
set version 0.1.1
}]
namespace eval oolib {
oo::class create collection {
variable o_data ;#dict
variable o_alias
constructor {} {
set o_data [dict create]
}
method info {} {
return [dict info $o_data]
}
method count {} {
return [dict size $o_data]
}
method isEmpty {} {
expr {[dict size $o_data] == 0}
}
method names {{globOrIdx {}}} {
if {[llength $globOrIdx]} {
if {[string is integer -strict $globOrIdx]} {
set idx $globOrIdx
if {$idx < 0} {
set idx "end-[expr {abs($idx + 1)}]"
}
if {[catch {lindex [dict keys $o_data] $idx} result]} {
error "[self object] no such index : '$idx'"
} else {
return $result
}
} else {
#glob
return [lsearch -glob -all -inline [dict keys $o_data] $globOrIdx]
}
} else {
return [dict keys $o_data]
}
}
#like names but without globbing
method keys {} {
dict keys $o_data
}
method key {{posn 0}} {
if {$posn < 0} {
set posn "end-[expr {abs($posn + 1)}]"
}
if {[catch {lindex [dict keys $o_data] $posn} result]} {
error "[self object] no such index : '$posn'"
} else {
return $result
}
}
method hasKey {key} {
dict exists $o_data $key
}
method get {} {
return $o_data
}
method items {} {
return [dict values $o_data]
}
method item {key} {
if {[string is integer -strict $key]} {
if {$key >= 0} {
set valposn [expr {(2*$key) +1}]
return [lindex $o_data $valposn]
} else {
set key "end-[expr {abs($key + 1)}]"
return [lindex $o_data $key]
#return [lindex [dict keys $o_data] $key]
}
}
if {[dict exists $o_data $key]} {
return [dict get $o_data $key]
}
}
#inverse lookup
method itemKeys {value} {
set value_indices [lsearch -all [dict values $o_data] $value]
set keylist [list]
foreach i $value_indices {
set idx [expr {(($i + 1) *2) -2}]
lappend keylist [lindex $o_data $idx]
}
return $keylist
}
method search {value args} {
set matches [lsearch {*}$args [dict values $o_data] $value]
if {"-inline" in $args} {
return $matches
} else {
set keylist [list]
foreach i $matches {
set idx [expr {(($i + 1) *2) -2}]
lappend keylist [lindex $o_data $idx]
}
return $keylist
}
}
#review - see patternlib. Is the intention for aliases to be configurable independent of whether the target exists?
method alias {newAlias existingKeyOrAlias} {
if {[string is integer -strict $newAlias]} {
error "[self object] collection key alias cannot be integer"
}
if {[string length $existingKeyOrAlias]} {
set o_alias($newAlias) $existingKeyOrAlias
} else {
unset o_alias($newAlias)
}
}
method aliases {{key ""}} {
if {[string length $key]} {
set result [list]
foreach {n v} [array get o_alias] {
if {$v eq $key} {
lappend result $n $v
}
}
return $result
} else {
return [array get o_alias]
}
}
#if the supplied index is an alias, return the underlying key; else return the index supplied.
method realKey {idx} {
if {[catch {set o_alias($idx)} key]} {
return $idx
} else {
return $key
}
}
method add {value key} {
if {[string is integer -strict $key]} {
error "[self object] collection key must not be an integer. Use another structure if integer keys required"
}
if {[dict exists $o_data $key]} {
error "[self object] col_processors object error: key '$key' already exists in collection"
}
dict set o_data $key $value
return [expr {[dict size $o_data] - 1}] ;#return index of item
}
method remove {idx {endRange ""}} {
if {[string length $endRange]} {
error "[self object] collection error: ranged removal not yet implemented.. remove one item at a time"
}
if {[string is integer -strict $idx]} {
if {$idx < 0} {
set idx "end-[expr {abs($idx+1)}]"
}
set key [lindex [dict keys $o_data] $idx]
set posn $idx
} else {
set key $idx
set posn [lsearch -exact [dict keys $o_data] $key]
if {$posn < 0} {
error "[self object] no such index: '$idx' in this collection"
}
}
dict unset o_data $key
return
}
method clear {} {
set o_data [dict create]
return
}
method reverse_the_collection {} {
#named slightly obtusely because reversing the data when there may be references held is a potential source of bugs
#the name reverse_the_collection should make it clear that the object is being modified in place as opposed to simply 'reverse' which may imply a view/copy.
#todo - consider implementing a get_reverse which provides an interface to the same collection without affecting original references, yet both allowing delete/edit operations.
set dictnew [dict create]
foreach k [lreverse [dict keys $o_data]] {
dict set dictnew $k [dict get $o_data $k]
}
set o_data $dictnew
return
}
#review - cmd as list vs cmd as script?
method map {cmd} {
set seed [list]
dict for {k v} $o_data {
lappend seed [uplevel #0 [list {*}$cmd $v]]
}
return $seed
}
method objectmap {cmd} {
set seed [list]
dict for {k v} $o_data {
lappend seed [uplevel #0 [list $v {*}$cmd]]
}
return $seed
}
}
}

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

@ -1748,6 +1748,7 @@ namespace eval punk::ansi {
dict set codestate_empty bg "" ;#40-47 + 100-107
#misnomer should have been sgr_merge_args ? :/
#as a common case optimisation - it will not merge a single element list, even if that code contains redundant elements
proc sgr_merge_list {args} {
if {[llength $args] == 0} {
@ -1755,9 +1756,30 @@ namespace eval punk::ansi {
} elseif {[llength $args] == 1} {
return [lindex $args 0]
}
sgr_merge $args
}
#codes *must* already have been split so that one esc per element in codelist
#e.g codelist [a+ Yellow Red underline] [a+ blue] [a+ red] is ok
#but codelist "[a+ Yellow Red underline][a+ blue]" [a+ red] is not
#(use punk::ansi::ta::split_codes_single)
proc sgr_merge {codelist args} {
variable codestate_empty
set othercodes [list]
set defaults [dict create\
-filter_fg 0\
-filter_bg 0\
]
dict for {k v} $args {
switch -- $k {
-filter_fg - -filter_bg {}
default {
error "sgr_merge unknown option '$k'. Known options [dict keys $defaults]"
}
}
}
set opts [dict merge $defaults $args]
set codestate $codestate_empty
set codestate_initial $codestate_empty ;#keep a copy for resets.
set did_reset 0
@ -1772,7 +1794,7 @@ namespace eval punk::ansi {
#We still output any non SGR codes in the list as they came in - preserving their CSI
foreach c $args {
foreach c $codelist {
#normalize 8bit to a token of the same length so our string operations on the code are the same and we can maintain a switch statement with literals rather than escapes
#.. but preserve original c
#set cnorm [string map [list \x9b {8[} ] $c]
@ -1911,7 +1933,7 @@ namespace eval punk::ansi {
dict set codestate hide 28 ;#reveal
}
29 {
dict set codestate strik 29;#off
dict set codestate strike 29;#off
}
30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 {
dict set codestate fg $p ;#foreground colour
@ -2067,13 +2089,38 @@ namespace eval punk::ansi {
}
set codemerge ""
dict for {k v} $codestate {
switch -- $v {
"" {
if {[dict get $opts -filter_fg] || [dict get $opts -filter_bg]} {
dict for {k v} $codestate {
switch -- $v {
"" {
}
default {
switch -- $k {
bg {
if {![dict get $opts -filter_bg]} {
append codemerge "${v}\;"
}
}
fg {
if {![dict get $opts -filter_fg]} {
append codemerge "${v}\;"
}
}
default {
append codemerge "${v}\;"
}
}
}
}
default {
append codemerge "${v}\;"
}
} else {
dict for {k v} $codestate {
switch -- $v {
"" {}
default {
append codemerge "${v}\;"
}
}
}
}
@ -3963,7 +4010,7 @@ namespace eval punk::ansi::ansistring {
#return empty string for each index that is out of range
#review - this is possibly too slow to be very useful as is.
# consider converting to oo and maintaining state of ansisplits so we don't repeat relatively expensive operations for same string
#see also punk::list_index_resolve / punk::list_index_get for ways to handle tcl list/string indices without parsing them.
#see also punk::lindex_resolve / punk::lindex_get for ways to handle tcl list/string indices without parsing them.
proc INDEXABSOLUTE {string args} {
set payload_len -1 ;# -1 as token to indicate we haven't calculated it yet (only want to call it once at most)
set testindices [list]

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

@ -211,7 +211,18 @@ namespace eval punk::lib {
#}
proc list_index_resolve {list index} {
proc lindex_resolve {list index} {
#*** !doctools
#[call [fun lindex_resolve] [arg list] [arg index]]
#[para]Resolve an index which may be of the forms accepted by Tcl list commands such as end-2 or 2+2 to the actual integer index for the supplied list
#[para]Users may define procs which accept a list index and wish to accept the forms understood by Tcl.
#[para]This means the proc may be called with something like $x+2 end-$y etc
#[para]Sometimes the actual integer index is desired.
#[para]We want to resolve the index used, without passing arbitrary expressions into the 'expr' function - which could have security risks.
#[para]lindex_resolve will parse the index expression and return -1 if the supplied index expression is out of bounds for the supplied list.
#[para]Otherwise it will return an integer corresponding to the position in the list.
#[para]Like Tcl list commands - it will produce an error if the form of the
#Note that for an index such as $x+1 - we never see the '$x' as it is substituted in the calling command. We will get something like 10+1 - which we will resolve (hopefully safely) with expr
if {![llength $list]} {
return -1
@ -271,7 +282,7 @@ namespace eval punk::lib {
}
}
}
proc list_index_resolve2 {list index} {
proc lindex_resolve2 {list index} {
set indices [list] ;#building this may be somewhat expensive in terms of storage and compute for large lists - we could use lseq in Tcl 8.7+ but that's likely unavailable here.
for {set i 0} {$i < [llength $list]} {incr i} {
lappend indices $i
@ -283,7 +294,7 @@ namespace eval punk::lib {
return $idx
}
}
proc list_index_get {list index} {
proc lindex_get {list index} {
set resultlist [lrange $list $index $index]
if {![llength $resultlist]} {
return -1

3076
src/bootsupport/modules/textblock-0.1.1.tm

File diff suppressed because it is too large Load Diff

20
src/embedded/man/files/punk/_module_lib-0.1.1.tm.n

@ -280,6 +280,8 @@ package require \fBpunk::lib \fR
.sp
\fBlpop\fR \fIlistvar\fR ?index?
.sp
\fBlindex_resolve\fR \fIlist\fR \fIindex\fR
.sp
\fBK\fR \fIx\fR \fIy\fR
.sp
\fBis_utf8_multibyteprefix\fR \fIstr\fR
@ -377,6 +379,24 @@ Forwards compatible lpop for versions 8\&.6 or less to support equivalent 8\&.7
.PP
Core API functions for punk::lib
.TP
\fBlindex_resolve\fR \fIlist\fR \fIindex\fR
.sp
Resolve an index which may be of the forms accepted by Tcl list commands such as end-2 or 2+2 to the actual integer index for the supplied list
.sp
Users may define procs which accept a list index and wish to accept the forms understood by Tcl\&.
.sp
This means the proc may be called with something like $x+2 end-$y etc
.sp
Sometimes the actual integer index is desired\&.
.sp
We want to resolve the index used, without passing arbitrary expressions into the 'expr' function - which could have security risks\&.
.sp
lindex_resolve will parse the index expression and return -1 if the supplied index expression is out of bounds for the supplied list\&.
.sp
Otherwise it will return an integer corresponding to the position in the list\&.
.sp
Like Tcl list commands - it will produce an error if the form of the
.TP
\fBK\fR \fIx\fR \fIy\fR
.sp
The K-combinator function - returns the first argument, x and discards y

122
src/embedded/md/doc/files/punk/_module_lib-0.1.1.tm.md

@ -48,31 +48,32 @@ package require punk::lib
[__lremove__ *list* ?index \.\.\.?](#1)
[__lpop__ *listvar* ?index?](#2)
[__K__ *x* *y*](#3)
[__is\_utf8\_multibyteprefix__ *str*](#4)
[__is\_utf8\_single__ *1234bytes*](#5)
[__get\_utf8\_leading__ *rawbytes*](#6)
[__hex2dec__ ?option value\.\.\.? *list\_largeHex*](#7)
[__dex2hex__ ?option value\.\.\.? *list\_decimals*](#8)
[__log2__ *x*](#9)
[__logbase__ *b* *x*](#10)
[__factors__ *x*](#11)
[__oddFactors__ *x*](#12)
[__greatestFactorBelow__ *x*](#13)
[__greatestOddFactorBelow__ *x*](#14)
[__greatestOddFactor__ *x*](#15)
[__gcd__ *n* *m*](#16)
[__lindex\_resolve__ *list* *index*](#3)
[__K__ *x* *y*](#4)
[__is\_utf8\_multibyteprefix__ *str*](#5)
[__is\_utf8\_single__ *1234bytes*](#6)
[__get\_utf8\_leading__ *rawbytes*](#7)
[__hex2dec__ ?option value\.\.\.? *list\_largeHex*](#8)
[__dex2hex__ ?option value\.\.\.? *list\_decimals*](#9)
[__log2__ *x*](#10)
[__logbase__ *b* *x*](#11)
[__factors__ *x*](#12)
[__oddFactors__ *x*](#13)
[__greatestFactorBelow__ *x*](#14)
[__greatestOddFactorBelow__ *x*](#15)
[__greatestOddFactor__ *x*](#16)
[__gcd__ *n* *m*](#17)
[__commonDivisors__ *x* *y*](#18)
[__hasglobs__ *str*](#19)
[__trimzero__ *number*](#20)
[__substring\_count__ *str* *substring*](#21)
[__dict\_merge\_ordered__ *defaults* *main*](#22)
[__askuser__ *question*](#23)
[__linesort__ ?sortoption ?val?\.\.\.? *textblock*](#24)
[__list\_as\_lines__ ?\-joinchar char? *linelist*](#25)
[__lines\_as\_list__ ?option value \.\.\.? *text*](#26)
[__opts\_values__ ?option value\.\.\.? *optionspecs* *rawargs*](#27)
[__gcd__ *n* *m*](#18)
[__commonDivisors__ *x* *y*](#19)
[__hasglobs__ *str*](#20)
[__trimzero__ *number*](#21)
[__substring\_count__ *str* *substring*](#22)
[__dict\_merge\_ordered__ *defaults* *main*](#23)
[__askuser__ *question*](#24)
[__linesort__ ?sortoption ?val?\.\.\.? *textblock*](#25)
[__list\_as\_lines__ ?\-joinchar char? *linelist*](#26)
[__lines\_as\_list__ ?option value \.\.\.? *text*](#27)
[__opts\_values__ ?option value\.\.\.? *optionspecs* *rawargs*](#28)
# <a name='description'></a>DESCRIPTION
@ -124,7 +125,30 @@ class definitions
Core API functions for punk::lib
- <a name='3'></a>__K__ *x* *y*
- <a name='3'></a>__lindex\_resolve__ *list* *index*
Resolve an index which may be of the forms accepted by Tcl list commands
such as end\-2 or 2\+2 to the actual integer index for the supplied list
Users may define procs which accept a list index and wish to accept the
forms understood by Tcl\.
This means the proc may be called with something like $x\+2 end\-$y etc
Sometimes the actual integer index is desired\.
We want to resolve the index used, without passing arbitrary expressions
into the 'expr' function \- which could have security risks\.
lindex\_resolve will parse the index expression and return \-1 if the supplied
index expression is out of bounds for the supplied list\.
Otherwise it will return an integer corresponding to the position in the
list\.
Like Tcl list commands \- it will produce an error if the form of the
- <a name='4'></a>__K__ *x* *y*
The K\-combinator function \- returns the first argument, x and discards y
@ -133,7 +157,7 @@ Core API functions for punk::lib
It is used in cases where command\-substitution at the calling\-point performs
some desired effect\.
- <a name='4'></a>__is\_utf8\_multibyteprefix__ *str*
- <a name='5'></a>__is\_utf8\_multibyteprefix__ *str*
Returns a boolean if str is potentially a prefix for a multibyte utf\-8
character
@ -152,12 +176,12 @@ Core API functions for punk::lib
e\.g using: set head \[get\_utf8\_leading $testbytes\] ; set tail \[string range
$testbytes \[string length $head\] end\]
- <a name='5'></a>__is\_utf8\_single__ *1234bytes*
- <a name='6'></a>__is\_utf8\_single__ *1234bytes*
Tests input of 1,2,3 or 4 bytes and responds with a boolean indicating if it
is a valid utf\-8 character \(codepoint\)
- <a name='6'></a>__get\_utf8\_leading__ *rawbytes*
- <a name='7'></a>__get\_utf8\_leading__ *rawbytes*
return the leading portion of rawbytes that is a valid utf8 sequence\.
@ -182,7 +206,7 @@ Core API functions for punk::lib
The utf\-8 BOM \\xEF\\xBB\\xBF is a valid UTF8 3\-byte sequence and so can also
be returned as part of the leading utf8 bytes
- <a name='7'></a>__hex2dec__ ?option value\.\.\.? *list\_largeHex*
- <a name='8'></a>__hex2dec__ ?option value\.\.\.? *list\_largeHex*
Convert a list of \(possibly large\) unprefixed hex strings to their decimal
values
@ -199,7 +223,7 @@ Core API functions for punk::lib
Internal whitespace e\.g "F F" is not permitted \- but a completely empty
element "" is allowed and will return 0
- <a name='8'></a>__dex2hex__ ?option value\.\.\.? *list\_decimals*
- <a name='9'></a>__dex2hex__ ?option value\.\.\.? *list\_decimals*
Convert a list of decimal integers to a list of hex values
@ -208,7 +232,7 @@ Core API functions for punk::lib
\-case upper&#124;lower determines the case of the hex letters in the output
- <a name='9'></a>__log2__ *x*
- <a name='10'></a>__log2__ *x*
log base2 of x
@ -218,7 +242,7 @@ Core API functions for punk::lib
\(courtesy of RS
[https://wiki\.tcl\-lang\.org/page/Additional\+math\+functions](https://wiki\.tcl\-lang\.org/page/Additional\+math\+functions)\)
- <a name='10'></a>__logbase__ *b* *x*
- <a name='11'></a>__logbase__ *b* *x*
log base b of x
@ -229,7 +253,7 @@ Core API functions for punk::lib
Use expr's log10\(\) function or tcl::mathfunc::log10 for base 10
- <a name='11'></a>__factors__ *x*
- <a name='12'></a>__factors__ *x*
Return a sorted list of the positive factors of x where x > 0
@ -265,11 +289,11 @@ Core API functions for punk::lib
In other mathematical contexts zero may be considered not to divide
anything\.
- <a name='12'></a>__oddFactors__ *x*
- <a name='13'></a>__oddFactors__ *x*
Return a list of odd integer factors of x, sorted in ascending order
- <a name='13'></a>__greatestFactorBelow__ *x*
- <a name='14'></a>__greatestFactorBelow__ *x*
Return the largest factor of x excluding itself
@ -277,17 +301,17 @@ Core API functions for punk::lib
See Tcllib math::numtheory for more extensive implementations
- <a name='14'></a>__greatestOddFactorBelow__ *x*
- <a name='15'></a>__greatestOddFactorBelow__ *x*
Return the largest odd integer factor of x excluding x itself
- <a name='15'></a>__greatestOddFactor__ *x*
- <a name='16'></a>__greatestOddFactor__ *x*
Return the largest odd integer factor of x
For an odd value of x \- this will always return x
- <a name='16'></a>__gcd__ *n* *m*
- <a name='17'></a>__gcd__ *n* *m*
Return the greatest common divisor of m and n
@ -299,19 +323,19 @@ Core API functions for punk::lib
only if c is a common divisor of a and b
- <a name='17'></a>__gcd__ *n* *m*
- <a name='18'></a>__gcd__ *n* *m*
Return the lowest common multiple of m and n
Straight from Lars Hellström's math::numtheory library in Tcllib
- <a name='18'></a>__commonDivisors__ *x* *y*
- <a name='19'></a>__commonDivisors__ *x* *y*
Return a list of all the common factors of x and y
\(equivalent to factors of their gcd\)
- <a name='19'></a>__hasglobs__ *str*
- <a name='20'></a>__hasglobs__ *str*
Return a boolean indicating whether str contains any of the glob characters:
\* ? \[ \]
@ -319,17 +343,17 @@ Core API functions for punk::lib
hasglobs uses append to preserve Tcls internal representation for str \- so
it should help avoid shimmering in the few cases where this may matter\.
- <a name='20'></a>__trimzero__ *number*
- <a name='21'></a>__trimzero__ *number*
Return number with left\-hand\-side zeros trimmed off \- unless all zero
If number is all zero \- a single 0 is returned
- <a name='21'></a>__substring\_count__ *str* *substring*
- <a name='22'></a>__substring\_count__ *str* *substring*
Search str and return number of occurrences of substring
- <a name='22'></a>__dict\_merge\_ordered__ *defaults* *main*
- <a name='23'></a>__dict\_merge\_ordered__ *defaults* *main*
The standard dict merge accepts multiple dicts with values from dicts to the
right \(2nd argument\) taking precedence\.
@ -341,7 +365,7 @@ Core API functions for punk::lib
This function merges the two dicts whilst maintaining the key order of main
followed by defaults\.
- <a name='23'></a>__askuser__ *question*
- <a name='24'></a>__askuser__ *question*
A basic utility to read an answer from stdin
@ -370,7 +394,7 @@ Core API functions for punk::lib
puts "Cancelled by user"
}
- <a name='24'></a>__linesort__ ?sortoption ?val?\.\.\.? *textblock*
- <a name='25'></a>__linesort__ ?sortoption ?val?\.\.\.? *textblock*
Sort lines in textblock
@ -379,7 +403,7 @@ Core API functions for punk::lib
options are flags as accepted by lsort ie \-ascii \-command \-decreasing
\-dictionary \-index \-indices \-integer \-nocase \-real \-stride \-unique
- <a name='25'></a>__list\_as\_lines__ ?\-joinchar char? *linelist*
- <a name='26'></a>__list\_as\_lines__ ?\-joinchar char? *linelist*
This simply joines the elements of the list with \-joinchar
@ -391,7 +415,7 @@ Core API functions for punk::lib
lines \- but with more options related to trimming the block and/or each
line\.
- <a name='26'></a>__lines\_as\_list__ ?option value \.\.\.? *text*
- <a name='27'></a>__lines\_as\_list__ ?option value \.\.\.? *text*
Returns a list of possibly trimmed lines depeding on options
@ -401,7 +425,7 @@ Core API functions for punk::lib
\- not console lines which may be entirely different due to control
characters such as vertical tabs or ANSI movements
- <a name='27'></a>__opts\_values__ ?option value\.\.\.? *optionspecs* *rawargs*
- <a name='28'></a>__opts\_values__ ?option value\.\.\.? *optionspecs* *rawargs*
Parse rawargs as a sequence of zero or more option\-value pairs followed by
zero or more values

108
src/embedded/www/doc/files/punk/_module_lib-0.1.1.tm.html

@ -142,31 +142,32 @@
<ul class="doctools_syntax">
<li><a href="#1"><b class="function">lremove</b> <i class="arg">list</i> <span class="opt">?index ...?</span></a></li>
<li><a href="#2"><b class="function">lpop</b> <i class="arg">listvar</i> <span class="opt">?index?</span></a></li>
<li><a href="#3"><b class="function">K</b> <i class="arg">x</i> <i class="arg">y</i></a></li>
<li><a href="#4"><b class="function">is_utf8_multibyteprefix</b> <i class="arg">str</i></a></li>
<li><a href="#5"><b class="function">is_utf8_single</b> <i class="arg">1234bytes</i></a></li>
<li><a href="#6"><b class="function">get_utf8_leading</b> <i class="arg">rawbytes</i></a></li>
<li><a href="#7"><b class="function">hex2dec</b> <span class="opt">?option value...?</span> <i class="arg">list_largeHex</i></a></li>
<li><a href="#8"><b class="function">dex2hex</b> <span class="opt">?option value...?</span> <i class="arg">list_decimals</i></a></li>
<li><a href="#9"><b class="function">log2</b> <i class="arg">x</i></a></li>
<li><a href="#10"><b class="function">logbase</b> <i class="arg">b</i> <i class="arg">x</i></a></li>
<li><a href="#11"><b class="function">factors</b> <i class="arg">x</i></a></li>
<li><a href="#12"><b class="function">oddFactors</b> <i class="arg">x</i></a></li>
<li><a href="#13"><b class="function">greatestFactorBelow</b> <i class="arg">x</i></a></li>
<li><a href="#14"><b class="function">greatestOddFactorBelow</b> <i class="arg">x</i></a></li>
<li><a href="#15"><b class="function">greatestOddFactor</b> <i class="arg">x</i></a></li>
<li><a href="#16"><b class="function">gcd</b> <i class="arg">n</i> <i class="arg">m</i></a></li>
<li><a href="#3"><b class="function">lindex_resolve</b> <i class="arg">list</i> <i class="arg">index</i></a></li>
<li><a href="#4"><b class="function">K</b> <i class="arg">x</i> <i class="arg">y</i></a></li>
<li><a href="#5"><b class="function">is_utf8_multibyteprefix</b> <i class="arg">str</i></a></li>
<li><a href="#6"><b class="function">is_utf8_single</b> <i class="arg">1234bytes</i></a></li>
<li><a href="#7"><b class="function">get_utf8_leading</b> <i class="arg">rawbytes</i></a></li>
<li><a href="#8"><b class="function">hex2dec</b> <span class="opt">?option value...?</span> <i class="arg">list_largeHex</i></a></li>
<li><a href="#9"><b class="function">dex2hex</b> <span class="opt">?option value...?</span> <i class="arg">list_decimals</i></a></li>
<li><a href="#10"><b class="function">log2</b> <i class="arg">x</i></a></li>
<li><a href="#11"><b class="function">logbase</b> <i class="arg">b</i> <i class="arg">x</i></a></li>
<li><a href="#12"><b class="function">factors</b> <i class="arg">x</i></a></li>
<li><a href="#13"><b class="function">oddFactors</b> <i class="arg">x</i></a></li>
<li><a href="#14"><b class="function">greatestFactorBelow</b> <i class="arg">x</i></a></li>
<li><a href="#15"><b class="function">greatestOddFactorBelow</b> <i class="arg">x</i></a></li>
<li><a href="#16"><b class="function">greatestOddFactor</b> <i class="arg">x</i></a></li>
<li><a href="#17"><b class="function">gcd</b> <i class="arg">n</i> <i class="arg">m</i></a></li>
<li><a href="#18"><b class="function">commonDivisors</b> <i class="arg">x</i> <i class="arg">y</i></a></li>
<li><a href="#19"><b class="function">hasglobs</b> <i class="arg">str</i></a></li>
<li><a href="#20"><b class="function">trimzero</b> <i class="arg">number</i></a></li>
<li><a href="#21"><b class="function">substring_count</b> <i class="arg">str</i> <i class="arg">substring</i></a></li>
<li><a href="#22"><b class="function">dict_merge_ordered</b> <i class="arg">defaults</i> <i class="arg">main</i></a></li>
<li><a href="#23"><b class="function">askuser</b> <i class="arg">question</i></a></li>
<li><a href="#24"><b class="function">linesort</b> <span class="opt">?sortoption ?val?...?</span> <i class="arg">textblock</i></a></li>
<li><a href="#25"><b class="function">list_as_lines</b> <span class="opt">?-joinchar char?</span> <i class="arg">linelist</i></a></li>
<li><a href="#26"><b class="function">lines_as_list</b> <span class="opt">?option value ...?</span> <i class="arg">text</i></a></li>
<li><a href="#27"><b class="function">opts_values</b> <span class="opt">?option value...?</span> <i class="arg">optionspecs</i> <i class="arg">rawargs</i></a></li>
<li><a href="#18"><b class="function">gcd</b> <i class="arg">n</i> <i class="arg">m</i></a></li>
<li><a href="#19"><b class="function">commonDivisors</b> <i class="arg">x</i> <i class="arg">y</i></a></li>
<li><a href="#20"><b class="function">hasglobs</b> <i class="arg">str</i></a></li>
<li><a href="#21"><b class="function">trimzero</b> <i class="arg">number</i></a></li>
<li><a href="#22"><b class="function">substring_count</b> <i class="arg">str</i> <i class="arg">substring</i></a></li>
<li><a href="#23"><b class="function">dict_merge_ordered</b> <i class="arg">defaults</i> <i class="arg">main</i></a></li>
<li><a href="#24"><b class="function">askuser</b> <i class="arg">question</i></a></li>
<li><a href="#25"><b class="function">linesort</b> <span class="opt">?sortoption ?val?...?</span> <i class="arg">textblock</i></a></li>
<li><a href="#26"><b class="function">list_as_lines</b> <span class="opt">?-joinchar char?</span> <i class="arg">linelist</i></a></li>
<li><a href="#27"><b class="function">lines_as_list</b> <span class="opt">?option value ...?</span> <i class="arg">text</i></a></li>
<li><a href="#28"><b class="function">opts_values</b> <span class="opt">?option value...?</span> <i class="arg">optionspecs</i> <i class="arg">rawargs</i></a></li>
</ul>
</div>
</div>
@ -208,20 +209,29 @@
<div id="subsection5" class="doctools_subsection"><h3><a name="subsection5">Namespace punk::lib</a></h3>
<p>Core API functions for punk::lib</p>
<dl class="doctools_definitions">
<dt><a name="3"><b class="function">K</b> <i class="arg">x</i> <i class="arg">y</i></a></dt>
<dt><a name="3"><b class="function">lindex_resolve</b> <i class="arg">list</i> <i class="arg">index</i></a></dt>
<dd><p>Resolve an index which may be of the forms accepted by Tcl list commands such as end-2 or 2+2 to the actual integer index for the supplied list</p>
<p>Users may define procs which accept a list index and wish to accept the forms understood by Tcl.</p>
<p>This means the proc may be called with something like $x+2 end-$y etc</p>
<p>Sometimes the actual integer index is desired.</p>
<p>We want to resolve the index used, without passing arbitrary expressions into the 'expr' function - which could have security risks.</p>
<p>lindex_resolve will parse the index expression and return -1 if the supplied index expression is out of bounds for the supplied list.</p>
<p>Otherwise it will return an integer corresponding to the position in the list.</p>
<p>Like Tcl list commands - it will produce an error if the form of the</p></dd>
<dt><a name="4"><b class="function">K</b> <i class="arg">x</i> <i class="arg">y</i></a></dt>
<dd><p>The K-combinator function - returns the first argument, x and discards y</p>
<p>see <a href="https://wiki.tcl-lang.org/page/K">https://wiki.tcl-lang.org/page/K</a></p>
<p>It is used in cases where command-substitution at the calling-point performs some desired effect.</p></dd>
<dt><a name="4"><b class="function">is_utf8_multibyteprefix</b> <i class="arg">str</i></a></dt>
<dt><a name="5"><b class="function">is_utf8_multibyteprefix</b> <i class="arg">str</i></a></dt>
<dd><p>Returns a boolean if str is potentially a prefix for a multibyte utf-8 character</p>
<p>ie - tests if it is possible that appending more data will result in a utf-8 codepoint</p>
<p>Will return false for an already complete utf-8 codepoint</p>
<p>It is assumed the incomplete sequence is at the beginning of the bytes argument</p>
<p>Suitable input for this might be from the unreturned tail portion of get_utf8_leading $testbytes</p>
<p>e.g using: set head [get_utf8_leading $testbytes] ; set tail [string range $testbytes [string length $head] end]</p></dd>
<dt><a name="5"><b class="function">is_utf8_single</b> <i class="arg">1234bytes</i></a></dt>
<dt><a name="6"><b class="function">is_utf8_single</b> <i class="arg">1234bytes</i></a></dt>
<dd><p>Tests input of 1,2,3 or 4 bytes and responds with a boolean indicating if it is a valid utf-8 character (codepoint)</p></dd>
<dt><a name="6"><b class="function">get_utf8_leading</b> <i class="arg">rawbytes</i></a></dt>
<dt><a name="7"><b class="function">get_utf8_leading</b> <i class="arg">rawbytes</i></a></dt>
<dd><p>return the leading portion of rawbytes that is a valid utf8 sequence.</p>
<p>This will stop at the point at which the bytes can't be interpreted as a complete utf-8 codepoint</p>
<p>e.g It will not return the first byte or 2 of a 3-byte utf-8 character if the last byte is missing, and will return only the valid utf-8 string from before the first byte of the incomplete character.</p>
@ -229,26 +239,26 @@
<p>Note that while this will return valid utf8 - it has no knowledge of grapheme clusters or diacritics</p>
<p>This means if it is being used to process bytes split at some arbitrary point - the trailing data that isn't returned could be part of a grapheme cluster that belongs with the last character of the leading string already returned</p>
<p>The utf-8 BOM \xEF\xBB\xBF is a valid UTF8 3-byte sequence and so can also be returned as part of the leading utf8 bytes</p></dd>
<dt><a name="7"><b class="function">hex2dec</b> <span class="opt">?option value...?</span> <i class="arg">list_largeHex</i></a></dt>
<dt><a name="8"><b class="function">hex2dec</b> <span class="opt">?option value...?</span> <i class="arg">list_largeHex</i></a></dt>
<dd><p>Convert a list of (possibly large) unprefixed hex strings to their decimal values</p>
<p>hex2dec accepts and ignores internal underscores in the same manner as Tcl 8.7+ numbers e.g hex2dec FF_FF returns 65535</p>
<p>Leading and trailing underscores are ignored as a matter of implementation convenience - but this shouldn't be relied upon.</p>
<p>Leading or trailing whitespace in each list member is allowed e.g hex2dec &quot; F&quot; returns 15</p>
<p>Internal whitespace e.g &quot;F F&quot; is not permitted - but a completely empty element &quot;&quot; is allowed and will return 0</p></dd>
<dt><a name="8"><b class="function">dex2hex</b> <span class="opt">?option value...?</span> <i class="arg">list_decimals</i></a></dt>
<dt><a name="9"><b class="function">dex2hex</b> <span class="opt">?option value...?</span> <i class="arg">list_decimals</i></a></dt>
<dd><p>Convert a list of decimal integers to a list of hex values</p>
<p>-width &lt;int&gt; can be used to make each hex value at least int characters wide, with leading zeroes.</p>
<p>-case upper|lower determines the case of the hex letters in the output</p></dd>
<dt><a name="9"><b class="function">log2</b> <i class="arg">x</i></a></dt>
<dt><a name="10"><b class="function">log2</b> <i class="arg">x</i></a></dt>
<dd><p>log base2 of x</p>
<p>This uses a 'live' proc body - the divisor for the change of base is computed once at definition time</p>
<p>(courtesy of RS <a href="https://wiki.tcl-lang.org/page/Additional+math+functions">https://wiki.tcl-lang.org/page/Additional+math+functions</a>)</p></dd>
<dt><a name="10"><b class="function">logbase</b> <i class="arg">b</i> <i class="arg">x</i></a></dt>
<dt><a name="11"><b class="function">logbase</b> <i class="arg">b</i> <i class="arg">x</i></a></dt>
<dd><p>log base b of x</p>
<p>This function uses expr's natural log and the change of base division.</p>
<p>This means for example that we can get results like: logbase 10 1000 = 2.9999999999999996</p>
<p>Use expr's log10() function or tcl::mathfunc::log10 for base 10</p></dd>
<dt><a name="11"><b class="function">factors</b> <i class="arg">x</i></a></dt>
<dt><a name="12"><b class="function">factors</b> <i class="arg">x</i></a></dt>
<dd><p>Return a sorted list of the positive factors of x where x &gt; 0</p>
<p>For x = 0 we return only 0 and 1 as technically any number divides zero and there are an infinite number of factors. (including zero itself in this context)*</p>
<p>This is a simple brute-force implementation that iterates all numbers below the square root of x to check the factors</p>
@ -261,42 +271,42 @@ but has the disadvantage of being slower for 'small' numbers and using more memo
<p>If the largest factor below x is needed - the greatestOddFactorBelow and GreatestFactorBelow functions are a faster way to get there than computing the whole list, even for small values of x</p>
<p>* Taking x=0; Notion of x being divisible by integer y being: There exists an integer p such that x = py</p>
<p>In other mathematical contexts zero may be considered not to divide anything.</p></dd>
<dt><a name="12"><b class="function">oddFactors</b> <i class="arg">x</i></a></dt>
<dt><a name="13"><b class="function">oddFactors</b> <i class="arg">x</i></a></dt>
<dd><p>Return a list of odd integer factors of x, sorted in ascending order</p></dd>
<dt><a name="13"><b class="function">greatestFactorBelow</b> <i class="arg">x</i></a></dt>
<dt><a name="14"><b class="function">greatestFactorBelow</b> <i class="arg">x</i></a></dt>
<dd><p>Return the largest factor of x excluding itself</p>
<p>factor functions can be useful for console layout calculations</p>
<p>See Tcllib math::numtheory for more extensive implementations</p></dd>
<dt><a name="14"><b class="function">greatestOddFactorBelow</b> <i class="arg">x</i></a></dt>
<dt><a name="15"><b class="function">greatestOddFactorBelow</b> <i class="arg">x</i></a></dt>
<dd><p>Return the largest odd integer factor of x excluding x itself</p></dd>
<dt><a name="15"><b class="function">greatestOddFactor</b> <i class="arg">x</i></a></dt>
<dt><a name="16"><b class="function">greatestOddFactor</b> <i class="arg">x</i></a></dt>
<dd><p>Return the largest odd integer factor of x</p>
<p>For an odd value of x - this will always return x</p></dd>
<dt><a name="16"><b class="function">gcd</b> <i class="arg">n</i> <i class="arg">m</i></a></dt>
<dt><a name="17"><b class="function">gcd</b> <i class="arg">n</i> <i class="arg">m</i></a></dt>
<dd><p>Return the greatest common divisor of m and n</p>
<p>Straight from Lars Hellstr&ouml;m's math::numtheory library in Tcllib</p>
<p>Graphical use:</p>
<p>An a by b rectangle can be covered with square tiles of side-length c,</p>
<p>only if c is a common divisor of a and b</p></dd>
<dt><a name="17"><b class="function">gcd</b> <i class="arg">n</i> <i class="arg">m</i></a></dt>
<dt><a name="18"><b class="function">gcd</b> <i class="arg">n</i> <i class="arg">m</i></a></dt>
<dd><p>Return the lowest common multiple of m and n</p>
<p>Straight from Lars Hellstr&ouml;m's math::numtheory library in Tcllib</p></dd>
<dt><a name="18"><b class="function">commonDivisors</b> <i class="arg">x</i> <i class="arg">y</i></a></dt>
<dt><a name="19"><b class="function">commonDivisors</b> <i class="arg">x</i> <i class="arg">y</i></a></dt>
<dd><p>Return a list of all the common factors of x and y</p>
<p>(equivalent to factors of their gcd)</p></dd>
<dt><a name="19"><b class="function">hasglobs</b> <i class="arg">str</i></a></dt>
<dt><a name="20"><b class="function">hasglobs</b> <i class="arg">str</i></a></dt>
<dd><p>Return a boolean indicating whether str contains any of the glob characters: * ? [ ]</p>
<p>hasglobs uses append to preserve Tcls internal representation for str - so it should help avoid shimmering in the few cases where this may matter.</p></dd>
<dt><a name="20"><b class="function">trimzero</b> <i class="arg">number</i></a></dt>
<dt><a name="21"><b class="function">trimzero</b> <i class="arg">number</i></a></dt>
<dd><p>Return number with left-hand-side zeros trimmed off - unless all zero</p>
<p>If number is all zero - a single 0 is returned</p></dd>
<dt><a name="21"><b class="function">substring_count</b> <i class="arg">str</i> <i class="arg">substring</i></a></dt>
<dt><a name="22"><b class="function">substring_count</b> <i class="arg">str</i> <i class="arg">substring</i></a></dt>
<dd><p>Search str and return number of occurrences of substring</p></dd>
<dt><a name="22"><b class="function">dict_merge_ordered</b> <i class="arg">defaults</i> <i class="arg">main</i></a></dt>
<dt><a name="23"><b class="function">dict_merge_ordered</b> <i class="arg">defaults</i> <i class="arg">main</i></a></dt>
<dd><p>The standard dict merge accepts multiple dicts with values from dicts to the right (2nd argument) taking precedence.</p>
<p>When merging with a dict of default values - this means that any default key/vals that weren't in the main dict appear in the output before the main data.</p>
<p>This function merges the two dicts whilst maintaining the key order of main followed by defaults.</p></dd>
<dt><a name="23"><b class="function">askuser</b> <i class="arg">question</i></a></dt>
<dt><a name="24"><b class="function">askuser</b> <i class="arg">question</i></a></dt>
<dd><p>A basic utility to read an answer from stdin</p>
<p>The prompt is written to the terminal and then it waits for a user to type something</p>
<p>stdin is temporarily configured to blocking and then put back in its original state in case it wasn't already so.</p>
@ -314,19 +324,19 @@ but has the disadvantage of being slower for 'small' numbers and using more memo
}
</pre>
</dd>
<dt><a name="24"><b class="function">linesort</b> <span class="opt">?sortoption ?val?...?</span> <i class="arg">textblock</i></a></dt>
<dt><a name="25"><b class="function">linesort</b> <span class="opt">?sortoption ?val?...?</span> <i class="arg">textblock</i></a></dt>
<dd><p>Sort lines in textblock</p>
<p>Returns another textblock with lines sorted</p>
<p>options are flags as accepted by lsort ie -ascii -command -decreasing -dictionary -index -indices -integer -nocase -real -stride -unique</p></dd>
<dt><a name="25"><b class="function">list_as_lines</b> <span class="opt">?-joinchar char?</span> <i class="arg">linelist</i></a></dt>
<dt><a name="26"><b class="function">list_as_lines</b> <span class="opt">?-joinchar char?</span> <i class="arg">linelist</i></a></dt>
<dd><p>This simply joines the elements of the list with -joinchar</p>
<p>It is mainly intended for use in pipelines where the primary argument comes at the end - but it can also be used as a general replacement for join $lines &lt;le&gt;</p>
<p>The sister function lines_as_list takes a block of text and splits it into lines - but with more options related to trimming the block and/or each line.</p></dd>
<dt><a name="26"><b class="function">lines_as_list</b> <span class="opt">?option value ...?</span> <i class="arg">text</i></a></dt>
<dt><a name="27"><b class="function">lines_as_list</b> <span class="opt">?option value ...?</span> <i class="arg">text</i></a></dt>
<dd><p>Returns a list of possibly trimmed lines depeding on options</p>
<p>The concept of lines is raw lines from splitting on newline after crlf is mapped to lf</p>
<p>- not console lines which may be entirely different due to control characters such as vertical tabs or ANSI movements</p></dd>
<dt><a name="27"><b class="function">opts_values</b> <span class="opt">?option value...?</span> <i class="arg">optionspecs</i> <i class="arg">rawargs</i></a></dt>
<dt><a name="28"><b class="function">opts_values</b> <span class="opt">?option value...?</span> <i class="arg">optionspecs</i> <i class="arg">rawargs</i></a></dt>
<dd><p>Parse rawargs as a sequence of zero or more option-value pairs followed by zero or more values</p>
<p>Returns a dict of the form: opts &lt;options_dict&gt; values &lt;values_dict&gt;</p>
<p>ARGUMENTS:</p>

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

@ -1748,6 +1748,7 @@ namespace eval punk::ansi {
dict set codestate_empty bg "" ;#40-47 + 100-107
#misnomer should have been sgr_merge_args ? :/
#as a common case optimisation - it will not merge a single element list, even if that code contains redundant elements
proc sgr_merge_list {args} {
if {[llength $args] == 0} {
@ -1755,9 +1756,30 @@ namespace eval punk::ansi {
} elseif {[llength $args] == 1} {
return [lindex $args 0]
}
sgr_merge $args
}
#codes *must* already have been split so that one esc per element in codelist
#e.g codelist [a+ Yellow Red underline] [a+ blue] [a+ red] is ok
#but codelist "[a+ Yellow Red underline][a+ blue]" [a+ red] is not
#(use punk::ansi::ta::split_codes_single)
proc sgr_merge {codelist args} {
variable codestate_empty
set othercodes [list]
set defaults [dict create\
-filter_fg 0\
-filter_bg 0\
]
dict for {k v} $args {
switch -- $k {
-filter_fg - -filter_bg {}
default {
error "sgr_merge unknown option '$k'. Known options [dict keys $defaults]"
}
}
}
set opts [dict merge $defaults $args]
set codestate $codestate_empty
set codestate_initial $codestate_empty ;#keep a copy for resets.
set did_reset 0
@ -1772,7 +1794,7 @@ namespace eval punk::ansi {
#We still output any non SGR codes in the list as they came in - preserving their CSI
foreach c $args {
foreach c $codelist {
#normalize 8bit to a token of the same length so our string operations on the code are the same and we can maintain a switch statement with literals rather than escapes
#.. but preserve original c
#set cnorm [string map [list \x9b {8[} ] $c]
@ -1911,7 +1933,7 @@ namespace eval punk::ansi {
dict set codestate hide 28 ;#reveal
}
29 {
dict set codestate strik 29;#off
dict set codestate strike 29;#off
}
30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 {
dict set codestate fg $p ;#foreground colour
@ -2067,13 +2089,38 @@ namespace eval punk::ansi {
}
set codemerge ""
dict for {k v} $codestate {
switch -- $v {
"" {
if {[dict get $opts -filter_fg] || [dict get $opts -filter_bg]} {
dict for {k v} $codestate {
switch -- $v {
"" {
}
default {
switch -- $k {
bg {
if {![dict get $opts -filter_bg]} {
append codemerge "${v}\;"
}
}
fg {
if {![dict get $opts -filter_fg]} {
append codemerge "${v}\;"
}
}
default {
append codemerge "${v}\;"
}
}
}
}
default {
append codemerge "${v}\;"
}
} else {
dict for {k v} $codestate {
switch -- $v {
"" {}
default {
append codemerge "${v}\;"
}
}
}
}
@ -3963,7 +4010,7 @@ namespace eval punk::ansi::ansistring {
#return empty string for each index that is out of range
#review - this is possibly too slow to be very useful as is.
# consider converting to oo and maintaining state of ansisplits so we don't repeat relatively expensive operations for same string
#see also punk::list_index_resolve / punk::list_index_get for ways to handle tcl list/string indices without parsing them.
#see also punk::lindex_resolve / punk::lindex_get for ways to handle tcl list/string indices without parsing them.
proc INDEXABSOLUTE {string args} {
set payload_len -1 ;# -1 as token to indicate we haven't calculated it yet (only want to call it once at most)
set testindices [list]

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

@ -211,7 +211,18 @@ namespace eval punk::lib {
#}
proc list_index_resolve {list index} {
proc lindex_resolve {list index} {
#*** !doctools
#[call [fun lindex_resolve] [arg list] [arg index]]
#[para]Resolve an index which may be of the forms accepted by Tcl list commands such as end-2 or 2+2 to the actual integer index for the supplied list
#[para]Users may define procs which accept a list index and wish to accept the forms understood by Tcl.
#[para]This means the proc may be called with something like $x+2 end-$y etc
#[para]Sometimes the actual integer index is desired.
#[para]We want to resolve the index used, without passing arbitrary expressions into the 'expr' function - which could have security risks.
#[para]lindex_resolve will parse the index expression and return -1 if the supplied index expression is out of bounds for the supplied list.
#[para]Otherwise it will return an integer corresponding to the position in the list.
#[para]Like Tcl list commands - it will produce an error if the form of the index is not acceptable
#Note that for an index such as $x+1 - we never see the '$x' as it is substituted in the calling command. We will get something like 10+1 - which we will resolve (hopefully safely) with expr
if {![llength $list]} {
return -1
@ -271,7 +282,7 @@ namespace eval punk::lib {
}
}
}
proc list_index_resolve2 {list index} {
proc lindex_resolve2 {list index} {
set indices [list] ;#building this may be somewhat expensive in terms of storage and compute for large lists - we could use lseq in Tcl 8.7+ but that's likely unavailable here.
for {set i 0} {$i < [llength $list]} {incr i} {
lappend indices $i
@ -283,7 +294,7 @@ namespace eval punk::lib {
return $idx
}
}
proc list_index_get {list index} {
proc lindex_get {list index} {
set resultlist [lrange $list $index $index]
if {![llength $resultlist]} {
return -1

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

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save