Browse Source

xbin (.xb) support without font

master
Julian Noble 3 weeks ago
parent
commit
20fde7a135
  1. 3
      src/bootsupport/modules/metaface-1.2.8.tm
  2. 1938
      src/bootsupport/modules/natsort-0.1.1.7.tm
  3. 20
      src/bootsupport/modules/overtype-1.7.4.tm
  4. 11
      src/bootsupport/modules/punk/mix/commandset/loadedlib-0.1.0.tm
  5. 24
      src/bootsupport/modules/punk/repl-0.1.2.tm
  6. 3
      src/bootsupport/modules/punk/repo-0.1.1.tm
  7. 127
      src/bootsupport/modules/textblock-0.1.3.tm
  8. 110
      src/modules/overtype-999999.0a1.0.tm
  9. 77
      src/modules/punk/ansi-999999.0a1.0.tm
  10. 3
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/metaface-1.2.8.tm
  11. 1938
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/natsort-0.1.1.7.tm
  12. 20
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/overtype-1.7.4.tm
  13. 11
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/commandset/loadedlib-0.1.0.tm
  14. 24
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/repl-0.1.2.tm
  15. 3
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/repo-0.1.1.tm
  16. 127
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/textblock-0.1.3.tm
  17. 3
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/metaface-1.2.8.tm
  18. 1938
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/natsort-0.1.1.7.tm
  19. 20
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/overtype-1.7.4.tm
  20. 11
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/commandset/loadedlib-0.1.0.tm
  21. 24
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/repl-0.1.2.tm
  22. 3
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/repo-0.1.1.tm
  23. 127
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/textblock-0.1.3.tm
  24. 3
      src/vendormodules/metaface-1.2.8.tm
  25. 6364
      src/vendormodules/metaface-1.2.9.tm
  26. BIN
      src/vendormodules/test/pattern-1.2.8.tm
  27. 2
      src/vfs/_vfscommon.vfs/modules/commandstack-0.4.1.tm
  28. 5
      src/vfs/_vfscommon.vfs/modules/funcl-0.1.tm
  29. 3
      src/vfs/_vfscommon.vfs/modules/metaface-1.2.8.tm
  30. 6364
      src/vfs/_vfscommon.vfs/modules/metaface-1.2.9.tm
  31. 1938
      src/vfs/_vfscommon.vfs/modules/natsort-0.1.1.7.tm
  32. 200
      src/vfs/_vfscommon.vfs/modules/oolib-0.1.3.tm
  33. 226
      src/vfs/_vfscommon.vfs/modules/overtype-1.7.4.tm
  34. 455
      src/vfs/_vfscommon.vfs/modules/patternpunk-1.1.1.tm
  35. 9288
      src/vfs/_vfscommon.vfs/modules/punk-0.1.1.tm
  36. 226
      src/vfs/_vfscommon.vfs/modules/punk/ansi-0.1.1.tm
  37. 21
      src/vfs/_vfscommon.vfs/modules/punk/ansi/sauce-0.1.0.tm
  38. 5
      src/vfs/_vfscommon.vfs/modules/punk/console-0.1.1.tm
  39. 33
      src/vfs/_vfscommon.vfs/modules/punk/du-0.1.0.tm
  40. 11
      src/vfs/_vfscommon.vfs/modules/punk/mix/commandset/loadedlib-0.1.0.tm
  41. 158
      src/vfs/_vfscommon.vfs/modules/punk/mod-0.1.1.tm
  42. 2
      src/vfs/_vfscommon.vfs/modules/punk/nav/fs-0.1.0.tm
  43. 192
      src/vfs/_vfscommon.vfs/modules/punk/overlay-0.1.1.tm
  44. 24
      src/vfs/_vfscommon.vfs/modules/punk/repl-0.1.2.tm
  45. 3
      src/vfs/_vfscommon.vfs/modules/punk/repo-0.1.1.tm
  46. 9
      src/vfs/_vfscommon.vfs/modules/punkapp-0.1.1.tm
  47. 2459
      src/vfs/_vfscommon.vfs/modules/punkcheck-0.1.1.tm
  48. 2
      src/vfs/_vfscommon.vfs/modules/punkcheck/cli-0.1.0.tm
  49. 897
      src/vfs/_vfscommon.vfs/modules/shellrun-0.1.2.tm
  50. BIN
      src/vfs/_vfscommon.vfs/modules/test/pattern-1.2.8.tm
  51. 127
      src/vfs/_vfscommon.vfs/modules/textblock-0.1.3.tm
  52. BIN
      src/vfs/_vfscommon.vfs/modules/zipper-0.14.tm
  53. 17
      src/vfs/_vfscommon.vfs/modules/zzzload-0.1.0.tm

3
src/bootsupport/modules/metaface-1.2.8.tm

@ -1,4 +1,4 @@
package require dictutils
package provide metaface [namespace eval metaface { package provide metaface [namespace eval metaface {
variable version variable version
set version 1.2.8 set version 1.2.8
@ -6173,6 +6173,7 @@ proc ::p::-1::INVOCANTDATA {_ID_} {
#obsolete? #obsolete?
dict set ::p::-1::_iface::o_methods UPDATEDINVOCANTDATA {arglist {}} dict set ::p::-1::_iface::o_methods UPDATEDINVOCANTDATA {arglist {}}
proc ::p::-1::UPDATEDINVOCANTDATA {_ID_} { proc ::p::-1::UPDATEDINVOCANTDATA {_ID_} {
#package require dictutils
set updated_ID_ $_ID_ set updated_ID_ $_ID_
array set updated_roles [list] array set updated_roles [list]

1938
src/bootsupport/modules/natsort-0.1.1.7.tm

File diff suppressed because it is too large Load Diff

20
src/bootsupport/modules/overtype-1.7.4.tm

@ -404,16 +404,16 @@ tcl::namespace::eval overtype {
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
#TODO #TODO
#REVIEW - punk::console package may not be loaded #REVIEW - punk::console package may not be loaded
set cursor_style_overtype {3 underline-blink} #set cursor_style_overtype {3 underline-blink}
set cursor_style_insert {5 beam-blink} #set cursor_style_insert {5 beam-blink}
if {$opt_insert_mode} { #if {$opt_insert_mode} {
set initial_cursor_style $cursor_style_insert # set initial_cursor_style $cursor_style_insert
} else { #} else {
set initial_cursor_style $cursor_style_overtype # set initial_cursor_style $cursor_style_overtype
} #}
catch { #catch {
punk::console::cursor_style -console $opt_console $cursor_style_overtype # punk::console::cursor_style -console $opt_console $cursor_style_overtype
} #}
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# ---------------------------- # ----------------------------

11
src/bootsupport/modules/punk/mix/commandset/loadedlib-0.1.0.tm

@ -247,12 +247,6 @@ namespace eval punk::mix::commandset::loadedlib {
set opts [dict merge $defaults $args] set opts [dict merge $defaults $args]
set opt_askme [dict get $opts -askme] set opt_askme [dict get $opts -askme]
if {[catch {package require natsort}]} {
set has_natsort 0
} else {
set has_natsort 1
}
catch {package require $library 1-0} ;#ensure pkg system has loaded/searched for everything for the path of the specified library (using unsatisfiable version range) catch {package require $library 1-0} ;#ensure pkg system has loaded/searched for everything for the path of the specified library (using unsatisfiable version range)
if {[file pathtype $modulefoldername] eq "absolute"} { if {[file pathtype $modulefoldername] eq "absolute"} {
@ -321,11 +315,6 @@ namespace eval punk::mix::commandset::loadedlib {
set versions [package versions [lindex $libfound 0]] set versions [package versions [lindex $libfound 0]]
set versions [lsort -command {package vcompare} $versions] set versions [lsort -command {package vcompare} $versions]
#if {$has_natsort} {
# set versions [natsort::sort $versions]
#} else {
# set versions [lsort $versions]
#}
if {![llength $versions]} { if {![llength $versions]} {
error "No version numbers found for library/module $libfound - sorry, you will need to copy it across manually" error "No version numbers found for library/module $libfound - sorry, you will need to copy it across manually"
} }

24
src/bootsupport/modules/punk/repl-0.1.2.tm

@ -1076,13 +1076,19 @@ namespace eval punk::repl::class {
append debug \n "input:[ansistring VIEW -lf 1 -vt 1 $new0] before row:$o_cursor_row after row: $result_row before col:$o_cursor_col after col:$result_col" append debug \n "input:[ansistring VIEW -lf 1 -vt 1 $new0] before row:$o_cursor_row after row: $result_row before col:$o_cursor_col after col:$result_col"
package require textblock package require textblock
set debug [textblock::frame -type $frametype -checkargs 0 -buildcache 0 $debug] set debug [textblock::frame -type $frametype -checkargs 0 -buildcache 0 $debug]
if {![punk::console::vt52]} {
catch {punk::console::move_emitblock_return $debug_first_row 1 $debug} #------------------------------------
} else { punk::console::cursorsave_move_emitblock_return $debug_first_row 1 $debug ;#supports also vt52
#?? #if {![punk::console::vt52]} {
} # #review
# catch {punk::console::move_emitblock_return $debug_first_row 1 $debug}
#} else {
# #??
#}
#------------------------------------
# -- --- --- --- --- --- # -- --- --- --- --- ---
set o_cursor_col $result_col set o_cursor_col $result_col
set cursor_row_idx [expr {$o_cursor_row-1}] set cursor_row_idx [expr {$o_cursor_row-1}]
lset o_rendered_lines $cursor_row_idx $result lset o_rendered_lines $cursor_row_idx $result
@ -3533,13 +3539,13 @@ namespace eval repl {
punk::ansi punk::ansi
punk::lib punk::lib
overtype overtype
dictutils
debug debug
punk::ns punk::ns
textblock textblock
punk::args::moduledoc::tclcore punk::args::moduledoc::tclcore
punk::aliascore punk::aliascore
}] }]
#dictutils
#pattern looks up versions available of patternlib before loading (but we don't have an index for tm files) todo fix pattern. #pattern looks up versions available of patternlib before loading (but we don't have an index for tm files) todo fix pattern.
# patterncmd\ # patterncmd\
@ -3784,7 +3790,7 @@ namespace eval repl {
#puts stderr "loading natsort" #puts stderr "loading natsort"
#natsort has 'application mode' which can exit. #natsort has 'application mode' which can exit.
#Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions #Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions
package require natsort #package require natsort
#package require punk ;# Thread #package require punk ;# Thread
#package require shellrun ;#subcommand exists of file #package require shellrun ;#subcommand exists of file
@ -3794,7 +3800,7 @@ namespace eval repl {
package require punk::ns ;#requires:punk::lib,punk::args,struct::list,cmdline+(tcllibc),struct::set,punk::ansi,punk::char, package require punk::ns ;#requires:punk::lib,punk::args,struct::list,cmdline+(tcllibc),struct::set,punk::ansi,punk::char,
#textutil,textutil::string,textutil::adjust,textutil::repeat,textutil::string,textutil::split,textutil::tabify,textutil::wcswidth #textutil,textutil::string,textutil::adjust,textutil::repeat,textutil::string,textutil::split,textutil::tabify,textutil::wcswidth
#punk::encmime,punk::assertion #punk::encmime,punk::assertion
#twapi,platform,registry,debug,overtype,patternpunk,pattern,patterncmd,metaface,patternpredator2,patternlib,dictutils #twapi,platform,registry,debug,overtype,patternpunk,pattern,patterncmd,metaface,patternpredator2,patternlib
#----------------------------------------------------------------------------------------------------------------------------------------- #-----------------------------------------------------------------------------------------------------------------------------------------
#package require textblock #package require textblock
@ -3921,7 +3927,7 @@ namespace eval repl {
#puts stderr "loading natsort" #puts stderr "loading natsort"
#natsort has 'application mode' which can exit. #natsort has 'application mode' which can exit.
#Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions #Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions
package require natsort #package require natsort
#catch {package require packageTrace} #catch {package require packageTrace}
if {[catch {package require punk::console} errM]} { if {[catch {package require punk::console} errM]} {
#review #review

3
src/bootsupport/modules/punk/repo-0.1.1.tm

@ -83,6 +83,7 @@ namespace eval punk::repo {
proc get_fossil_usage {} { proc get_fossil_usage {} {
set allcmds [runout -n fossil help -a] set allcmds [runout -n fossil help -a]
#review - fix runout which is introducing addition ansi (repl problem?)
set allcmds [punk::ansi::ansistrip $allcmds] set allcmds [punk::ansi::ansistrip $allcmds]
set mainhelp [runout -n fossil help] set mainhelp [runout -n fossil help]
set mainhelp [punk::ansi::ansistrip $mainhelp] set mainhelp [punk::ansi::ansistrip $mainhelp]
@ -190,7 +191,7 @@ namespace eval punk::repo {
foreach ln $basic_opt_lines { foreach ln $basic_opt_lines {
set ln [string trim $ln] set ln [string trim $ln]
#fossil sometimes emits cursor control sequences e.g CSI 3 q #REVIEW - we only need to strip because 'runout' is introducing ansi.
set ln [punk::ansi::ansistrip $ln] set ln [punk::ansi::ansistrip $ln]
if {$ln eq ""} { if {$ln eq ""} {
continue continue

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

@ -6475,6 +6475,58 @@ tcl::namespace::eval textblock {
} }
} }
variable framedef_cache [tcl::dict::create] variable framedef_cache [tcl::dict::create]
namespace eval argdoc {
set DYN_FRAME_TYPES {${[set ::textblock::frametypes]}}
punk::args::define {
@dynamic
@id -id ::textblock::framedef
@cmd -name textblock::framedef\
-summary "Return frame graphical elements as a dictionary."\
-help "Return a dict of the elements that make up a frame border.
May return a subset of available elements based on memberglob values."
@leaders -min 0 -max 0
@opts
-joins -default "" -type list\
-help "List of join directions, any of: up down left right
or those combined with another frametype e.g left-heavy down-light."
-boxonly -default 0 -type boolean\
-help "-boxonly true restricts results to the corner,vertical and horizontal box elements
It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj."
@values -min 1 -max -1
frametype -choices "${$DYN_FRAME_TYPES}" -choiceprefix 0 -choicerestricted 0 -type dict\
-help "name from the predefined frametypes or an adhoc dictionary."
memberglob -type globstring -optional 1 -multiple 1 -choiceprefix 0 -choicerestricted 0 -choices {
corner noncorner top bottom vertical horizontal left right
hl hlt hlb vsl vll vlr tlc trc blc brc hltj hlbj vllj vlrj
}\
-help "restrict to keys matching memberglob."
}
#set spec [string map [list <ftlist> $::textblock::frametypes] {
# @id -id ::textblock::framedef
# @cmd -name textblock::framedef\
# -summary "Return frame graphical elements as a dictionary."\
# -help "Return a dict of the elements that make up a frame border.
# May return a subset of available elements based on memberglob values."
# @leaders -min 0 -max 0
# @opts
# -joins -default "" -type list\
# -help "List of join directions, any of: up down left right
# or those combined with another frametype e.g left-heavy down-light."
# -boxonly -default 0 -type boolean\
# -help "-boxonly true restricts results to the corner,vertical and horizontal box elements
# It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj."
# @values -min 1 -max -1
# frametype -choices "<ftlist>" -choiceprefix 0 -choicerestricted 0 -type dict\
# -help "name from the predefined frametypes or an adhoc dictionary."
# memberglob -type globstring -optional 1 -multiple 1 -choiceprefix 0 -choicerestricted 0 -choices {
# corner noncorner top bottom vertical horizontal left right
# hl hlt hlb vsl vll vlr tlc trc blc brc hltj hlbj vllj vlrj
# }\
# -help "restrict to keys matching memberglob."
#}]
}
proc framedef {args} { proc framedef {args} {
#unicode box drawing only provides enough characters for seamless joining of unicode boxes light and heavy. #unicode box drawing only provides enough characters for seamless joining of unicode boxes light and heavy.
#e.g with characters such as \u2539 Box Drawings Right Light and Left Up Heavy. #e.g with characters such as \u2539 Box Drawings Right Light and Left Up Heavy.
@ -6520,6 +6572,9 @@ tcl::namespace::eval textblock {
} }
} }
set f [lindex $values 0] set f [lindex $values 0]
#expect either a known frametype or a dict with known keys
set rawglobs [lrange $values 1 end] set rawglobs [lrange $values 1 end]
if {![llength $rawglobs] || "all" in $rawglobs || "*" in $rawglobs} { if {![llength $rawglobs] || "all" in $rawglobs || "*" in $rawglobs} {
set globs * set globs *
@ -6570,32 +6625,7 @@ tcl::namespace::eval textblock {
} }
if {$bad_option || [llength $values] == 0} { if {$bad_option || [llength $values] == 0} {
#no framedef supplied, or unrecognised opt seen #no framedef supplied, or unrecognised opt seen
set spec [string map [list <ftlist> $::textblock::frametypes] { punk::args::parse $args withid ::textblock::framedef
@id -id ::textblock::framedef
@cmd -name textblock::framedef\
-summary "Return frame graphical elements as a dictionary."\
-help "Return a dict of the elements that make up a frame border.
May return a subset of available elements based on memberglob values."
@leaders -min 0 -max 0
@opts
-joins -default "" -type list\
-help "List of join directions, any of: up down left right
or those combined with another frametype e.g left-heavy down-light."
-boxonly -default 0 -type boolean\
-help "-boxonly true restricts results to the corner,vertical and horizontal box elements
It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj."
@values -min 1 -max -1
frametype -choices "<ftlist>" -choiceprefix 0 -choicerestricted 0 -type dict\
-help "name from the predefined frametypes or an adhoc dictionary."
memberglob -type globstring -optional 1 -multiple 1 -choiceprefix 0 -choicerestricted 0 -choices {
corner noncorner top bottom vertical horizontal left right
hl hlt hlb vsl vll vlr tlc trc blc brc hltj hlbj vllj vlrj
}\
-help "restrict to keys matching memberglob."
}]
#append spec \n "frametype -help \"A predefined \""
punk::args::parse $args withdef $spec
return return
} }
@ -7837,16 +7867,23 @@ tcl::namespace::eval textblock {
set blc \U1fb7c ;#legacy block set blc \U1fb7c ;#legacy block
set brc \U1fb7f ;#legacy block set brc \U1fb7f ;#legacy block
if {(![interp issafe])} {
if {![catch {punk::console::check::has_bug_legacysymbolwidth} symbug] && $symbug} { #------------------------------------------------------------------------------------------------------
#rather than totally fail on some mixed layout that happens to use block2 - just degrade it - but prevent alignment problems #REVIEW - framedef may be called in a context where we don't have a console that can respond to ansi queries.
set sp \u00a0 ;#non breaking space (plain space may act transparent in some use cases) #We should either check has_bug_legacysymbolwidth at initial console detection and set a global var,
set tlc $sp #or find some other way to detect if we are in a terminal that has this problem.
set trc $sp
set blc $sp #if {(![interp issafe])} {
set brc $sp # if {![catch {punk::console::check::has_bug_legacysymbolwidth} symbug] && $symbug} {
} # #rather than totally fail on some mixed layout that happens to use block2 - just degrade it - but prevent alignment problems
} # set sp \u00a0 ;#non breaking space (plain space may act transparent in some use cases)
# set tlc $sp
# set trc $sp
# set blc $sp
# set brc $sp
# }
#}
#------------------------------------------------------------------------------------------------------
#horizontal and vertical bar joins #horizontal and vertical bar joins
set hltj $hlt set hltj $hlt
@ -7909,22 +7946,30 @@ tcl::namespace::eval textblock {
set vlrj $vlr set vlrj $vlr
} }
default { default {
if {[llength $f] % 2 != 0} {
#todo - retrieve usage from punk::args
#error "textblock::frametype frametype '$f' is not one of the predefined frametypes: $::textblock::frametypes and does not appear to be a dictionary for a custom frametype"
punk::args::parse $args withid ::textblock::framedef
return
}
#set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "] ;#only default the general types - these form defaults for more specific types if they're missing #set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "] ;#only default the general types - these form defaults for more specific types if they're missing
set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "] set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "]
if {"all" in [dict keys $f]} { if {"all" in [dict keys $f]} {
set A [dict get $f all] set A [dict get $f all]
set default_custom [tcl::dict::create hl $A vl $A tlc $A trc $A blc $A brc $A] set default_custom [tcl::dict::create hl $A vl $A tlc $A trc $A blc $A brc $A]
} }
if {[llength $f] % 2} { ####
#todo - retrieve usage from punk::args
error "textblock::frametype frametype '$f' is not one of the predefined frametypes: $::textblock::frametypes and does not appear to be a dictionary for a custom frametype"
}
#unknown order of keys specified by user - validate before creating vars as we need more general elements to be available as defaults #unknown order of keys specified by user - validate before creating vars as we need more general elements to be available as defaults
dict for {k v} $f { dict for {k v} $f {
switch -- $k { switch -- $k {
all - hl - vl - tlc - trc - blc - brc - hlt - hlb - vll - vlr - hltj - hlbj - vllj - vlrj {} all - hl - vl - tlc - trc - blc - brc - hlt - hlb - vll - vlr - hltj - hlbj - vllj - vlrj {}
default { default {
error "textblock::frametype '$f' has unknown element '$k'" #error "textblock::frametype '$f' has unknown element '$k'"
set errmsg [punk::args::usage -scheme error ::textblock::framedef]
append errmsg "\ntextblock::frametype frametype '$f' has unknown element '$k'"
error $errmsg
return
} }
} }
} }

110
src/modules/overtype-999999.0a1.0.tm

@ -437,8 +437,18 @@ tcl::namespace::eval overtype {
} }
# ---------------------------- # ----------------------------
#---------------------------------------------------------
#underblock is expected to be pre-rendered - ie any ANSI codes have already been processed and rendered into the text.
#This is because the underblock is used as the basis for calculating the layout of the output
#- so it needs to be in a form where we can determine the width of each line and how many lines there are.
set underblock [tcl::string::map {\r\n \n} $underblock] set underblock [tcl::string::map {\r\n \n} $underblock]
set overblock [tcl::string::map {\r\n \n} $overblock]
#do not split the overblock into lines at this stage - it may contain binary data.
#REVIEW - xbin (or binarytext?) may contain binary data which could be corrupted by mapping \r\n to \n.
#set overblock [tcl::string::map {\r\n \n} $overblock]
#---------------------------------------------------------
if {$opt_startrow > 1} { if {$opt_startrow > 1} {
set down [expr {$opt_startrow -1}] set down [expr {$opt_startrow -1}]
#when vt52? #when vt52?
@ -532,6 +542,7 @@ tcl::namespace::eval overtype {
#overblock height/width isn't useful in the presence of an ansi input overlay with movements. The number of lines may bear little relationship to the output height #overblock height/width isn't useful in the presence of an ansi input overlay with movements. The number of lines may bear little relationship to the output height
#lassign [blocksize $overblock] _w overblock_width _h overblock_height #lassign [blocksize $overblock] _w overblock_width _h overblock_height
#temporary scheme selector for experimenting with different approaches to chunking the input overlay for processing.
set scheme 4 set scheme 4
switch -- $scheme { switch -- $scheme {
0 { 0 {
@ -576,9 +587,11 @@ tcl::namespace::eval overtype {
} }
4 { 4 {
#active development scheme - 2026.
set inputchunks [list] set inputchunks [list]
switch -- $opt_format { switch -- $opt_format {
ansi { ansi {
set overblock [tcl::string::map {\r\n \n} $overblock]
foreach ln [split $overblock \n] { foreach ln [split $overblock \n] {
lappend inputchunks [list mixed $ln\n] lappend inputchunks [list mixed $ln\n]
} }
@ -621,17 +634,24 @@ tcl::namespace::eval overtype {
set xbin_header_info [punk::ansi::xbin::parse_header $xbin_header] set xbin_header_info [punk::ansi::xbin::parse_header $xbin_header]
set overblock [string range $overblock 11 end] set overblock [string range $overblock 11 end]
set flags [dict get $xbin_header_info flags] set flags [dict get $xbin_header_info flags]
set xbin_width [dict get $xbin_header_info width]
set xbin_height [dict get $xbin_header_info height]
set expected_cells [expr {$xbin_width * $xbin_height}]
set xbin_nonblink [expr {"nonblink" in $flags}] ;# ice.
set xbin_palette [punk::ansi::xbin::default_palette]
puts "xbin [dict get $xbin_header_info width]x[dict get $xbin_header_info height]" puts "xbin ${xbin_width}x${xbin_height}"
puts "xbin flags $flags" puts "xbin flags $flags"
#TODO - compression bios ice #optional 16-entry palette, 3 bytes per entry, RGB values 0..63
#hack - skip over palette (48 bytes)
if {"palette" in $flags} { if {"palette" in $flags} {
puts stderr "renderspace warning - palette unimplemented" #puts stderr "renderspace warning - palette unimplemented"
set xbin_palette [punk::ansi::xbin::parse_palette [string range $overblock 0 47]]
set overblock [string range $overblock 48 end] set overblock [string range $overblock 48 end]
} }
#todo - font.
#hack - skip over font 256 x fontsize or 512 x fontsize #hack - skip over font 256 x fontsize or 512 x fontsize
if {"512chars" in $flags} { if {"512chars" in $flags} {
set sz 512 set sz 512
@ -641,7 +661,8 @@ tcl::namespace::eval overtype {
#temp #temp
set skip [expr {$sz * [dict get $xbin_header_info fontsize]}] set skip [expr {$sz * [dict get $xbin_header_info fontsize]}]
if {"font" in $flags} { if {"font" in $flags} {
puts stderr "renderspace warning - font unimplemented" #todo - consider sixel or similar for font data - but for now we just skip over it.
puts stderr "renderspace warning - xbin font unimplemented"
set overblock [string range $overblock $skip end] set overblock [string range $overblock $skip end]
} }
puts stdout "xbin image data size [string length $overblock]" puts stdout "xbin image data size [string length $overblock]"
@ -658,8 +679,9 @@ tcl::namespace::eval overtype {
#remaining 6 bits - counter #remaining 6 bits - counter
set input "" set input ""
set bytes [split $overblock ""] set bytes [split $overblock ""]
#hacktest set byte_count [llength $bytes]
for {set b 0} {$b < [llength $bytes]} {} { set decoded_cells 0
for {set b 0} {$b < $byte_count} {} {
set rc [lindex $bytes $b] set rc [lindex $bytes $b]
set dec [scan $rc %c] set dec [scan $rc %c]
set ctype [expr {$dec >> 6}] set ctype [expr {$dec >> 6}]
@ -669,20 +691,39 @@ tcl::namespace::eval overtype {
if {$count < 1 || $count > 64} { if {$count < 1 || $count > 64} {
puts stderr "xbin - something wrong - max must be between 1 and 64 inclusive. received $count" puts stderr "xbin - something wrong - max must be between 1 and 64 inclusive. received $count"
} }
if {$count == 32} {
puts stderr "xbin ---> byte:[ansistring VIEW $rc] at posn $b"
}
incr b incr b
switch -- $ctype { if {$decoded_cells + $count > $expected_cells} {
error "overtype::renderspace xbin decode overflow: record would emit $count cells at decoded offset $decoded_cells, expected total $expected_cells cells for image dimensions ${xbin_width}x${xbin_height}"
}
switch -exact -- $ctype {
0 {
set needed [expr {$count * 2}]
}
1 -
2 {
set needed [expr {$count + 1}]
}
3 {
set needed 2
}
default {
error "overtype::renderspace xbin invalid compression type $ctype in repeatcounter byte '$rc' at offset $b"
}
}
if {$b + $needed > $byte_count} {
error "overtype::renderspace xbin truncated record: type $ctype requires $needed bytes at payload offset $b, but only [expr {$byte_count - $b}] bytes remain."
}
switch -exact -- $ctype {
0 { 0 {
#no compression #no compression
for {set c 0} {$c < $count*2} {incr c 2} { for {set c 0} {$c < $count*2} {incr c 2} {
set ch [lindex $bytes $b+$c] set ch [lindex $bytes $b+$c]
set ch [encoding convertfrom cp437 $ch] set ch [encoding convertfrom cp437 $ch]
set at [lindex $bytes [expr {$b+$c+1}]] set at [lindex $bytes [expr {$b+$c+1}]]
binary scan $at cu code #binary scan $at cu code
#set clr [a+ term-$code] #set clr [a+ term-$code]
set clr [a+ red] #set clr [a+ red] ;#debug
set clr [punk::ansi::xbin::attribute_ansi $at $xbin_palette $xbin_nonblink]
lappend ansisplit $clr $ch lappend ansisplit $clr $ch
} }
incr b [expr {$count*2}] incr b [expr {$count*2}]
@ -694,9 +735,10 @@ tcl::namespace::eval overtype {
incr b incr b
for {set c 0} {$c < $count} {incr c} { for {set c 0} {$c < $count} {incr c} {
set at [lindex $bytes $b+$c] set at [lindex $bytes $b+$c]
binary scan $at cu code #binary scan $at cu code
#set clr [a+ term-$code] #set clr [a+ term-$code]
set clr [a+ cyan] #set clr [a+ cyan] ;#debug
set clr [punk::ansi::xbin::attribute_ansi $at $xbin_palette $xbin_nonblink]
lappend ansisplit $clr $ch lappend ansisplit $clr $ch
} }
incr b [expr {$count}] incr b [expr {$count}]
@ -704,9 +746,10 @@ tcl::namespace::eval overtype {
2 { 2 {
#attribute compression #attribute compression
set at [lindex $bytes $b] set at [lindex $bytes $b]
binary scan $at cu code #binary scan $at cu code
#set clr [a+ term-$code] #set clr [a+ term-$code]
set clr [a+ green] #set clr [a+ green] ;#debug
set clr [punk::ansi::xbin::attribute_ansi $at $xbin_palette $xbin_nonblink]
incr b incr b
for {set c 0} {$c < $count} {incr c} { for {set c 0} {$c < $count} {incr c} {
set ch [lindex $bytes $b+$c] set ch [lindex $bytes $b+$c]
@ -720,25 +763,38 @@ tcl::namespace::eval overtype {
set ch [lindex $bytes $b] set ch [lindex $bytes $b]
set ch [encoding convertfrom cp437 $ch] set ch [encoding convertfrom cp437 $ch]
set at [lindex $bytes $b+1] set at [lindex $bytes $b+1]
binary scan $at cu code #binary scan $at cu code
#set clr [a+ term-$code] #set clr [a+ term-$code]
set clr [a+ white] #set clr [a+ white] ;#debug
set clr [punk::ansi::xbin::attribute_ansi $at $xbin_palette $xbin_nonblink]
for {set c 0} {$c < $count} {incr c} { for {set c 0} {$c < $count} {incr c} {
lappend ansisplit $clr $ch lappend ansisplit $clr $ch
} }
incr b 2 incr b 2
} }
} }
incr decoded_cells $count
}
if {$decoded_cells != $expected_cells} {
puts stderr "overtype::renderspace xbin decoded $decoded_cells cells, expected $expected_cells cells for image dimensions ${xbin_width}x${xbin_height}"
} }
lappend inputchunks [list ansisplit $ansisplit] lappend inputchunks [list ansisplit $ansisplit]
} else { } else {
foreach {ch at} [split $overblock ""] { foreach {ch at} [split $overblock ""] {
binary scan $at cu code #binary scan $at cu code
#palette? #set clr [a+ term-$code]
set clr [a+ term-$code] if {$at eq ""} {
set ch [encoding convertfrom cp437 $ch] #eg src/testansi/formatsamples/image/xbin/test.xb
lappend ansisplit $clr $ch #has trailing nul byte. for now just warn.
puts stderr "renderspace warning - xbin attribute byte is empty at char '[ansistring VIEW $ch]'"
#break ?
#experiment - treat as a reset.
lappend ansisplit [a+] $ch
} else {
set clr [punk::ansi::xbin::attribute_ansi $at $xbin_palette $xbin_nonblink]
set ch [encoding convertfrom cp437 $ch]
lappend ansisplit $clr $ch
}
} }
lappend inputchunks [list ansisplit $ansisplit] lappend inputchunks [list ansisplit $ansisplit]
} }

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

@ -762,7 +762,7 @@ tcl::namespace::eval punk::ansi {
} }
if {$format eq "xbin"} { if {$format eq "xbin"} {
set ansidata [fcat -translation binary $fname] ;#don't split on \x1a - this is also present in xbin header #set ansidata [fcat -translation binary $fname] ;#don't split on \x1a - this is also present in xbin header
set xbin_header [string range $ansidata 0 10] ;#11 bytes set xbin_header [string range $ansidata 0 10] ;#11 bytes
set non_header [string range $ansidata 11 end] set non_header [string range $ansidata 11 end]
#set ansidata $xbin_header[lindex [split $non_header \x1a] 0] ;#ignore sauce at tail #set ansidata $xbin_header[lindex [split $non_header \x1a] 0] ;#ignore sauce at tail
@ -11872,7 +11872,7 @@ namespace eval punk::ansi::colour {
@cmd -name "punk::ansi::colour::byteAnsi" -summary\ @cmd -name "punk::ansi::colour::byteAnsi" -summary\
"ANSI/BIOS colour codes from attribute byte."\ "ANSI/BIOS colour codes from attribute byte."\
-help\ -help\
"Convert an attribute-byte (character) to ANSI SGR "Convert a binarytext (.bin) attribute-byte (character) to ANSI SGR
foreground and background colour. foreground and background colour.
This is allows 16 foreground colours and only 8 This is allows 16 foreground colours and only 8
background colours, with the highest bit being background colours, with the highest bit being
@ -11892,7 +11892,7 @@ namespace eval punk::ansi::colour {
lappend PUNKARGS [list { lappend PUNKARGS [list {
@id -id "::punk::ansi::colour::byteAnsiIce" @id -id "::punk::ansi::colour::byteAnsiIce"
@cmd -name "punk::ansi::colour::byteAnsiIce" -summary\ @cmd -name "punk::ansi::colour::byteAnsiIce" -summary\
"iCE colour codes from attribute byte."\ "iCE colour codes from binarytext (.bin) attribute byte."\
-help\ -help\
"Convert an attribute-byte (character) to ANSI SGR "Convert an attribute-byte (character) to ANSI SGR
foreground and background colour. foreground and background colour.
@ -11956,6 +11956,77 @@ tcl::namespace::eval punk::ansi::xbin {
#width - number of columns, height - number of character rows #width - number of columns, height - number of character rows
return [dict create width $xbin_width height $xbin_height fontsize $xbin_fontsize flags $xbin_flags] return [dict create width $xbin_width height $xbin_height fontsize $xbin_fontsize flags $xbin_flags]
} }
proc default_palette {} {
# VGA 16-colour default palette as RGB 0-255 triples.
return {
{0 0 0}
{0 0 170}
{0 170 0}
{0 170 170}
{170 0 0}
{170 0 170}
{170 85 0}
{170 170 170}
{85 85 85}
{0 0 255}
{0 255 0}
{0 255 255}
{255 0 0}
{255 0 255}
{255 255 0}
{255 255 255}
}
}
proc palette_value_8bit {value} {
if {$value < 0 || $value > 63} {
error "punk::ansi::xbin::palette_value_8bit error - expected palette value from 0 to 63 inclusive. received $value"
}
return [expr {round(($value * 255.0) / 63.0)}]
}
proc parse_palette {str} {
if {[string length $str] < 48} {
error "punk::ansi::xbin::parse_palette error - invalid XBIN palette - less than 48 bytes received"
}
binary scan [string range $str 0 47] cu* components
set palette [list]
foreach {r g b} $components {
lappend palette [list [palette_value_8bit $r] [palette_value_8bit $g] [palette_value_8bit $b]]
}
#for {set i 0} {$i < 48} {incr i 3} {
# set r [palette_value_8bit [lindex $components $i]]
# set g [palette_value_8bit [lindex $components $i+1]]
# set b [palette_value_8bit [lindex $components $i+2]]
# lappend palette [list $r $g $b]
#}
return $palette
}
proc attribute_ansi {char palette nonblink} {
#convert a binarytext (.bin) attribute byte (character) to ANSI SGR
#foreground and background colour.
#When nonblink is false, this allows 16 foreground colours and only 8
#background colours, with the highest bit being
#used to set 'blink' on.
if {![binary scan $char cu value]} {
error "punk::ansi::xbin::attribute_ansi error - expected a single character for attribute byte. received string of length [string length $char] - '[ansistring VIEW $char]'"
}
set fg_index [expr {$value & 0x0F}]
if {$nonblink} {
set bg_index [expr {($value >> 4) & 0x0F}]
set blink noblink
} else {
set bg_index [expr {($value >> 4) & 0x07}]
if {$value & 0x80} {
set blink blink
} else {
set blink noblink
}
}
lassign [lindex $palette $fg_index] fr fg fb
lassign [lindex $palette $bg_index] br bg bb
return [punk::ansi::a+ $blink rgb-$fr-$fg-$fb Rgb-$br-$bg-$bb]
}
} }
tcl::namespace::eval punk::ansi::internal { tcl::namespace::eval punk::ansi::internal {

3
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/metaface-1.2.8.tm

@ -1,4 +1,4 @@
package require dictutils
package provide metaface [namespace eval metaface { package provide metaface [namespace eval metaface {
variable version variable version
set version 1.2.8 set version 1.2.8
@ -6173,6 +6173,7 @@ proc ::p::-1::INVOCANTDATA {_ID_} {
#obsolete? #obsolete?
dict set ::p::-1::_iface::o_methods UPDATEDINVOCANTDATA {arglist {}} dict set ::p::-1::_iface::o_methods UPDATEDINVOCANTDATA {arglist {}}
proc ::p::-1::UPDATEDINVOCANTDATA {_ID_} { proc ::p::-1::UPDATEDINVOCANTDATA {_ID_} {
#package require dictutils
set updated_ID_ $_ID_ set updated_ID_ $_ID_
array set updated_roles [list] array set updated_roles [list]

1938
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/natsort-0.1.1.7.tm

File diff suppressed because it is too large Load Diff

20
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/overtype-1.7.4.tm

@ -404,16 +404,16 @@ tcl::namespace::eval overtype {
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
#TODO #TODO
#REVIEW - punk::console package may not be loaded #REVIEW - punk::console package may not be loaded
set cursor_style_overtype {3 underline-blink} #set cursor_style_overtype {3 underline-blink}
set cursor_style_insert {5 beam-blink} #set cursor_style_insert {5 beam-blink}
if {$opt_insert_mode} { #if {$opt_insert_mode} {
set initial_cursor_style $cursor_style_insert # set initial_cursor_style $cursor_style_insert
} else { #} else {
set initial_cursor_style $cursor_style_overtype # set initial_cursor_style $cursor_style_overtype
} #}
catch { #catch {
punk::console::cursor_style -console $opt_console $cursor_style_overtype # punk::console::cursor_style -console $opt_console $cursor_style_overtype
} #}
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# ---------------------------- # ----------------------------

11
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/commandset/loadedlib-0.1.0.tm

@ -247,12 +247,6 @@ namespace eval punk::mix::commandset::loadedlib {
set opts [dict merge $defaults $args] set opts [dict merge $defaults $args]
set opt_askme [dict get $opts -askme] set opt_askme [dict get $opts -askme]
if {[catch {package require natsort}]} {
set has_natsort 0
} else {
set has_natsort 1
}
catch {package require $library 1-0} ;#ensure pkg system has loaded/searched for everything for the path of the specified library (using unsatisfiable version range) catch {package require $library 1-0} ;#ensure pkg system has loaded/searched for everything for the path of the specified library (using unsatisfiable version range)
if {[file pathtype $modulefoldername] eq "absolute"} { if {[file pathtype $modulefoldername] eq "absolute"} {
@ -321,11 +315,6 @@ namespace eval punk::mix::commandset::loadedlib {
set versions [package versions [lindex $libfound 0]] set versions [package versions [lindex $libfound 0]]
set versions [lsort -command {package vcompare} $versions] set versions [lsort -command {package vcompare} $versions]
#if {$has_natsort} {
# set versions [natsort::sort $versions]
#} else {
# set versions [lsort $versions]
#}
if {![llength $versions]} { if {![llength $versions]} {
error "No version numbers found for library/module $libfound - sorry, you will need to copy it across manually" error "No version numbers found for library/module $libfound - sorry, you will need to copy it across manually"
} }

24
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/repl-0.1.2.tm

@ -1076,13 +1076,19 @@ namespace eval punk::repl::class {
append debug \n "input:[ansistring VIEW -lf 1 -vt 1 $new0] before row:$o_cursor_row after row: $result_row before col:$o_cursor_col after col:$result_col" append debug \n "input:[ansistring VIEW -lf 1 -vt 1 $new0] before row:$o_cursor_row after row: $result_row before col:$o_cursor_col after col:$result_col"
package require textblock package require textblock
set debug [textblock::frame -type $frametype -checkargs 0 -buildcache 0 $debug] set debug [textblock::frame -type $frametype -checkargs 0 -buildcache 0 $debug]
if {![punk::console::vt52]} {
catch {punk::console::move_emitblock_return $debug_first_row 1 $debug} #------------------------------------
} else { punk::console::cursorsave_move_emitblock_return $debug_first_row 1 $debug ;#supports also vt52
#?? #if {![punk::console::vt52]} {
} # #review
# catch {punk::console::move_emitblock_return $debug_first_row 1 $debug}
#} else {
# #??
#}
#------------------------------------
# -- --- --- --- --- --- # -- --- --- --- --- ---
set o_cursor_col $result_col set o_cursor_col $result_col
set cursor_row_idx [expr {$o_cursor_row-1}] set cursor_row_idx [expr {$o_cursor_row-1}]
lset o_rendered_lines $cursor_row_idx $result lset o_rendered_lines $cursor_row_idx $result
@ -3533,13 +3539,13 @@ namespace eval repl {
punk::ansi punk::ansi
punk::lib punk::lib
overtype overtype
dictutils
debug debug
punk::ns punk::ns
textblock textblock
punk::args::moduledoc::tclcore punk::args::moduledoc::tclcore
punk::aliascore punk::aliascore
}] }]
#dictutils
#pattern looks up versions available of patternlib before loading (but we don't have an index for tm files) todo fix pattern. #pattern looks up versions available of patternlib before loading (but we don't have an index for tm files) todo fix pattern.
# patterncmd\ # patterncmd\
@ -3784,7 +3790,7 @@ namespace eval repl {
#puts stderr "loading natsort" #puts stderr "loading natsort"
#natsort has 'application mode' which can exit. #natsort has 'application mode' which can exit.
#Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions #Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions
package require natsort #package require natsort
#package require punk ;# Thread #package require punk ;# Thread
#package require shellrun ;#subcommand exists of file #package require shellrun ;#subcommand exists of file
@ -3794,7 +3800,7 @@ namespace eval repl {
package require punk::ns ;#requires:punk::lib,punk::args,struct::list,cmdline+(tcllibc),struct::set,punk::ansi,punk::char, package require punk::ns ;#requires:punk::lib,punk::args,struct::list,cmdline+(tcllibc),struct::set,punk::ansi,punk::char,
#textutil,textutil::string,textutil::adjust,textutil::repeat,textutil::string,textutil::split,textutil::tabify,textutil::wcswidth #textutil,textutil::string,textutil::adjust,textutil::repeat,textutil::string,textutil::split,textutil::tabify,textutil::wcswidth
#punk::encmime,punk::assertion #punk::encmime,punk::assertion
#twapi,platform,registry,debug,overtype,patternpunk,pattern,patterncmd,metaface,patternpredator2,patternlib,dictutils #twapi,platform,registry,debug,overtype,patternpunk,pattern,patterncmd,metaface,patternpredator2,patternlib
#----------------------------------------------------------------------------------------------------------------------------------------- #-----------------------------------------------------------------------------------------------------------------------------------------
#package require textblock #package require textblock
@ -3921,7 +3927,7 @@ namespace eval repl {
#puts stderr "loading natsort" #puts stderr "loading natsort"
#natsort has 'application mode' which can exit. #natsort has 'application mode' which can exit.
#Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions #Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions
package require natsort #package require natsort
#catch {package require packageTrace} #catch {package require packageTrace}
if {[catch {package require punk::console} errM]} { if {[catch {package require punk::console} errM]} {
#review #review

3
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/repo-0.1.1.tm

@ -83,6 +83,7 @@ namespace eval punk::repo {
proc get_fossil_usage {} { proc get_fossil_usage {} {
set allcmds [runout -n fossil help -a] set allcmds [runout -n fossil help -a]
#review - fix runout which is introducing addition ansi (repl problem?)
set allcmds [punk::ansi::ansistrip $allcmds] set allcmds [punk::ansi::ansistrip $allcmds]
set mainhelp [runout -n fossil help] set mainhelp [runout -n fossil help]
set mainhelp [punk::ansi::ansistrip $mainhelp] set mainhelp [punk::ansi::ansistrip $mainhelp]
@ -190,7 +191,7 @@ namespace eval punk::repo {
foreach ln $basic_opt_lines { foreach ln $basic_opt_lines {
set ln [string trim $ln] set ln [string trim $ln]
#fossil sometimes emits cursor control sequences e.g CSI 3 q #REVIEW - we only need to strip because 'runout' is introducing ansi.
set ln [punk::ansi::ansistrip $ln] set ln [punk::ansi::ansistrip $ln]
if {$ln eq ""} { if {$ln eq ""} {
continue continue

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

@ -6475,6 +6475,58 @@ tcl::namespace::eval textblock {
} }
} }
variable framedef_cache [tcl::dict::create] variable framedef_cache [tcl::dict::create]
namespace eval argdoc {
set DYN_FRAME_TYPES {${[set ::textblock::frametypes]}}
punk::args::define {
@dynamic
@id -id ::textblock::framedef
@cmd -name textblock::framedef\
-summary "Return frame graphical elements as a dictionary."\
-help "Return a dict of the elements that make up a frame border.
May return a subset of available elements based on memberglob values."
@leaders -min 0 -max 0
@opts
-joins -default "" -type list\
-help "List of join directions, any of: up down left right
or those combined with another frametype e.g left-heavy down-light."
-boxonly -default 0 -type boolean\
-help "-boxonly true restricts results to the corner,vertical and horizontal box elements
It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj."
@values -min 1 -max -1
frametype -choices "${$DYN_FRAME_TYPES}" -choiceprefix 0 -choicerestricted 0 -type dict\
-help "name from the predefined frametypes or an adhoc dictionary."
memberglob -type globstring -optional 1 -multiple 1 -choiceprefix 0 -choicerestricted 0 -choices {
corner noncorner top bottom vertical horizontal left right
hl hlt hlb vsl vll vlr tlc trc blc brc hltj hlbj vllj vlrj
}\
-help "restrict to keys matching memberglob."
}
#set spec [string map [list <ftlist> $::textblock::frametypes] {
# @id -id ::textblock::framedef
# @cmd -name textblock::framedef\
# -summary "Return frame graphical elements as a dictionary."\
# -help "Return a dict of the elements that make up a frame border.
# May return a subset of available elements based on memberglob values."
# @leaders -min 0 -max 0
# @opts
# -joins -default "" -type list\
# -help "List of join directions, any of: up down left right
# or those combined with another frametype e.g left-heavy down-light."
# -boxonly -default 0 -type boolean\
# -help "-boxonly true restricts results to the corner,vertical and horizontal box elements
# It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj."
# @values -min 1 -max -1
# frametype -choices "<ftlist>" -choiceprefix 0 -choicerestricted 0 -type dict\
# -help "name from the predefined frametypes or an adhoc dictionary."
# memberglob -type globstring -optional 1 -multiple 1 -choiceprefix 0 -choicerestricted 0 -choices {
# corner noncorner top bottom vertical horizontal left right
# hl hlt hlb vsl vll vlr tlc trc blc brc hltj hlbj vllj vlrj
# }\
# -help "restrict to keys matching memberglob."
#}]
}
proc framedef {args} { proc framedef {args} {
#unicode box drawing only provides enough characters for seamless joining of unicode boxes light and heavy. #unicode box drawing only provides enough characters for seamless joining of unicode boxes light and heavy.
#e.g with characters such as \u2539 Box Drawings Right Light and Left Up Heavy. #e.g with characters such as \u2539 Box Drawings Right Light and Left Up Heavy.
@ -6520,6 +6572,9 @@ tcl::namespace::eval textblock {
} }
} }
set f [lindex $values 0] set f [lindex $values 0]
#expect either a known frametype or a dict with known keys
set rawglobs [lrange $values 1 end] set rawglobs [lrange $values 1 end]
if {![llength $rawglobs] || "all" in $rawglobs || "*" in $rawglobs} { if {![llength $rawglobs] || "all" in $rawglobs || "*" in $rawglobs} {
set globs * set globs *
@ -6570,32 +6625,7 @@ tcl::namespace::eval textblock {
} }
if {$bad_option || [llength $values] == 0} { if {$bad_option || [llength $values] == 0} {
#no framedef supplied, or unrecognised opt seen #no framedef supplied, or unrecognised opt seen
set spec [string map [list <ftlist> $::textblock::frametypes] { punk::args::parse $args withid ::textblock::framedef
@id -id ::textblock::framedef
@cmd -name textblock::framedef\
-summary "Return frame graphical elements as a dictionary."\
-help "Return a dict of the elements that make up a frame border.
May return a subset of available elements based on memberglob values."
@leaders -min 0 -max 0
@opts
-joins -default "" -type list\
-help "List of join directions, any of: up down left right
or those combined with another frametype e.g left-heavy down-light."
-boxonly -default 0 -type boolean\
-help "-boxonly true restricts results to the corner,vertical and horizontal box elements
It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj."
@values -min 1 -max -1
frametype -choices "<ftlist>" -choiceprefix 0 -choicerestricted 0 -type dict\
-help "name from the predefined frametypes or an adhoc dictionary."
memberglob -type globstring -optional 1 -multiple 1 -choiceprefix 0 -choicerestricted 0 -choices {
corner noncorner top bottom vertical horizontal left right
hl hlt hlb vsl vll vlr tlc trc blc brc hltj hlbj vllj vlrj
}\
-help "restrict to keys matching memberglob."
}]
#append spec \n "frametype -help \"A predefined \""
punk::args::parse $args withdef $spec
return return
} }
@ -7837,16 +7867,23 @@ tcl::namespace::eval textblock {
set blc \U1fb7c ;#legacy block set blc \U1fb7c ;#legacy block
set brc \U1fb7f ;#legacy block set brc \U1fb7f ;#legacy block
if {(![interp issafe])} {
if {![catch {punk::console::check::has_bug_legacysymbolwidth} symbug] && $symbug} { #------------------------------------------------------------------------------------------------------
#rather than totally fail on some mixed layout that happens to use block2 - just degrade it - but prevent alignment problems #REVIEW - framedef may be called in a context where we don't have a console that can respond to ansi queries.
set sp \u00a0 ;#non breaking space (plain space may act transparent in some use cases) #We should either check has_bug_legacysymbolwidth at initial console detection and set a global var,
set tlc $sp #or find some other way to detect if we are in a terminal that has this problem.
set trc $sp
set blc $sp #if {(![interp issafe])} {
set brc $sp # if {![catch {punk::console::check::has_bug_legacysymbolwidth} symbug] && $symbug} {
} # #rather than totally fail on some mixed layout that happens to use block2 - just degrade it - but prevent alignment problems
} # set sp \u00a0 ;#non breaking space (plain space may act transparent in some use cases)
# set tlc $sp
# set trc $sp
# set blc $sp
# set brc $sp
# }
#}
#------------------------------------------------------------------------------------------------------
#horizontal and vertical bar joins #horizontal and vertical bar joins
set hltj $hlt set hltj $hlt
@ -7909,22 +7946,30 @@ tcl::namespace::eval textblock {
set vlrj $vlr set vlrj $vlr
} }
default { default {
if {[llength $f] % 2 != 0} {
#todo - retrieve usage from punk::args
#error "textblock::frametype frametype '$f' is not one of the predefined frametypes: $::textblock::frametypes and does not appear to be a dictionary for a custom frametype"
punk::args::parse $args withid ::textblock::framedef
return
}
#set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "] ;#only default the general types - these form defaults for more specific types if they're missing #set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "] ;#only default the general types - these form defaults for more specific types if they're missing
set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "] set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "]
if {"all" in [dict keys $f]} { if {"all" in [dict keys $f]} {
set A [dict get $f all] set A [dict get $f all]
set default_custom [tcl::dict::create hl $A vl $A tlc $A trc $A blc $A brc $A] set default_custom [tcl::dict::create hl $A vl $A tlc $A trc $A blc $A brc $A]
} }
if {[llength $f] % 2} { ####
#todo - retrieve usage from punk::args
error "textblock::frametype frametype '$f' is not one of the predefined frametypes: $::textblock::frametypes and does not appear to be a dictionary for a custom frametype"
}
#unknown order of keys specified by user - validate before creating vars as we need more general elements to be available as defaults #unknown order of keys specified by user - validate before creating vars as we need more general elements to be available as defaults
dict for {k v} $f { dict for {k v} $f {
switch -- $k { switch -- $k {
all - hl - vl - tlc - trc - blc - brc - hlt - hlb - vll - vlr - hltj - hlbj - vllj - vlrj {} all - hl - vl - tlc - trc - blc - brc - hlt - hlb - vll - vlr - hltj - hlbj - vllj - vlrj {}
default { default {
error "textblock::frametype '$f' has unknown element '$k'" #error "textblock::frametype '$f' has unknown element '$k'"
set errmsg [punk::args::usage -scheme error ::textblock::framedef]
append errmsg "\ntextblock::frametype frametype '$f' has unknown element '$k'"
error $errmsg
return
} }
} }
} }

3
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/metaface-1.2.8.tm

@ -1,4 +1,4 @@
package require dictutils
package provide metaface [namespace eval metaface { package provide metaface [namespace eval metaface {
variable version variable version
set version 1.2.8 set version 1.2.8
@ -6173,6 +6173,7 @@ proc ::p::-1::INVOCANTDATA {_ID_} {
#obsolete? #obsolete?
dict set ::p::-1::_iface::o_methods UPDATEDINVOCANTDATA {arglist {}} dict set ::p::-1::_iface::o_methods UPDATEDINVOCANTDATA {arglist {}}
proc ::p::-1::UPDATEDINVOCANTDATA {_ID_} { proc ::p::-1::UPDATEDINVOCANTDATA {_ID_} {
#package require dictutils
set updated_ID_ $_ID_ set updated_ID_ $_ID_
array set updated_roles [list] array set updated_roles [list]

1938
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/natsort-0.1.1.7.tm

File diff suppressed because it is too large Load Diff

20
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/overtype-1.7.4.tm

@ -404,16 +404,16 @@ tcl::namespace::eval overtype {
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
#TODO #TODO
#REVIEW - punk::console package may not be loaded #REVIEW - punk::console package may not be loaded
set cursor_style_overtype {3 underline-blink} #set cursor_style_overtype {3 underline-blink}
set cursor_style_insert {5 beam-blink} #set cursor_style_insert {5 beam-blink}
if {$opt_insert_mode} { #if {$opt_insert_mode} {
set initial_cursor_style $cursor_style_insert # set initial_cursor_style $cursor_style_insert
} else { #} else {
set initial_cursor_style $cursor_style_overtype # set initial_cursor_style $cursor_style_overtype
} #}
catch { #catch {
punk::console::cursor_style -console $opt_console $cursor_style_overtype # punk::console::cursor_style -console $opt_console $cursor_style_overtype
} #}
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# ---------------------------- # ----------------------------

11
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/commandset/loadedlib-0.1.0.tm

@ -247,12 +247,6 @@ namespace eval punk::mix::commandset::loadedlib {
set opts [dict merge $defaults $args] set opts [dict merge $defaults $args]
set opt_askme [dict get $opts -askme] set opt_askme [dict get $opts -askme]
if {[catch {package require natsort}]} {
set has_natsort 0
} else {
set has_natsort 1
}
catch {package require $library 1-0} ;#ensure pkg system has loaded/searched for everything for the path of the specified library (using unsatisfiable version range) catch {package require $library 1-0} ;#ensure pkg system has loaded/searched for everything for the path of the specified library (using unsatisfiable version range)
if {[file pathtype $modulefoldername] eq "absolute"} { if {[file pathtype $modulefoldername] eq "absolute"} {
@ -321,11 +315,6 @@ namespace eval punk::mix::commandset::loadedlib {
set versions [package versions [lindex $libfound 0]] set versions [package versions [lindex $libfound 0]]
set versions [lsort -command {package vcompare} $versions] set versions [lsort -command {package vcompare} $versions]
#if {$has_natsort} {
# set versions [natsort::sort $versions]
#} else {
# set versions [lsort $versions]
#}
if {![llength $versions]} { if {![llength $versions]} {
error "No version numbers found for library/module $libfound - sorry, you will need to copy it across manually" error "No version numbers found for library/module $libfound - sorry, you will need to copy it across manually"
} }

24
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/repl-0.1.2.tm

@ -1076,13 +1076,19 @@ namespace eval punk::repl::class {
append debug \n "input:[ansistring VIEW -lf 1 -vt 1 $new0] before row:$o_cursor_row after row: $result_row before col:$o_cursor_col after col:$result_col" append debug \n "input:[ansistring VIEW -lf 1 -vt 1 $new0] before row:$o_cursor_row after row: $result_row before col:$o_cursor_col after col:$result_col"
package require textblock package require textblock
set debug [textblock::frame -type $frametype -checkargs 0 -buildcache 0 $debug] set debug [textblock::frame -type $frametype -checkargs 0 -buildcache 0 $debug]
if {![punk::console::vt52]} {
catch {punk::console::move_emitblock_return $debug_first_row 1 $debug} #------------------------------------
} else { punk::console::cursorsave_move_emitblock_return $debug_first_row 1 $debug ;#supports also vt52
#?? #if {![punk::console::vt52]} {
} # #review
# catch {punk::console::move_emitblock_return $debug_first_row 1 $debug}
#} else {
# #??
#}
#------------------------------------
# -- --- --- --- --- --- # -- --- --- --- --- ---
set o_cursor_col $result_col set o_cursor_col $result_col
set cursor_row_idx [expr {$o_cursor_row-1}] set cursor_row_idx [expr {$o_cursor_row-1}]
lset o_rendered_lines $cursor_row_idx $result lset o_rendered_lines $cursor_row_idx $result
@ -3533,13 +3539,13 @@ namespace eval repl {
punk::ansi punk::ansi
punk::lib punk::lib
overtype overtype
dictutils
debug debug
punk::ns punk::ns
textblock textblock
punk::args::moduledoc::tclcore punk::args::moduledoc::tclcore
punk::aliascore punk::aliascore
}] }]
#dictutils
#pattern looks up versions available of patternlib before loading (but we don't have an index for tm files) todo fix pattern. #pattern looks up versions available of patternlib before loading (but we don't have an index for tm files) todo fix pattern.
# patterncmd\ # patterncmd\
@ -3784,7 +3790,7 @@ namespace eval repl {
#puts stderr "loading natsort" #puts stderr "loading natsort"
#natsort has 'application mode' which can exit. #natsort has 'application mode' which can exit.
#Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions #Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions
package require natsort #package require natsort
#package require punk ;# Thread #package require punk ;# Thread
#package require shellrun ;#subcommand exists of file #package require shellrun ;#subcommand exists of file
@ -3794,7 +3800,7 @@ namespace eval repl {
package require punk::ns ;#requires:punk::lib,punk::args,struct::list,cmdline+(tcllibc),struct::set,punk::ansi,punk::char, package require punk::ns ;#requires:punk::lib,punk::args,struct::list,cmdline+(tcllibc),struct::set,punk::ansi,punk::char,
#textutil,textutil::string,textutil::adjust,textutil::repeat,textutil::string,textutil::split,textutil::tabify,textutil::wcswidth #textutil,textutil::string,textutil::adjust,textutil::repeat,textutil::string,textutil::split,textutil::tabify,textutil::wcswidth
#punk::encmime,punk::assertion #punk::encmime,punk::assertion
#twapi,platform,registry,debug,overtype,patternpunk,pattern,patterncmd,metaface,patternpredator2,patternlib,dictutils #twapi,platform,registry,debug,overtype,patternpunk,pattern,patterncmd,metaface,patternpredator2,patternlib
#----------------------------------------------------------------------------------------------------------------------------------------- #-----------------------------------------------------------------------------------------------------------------------------------------
#package require textblock #package require textblock
@ -3921,7 +3927,7 @@ namespace eval repl {
#puts stderr "loading natsort" #puts stderr "loading natsort"
#natsort has 'application mode' which can exit. #natsort has 'application mode' which can exit.
#Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions #Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions
package require natsort #package require natsort
#catch {package require packageTrace} #catch {package require packageTrace}
if {[catch {package require punk::console} errM]} { if {[catch {package require punk::console} errM]} {
#review #review

3
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/repo-0.1.1.tm

@ -83,6 +83,7 @@ namespace eval punk::repo {
proc get_fossil_usage {} { proc get_fossil_usage {} {
set allcmds [runout -n fossil help -a] set allcmds [runout -n fossil help -a]
#review - fix runout which is introducing addition ansi (repl problem?)
set allcmds [punk::ansi::ansistrip $allcmds] set allcmds [punk::ansi::ansistrip $allcmds]
set mainhelp [runout -n fossil help] set mainhelp [runout -n fossil help]
set mainhelp [punk::ansi::ansistrip $mainhelp] set mainhelp [punk::ansi::ansistrip $mainhelp]
@ -190,7 +191,7 @@ namespace eval punk::repo {
foreach ln $basic_opt_lines { foreach ln $basic_opt_lines {
set ln [string trim $ln] set ln [string trim $ln]
#fossil sometimes emits cursor control sequences e.g CSI 3 q #REVIEW - we only need to strip because 'runout' is introducing ansi.
set ln [punk::ansi::ansistrip $ln] set ln [punk::ansi::ansistrip $ln]
if {$ln eq ""} { if {$ln eq ""} {
continue continue

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

@ -6475,6 +6475,58 @@ tcl::namespace::eval textblock {
} }
} }
variable framedef_cache [tcl::dict::create] variable framedef_cache [tcl::dict::create]
namespace eval argdoc {
set DYN_FRAME_TYPES {${[set ::textblock::frametypes]}}
punk::args::define {
@dynamic
@id -id ::textblock::framedef
@cmd -name textblock::framedef\
-summary "Return frame graphical elements as a dictionary."\
-help "Return a dict of the elements that make up a frame border.
May return a subset of available elements based on memberglob values."
@leaders -min 0 -max 0
@opts
-joins -default "" -type list\
-help "List of join directions, any of: up down left right
or those combined with another frametype e.g left-heavy down-light."
-boxonly -default 0 -type boolean\
-help "-boxonly true restricts results to the corner,vertical and horizontal box elements
It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj."
@values -min 1 -max -1
frametype -choices "${$DYN_FRAME_TYPES}" -choiceprefix 0 -choicerestricted 0 -type dict\
-help "name from the predefined frametypes or an adhoc dictionary."
memberglob -type globstring -optional 1 -multiple 1 -choiceprefix 0 -choicerestricted 0 -choices {
corner noncorner top bottom vertical horizontal left right
hl hlt hlb vsl vll vlr tlc trc blc brc hltj hlbj vllj vlrj
}\
-help "restrict to keys matching memberglob."
}
#set spec [string map [list <ftlist> $::textblock::frametypes] {
# @id -id ::textblock::framedef
# @cmd -name textblock::framedef\
# -summary "Return frame graphical elements as a dictionary."\
# -help "Return a dict of the elements that make up a frame border.
# May return a subset of available elements based on memberglob values."
# @leaders -min 0 -max 0
# @opts
# -joins -default "" -type list\
# -help "List of join directions, any of: up down left right
# or those combined with another frametype e.g left-heavy down-light."
# -boxonly -default 0 -type boolean\
# -help "-boxonly true restricts results to the corner,vertical and horizontal box elements
# It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj."
# @values -min 1 -max -1
# frametype -choices "<ftlist>" -choiceprefix 0 -choicerestricted 0 -type dict\
# -help "name from the predefined frametypes or an adhoc dictionary."
# memberglob -type globstring -optional 1 -multiple 1 -choiceprefix 0 -choicerestricted 0 -choices {
# corner noncorner top bottom vertical horizontal left right
# hl hlt hlb vsl vll vlr tlc trc blc brc hltj hlbj vllj vlrj
# }\
# -help "restrict to keys matching memberglob."
#}]
}
proc framedef {args} { proc framedef {args} {
#unicode box drawing only provides enough characters for seamless joining of unicode boxes light and heavy. #unicode box drawing only provides enough characters for seamless joining of unicode boxes light and heavy.
#e.g with characters such as \u2539 Box Drawings Right Light and Left Up Heavy. #e.g with characters such as \u2539 Box Drawings Right Light and Left Up Heavy.
@ -6520,6 +6572,9 @@ tcl::namespace::eval textblock {
} }
} }
set f [lindex $values 0] set f [lindex $values 0]
#expect either a known frametype or a dict with known keys
set rawglobs [lrange $values 1 end] set rawglobs [lrange $values 1 end]
if {![llength $rawglobs] || "all" in $rawglobs || "*" in $rawglobs} { if {![llength $rawglobs] || "all" in $rawglobs || "*" in $rawglobs} {
set globs * set globs *
@ -6570,32 +6625,7 @@ tcl::namespace::eval textblock {
} }
if {$bad_option || [llength $values] == 0} { if {$bad_option || [llength $values] == 0} {
#no framedef supplied, or unrecognised opt seen #no framedef supplied, or unrecognised opt seen
set spec [string map [list <ftlist> $::textblock::frametypes] { punk::args::parse $args withid ::textblock::framedef
@id -id ::textblock::framedef
@cmd -name textblock::framedef\
-summary "Return frame graphical elements as a dictionary."\
-help "Return a dict of the elements that make up a frame border.
May return a subset of available elements based on memberglob values."
@leaders -min 0 -max 0
@opts
-joins -default "" -type list\
-help "List of join directions, any of: up down left right
or those combined with another frametype e.g left-heavy down-light."
-boxonly -default 0 -type boolean\
-help "-boxonly true restricts results to the corner,vertical and horizontal box elements
It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj."
@values -min 1 -max -1
frametype -choices "<ftlist>" -choiceprefix 0 -choicerestricted 0 -type dict\
-help "name from the predefined frametypes or an adhoc dictionary."
memberglob -type globstring -optional 1 -multiple 1 -choiceprefix 0 -choicerestricted 0 -choices {
corner noncorner top bottom vertical horizontal left right
hl hlt hlb vsl vll vlr tlc trc blc brc hltj hlbj vllj vlrj
}\
-help "restrict to keys matching memberglob."
}]
#append spec \n "frametype -help \"A predefined \""
punk::args::parse $args withdef $spec
return return
} }
@ -7837,16 +7867,23 @@ tcl::namespace::eval textblock {
set blc \U1fb7c ;#legacy block set blc \U1fb7c ;#legacy block
set brc \U1fb7f ;#legacy block set brc \U1fb7f ;#legacy block
if {(![interp issafe])} {
if {![catch {punk::console::check::has_bug_legacysymbolwidth} symbug] && $symbug} { #------------------------------------------------------------------------------------------------------
#rather than totally fail on some mixed layout that happens to use block2 - just degrade it - but prevent alignment problems #REVIEW - framedef may be called in a context where we don't have a console that can respond to ansi queries.
set sp \u00a0 ;#non breaking space (plain space may act transparent in some use cases) #We should either check has_bug_legacysymbolwidth at initial console detection and set a global var,
set tlc $sp #or find some other way to detect if we are in a terminal that has this problem.
set trc $sp
set blc $sp #if {(![interp issafe])} {
set brc $sp # if {![catch {punk::console::check::has_bug_legacysymbolwidth} symbug] && $symbug} {
} # #rather than totally fail on some mixed layout that happens to use block2 - just degrade it - but prevent alignment problems
} # set sp \u00a0 ;#non breaking space (plain space may act transparent in some use cases)
# set tlc $sp
# set trc $sp
# set blc $sp
# set brc $sp
# }
#}
#------------------------------------------------------------------------------------------------------
#horizontal and vertical bar joins #horizontal and vertical bar joins
set hltj $hlt set hltj $hlt
@ -7909,22 +7946,30 @@ tcl::namespace::eval textblock {
set vlrj $vlr set vlrj $vlr
} }
default { default {
if {[llength $f] % 2 != 0} {
#todo - retrieve usage from punk::args
#error "textblock::frametype frametype '$f' is not one of the predefined frametypes: $::textblock::frametypes and does not appear to be a dictionary for a custom frametype"
punk::args::parse $args withid ::textblock::framedef
return
}
#set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "] ;#only default the general types - these form defaults for more specific types if they're missing #set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "] ;#only default the general types - these form defaults for more specific types if they're missing
set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "] set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "]
if {"all" in [dict keys $f]} { if {"all" in [dict keys $f]} {
set A [dict get $f all] set A [dict get $f all]
set default_custom [tcl::dict::create hl $A vl $A tlc $A trc $A blc $A brc $A] set default_custom [tcl::dict::create hl $A vl $A tlc $A trc $A blc $A brc $A]
} }
if {[llength $f] % 2} { ####
#todo - retrieve usage from punk::args
error "textblock::frametype frametype '$f' is not one of the predefined frametypes: $::textblock::frametypes and does not appear to be a dictionary for a custom frametype"
}
#unknown order of keys specified by user - validate before creating vars as we need more general elements to be available as defaults #unknown order of keys specified by user - validate before creating vars as we need more general elements to be available as defaults
dict for {k v} $f { dict for {k v} $f {
switch -- $k { switch -- $k {
all - hl - vl - tlc - trc - blc - brc - hlt - hlb - vll - vlr - hltj - hlbj - vllj - vlrj {} all - hl - vl - tlc - trc - blc - brc - hlt - hlb - vll - vlr - hltj - hlbj - vllj - vlrj {}
default { default {
error "textblock::frametype '$f' has unknown element '$k'" #error "textblock::frametype '$f' has unknown element '$k'"
set errmsg [punk::args::usage -scheme error ::textblock::framedef]
append errmsg "\ntextblock::frametype frametype '$f' has unknown element '$k'"
error $errmsg
return
} }
} }
} }

3
src/vendormodules/metaface-1.2.8.tm

@ -1,4 +1,4 @@
package require dictutils
package provide metaface [namespace eval metaface { package provide metaface [namespace eval metaface {
variable version variable version
set version 1.2.8 set version 1.2.8
@ -6173,6 +6173,7 @@ proc ::p::-1::INVOCANTDATA {_ID_} {
#obsolete? #obsolete?
dict set ::p::-1::_iface::o_methods UPDATEDINVOCANTDATA {arglist {}} dict set ::p::-1::_iface::o_methods UPDATEDINVOCANTDATA {arglist {}}
proc ::p::-1::UPDATEDINVOCANTDATA {_ID_} { proc ::p::-1::UPDATEDINVOCANTDATA {_ID_} {
#package require dictutils
set updated_ID_ $_ID_ set updated_ID_ $_ID_
array set updated_roles [list] array set updated_roles [list]

6364
src/vendormodules/metaface-1.2.9.tm

File diff suppressed because it is too large Load Diff

BIN
src/vendormodules/test/pattern-1.2.8.tm

Binary file not shown.

2
src/vendormodules/commandstack-0.4.tm → src/vfs/_vfscommon.vfs/modules/commandstack-0.4.1.tm

@ -519,7 +519,7 @@ namespace eval commandstack::lib {
} }
package provide commandstack [namespace eval commandstack { package provide commandstack [namespace eval commandstack {
set version 0.4 set version 0.4.1
}] }]

5
src/vfs/_vfscommon.vfs/modules/funcl-0.1.tm

@ -1,3 +1,6 @@
#experimental.
package provide funcl [namespace eval funcl { package provide funcl [namespace eval funcl {
variable version variable version
set version 0.1 set version 0.1
@ -235,7 +238,7 @@ namespace eval funcl {
} }
set comp [list] ;#composition list set comp [list] ;#composition list
set end [lindex $args end] set end [lindex $args end]
if {[lindex $end 0] in {_fn _call}]} { if {[lindex $end 0] in {_fn _call}} {
#is_funcl #is_funcl
set endfunc [lindex $args end] set endfunc [lindex $args end]
} else { } else {

3
src/vfs/_vfscommon.vfs/modules/metaface-1.2.8.tm

@ -1,4 +1,4 @@
package require dictutils
package provide metaface [namespace eval metaface { package provide metaface [namespace eval metaface {
variable version variable version
set version 1.2.8 set version 1.2.8
@ -6173,6 +6173,7 @@ proc ::p::-1::INVOCANTDATA {_ID_} {
#obsolete? #obsolete?
dict set ::p::-1::_iface::o_methods UPDATEDINVOCANTDATA {arglist {}} dict set ::p::-1::_iface::o_methods UPDATEDINVOCANTDATA {arglist {}}
proc ::p::-1::UPDATEDINVOCANTDATA {_ID_} { proc ::p::-1::UPDATEDINVOCANTDATA {_ID_} {
#package require dictutils
set updated_ID_ $_ID_ set updated_ID_ $_ID_
array set updated_roles [list] array set updated_roles [list]

6364
src/vfs/_vfscommon.vfs/modules/metaface-1.2.9.tm

File diff suppressed because it is too large Load Diff

1938
src/vfs/_vfscommon.vfs/modules/natsort-0.1.1.7.tm

File diff suppressed because it is too large Load Diff

200
src/vfs/_vfscommon.vfs/modules/oolib-0.1.3.tm

@ -0,0 +1,200 @@
#JMN - api should be kept in sync with package patternlib where possible
#
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?
#review - what is the point of alias anyway? - why slow down other operations when a variable can hold a keyname perfectly well?
#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
}
}
}
package provide oolib [namespace eval oolib {
variable version
set version 0.1.3
}]

226
src/vfs/_vfscommon.vfs/modules/overtype-1.7.4.tm

@ -263,6 +263,7 @@ tcl::namespace::eval overtype {
-wrap -default 0 -type boolean -wrap -default 0 -type boolean
-info -default 0 -type boolean -help\ -info -default 0 -type boolean -help\
"When set to 1, return a dictionary (experimental)" "When set to 1, return a dictionary (experimental)"
-format -default ansi -type string -choices {ansi binarytext-bios binarytext-ice xbin}
-binarytext -default "" -type string -choices {"" bios ice} -binarytext -default "" -type string -choices {"" bios ice}
-console -default {stdin stdout stderr} -type list -console -default {stdin stdout stderr} -type list
@ -337,6 +338,7 @@ tcl::namespace::eval overtype {
-wrap 0 -wrap 0
-info 0 -info 0
-binarytext "" -binarytext ""
-format ansi
-console {stdin stdout stderr} -console {stdin stdout stderr}
}] }]
#expand_right is perhaps consistent with the idea of the page_size being allowed to grow horizontally.. #expand_right is perhaps consistent with the idea of the page_size being allowed to grow horizontally..
@ -357,7 +359,7 @@ tcl::namespace::eval overtype {
- -expand_right - -appendlines - -expand_right - -appendlines
- -reverse_mode - -crm_mode - -insert_mode - -reverse_mode - -crm_mode - -insert_mode
- -cp437 - -cp437
- -info - -binarytext - -console { - -info - -binarytext - -format - -console {
tcl::dict::set opts $k $v tcl::dict::set opts $k $v
} }
-wrap - -autowrap_mode { -wrap - -autowrap_mode {
@ -398,22 +400,23 @@ tcl::namespace::eval overtype {
set opt_cp437 [tcl::dict::get $opts -cp437] set opt_cp437 [tcl::dict::get $opts -cp437]
set opt_info [tcl::dict::get $opts -info] set opt_info [tcl::dict::get $opts -info]
set opt_binarytext [tcl::dict::get $opts -binarytext] set opt_binarytext [tcl::dict::get $opts -binarytext]
set opt_format [tcl::dict::get $opts -format]
set opt_console [tcl::dict::get $opts -console] set opt_console [tcl::dict::get $opts -console]
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
#TODO #TODO
#REVIEW - punk::console package may not be loaded #REVIEW - punk::console package may not be loaded
set cursor_style_overtype {3 underline-blink} #set cursor_style_overtype {3 underline-blink}
set cursor_style_insert {5 beam-blink} #set cursor_style_insert {5 beam-blink}
if {$opt_insert_mode} { #if {$opt_insert_mode} {
set initial_cursor_style $cursor_style_insert # set initial_cursor_style $cursor_style_insert
} else { #} else {
set initial_cursor_style $cursor_style_overtype # set initial_cursor_style $cursor_style_overtype
} #}
catch { #catch {
punk::console::cursor_style -console $opt_console $cursor_style_overtype # punk::console::cursor_style -console $opt_console $cursor_style_overtype
} #}
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# ---------------------------- # ----------------------------
@ -434,8 +437,18 @@ tcl::namespace::eval overtype {
} }
# ---------------------------- # ----------------------------
#---------------------------------------------------------
#underblock is expected to be pre-rendered - ie any ANSI codes have already been processed and rendered into the text.
#This is because the underblock is used as the basis for calculating the layout of the output
#- so it needs to be in a form where we can determine the width of each line and how many lines there are.
set underblock [tcl::string::map {\r\n \n} $underblock] set underblock [tcl::string::map {\r\n \n} $underblock]
set overblock [tcl::string::map {\r\n \n} $overblock]
#do not split the overblock into lines at this stage - it may contain binary data.
#REVIEW - xbin (or binarytext?) may contain binary data which could be corrupted by mapping \r\n to \n.
#set overblock [tcl::string::map {\r\n \n} $overblock]
#---------------------------------------------------------
if {$opt_startrow > 1} { if {$opt_startrow > 1} {
set down [expr {$opt_startrow -1}] set down [expr {$opt_startrow -1}]
#when vt52? #when vt52?
@ -529,6 +542,7 @@ tcl::namespace::eval overtype {
#overblock height/width isn't useful in the presence of an ansi input overlay with movements. The number of lines may bear little relationship to the output height #overblock height/width isn't useful in the presence of an ansi input overlay with movements. The number of lines may bear little relationship to the output height
#lassign [blocksize $overblock] _w overblock_width _h overblock_height #lassign [blocksize $overblock] _w overblock_width _h overblock_height
#temporary scheme selector for experimenting with different approaches to chunking the input overlay for processing.
set scheme 4 set scheme 4
switch -- $scheme { switch -- $scheme {
0 { 0 {
@ -573,9 +587,11 @@ tcl::namespace::eval overtype {
} }
4 { 4 {
#active development scheme - 2026.
set inputchunks [list] set inputchunks [list]
switch -- $opt_binarytext { switch -- $opt_format {
"" { ansi {
set overblock [tcl::string::map {\r\n \n} $overblock]
foreach ln [split $overblock \n] { foreach ln [split $overblock \n] {
lappend inputchunks [list mixed $ln\n] lappend inputchunks [list mixed $ln\n]
} }
@ -583,7 +599,7 @@ tcl::namespace::eval overtype {
lset inputchunks end 1 [tcl::string::range [lindex $inputchunks end 1] 0 end-1] lset inputchunks end 1 [tcl::string::range [lindex $inputchunks end 1] 0 end-1]
} }
} }
bios { binarytext-bios {
#16 fg, 8 fg + possible blink #16 fg, 8 fg + possible blink
set input "" set input ""
set ansisplit [list ""] set ansisplit [list ""]
@ -604,7 +620,7 @@ tcl::namespace::eval overtype {
#lappend inputchunks [list mixed $input] #lappend inputchunks [list mixed $input]
lappend inputchunks [list ansisplit $ansisplit] lappend inputchunks [list ansisplit $ansisplit]
} }
ice { binarytext-ice {
#16 fg, 16 bg (no blink) #16 fg, 16 bg (no blink)
set input "" set input ""
foreach {ch at} [split $overblock ""] { foreach {ch at} [split $overblock ""] {
@ -613,6 +629,178 @@ tcl::namespace::eval overtype {
} }
lappend inputchunks [list mixed $input] lappend inputchunks [list mixed $input]
} }
xbin {
set xbin_header [string range $overblock 0 10] ;#11 bytes
set xbin_header_info [punk::ansi::xbin::parse_header $xbin_header]
set overblock [string range $overblock 11 end]
set flags [dict get $xbin_header_info flags]
set xbin_width [dict get $xbin_header_info width]
set xbin_height [dict get $xbin_header_info height]
set expected_cells [expr {$xbin_width * $xbin_height}]
set xbin_nonblink [expr {"nonblink" in $flags}] ;# ice.
set xbin_palette [punk::ansi::xbin::default_palette]
puts "xbin ${xbin_width}x${xbin_height}"
puts "xbin flags $flags"
#optional 16-entry palette, 3 bytes per entry, RGB values 0..63
if {"palette" in $flags} {
#puts stderr "renderspace warning - palette unimplemented"
set xbin_palette [punk::ansi::xbin::parse_palette [string range $overblock 0 47]]
set overblock [string range $overblock 48 end]
}
#todo - font.
#hack - skip over font 256 x fontsize or 512 x fontsize
if {"512chars" in $flags} {
set sz 512
} else {
set sz 256
}
#temp
set skip [expr {$sz * [dict get $xbin_header_info fontsize]}]
if {"font" in $flags} {
#todo - consider sixel or similar for font data - but for now we just skip over it.
puts stderr "renderspace warning - xbin font unimplemented"
set overblock [string range $overblock $skip end]
}
puts stdout "xbin image data size [string length $overblock]"
set ansisplit [list ""]
if {"compress" in $flags} {
#puts stderr "renderspace warning - compress experimental"
#process 'repeatcounter' bytes
#first 2 bits - compression type
# 00 - no compression
# 01 - character compression
# 10 - attribute compression
# 11 - character/attribute compression
#remaining 6 bits - counter
set input ""
set bytes [split $overblock ""]
set byte_count [llength $bytes]
set decoded_cells 0
for {set b 0} {$b < $byte_count} {} {
set rc [lindex $bytes $b]
set dec [scan $rc %c]
set ctype [expr {$dec >> 6}]
#0x3F - 00111111
set count [expr {$dec & 0x3F}]
incr count ;#count stored as 1 less than actual number of repeats
if {$count < 1 || $count > 64} {
puts stderr "xbin - something wrong - max must be between 1 and 64 inclusive. received $count"
}
incr b
if {$decoded_cells + $count > $expected_cells} {
error "overtype::renderspace xbin decode overflow: record would emit $count cells at decoded offset $decoded_cells, expected total $expected_cells cells for image dimensions ${xbin_width}x${xbin_height}"
}
switch -exact -- $ctype {
0 {
set needed [expr {$count * 2}]
}
1 -
2 {
set needed [expr {$count + 1}]
}
3 {
set needed 2
}
default {
error "overtype::renderspace xbin invalid compression type $ctype in repeatcounter byte '$rc' at offset $b"
}
}
if {$b + $needed > $byte_count} {
error "overtype::renderspace xbin truncated record: type $ctype requires $needed bytes at payload offset $b, but only [expr {$byte_count - $b}] bytes remain."
}
switch -exact -- $ctype {
0 {
#no compression
for {set c 0} {$c < $count*2} {incr c 2} {
set ch [lindex $bytes $b+$c]
set ch [encoding convertfrom cp437 $ch]
set at [lindex $bytes [expr {$b+$c+1}]]
#binary scan $at cu code
#set clr [a+ term-$code]
#set clr [a+ red] ;#debug
set clr [punk::ansi::xbin::attribute_ansi $at $xbin_palette $xbin_nonblink]
lappend ansisplit $clr $ch
}
incr b [expr {$count*2}]
}
1 {
#char compression
set ch [lindex $bytes $b]
set ch [encoding convertfrom cp437 $ch]
incr b
for {set c 0} {$c < $count} {incr c} {
set at [lindex $bytes $b+$c]
#binary scan $at cu code
#set clr [a+ term-$code]
#set clr [a+ cyan] ;#debug
set clr [punk::ansi::xbin::attribute_ansi $at $xbin_palette $xbin_nonblink]
lappend ansisplit $clr $ch
}
incr b [expr {$count}]
}
2 {
#attribute compression
set at [lindex $bytes $b]
#binary scan $at cu code
#set clr [a+ term-$code]
#set clr [a+ green] ;#debug
set clr [punk::ansi::xbin::attribute_ansi $at $xbin_palette $xbin_nonblink]
incr b
for {set c 0} {$c < $count} {incr c} {
set ch [lindex $bytes $b+$c]
set ch [encoding convertfrom cp437 $ch]
lappend ansisplit $clr $ch
}
incr b $count
}
3 {
#attribute and char compression
set ch [lindex $bytes $b]
set ch [encoding convertfrom cp437 $ch]
set at [lindex $bytes $b+1]
#binary scan $at cu code
#set clr [a+ term-$code]
#set clr [a+ white] ;#debug
set clr [punk::ansi::xbin::attribute_ansi $at $xbin_palette $xbin_nonblink]
for {set c 0} {$c < $count} {incr c} {
lappend ansisplit $clr $ch
}
incr b 2
}
}
incr decoded_cells $count
}
if {$decoded_cells != $expected_cells} {
puts stderr "overtype::renderspace xbin decoded $decoded_cells cells, expected $expected_cells cells for image dimensions ${xbin_width}x${xbin_height}"
}
lappend inputchunks [list ansisplit $ansisplit]
} else {
foreach {ch at} [split $overblock ""] {
#binary scan $at cu code
#set clr [a+ term-$code]
if {$at eq ""} {
#eg src/testansi/formatsamples/image/xbin/test.xb
#has trailing nul byte. for now just warn.
puts stderr "renderspace warning - xbin attribute byte is empty at char '[ansistring VIEW $ch]'"
#break ?
#experiment - treat as a reset.
lappend ansisplit [a+] $ch
} else {
set clr [punk::ansi::xbin::attribute_ansi $at $xbin_palette $xbin_nonblink]
set ch [encoding convertfrom cp437 $ch]
lappend ansisplit $clr $ch
}
}
lappend inputchunks [list ansisplit $ansisplit]
}
puts stdout "xbin decoded"
flush stdout
}
} }
} }
} }
@ -2303,8 +2491,10 @@ tcl::namespace::eval overtype {
#At the moment we return a reset at the end of the renderline result instead of the replay codes. #At the moment we return a reset at the end of the renderline result instead of the replay codes.
proc renderline {args} { proc renderline {args} {
#todo - fix 'unapplied' mechanism.This is particularly inefficient for long lines, or data such as binarytext which is not line-based. #-------------------------------------------------------------------------------------------------------------------------------------
#All unapplied data is re-split/reprocessed repeatedly for each line! This is very wasteful and slow. #todo - fix 'unapplied' mechanism.This is particularly inefficient for long lines, or data such as binarytext/xbin which is not line-based.
#All unapplied data is re-split/reprocessed repeatedly for each line! This is very wasteful and very slow.
#-------------------------------------------------------------------------------------------------------------------------------------
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### # ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
# renderline written from a left-right line orientation perspective as a first-shot at getting something useful. # renderline written from a left-right line orientation perspective as a first-shot at getting something useful.

455
src/vfs/_vfscommon.vfs/modules/patternpunk-1.1.1.tm

@ -0,0 +1,455 @@
#<?xml version="1.0"?>
#<xml>
#<xpack>
#<code>
#<![CDATA[
# Author: Julian Marcel Noble <julian@cyberclad.com>
# 2004 - Public Domain
#
# PatternPunk - DIALECT
#Dynamic Instance Accumulation Language Extending Classic Tcl
#The goofy acronym is a fancy way of not referring to PatternPunk as yet another OO system.
package require pattern
package require overtype
package require punk::args
package require punk::ansi
package require punk::lib
#pattern::init
::>pattern .. Create ::>punk
::>punk .. Property license {Public Domain}
::>punk .. Property logo_ascii [string trim {
+-----------------------+
| Pattern PUNK |
| . \\\_ . |
| .*. \@ > .=. |
| .*.*. | ~ .=.=. |
|.*.*.*.\_- -_/.=.=.=.|
| .*.*. \\ .=.=. |
| .*. / \ .=. |
| . _+ +_ . |
+-----------------------+
} \n]
set ::punk::bannerTemplate0 [string trim {
+-----------------------+
| .000000000000000. |
| .*. \\\_ .=. |
| .*.*. \@ > .=.=. |
|.*.*.*. | ~ .=.=.=.|
| .*.*. \_- -_/ .=.=. |
| .*. \\ .=. |
| . / \ . |
|111111111_+ +_2222222|
+-----------------------+
} \n]
set ::punk::bannerTemplate [string trim {
.000000000000000.
.*. \\\_ .=.
.*.*. \@ > .=.=.
.*.*.*. | ~ .=.=.=.
.*.*. \_- -_/ .=.=.
.*. \\ .=.
. / \ .
111111111_+ +_2222222
} \n]
>punk .. Method banner {args} {
set defaults [list -title "Pattern PUNK" -left "" -right ""]
if {[catch {set opts [dict merge $defaults $args]} ]} {
error "usage: banner \[-title \$title -left \$left -right \$right\]"
}
set word1 [overtype::left [string repeat " " 9] [dict get $opts -left]]
set word2 [overtype::right [string repeat " " 7] [dict get $opts -right]]
set title [overtype::centre [string repeat " " 15] [dict get $opts -title]]
return [string map [list 111111111 $word1 2222222 $word2 000000000000000 $title] $::punk::bannerTemplate]
}
>punk .. Property logo2 "\[TCL\\\nPUNK\]"
>punk .. Method logo3 {{cborder_ctext ""}} {
set this @this@
if {$cborder_ctext eq ""} {
set cborder "web-seagreen"
set ctext "web-steelblue"
} else {
lassign $cborder_ctext cborder ctext
}
return [ textblock::frame -checkargs 0 -type arc -ansiborder [a+ Web-black $cborder] [a+ Web-black $ctext][$this . logo2]]
}
>punk .. Property logotk "\[TCL\\\n TK \]"
proc TCL {args} {
switch -- [lindex $args 0] {
TK {
return [>punk . logotk .]
#return [textblock::frame -type arc [>punk . logotk]]
}
PUNK {
return [>punk . logo2 .]
#return [textblock::frame -type arc [>punk . logo2]]
}
default {
return [textblock::join -- [>punk . logo3] " " "\nmodule : patternpunk\nversion: [package present patternpunk]"]
}
}
}
>punk .. Property logo [>punk . banner]
>punk .. Method versionLogo {} {
set this @this@
>punk . banner -left " Ver" -right "[$this . version] "
}
>punk .. Method version {} {
if {[package provide punk] ne ""} {
set version $::punk::version
} else {
set version "N/A"
}
return $version
}
punk::args::define {
#Review
@id -id "::>punk . poses"
@cmd -name ">punk . poses" -help "Show or list the poses for the Punk mascot"
-censored -default 1 -type boolean -help "Set true to include mild toilet humour poses"
-return -default table -choices {names table list dict}
}
>punk .. Method poses {args} {
set argd [punk::args::parse $args withid "::>punk . poses"]
set censored [dict get $argd opts -censored]
set return [dict get $argd opts -return]
set poses [list {*}{
front
back
lhs
left
rhs
right
lhs_air
rhs_air
lhs_hips
rhs_hips
lhs_bend
rhs_bend
lhs_thrust
rhs_thrust
}]
if {!$censored} {
#allow toilet humour
lappend poses piss poop
}
switch -- $return {
names {
return $poses
}
list {
set result [list]
foreach pose $poses {
lappend result [list $pose [>punk . $pose]]
}
return $result
}
dict {
set result [dict create]
foreach pose $poses {
dict set result $pose [>punk . $pose]
}
return $result
}
table {
set cells [list]
foreach pose $poses {
lappend cells "$pose\n\n[>punk . $pose]"
}
return [textblock::list_as_table -show_hseps 1 -columns 4 $cells]
}
}
}
>punk .. Property front [string trim {
_|_
@ v @
~
- -
|_\ /_|
/ \
_+ +_
} \n]
>punk .. Property front_2003 [string trim [string map "% \u2003" {
_|_
@%v%@
%~%
-%%%-
|_\%/_|
/ \
_+ +_
}] \n]
>punk .. Property back [string trim {
|
( | )
|
- -
|_\ /_|
/ \
_- -_
} \n]
>punk .. Property rhs [string trim {
\\\_
\@ >
| ~
\_- -_
\\ /
/ \
_+ +_
} \n]
>punk .. Property rhs_2003 [string trim [string map "% \u2003" {
\\\_
\@%%>
|%~
\_-%%%-_
\\ /
/ \
_+ +_
}] \n]
>punk .. Property right
>punk .. PropertyRead right {} {
return $o_rhs
}
>punk .. Property lhs [string trim {
_///
< @/
~ |
_- -_/
\ //
/ \
_+ +_
} \n]
>punk .. Property lhs_2003 [string trim [string map "% \u2003" {
_///
<%%@/
~%|
_-%%%-_/
\ //
/ \
_+ +_
}] \n]
>punk .. Property left
>punk .. PropertyRead left {} {
return $o_lhs
}
>punk .. Property rhs_air [string trim {
\\\_
\@ >
| ~
\_- -_/
\\
/ \
_+ +_
} \n]
>punk .. Property lhs_air [string trim {
_///
< @/
~ |
\_- -_/
//
/ \
_+ +_
} \n]
>punk .. Property lhs_hips [string trim {
_///
< @/
~ |
_- -_
\ | | /
/ \
_+ +_
} \n]
>punk .. Property rhs_hips [string trim {
\\\_
\@ >
| ~
_- -_
\ | | /
/ \
_+ +_
} \n]
>punk .. Property piss [string trim {
\\\_
\@ >
| ~
\_- -_/
\\_ ..
/ \ ..
_+ +_ .
} \n]
>punk .. Property poop [string trim {
_///
< @/
~ |
_- -_
\ \\ /
//. ~
_+_+ @
} \n]
>punk .. Property lhs_bend [string trim {
_///
< @/
~ |
_- -_
\ \\ /
//
_+_+
} \n]
>punk .. Property lhs_thrust [string trim {
_///
< @/
~ |
_- -_
\ // /
\\
_+_+
} \n]
>punk .. Property rhs_bend [string trim {
\\\_
\@ >
| ~
_- -_
\ // /
\\
+_+_
} \n]
>punk .. Property rhs_thrust [string trim {
\\\_
\@ >
| ~
_- -_
\ \\ /
//
+_+_
} \n]
>punk .. Property fossil [punk::args::lib::tstr [string trim {
..
> <
\ / v
v \\_/
\/\\ v .
v_ /|\/ /
\__/
} \n]]
>punk .. Method deck {args} {
#todo - themes?
set this @this@
set RST [a]
set punk_colour [a+ term-71] ;#term-darkseagreen4-b
set hbar_colour [a+ web-silver]
set vbar_colour [a+ web-steelblue]
set border_colour [a+ web-lightslategray]
set frame_type arc
set punk $punk_colour[$this . lhs_air]$RST
package require punk::args
set standard_frame_types [textblock::frametypes]
set argd [punk::args::parse $args withdef [tstr -return string {
@id -id "::>punk . deck"
@cmd -name "deck" -help "Punk Deck mascot"
-frame -default arc -choices "${$standard_frame_types}" -choicerestricted 0 -choiceprefix 1
-boxmap -default {} -type dict
-boxlimits -default {hl vl tlc blc trc brc} -help "Limit the border box to listed elements."
-border_colour -default ${$border_colour} -type ansistring -regexprepass {^$} -validationtransform {
-function stripansi -maxsize 0
}
-title -default "PATTERN" -type string
-subtitle -default "PUNK" -type string
@values -max 0
}]]
set frame_type [dict get $argd opts -frame]
set box_map [dict get $argd opts -boxmap]
set box_limits [dict get $argd opts -boxlimits]
set border_colour [dict get $argd opts -border_colour]
set title [dict get $argd opts -title]
set subtitle [dict get $argd opts -subtitle]
set punkdeck [overtype::right [overtype::left [textblock::frame -ansiborder $border_colour -type $frame_type -boxmap $box_map -boxlimits $box_limits -title $hbar_colour$title$RST -subtitle $hbar_colour$subtitle$RST $punk] "$vbar_colour\n\n\P\nU\nN\nK$RST"] "$vbar_colour\n\nD\nE\nC\nK"]
}
#TODO - reuse textblock::gcross arguments - but reorder for error display
>punk .. Method gcross {{size 1} args} {
package require textblock
set argd [punk::args::parse [list {*}$args $size] withid ::textblock::gcross]
textblock::gcross {*}$args $size
}
>punk .. Method dumpProperties {{object ::>punk}} {
set text ""
foreach {p v} [$object .. Properties . pairs] {
append text $p \n
append text [set $v] \n \n
}
return $text
}
>punk .. Method listProperties {{object ::>punk}} {
set result {}
foreach {p v} [$object .. Properties . pairs] {
lappend result $p [set $v]
}
return $result
}
##########################################################
#CANDY-CODE
#
#Cute names for file I/O
proc <- filename {
set fp [open $filename]
::patternpunk:lib::K [read $fp] [close $fp]
}
proc -> {filename string} {
set fp [open $filename w]
puts $fp $string
close $fp
}
proc ->> {filename string} {
set fp [open $filename a]
puts $fp $string
close $fp
}
#presumably this is to allow calling of standard objects using dotted notation?
::>pattern .. Create ::>
::> .. Method item {args} {
#uplevel #0 $args
#uplevel #0 [join $args]
uplevel #0 $args
}
::> .. DefaultMethod item
namespace eval patternpunk::lib {
proc K {x y} {return $x}
}
package provide patternpunk [namespace eval patternpunk {
variable version
set version 1.1.1
}]
#]]>
#</code>
#<files>
#</files>
#</xpack>
#</xml>

9288
src/vfs/_vfscommon.vfs/modules/punk-0.1.1.tm

File diff suppressed because it is too large Load Diff

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

@ -128,6 +128,7 @@ tcl::namespace::eval punk::ansi::class {
-height -type integer -default "" -height -type integer -default ""
-crm_mode -type boolean -default 0 -crm_mode -type boolean -default 0
-binarytext -type string -default "" -choices {"" bios ice} -binarytext -type string -default "" -choices {"" bios ice}
-format -type string -choices {ansi binarytext-bios binarytext-ice xbin}
@values -min 0 -max 0 @values -min 0 -max 0
}] }]
method rendertest {args} { method rendertest {args} {
@ -136,6 +137,7 @@ tcl::namespace::eval punk::ansi::class {
set opt_height [dict get $argd opts -height] set opt_height [dict get $argd opts -height]
set opt_crm_mode [dict get $argd opts -crm_mode] set opt_crm_mode [dict get $argd opts -crm_mode]
set opt_binarytext [dict get $argd opts -binarytext] set opt_binarytext [dict get $argd opts -binarytext]
set opt_format [dict get $argd opts -format]
set existing_dimensions $o_render_dimensions set existing_dimensions $o_render_dimensions
if {![regexp {^([0-9]+)[xX]([0-9]+)$} $existing_dimensions _m w h]} { if {![regexp {^([0-9]+)[xX]([0-9]+)$} $existing_dimensions _m w h]} {
@ -151,7 +153,8 @@ tcl::namespace::eval punk::ansi::class {
set o_render_dimensions ${w}x${h} set o_render_dimensions ${w}x${h}
set rendered [overtype::renderspace -binarytext $opt_binarytext -cp437 1 -crm_mode $opt_crm_mode -expand_right 0 -wrap 1 -width $w -height $h -appendlines 1 "" [$o_ansistringobj get]] #set rendered [overtype::renderspace -binarytext $opt_binarytext -cp437 1 -crm_mode $opt_crm_mode -expand_right 0 -wrap 1 -width $w -height $h -appendlines 1 "" [$o_ansistringobj get]]
set rendered [overtype::renderspace -format $opt_format -cp437 1 -crm_mode $opt_crm_mode -expand_right 0 -wrap 1 -width $w -height $h -appendlines 1 "" [$o_ansistringobj get]]
return $rendered return $rendered
} }
@ -630,7 +633,8 @@ tcl::namespace::eval punk::ansi {
package require punk::ansi::sauce package require punk::ansi::sauce
set sdict [punk::ansi::sauce::from_file $filename] set sdict [punk::ansi::sauce::from_file $filename]
set result "" set result ""
if {[dict size $sdict]} { #if no sauce header - sdict will contain only posn -1
if {[dict size $sdict] > 1} {
if {$opt_return eq "dict"} { if {$opt_return eq "dict"} {
return $sdict return $sdict
} }
@ -700,28 +704,74 @@ tcl::namespace::eval punk::ansi {
#if SAUCE data is present - it may give an indication of encoding as well as number of columns/lines #if SAUCE data is present - it may give an indication of encoding as well as number of columns/lines
if {![catch {package require punk::ansi::sauce}]} { if {![catch {package require punk::ansi::sauce}]} {
if {[catch {punk::ansi::sauce::from_file $fname} sdict]} { if {[catch {punk::ansi::sauce::from_file $fname} sdict]} {
#no 128 Byte SAUCE record at end of file #error parsing 128 Byte SAUCE record at end of file
set sdict [dict create] set sdict [dict create]
} }
#if no error - there may be no SAUCE record at all (sdict is just posn -1)
} else { } else {
puts stderr "Warning punk::ansi::sauce package not loaded - unable to detect or use any SAUCE data to aid in display" puts stderr "Warning punk::ansi::sauce package not loaded - unable to detect or use any SAUCE data to aid in display"
} }
if {![dict size $sdict]} {
if {[string tolower [file extension $fname]] eq ".bin"} { set format ansi ;#default assumption
#In the absence of SAUCE data - assume .bin is binary text
set binarytext bios ;#16 fg, 8 bg + blink
if {[dict size $sdict] < 2} {
#either no SAUCE (dict is just posn -1) or there was an error during sauce::from_file parsing (empty sdict)
switch -exact -- [string tolower [file extension $fname]] {
.bin {
#In the absence of SAUCE data - assume .bin is binary text
set binarytext bios ;#16 fg, 8 bg + blink
set format binarytext-bios
}
.xb {
set format xbin
}
} }
} }
#review - we open and read from file twice - once for sauce, once to slurp in whole file.
# - consider optimising to read file in first and use slurped data for sauce
#(create punk::ansi::sauce::from_data ?)
set ansidata [fcat -translation binary $fname]
if {[dict size $sdict] && [dict get $sdict posn] != -1} {
#the SAUCE ctrl-z may not be the only ctrl-z in the file data
#use the position returned by sauce::from_file rather than splitting on ctrl-z
#posn will be -1 if no SAUCE, or the position of the ctrl-z immediatly before the entire SAUCE block (including comments)
set ansidata [string range $ansidata 0 [dict get $sdict posn]-1]
}
if {[dict exists $sdict datatype_name]} { if {[dict exists $sdict datatype_name]} {
if {[dict get $sdict datatype_name] eq "binarytext"} { switch -- [dict get $sdict datatype_name] {
#todo - SAUCE ANSiFlags - ice vs default bios binarytext {
if {[dict exists $sdict ansiflags_ice] && [dict get $sdict ansiflags_ice]} { #SAUCE ANSiFlags - ice vs default bios
set binarytext ice if {[dict exists $sdict ansiflags_ice] && [dict get $sdict ansiflags_ice]} {
} else { set binarytext ice
set binarytext bios set format binarytext-ice
} else {
set binarytext bios
set format binarytext-bios
}
}
xbin {
set format xbin
}
default {
} }
} }
} }
if {$format eq "xbin"} {
#set ansidata [fcat -translation binary $fname] ;#don't split on \x1a - this is also present in xbin header
set xbin_header [string range $ansidata 0 10] ;#11 bytes
set non_header [string range $ansidata 11 end]
#set ansidata $xbin_header[lindex [split $non_header \x1a] 0] ;#ignore sauce at tail
set xbin_header_info [punk::ansi::xbin::parse_header $xbin_header]
#keys width height fontsize flags
set dimensions [dict get $xbin_header_info width]x[dict get $xbin_header_info height] ;#cols x rows
}
if {$encoding eq ""} { if {$encoding eq ""} {
if {[dict exists $sdict codepage]} { if {[dict exists $sdict codepage]} {
set encoding [dict get $sdict codepage] set encoding [dict get $sdict codepage]
@ -733,11 +783,13 @@ tcl::namespace::eval punk::ansi {
if {$dimensions eq ""} { if {$dimensions eq ""} {
# defaults # defaults
if {$binarytext ne ""} { if {[string match binarytext* $format]} {
set cols 160 set cols 160
} else { } else {
set cols 80 set cols 80
} }
#sauce-specified
if {[dict exists $sdict columns]} { if {[dict exists $sdict columns]} {
set c [dict get $sdict columns] set c [dict get $sdict columns]
if {$c > 0} { if {$c > 0} {
@ -764,17 +816,23 @@ tcl::namespace::eval punk::ansi {
} }
lassign [split $dimensions x] cols rows lassign [split $dimensions x] cols rows
#set ansidata [fcat -encoding $encoding $fname]
set ansidata [lindex [split [fcat -translation binary $fname] \x1a] 0]
#hack if {$format eq "xbin"} {
#if {$binarytext eq ""} { #review
##don't decode binary xbin header
#set hdr [string range $ansidata 0 10]
#set data [encoding convertfrom $encoding [string range $ansidata 11 end]]
#set ansidata $hdr$data
#don't convert at all - compressed is binary?
} else {
set ansidata [encoding convertfrom $encoding $ansidata] set ansidata [encoding convertfrom $encoding $ansidata]
#} }
set obj [punk::ansi::class::class_ansi new $ansidata] set obj [punk::ansi::class::class_ansi new $ansidata]
if {$encoding eq "cp437"} { if {$encoding eq "cp437"} {
set result [$obj rendertest -binarytext $binarytext -width $cols -height $rows -crm_mode $opt_crm_mode] #set result [$obj rendertest -binarytext $binarytext -width $cols -height $rows -crm_mode $opt_crm_mode]
set result [$obj rendertest -format $format -width $cols -height $rows -crm_mode $opt_crm_mode]
} else { } else {
set result [$obj render $dimensions] set result [$obj render $dimensions]
} }
@ -7070,6 +7128,12 @@ be as if this was off - ie lone CR.
set prev_stop_idx [lsearch -integer -bisect $tstops $current_column] set prev_stop_idx [lsearch -integer -bisect $tstops $current_column]
set next_stop [lindex $tstops $prev_stop_idx+1] ;#if our current_column is exactly on a stop, we still want to move to the next stop. set next_stop [lindex $tstops $prev_stop_idx+1] ;#if our current_column is exactly on a stop, we still want to move to the next stop.
if {$next_stop eq ""} {
#if we run out of stops
#Review
break
}
# how far is the next tab position ? # how far is the next tab position ?
#set dist [expr {$num - ($currPos % $num)}] #set dist [expr {$num - ($currPos % $num)}]
set this_tab_width [expr {$next_stop - $current_column}] ;#diff between two adjacent columns is one. set this_tab_width [expr {$next_stop - $current_column}] ;#diff between two adjacent columns is one.
@ -11808,7 +11872,7 @@ namespace eval punk::ansi::colour {
@cmd -name "punk::ansi::colour::byteAnsi" -summary\ @cmd -name "punk::ansi::colour::byteAnsi" -summary\
"ANSI/BIOS colour codes from attribute byte."\ "ANSI/BIOS colour codes from attribute byte."\
-help\ -help\
"Convert an attribute-byte (character) to ANSI SGR "Convert a binarytext (.bin) attribute-byte (character) to ANSI SGR
foreground and background colour. foreground and background colour.
This is allows 16 foreground colours and only 8 This is allows 16 foreground colours and only 8
background colours, with the highest bit being background colours, with the highest bit being
@ -11828,7 +11892,7 @@ namespace eval punk::ansi::colour {
lappend PUNKARGS [list { lappend PUNKARGS [list {
@id -id "::punk::ansi::colour::byteAnsiIce" @id -id "::punk::ansi::colour::byteAnsiIce"
@cmd -name "punk::ansi::colour::byteAnsiIce" -summary\ @cmd -name "punk::ansi::colour::byteAnsiIce" -summary\
"iCE colour codes from attribute byte."\ "iCE colour codes from binarytext (.bin) attribute byte."\
-help\ -help\
"Convert an attribute-byte (character) to ANSI SGR "Convert an attribute-byte (character) to ANSI SGR
foreground and background colour. foreground and background colour.
@ -11847,6 +11911,124 @@ namespace eval punk::ansi::colour {
dict get $byte_to_ansi_ice $char dict get $byte_to_ansi_ice $char
} }
} }
tcl::namespace::eval punk::ansi::xbin {
proc parse_header {str} {
#https://web.archive.org/web/20120204063040/http://www.acid.org/info/xbin/x_spec.htm
if {[string length $str] < 11} {
error "punk::ansi::xbin::parse_header error - invalid XBIN header - less than 11 bytes received"
}
set xbin_header [string range $str 0 10] ;#11 bytes
set xbin_id [string range $xbin_header 0 3]
if {$xbin_id ne "XBIN"} {
error "punk::ansi::xbin::parse_header error - invalid XBIN header"
}
set xbin_eofchar [string index $xbin_header 4]
set xbin_width_raw [string range $xbin_header 5 6]
binary scan $xbin_width_raw su xbin_width ;#16bit unsigned little-endian
set xbin_height_raw [string range $xbin_header 7 8]
binary scan $xbin_height_raw su xbin_height ;#16bit unsigned little-endian
set xbin_fontsize_raw [string index $xbin_header 9]
if {[binary scan $xbin_fontsize_raw cu xbin_fontsize]} {
#1 byte - unsigned
#numeric number of pixel rows (scanlines) in font.
#Any value from 1 to 32 is technically possible on VGA.
#Any other values should be considered illegal
if {$xbin_fontsize < 1 || $xbin_fontsize > 32} {
error "punk::ansi::xbin::parse_header error - invalid XBIN header - fontsize not in range 1 to 32 inclusive. received $xbin_fontsize"
}
}
set xbin_flags_raw [string index $xbin_header 10]
#valid flags: 512chars nonblink compress font palette
#bits:
#7 unused 6 unused 5 unused 4 512chars 3 nonblink 2 compress 1 font 0 palette
binary scan $xbin_flags_raw B8 flagbits
set flagbits [lrange [split $flagbits ""] 3 end] ;#skip first 3 unused
set allflags [list 512chars nonblink compress font palette]
set xbin_flags [list]
#puts "flagbits $flagbits"
foreach b $flagbits f $allflags {
if {$b} {
lappend xbin_flags $f
}
}
#width - number of columns, height - number of character rows
return [dict create width $xbin_width height $xbin_height fontsize $xbin_fontsize flags $xbin_flags]
}
proc default_palette {} {
# VGA 16-colour default palette as RGB 0-255 triples.
return {
{0 0 0}
{0 0 170}
{0 170 0}
{0 170 170}
{170 0 0}
{170 0 170}
{170 85 0}
{170 170 170}
{85 85 85}
{0 0 255}
{0 255 0}
{0 255 255}
{255 0 0}
{255 0 255}
{255 255 0}
{255 255 255}
}
}
proc palette_value_8bit {value} {
if {$value < 0 || $value > 63} {
error "punk::ansi::xbin::palette_value_8bit error - expected palette value from 0 to 63 inclusive. received $value"
}
return [expr {round(($value * 255.0) / 63.0)}]
}
proc parse_palette {str} {
if {[string length $str] < 48} {
error "punk::ansi::xbin::parse_palette error - invalid XBIN palette - less than 48 bytes received"
}
binary scan [string range $str 0 47] cu* components
set palette [list]
foreach {r g b} $components {
lappend palette [list [palette_value_8bit $r] [palette_value_8bit $g] [palette_value_8bit $b]]
}
#for {set i 0} {$i < 48} {incr i 3} {
# set r [palette_value_8bit [lindex $components $i]]
# set g [palette_value_8bit [lindex $components $i+1]]
# set b [palette_value_8bit [lindex $components $i+2]]
# lappend palette [list $r $g $b]
#}
return $palette
}
proc attribute_ansi {char palette nonblink} {
#convert a binarytext (.bin) attribute byte (character) to ANSI SGR
#foreground and background colour.
#When nonblink is false, this allows 16 foreground colours and only 8
#background colours, with the highest bit being
#used to set 'blink' on.
if {![binary scan $char cu value]} {
error "punk::ansi::xbin::attribute_ansi error - expected a single character for attribute byte. received string of length [string length $char] - '[ansistring VIEW $char]'"
}
set fg_index [expr {$value & 0x0F}]
if {$nonblink} {
set bg_index [expr {($value >> 4) & 0x0F}]
set blink noblink
} else {
set bg_index [expr {($value >> 4) & 0x07}]
if {$value & 0x80} {
set blink blink
} else {
set blink noblink
}
}
lassign [lindex $palette $fg_index] fr fg fb
lassign [lindex $palette $bg_index] br bg bb
return [punk::ansi::a+ $blink rgb-$fr-$fg-$fb Rgb-$br-$bg-$bb]
}
}
tcl::namespace::eval punk::ansi::internal { tcl::namespace::eval punk::ansi::internal {
proc splitn {str {len 1}} { proc splitn {str {len 1}} {
#from textutil::split::splitn #from textutil::split::splitn

21
src/vfs/_vfscommon.vfs/modules/punk/ansi/sauce-0.1.0.tm

@ -39,32 +39,35 @@ tcl::namespace::eval punk::ansi::sauce {
proc from_file {fname} { proc from_file {fname} {
if {[file size $fname] < 128} { if {[file size $fname] < 128} {
return return [dict create posn -1]
} }
set fd [open $fname r] set fd [open $fname r]
chan conf $fd -translation binary chan conf $fd -translation binary
chan seek $fd -128 end chan seek $fd -128 end
set sauce_block_posn [expr {[chan tell $fd] -1}] ;#entire sauce block including ctrl-z and any comments - initial value assuming no comments
#If we treat the ctrl-z (\x1a) as part of the sauce - actual start of entire sauce info is 1 before sauce_header_posn,
#or further back if there are comments.
set srec [read $fd] set srec [read $fd]
set srec_len 128 ;#This is the normal length of a SAUCE record - we may need to set it shorter if truncation detected set srec_len 128 ;#This is the normal length of a SAUCE record - we may need to set it shorter if truncation detected
if {[catch {set sdict [to_dict $srec]}]} { if {[catch {set sdict [to_dict $srec]}]} {
#review - have seen truncated SAUCE records < 128 bytes #review - have seen truncated SAUCE records < 128 bytes
#we could search for SAUCE00 in the tail and see what records can be parsed? #we could search for SAUCE00 in the tail and see what records can be parsed?
#specifically publicdomain roysac images sometimes only 99 Bytes of sauce - suspect remaining were null \x0 padded and trimmed #specifically publicdomain roysac images sometimes only 99 Bytes of sauce - suspect remaining were null \x0 padded and trimmed
set sauceposn [string first SAUCE00 $srec] set saucestart [string first SAUCE00 $srec]
if {$sauceposn <= 0} { if {$saucestart <= 0} {
close $fd close $fd
return return [dict create posn -1]
} }
#emit something to give user an indication something isn't right #emit something to give user an indication something isn't right
puts stderr "punk::ansi::sauce::from_file WARNING SAUCE record seems to be truncated - padding rhs with nulls and trying again.." puts stderr "punk::ansi::sauce::from_file WARNING SAUCE record seems to be truncated - padding rhs with nulls and trying again.."
#SAUCE00 is not at the beginning #SAUCE00 is not at the beginning
#pad the tail with nulls and try again #pad the tail with nulls and try again
set srec [string range $srec $sauceposn end] set srec [string range $srec $saucestart end]
set srec_len [string length $srec] set srec_len [string length $srec]
set srec ${srec}[string repeat \x0 [expr {128 - [string length $srec]}]] set srec ${srec}[string repeat \x0 [expr {128 - [string length $srec]}]]
if {[catch {set sdict [to_dict $srec]}]} { if {[catch {set sdict [to_dict $srec]}]} {
close $fd close $fd
return return [dict create posn -1]
} }
dict set sdict warning "SAUCE truncation to $srec_len bytes detected" dict set sdict warning "SAUCE truncation to $srec_len bytes detected"
} }
@ -73,6 +76,7 @@ tcl::namespace::eval punk::ansi::sauce {
#Use srec_len instead of 128 - in case we had truncated source record which we padded and were able to parse #Use srec_len instead of 128 - in case we had truncated source record which we padded and were able to parse
set offset [expr {-1 *($srec_len + ($clines * 64) + 5)}] set offset [expr {-1 *($srec_len + ($clines * 64) + 5)}]
chan seek $fd $offset end chan seek $fd $offset end
set sauce_block_posn [expr {[chan tell $fd] -1}] ;#entire sauce block including ctrl-z and any comments
set tag [chan read $fd 5] set tag [chan read $fd 5]
if {$tag eq "COMNT"} { if {$tag eq "COMNT"} {
#'character' data - shouldn't be null terminated c-style string - but can be #'character' data - shouldn't be null terminated c-style string - but can be
@ -95,6 +99,7 @@ tcl::namespace::eval punk::ansi::sauce {
dict set sdict commentlines $commentlines dict set sdict commentlines $commentlines
} }
} }
dict set sdict posn $sauce_block_posn
close $fd close $fd
return $sdict return $sdict
} }
@ -447,11 +452,13 @@ tcl::namespace::eval punk::ansi::sauce {
} }
6 { 6 {
#xbin - only filtype is 0 #xbin - only filetype is 0
#https://web.archive.org/web/20120204063040/http://www.acid.org/info/xbin/x_spec.htm #https://web.archive.org/web/20120204063040/http://www.acid.org/info/xbin/x_spec.htm
dict set sdict columns [dict get $sdict tinfo1] dict set sdict columns [dict get $sdict tinfo1]
dict set sdict rows [dict get $sdict tinfo2] dict set sdict rows [dict get $sdict tinfo2]
dict set sdict fontname [dict get $sdict tinfos] dict set sdict fontname [dict get $sdict tinfos]
#Values from sauce record are probably only informational, because xbin has an 11-byte header with width,height,fontsize and flags.
#presumably the header-info should take precedence over all sauce data (? review)
} }
} }
if {[dict exists $sdict fontname]} { if {[dict exists $sdict fontname]} {

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

@ -71,11 +71,6 @@ package require punk::args
#if {"windows" eq $::tcl_platform(platform)} {
# #package require zzzload
# #zzzload::pkg_require twapi
#}
#see https://learn.microsoft.com/en-us/windows/console/classic-vs-vt #see https://learn.microsoft.com/en-us/windows/console/classic-vs-vt
#https://learn.microsoft.com/en-us/windows/console/creating-a-pseudoconsole-session #https://learn.microsoft.com/en-us/windows/console/creating-a-pseudoconsole-session

33
src/vfs/_vfscommon.vfs/modules/punk/du-0.1.0.tm

@ -2529,21 +2529,30 @@ namespace eval punk::du {
#jmn disable twapi #jmn disable twapi
#tailcall du_dirlisting_generic $folderpath {*}$args #tailcall du_dirlisting_generic $folderpath {*}$args
package require zzzload #package require zzzload
set loadstate [zzzload::pkg_require twapi] #set loadstate [zzzload::pkg_require twapi]
if {$loadstate ni [list loading failed]} { #if {$loadstate ni [list loading failed]} {
#either already loaded by zzload or ordinary package require # #either already loaded by zzload or ordinary package require
package require twapi ;#should be fast once twapi dll loaded in zzzload thread # package require twapi ;#should be fast once twapi dll loaded in zzzload thread
# set ::punk::du::has_twapi 1
# punk::du::active::set_active_function du_dirlisting du_dirlisting_twapi
# tailcall du_dirlisting_twapi $folderpath {*}$args
#} else {
# if {$loadstate eq "failed"} {
# puts stderr "punk::du defaulting to du_dirlisting_generic because twapi load failed"
# punk::du::active::set_active_function du_dirlisting du_dirlisting_generic
# }
# tailcall du_dirlisting_generic $folderpath {*}$args
#}
if {[catch {package require twapi} errM]} {
puts stderr "punk::du defaulting to du_dirlisting_generic because twapi load failed: $errM"
punk::du::active::set_active_function du_dirlisting du_dirlisting_generic
tailcall du_dirlisting_generic $folderpath {*}$args
} else {
set ::punk::du::has_twapi 1 set ::punk::du::has_twapi 1
punk::du::active::set_active_function du_dirlisting du_dirlisting_twapi punk::du::active::set_active_function du_dirlisting du_dirlisting_twapi
tailcall du_dirlisting_twapi $folderpath {*}$args tailcall du_dirlisting_twapi $folderpath {*}$args
} else {
if {$loadstate eq "failed"} {
puts stderr "punk::du defaulting to du_dirlisting_generic because twapi load failed"
punk::du::active::set_active_function du_dirlisting du_dirlisting_generic
}
tailcall du_dirlisting_generic $folderpath {*}$args
} }
} }
default { default {

11
src/vfs/_vfscommon.vfs/modules/punk/mix/commandset/loadedlib-0.1.0.tm

@ -247,12 +247,6 @@ namespace eval punk::mix::commandset::loadedlib {
set opts [dict merge $defaults $args] set opts [dict merge $defaults $args]
set opt_askme [dict get $opts -askme] set opt_askme [dict get $opts -askme]
if {[catch {package require natsort}]} {
set has_natsort 0
} else {
set has_natsort 1
}
catch {package require $library 1-0} ;#ensure pkg system has loaded/searched for everything for the path of the specified library (using unsatisfiable version range) catch {package require $library 1-0} ;#ensure pkg system has loaded/searched for everything for the path of the specified library (using unsatisfiable version range)
if {[file pathtype $modulefoldername] eq "absolute"} { if {[file pathtype $modulefoldername] eq "absolute"} {
@ -321,11 +315,6 @@ namespace eval punk::mix::commandset::loadedlib {
set versions [package versions [lindex $libfound 0]] set versions [package versions [lindex $libfound 0]]
set versions [lsort -command {package vcompare} $versions] set versions [lsort -command {package vcompare} $versions]
#if {$has_natsort} {
# set versions [natsort::sort $versions]
#} else {
# set versions [lsort $versions]
#}
if {![llength $versions]} { if {![llength $versions]} {
error "No version numbers found for library/module $libfound - sorry, you will need to copy it across manually" error "No version numbers found for library/module $libfound - sorry, you will need to copy it across manually"
} }

158
src/vfs/_vfscommon.vfs/modules/punk/mod-0.1.1.tm

@ -0,0 +1,158 @@
#punkapps app manager
# deck cli
namespace eval punk::mod::cli {
namespace export help list run
namespace ensemble create
# namespace ensemble configure [namespace current] -unknown punk::mod::cli::_unknown
if 0 {
proc _unknown {ns args} {
puts stderr "punk::mod::cli::_unknown '$ns' '$args'"
puts stderr "punk::mod::cli::help $args"
puts stderr "arglen:[llength $args]"
punk::mod::cli::help {*}$args
}
}
#cli must have _init method - usually used to load commandsets lazily
#
variable initialised 0
proc _init {args} {
variable initialised
if {$initialised} {
return
}
#...
set initialised 1
}
proc help {args} {
set basehelp [punk::mix::base help {*}$args]
#namespace export
return $basehelp
}
proc getraw {appname} {
set app_folders [punk::config::configure running apps]
#todo search each app folder
set bases [::list]
set versions [::list]
set mains [::list]
set appinfo [::list bases {} mains {} versions {}]
foreach containerfolder $app_folders {
lappend bases $containerfolder
if {[file exists $containerfolder]} {
if {[file exists $containerfolder/$appname/main.tcl]} {
#exact match - only return info for the exact one specified
set namematches $appname
set parts [split $appname -]
} else {
set namematches [glob -nocomplain -dir $containerfolder -type d -tail ${appname}-*]
set namematches [lsort $namematches] ;#todo - -ascii? -dictionary? natsort?
}
foreach nm $namematches {
set mainfile $containerfolder/$nm/main.tcl
set parts [split $nm -]
if {[llength $parts] == 1} {
set ver ""
} else {
set ver [lindex $parts end]
}
if {$ver ni $versions} {
lappend versions $ver
lappend mains $ver $mainfile
} else {
puts stderr "punk::apps::app version '$ver' of app '$appname' already encountered at $mainfile. (will use earliest encountered in running-config apps and ignore others of same version)"
}
}
} else {
puts stderr "punk::apps::app missing apps_folder:'$containerfolder' Ensure apps_folder is set in punk::config"
}
}
dict set appinfo versions $versions
#todo - natsort!
set sorted_versions [lsort $versions]
set latest [lindex $sorted_versions 0]
if {$latest eq "" && [llength $sorted_versions] > 1} {
set latest [lindex $sorted_versions 1]
}
dict set appinfo latest $latest
dict set appinfo bases $bases
dict set appinfo mains $mains
return $appinfo
}
proc list {{glob *}} {
set apps_folder [punk::config::configure running apps]
if {[file exists $apps_folder]} {
if {[file exists $apps_folder/$glob]} {
#tailcall source $apps_folder/$glob/main.tcl
return $glob
}
set apps [glob -nocomplain -dir $apps_folder -type d -tail $glob]
if {[llength $apps] == 0} {
if {[string first * $glob] <0 && [string first ? $glob] <0} {
#no glob chars supplied - only launch if exact match for name part
set namematches [glob -nocomplain -dir $apps_folder -type d -tail ${glob}-*]
set namematches [lsort $namematches] ;#todo - -ascii? -dictionary? natsort?
if {[llength $namematches] > 0} {
set latest [lindex $namematches end]
lassign $latest nm ver
#tailcall source $apps_folder/$latest/main.tcl
}
}
}
return $apps
}
}
#todo - way to launch as separate process
# solo-opts only before appname - args following appname are passed to the app
proc run {args} {
set nameposn [lsearch -not $args -*]
if {$nameposn < 0} {
error "punkapp::run unable to determine application name"
}
set appname [lindex $args $nameposn]
set controlargs [lrange $args 0 $nameposn-1]
set appargs [lrange $args $nameposn+1 end]
set appinfo [punk::mod::cli::getraw $appname]
if {[llength [dict get $appinfo versions]]} {
set ver [dict get $appinfo latest]
puts stdout "info: $appinfo"
set ::argc [llength $appargs]
set ::argv $appargs
source [dict get $appinfo mains $ver]
if {"-hideconsole" in $controlargs} {
puts stderr "attempting console hide"
#todo - something better - a callback when window mapped?
after 500 {::punkapp::hide_console}
}
return $appinfo
} else {
error "punk::mod::cli unable to run '$appname'. main.tcl not found in [dict get $appinfo bases]"
}
}
}
namespace eval punk::mod::cli {
proc _cli {args} {
#don't use tailcall - base uses info level to determine caller
::punk::mix::base::_cli {*}$args
}
variable default_command help
package require punk::mix::base
package require punk::overlay
punk::overlay::custom_from_base [namespace current] ::punk::mix::base
}
package provide punk::mod [namespace eval punk::mod {
variable version
set version 0.1.1
}]

2
src/vfs/_vfscommon.vfs/modules/punk/nav/fs-0.1.0.tm

@ -847,7 +847,7 @@ tcl::namespace::eval punk::nav::fs {
Regardless of whether -nonportable is supplied or not, some characters are not Regardless of whether -nonportable is supplied or not, some characters are not
suitable for windows or most other platforms and will be rejected with an error. suitable for windows or most other platforms and will be rejected with an error.
An example of this is the null character (\0)." An example of this is the null character (\\0)."
@values -min 1 -max -1 -type string @values -min 1 -max -1 -type string
path -type string -multiple 1 -help\ path -type string -multiple 1 -help\
"Path(s) to create. Can be absolute or relative. "Path(s) to create. Can be absolute or relative.

192
src/vfs/_vfscommon.vfs/modules/punk/overlay-0.1.1.tm

@ -0,0 +1,192 @@
package require punk::mix::util
package require punk::args
tcl::namespace::eval ::punk::overlay {
#based *loosely* on: wiki.tcl-lang.org/page/ensemble+extend
# extend an ensemble-like routine with the routines in some namespace
#
# e.g custom_from_base ::punk::mix::cli ::punk::mix::base
#
proc custom_from_base {routine base} {
if {![tcl::string::match ::* $routine]} {
set resolved [uplevel 1 [list ::tcl::namespace::which $routine]]
if {$resolved eq {}} {
error [list {no such routine} $routine]
}
set routine $resolved
}
set routinens [tcl::namespace::qualifiers $routine]
if {$routinens eq {::}} {
set routinens {}
}
set routinetail [tcl::namespace::tail $routine]
if {![tcl::string::match ::* $base]} {
set base [uplevel 1 [
list [tcl::namespace::which namespace] current]]::$base
}
if {![tcl::namespace::exists $base]} {
error [list {no such namespace} $base]
}
set base [tcl::namespace::eval $base [
list [tcl::namespace::which namespace] current]]
#while 1 {
# set renamed ${routinens}::${routinetail}_[info cmdcount]
# if {[namespace which $renamed] eq {}} break
#}
tcl::namespace::eval $routine [
::list tcl::namespace::ensemble configure $routine -unknown [
::list ::apply {{base ensemble subcommand args} {
::list ${base}::_redirected $ensemble $subcommand
}} $base
]
]
punk::mix::util::namespace_import_pattern_to_namespace_noclobber ::punk::mix::util::* ${routine}::util
#namespace eval ${routine}::util {
#::namespace import ::punk::mix::util::*
#}
punk::mix::util::namespace_import_pattern_to_namespace_noclobber ${base}::lib::* ${routine}::lib
#namespace eval ${routine}::lib [string map [list <base> $base] {
# ::namespace import <base>::lib::*
#}]
tcl::namespace::eval ${routine}::lib [tcl::string::map [list <base> $base <routine> $routine] {
if {[tcl::namespace::exists <base>::lib]} {
::set current_paths [tcl::namespace::path]
if {"<routine>" ni $current_paths} {
::lappend current_paths <routine>
}
tcl::namespace::path $current_paths
}
}]
tcl::namespace::eval $routine {
::set exportlist [::list]
::foreach cmd [tcl::info::commands [tcl::namespace::current]::*] {
::set c [tcl::namespace::tail $cmd]
if {![tcl::string::match _* $c]} {
::lappend exportlist $c
}
}
tcl::namespace::export {*}$exportlist
}
return $routine
}
punk::args::define {
@id -id ::punk::overlay::import_commandset
@cmd -name punk::overlay::import_commandset\
-summary\
"Import commands into caller's namespace with optional prefix and separator."\
-help\
"Import commands that have been exported by another namespace into the caller's
namespace. Usually a prefix and optionally a separator should be used.
This is part of the punk::mix CLI commandset infrastructure - design in flux.
Todo - .toml configuration files for defining CLI configurations."
@values
prefix -type string
separator -type string -help\
"A string, usually punctuation, to separate the prefix and the command name
of the final imported command. The value \"::\" is disallowed in this context."
cmdnamespace -type string -help\
"Namespace from which to import commands. Commands are those that have been exported."
}
#load *exported* commands from cmdnamespace into caller's namespace - prefixing each command with $prefix
#Note: commandset may be imported by different CLIs with different bases *at the same time*
#so we don't make commands from the cli or its base available automatically (will generally require fully-qualified commands to use code from cli/base)
#we do load punk::mix::util::* into the util subnamespace even though the commandset might not be loaded in a cli using punk::mix::base i.e punk::mix::util is a common dependency for CLIs.
#commandsets designed to be used with a specific cli/base may choose to do their own import e.g with util::namespace_import_pattern_to_namespace_noclobber and/or set namespace path if they
#want the convenience of using lib:xxx with commands coming from those packages.
#This won't stop the commandset being used with other cli/bases unless the import is done by looking up the callers namespace.
#The basic principle is that the commandset is loaded into the caller(s) with a prefix
#- but commandsets should explicitly package require if they have any backwards dependencies on cli/base (which they may or may not be loaded into)
proc import_commandset {prefix separator cmdnamespace} {
set bad_seps [list "::"]
if {$separator in $bad_seps} {
error "import_commandset invalid separator '$separator'"
}
if {$prefix in $bad_seps} {
error "import_commandset invalid prefix '$prefix'"
}
if {"$prefix$separator" in $bad_seps} {
error "import_commandset invalid prefix/separator combination '$prefix$separator'"
}
if {"[string index $prefix end][string index $separator 0]" in $bad_seps} {
error "import_commandset invalid prefix/separator combination '$prefix$separator'"
}
#review - do we allow prefixes/separators such as a::b?
#namespace may or may not be a package
# allow with or without leading ::
if {[tcl::string::range $cmdnamespace 0 1] eq "::"} {
set cmdpackage [tcl::string::range $cmdnamespace 2 end]
} else {
set cmdpackage $cmdnamespace
set cmdnamespace ::$cmdnamespace
}
if {![tcl::namespace::exists $cmdnamespace]} {
#only do package require if the namespace not already present
catch {package require $cmdpackage} pkg_load_info
#recheck
if {![tcl::namespace::exists $cmdnamespace]} {
set prov [package provide $cmdpackage]
if {[tcl::string::length $prov]} {
set provinfo "(package $cmdpackage is present with version $prov)"
} else {
set provinfo "(package $cmdpackage not present)"
}
error "punk::overlay::import_commandset supplied namespace '$cmdnamespace' doesn't exist. $provinfo Pkg_load_result: $pkg_load_info Usage: import_commandset prefix separator namespace"
}
}
punk::mix::util::namespace_import_pattern_to_namespace_noclobber ::punk::mix::util::* ${cmdnamespace}::util
#let child namespace 'lib' resolve parent namespace and thus util::xxx
tcl::namespace::eval ${cmdnamespace}::lib [tcl::string::map [list <cmdns> $cmdnamespace] {
::set nspaths [tcl::namespace::path]
if {"<cmdns>" ni $nspaths} {
::lappend nspaths <cmdns>
}
tcl::namespace::path $nspaths
}]
set imported_commands [list]
set imported_tails [list]
set nscaller [uplevel 1 [list tcl::namespace::current]]
if {[catch {
#review - noclobber?
tcl::namespace::eval ${nscaller}::temp_import [list tcl::namespace::import ${cmdnamespace}::*]
foreach cmd [tcl::info::commands ${nscaller}::temp_import::*] {
set cmdtail [tcl::namespace::tail $cmd]
if {$cmdtail eq "_default"} {
set import_as ${nscaller}::${prefix}
} else {
set import_as ${nscaller}::${prefix}${separator}${cmdtail}
}
rename $cmd $import_as
lappend imported_commands $import_as
lappend imported_tails [namespace tail $import_as]
}
#make imported commands exported so they are available to the ensemble
tcl::namespace::eval ${nscaller} [list namespace export {*}$imported_tails]
} errM]} {
puts stderr "Error loading commandset $prefix $separator $cmdnamespace"
puts stderr "err: $errM"
}
return $imported_commands
}
}
package provide punk::overlay [tcl::namespace::eval punk::overlay {
variable version
set version 0.1.1
}]

24
src/vfs/_vfscommon.vfs/modules/punk/repl-0.1.2.tm

@ -1076,13 +1076,19 @@ namespace eval punk::repl::class {
append debug \n "input:[ansistring VIEW -lf 1 -vt 1 $new0] before row:$o_cursor_row after row: $result_row before col:$o_cursor_col after col:$result_col" append debug \n "input:[ansistring VIEW -lf 1 -vt 1 $new0] before row:$o_cursor_row after row: $result_row before col:$o_cursor_col after col:$result_col"
package require textblock package require textblock
set debug [textblock::frame -type $frametype -checkargs 0 -buildcache 0 $debug] set debug [textblock::frame -type $frametype -checkargs 0 -buildcache 0 $debug]
if {![punk::console::vt52]} {
catch {punk::console::move_emitblock_return $debug_first_row 1 $debug} #------------------------------------
} else { punk::console::cursorsave_move_emitblock_return $debug_first_row 1 $debug ;#supports also vt52
#?? #if {![punk::console::vt52]} {
} # #review
# catch {punk::console::move_emitblock_return $debug_first_row 1 $debug}
#} else {
# #??
#}
#------------------------------------
# -- --- --- --- --- --- # -- --- --- --- --- ---
set o_cursor_col $result_col set o_cursor_col $result_col
set cursor_row_idx [expr {$o_cursor_row-1}] set cursor_row_idx [expr {$o_cursor_row-1}]
lset o_rendered_lines $cursor_row_idx $result lset o_rendered_lines $cursor_row_idx $result
@ -3533,13 +3539,13 @@ namespace eval repl {
punk::ansi punk::ansi
punk::lib punk::lib
overtype overtype
dictutils
debug debug
punk::ns punk::ns
textblock textblock
punk::args::moduledoc::tclcore punk::args::moduledoc::tclcore
punk::aliascore punk::aliascore
}] }]
#dictutils
#pattern looks up versions available of patternlib before loading (but we don't have an index for tm files) todo fix pattern. #pattern looks up versions available of patternlib before loading (but we don't have an index for tm files) todo fix pattern.
# patterncmd\ # patterncmd\
@ -3784,7 +3790,7 @@ namespace eval repl {
#puts stderr "loading natsort" #puts stderr "loading natsort"
#natsort has 'application mode' which can exit. #natsort has 'application mode' which can exit.
#Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions #Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions
package require natsort #package require natsort
#package require punk ;# Thread #package require punk ;# Thread
#package require shellrun ;#subcommand exists of file #package require shellrun ;#subcommand exists of file
@ -3794,7 +3800,7 @@ namespace eval repl {
package require punk::ns ;#requires:punk::lib,punk::args,struct::list,cmdline+(tcllibc),struct::set,punk::ansi,punk::char, package require punk::ns ;#requires:punk::lib,punk::args,struct::list,cmdline+(tcllibc),struct::set,punk::ansi,punk::char,
#textutil,textutil::string,textutil::adjust,textutil::repeat,textutil::string,textutil::split,textutil::tabify,textutil::wcswidth #textutil,textutil::string,textutil::adjust,textutil::repeat,textutil::string,textutil::split,textutil::tabify,textutil::wcswidth
#punk::encmime,punk::assertion #punk::encmime,punk::assertion
#twapi,platform,registry,debug,overtype,patternpunk,pattern,patterncmd,metaface,patternpredator2,patternlib,dictutils #twapi,platform,registry,debug,overtype,patternpunk,pattern,patterncmd,metaface,patternpredator2,patternlib
#----------------------------------------------------------------------------------------------------------------------------------------- #-----------------------------------------------------------------------------------------------------------------------------------------
#package require textblock #package require textblock
@ -3921,7 +3927,7 @@ namespace eval repl {
#puts stderr "loading natsort" #puts stderr "loading natsort"
#natsort has 'application mode' which can exit. #natsort has 'application mode' which can exit.
#Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions #Requiring it shouldn't trigger application - but zipfs/vfs interactions confused it in some early versions
package require natsort #package require natsort
#catch {package require packageTrace} #catch {package require packageTrace}
if {[catch {package require punk::console} errM]} { if {[catch {package require punk::console} errM]} {
#review #review

3
src/vfs/_vfscommon.vfs/modules/punk/repo-0.1.1.tm

@ -83,6 +83,7 @@ namespace eval punk::repo {
proc get_fossil_usage {} { proc get_fossil_usage {} {
set allcmds [runout -n fossil help -a] set allcmds [runout -n fossil help -a]
#review - fix runout which is introducing addition ansi (repl problem?)
set allcmds [punk::ansi::ansistrip $allcmds] set allcmds [punk::ansi::ansistrip $allcmds]
set mainhelp [runout -n fossil help] set mainhelp [runout -n fossil help]
set mainhelp [punk::ansi::ansistrip $mainhelp] set mainhelp [punk::ansi::ansistrip $mainhelp]
@ -190,7 +191,7 @@ namespace eval punk::repo {
foreach ln $basic_opt_lines { foreach ln $basic_opt_lines {
set ln [string trim $ln] set ln [string trim $ln]
#fossil sometimes emits cursor control sequences e.g CSI 3 q #REVIEW - we only need to strip because 'runout' is introducing ansi.
set ln [punk::ansi::ansistrip $ln] set ln [punk::ansi::ansistrip $ln]
if {$ln eq ""} { if {$ln eq ""} {
continue continue

9
src/vfs/_vfscommon.vfs/modules/punkapp-0.1.tm → src/vfs/_vfscommon.vfs/modules/punkapp-0.1.1.tm

@ -1,9 +1,5 @@
#utilities for punk apps to call #utilities for punk apps to call
package provide punkapp [namespace eval punkapp {
variable version
set version 0.1
}]
namespace eval punkapp { namespace eval punkapp {
variable result variable result
@ -237,3 +233,8 @@ namespace eval punkapp {
} }
} }
package provide punkapp [namespace eval punkapp {
variable version
set version 0.1.1
}]

2459
src/vfs/_vfscommon.vfs/modules/punkcheck-0.1.1.tm

File diff suppressed because it is too large Load Diff

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

@ -259,7 +259,6 @@ namespace eval punkcheck::cli {
} }
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval punkcheck::cli::lib { namespace eval punkcheck::cli::lib {
namespace path ::punk::mix::util ;#askuser, do_in_path, foreach-file etc namespace path ::punk::mix::util ;#askuser, do_in_path, foreach-file etc
@ -307,7 +306,6 @@ namespace eval punkcheck::cli::lib {
} }
return {} return {}
} }
} }

897
src/vfs/_vfscommon.vfs/modules/shellrun-0.1.2.tm

@ -0,0 +1,897 @@
# vim: set ft=tcl
#
#purpose: handle the run commands that call shellfilter::run
#e.g run,runout,runerr,runx
package require shellfilter
package require punk::ansi
#NOTE: the run,runout,runerr,runx commands only produce an error if the command didn't run.
# - If it did run, but there was a non-zero exitcode it is up to the application to check that.
#This is deliberate, but means 'catch' doesn't catch errors within the command itself - the exitcode has to be checked.
#The user can always use exec for different process error semantics (they don't get exitcode with exec)
namespace eval shellrun {
variable PUNKARGS
variable runout
variable runerr
#do we need these?
#variable punkout
#variable punkerr
#some ugly coupling with punk/punk::config for now
#todo - something better
if {[info exists ::punk::config::configdata]} {
set conf_running [punk::config::configure running]
set syslog_stdout [dict get $conf_running syslog_stdout]
set syslog_stderr [dict get $conf_running syslog_stderr]
set logfile_stdout [dict get $conf_running logfile_stdout]
set logfile_stderr [dict get $conf_running logfile_stderr]
} else {
lassign [list "" "" "" ""] syslog_stdout syslog_stderr logfile_stdout logfile_stderr
}
if {"punkshout" ni [shellfilter::stack::items]} {
set outdevice [shellfilter::stack::new punkshout -settings [list -tag "punkshout" -buffering none -raw 1 -syslog $syslog_stdout -file $logfile_stdout]]
set out [dict get $outdevice localchan]
} else {
set out [dict get [shellfilter::stack::item punkshout] device localchan]
}
if {"punksherr" ni [shellfilter::stack::items]} {
set errdevice [shellfilter::stack::new punksherr -settings [list -tag "punksherr" -buffering none -raw 1 -syslog $syslog_stderr -file $logfile_stderr]]
set err [dict get $errdevice localchan]
} else {
set err [dict get [shellfilter::stack::item punksherr] device localchan]
}
namespace import ::punk::ansi::a+
namespace import ::punk::ansi::a
#repltelemetry - additional/alternative display info used in a repl context i.e info directed towards the screen
#todo - package up in repltelemetry module and rewrite proc based on whether the module was found/loaded.
#somewhat strong coupling to punk - but let's try to behave decently if it's not loaded
#The last_run_display is actually intended for the repl - but is resident in the punk namespace with a view to the possibility of a different repl being in use.
proc set_last_run_display {chunklist} {
#chunklist as understood by the
if {![info exists ::punk::repltelemetry_emmitters]} {
namespace eval ::punk {
variable repltelemetry_emmitters
set repltelemetry_emmitters "shellrun"
}
} else {
if {"shellrun" ni $::punk::repltelemetry_emmitters} {
lappend punk::repltelemetry_emmitters "shellrun"
}
}
#most basic of validity tests here.. just that it is a list (can be empty). We don't want to duplicate or over-constrain the way repls/shells/terminals interpet the info
if {[catch {llength $chunklist} errMsg]} {
error "set_last_run_display expects a list. Value supplied doesn't appear to be a well formed tcl list. '$errMsg'"
}
#todo -
tsv::lappend repl runchunks-[tsv::get repl runid] {*}$chunklist
}
#maintenance: similar used in punk::ns & punk::winrun
#todo - take runopts + aliases as args
#longopts must be passed as a single item ie --timeout=100 not --timeout 100
proc get_run_opts {arglist} {
if {[catch {
set callerinfo [info level -1]
} errM]} {
set caller ""
} else {
set caller [lindex $callerinfo 0]
}
#we provide -nonewline even for 'run' even though run doesn't deliver stderr or stdout to the tcl return value
#This is for compatibility with other runX commands, and the difference is also visible when calling from repl.
set known_runopts [list "-echo" "-e" "-nonewline" "-n" "-tcl" "-debug"]
set known_longopts [list "--timeout"]
set known_longopts_msg ""
foreach lng $known_longopts {
append known_longopts_msg "${lng}=val "
}
set aliases [list "-e" "-echo" "-echo" "-echo" "-n" "-nonewline" "-nonewline" "-nonewline" "-tcl" "-tcl" "-debug" "-debug"] ;#include map to self
set runopts [list]
set runoptslong [list]
set cmdargs [list]
set idx_first_cmdarg [lsearch -not $arglist "-*"]
set allopts [lrange $arglist 0 $idx_first_cmdarg-1]
set cmdargs [lrange $arglist $idx_first_cmdarg end]
foreach o $allopts {
if {[string match --* $o]} {
lassign [split $o =] flagpart valpart
if {$valpart eq ""} {
error "$caller: longopt $o seems to be missing a value - must be of form --option=value"
}
if {$flagpart ni $known_longopts} {
error "$caller: Unknown runoption $o - known options $known_runopts $known_longopts_msg"
}
lappend runoptslong $flagpart $valpart
} else {
if {$o ni $known_runopts} {
error "$caller: Unknown runoption $o - known options $known_runopts $known_longopts_msg"
}
lappend runopts [dict get $aliases $o]
}
}
return [list runopts $runopts runoptslong $runoptslong cmdargs $cmdargs]
}
#todo - investigate cause of punk86 run hanging sometimes. An 'after 500' before exit in the called script fixes the issue. punk87 doesn't seem to be affected.
lappend PUNKARGS [list {
@id -id ::shellrun::run
@leaders -min 0 -max 0
@opts
-nonewline -type none
-tcl -type none -default 0
-debug -type none -default 0
--timeout= -type integer
@values -min 1 -max -1
cmdname -type string
cmdarg -type any -multiple 1 -optional 1
}]
proc run {args} {
#set_last_run_display [list]
#set splitargs [get_run_opts $args]
#set runopts [dict get $splitargs runopts]
#set runoptslong [dict get $splitargs runoptslong]
#set cmdargs [dict get $splitargs cmdargs]
set argd [punk::args::parse $args withid ::shellrun::run]
lassign [dict values $argd] leaders opts values received
if {[dict exists $received "-nonewline"]} {
set nonewline 1
} else {
set nonewline 0
}
#review nonewline does nothing here..
set idlist_stderr [list]
#we leave stdout without imposed ansi colouring - because the source may be colourised and because ansi-wrapping a stream at whatever boundaries it comes in at isn't a really nice thing to do.
#stderr might have source colouring - but it usually doesn't seem to, and the visual distiction of red stderr can be very handy for the run command.
#A further enhancement could be to detect well-known options such as --color and/or use a configuration for specific commands that have useful colourised stderr,
#but having an option to configure stderr to red is a compromise.
#Note that the other run commands, runout,runerr, runx don't emit in real-time - so for those commands there may be options to detect and/or post-process stdout and stderr.
#TODO - fix. This has no effect if/when the repl adds an ansiwrap transform
# what we probably want to do is 'aside' that transform for runxxx commands only.
#lappend idlist_stderr [shellfilter::stack::add stderr ansiwrap -settings {-colour {red bold}}]
set callopts [dict create]
if {[dict exists $received "-tcl"]} {
dict set callopts -tclscript 1
}
if {[dict exists $received "-debug"]} {
dict set callopts -debug 1
}
if {[dict exists $received --timeout]} {
dict set callopts -timeout [dict get $opts --timeout] ;#convert to single dash
}
set cmdname [dict get $values cmdname]
if {[dict exists $received cmdarg]} {
set cmdarglist [dict get $values cmdarg]
} else {
set cmdarglist {}
}
set cmdargs [concat $cmdname $cmdarglist]
#---------------------------------------------------------------------------------------------
set exitinfo [shellfilter::run $cmdargs {*}$callopts -teehandle punksh -inbuffering none -outbuffering none ]
#---------------------------------------------------------------------------------------------
foreach id $idlist_stderr {
shellfilter::stack::remove stderr $id
}
#puts stderr "shellrun::run exitinfo: $exitinfo"
flush stderr
flush stdout
if {[dict exists $exitinfo error]} {
error "[dict get $exitinfo error]\n$exitinfo"
}
return $exitinfo
}
lappend PUNKARGS [list {
@id -id ::shellrun::runconsole
@leaders -min 0 -max 0
@opts
@values -min 1 -max -1
cmdname -type string
cmdarg -type any -multiple 1 -optional 1
}]
#run in the way tcl unknown does - but without regard to auto_noexec
proc runconsole {args} {
set argd [punk::args::parse $args withid ::shellrun::runconsole]
lassign [dict values $argd] leaders opts values received
set cmdname [dict get $values cmdname]
if {[dict exists $received cmdarg]} {
set arglist [dict get $values cmdarg]
} else {
set arglist {}
}
set resolved_cmdname [auto_execok $cmdname]
if {$resolved_cmdname eq ""} {
error "Cannot find path for executable '$cmdname'"
}
set repl_runid [punk::get_repl_runid]
#set ::punk::last_run_display [list]
set redir ">&@stdout <@stdin"
uplevel 1 [list ::catch [concat exec $redir $resolved_cmdname $arglist] ::tcl::UnknownResult ::tcl::UnknownOptions]
#we can't detect stdout/stderr output from the exec
#for now emit an extra \n on stderr
#todo - there is probably no way around this but to somehow exec in the context of a completely separate console
#This is probably a tricky problem - especially to do cross-platform
#
# - use [dict get $::tcl::UnknownOptions -code] (0|1) exit
if {[dict get $::tcl::UnknownOptions -code] == 0} {
set c green
set m "ok"
} else {
set c yellow
set m "errorCode $::errorCode"
}
set chunklist [list]
lappend chunklist [list "info" "[a $c]$m[a] " ]
if {$repl_runid != 0} {
tsv::lappend repl runchunks-$repl_runid {*}$chunklist
}
dict incr ::tcl::UnknownOptions -level
return -options $::tcl::UnknownOptions $::tcl::UnknownResult
}
lappend PUNKARGS [list {
@id -id ::shellrun::runout
@leaders -min 0 -max 0
@opts
-echo -type none
-nonewline -type none
-tcl -type none -default 0
-debug -type none -default 0
--timeout= -type integer
@values -min 1 -max -1
cmdname -type string
cmdarg -type any -multiple 1 -optional 1
}]
proc runout {args} {
set argd [punk::args::parse $args withid ::shellrun::runout]
lassign [dict values $argd] leaders opts values received
if {[dict exists $received "-nonewline"]} {
set nonewline 1
} else {
set nonewline 0
}
#set_last_run_display [list]
variable runout
variable runerr
set runout ""
set runerr ""
set RST [a]
#set splitargs [get_run_opts $args]
#set runopts [dict get $splitargs runopts]
#set cmdargs [dict get $splitargs cmdargs]
#puts stdout "RUNOUT cmdargs: $cmdargs"
#todo add -data boolean and -data lastwrite to -settings with default being -data all
# because sometimes we're only interested in last char (e.g to detect something was output)
#set outvar_stackid [shellfilter::stack::add commandout tee_to_var -action float -settings {-varname ::runout}]
#
#when not echoing - use float-locked so that the repl's stack is bypassed
if {[dict exists $received "-echo"]} {
set stdout_stackid [shellfilter::stack::add stdout tee_to_var -action float-locked -settings {-varname ::shellrun::runout}]
set stderr_stackid [shellfilter::stack::add stderr tee_to_var -action float-locked -settings {-varname ::shellrun::runerr}]
#set stderr_stackid [shellfilter::stack::add stderr tee_to_var -action sink-locked -settings {-varname ::shellrun::runerr}]
} else {
set stdout_stackid [shellfilter::stack::add stdout var -action float-locked -settings {-varname ::shellrun::runout}]
set stderr_stackid [shellfilter::stack::add stderr var -action float-locked -settings {-varname ::shellrun::runerr}]
}
set callopts [dict create]
if {[dict exists $received "-tcl"]} {
dict set callopts -tclscript 1
}
if {[dict exists $received "-debug"]} {
dict set callopts -debug 1
}
if {[dict exists $received --timeout]} {
dict set callopts -timeout [dict get $opts --timeout] ;#convert to single dash
}
set cmdname [dict get $values cmdname]
if {[dict exists $received cmdarg]} {
set cmdarglist [dict get $values cmdarg]
} else {
set cmdarglist {}
}
set cmdargs [concat $cmdname $cmdarglist]
#shellfilter::run [lrange $args 1 end] -teehandle punksh -outchan stdout -inbuffering none -outbuffering none -stdinhandler ::repl::repl_handler
set exitinfo [shellfilter::run $cmdargs {*}$callopts -teehandle punksh -inbuffering none -outbuffering none ]
flush stderr
flush stdout
shellfilter::stack::remove stdout $stdout_stackid
shellfilter::stack::remove stderr $stderr_stackid
#shellfilter::stack::remove commandout $outvar_stackid
if {[dict exists $exitinfo error]} {
if {[dict exists $received "-tcl"]} {
} else {
#we must raise an error.
#todo - check errorInfo makes sense.. return -code? tailcall?
#
set msg ""
append msg [dict get $exitinfo error]
append msg "\n(add -tcl option to run as a tcl command/script instead of an external command)"
error $msg
}
}
set chunklist [list]
#exitcode not part of return value for runout - colourcode appropriately
set n $RST
set c ""
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]} {
# -tcl (with 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]"]
#lappend chunklist [list "info" "errorInfo [list [dict get $exitinfo errorInfo]]"]
lappend chunklist [list "info" errorInfo]
lappend chunklist [list "stderr" [dict get $exitinfo errorInfo]]
} else {
# -tcl (without error)
set c [a+ Green white bold]
#lappend chunklist [list "info" "$c$exitinfo$n"]
lappend chunklist [list "info" [punk::ansi::ansiwrap_raw $c \x1b\[m "" $exitinfo]]
}
set chunk "[a+ red bold]stderr$RST"
lappend chunklist [list "info" $chunk]
set chunk ""
if {[string length $::shellrun::runerr]} {
if {$nonewline} {
set e [string trimright $::shellrun::runerr \r\n]
} else {
set e $::shellrun::runerr
}
#append chunk "[a+ red normal]$e$RST\n"
append chunk "[a+ red normal]$e$RST"
}
lappend chunklist [list stderr $chunk]
lappend chunklist [list "info" "[a+ white bold]stdout$RST"]
set chunk ""
if {[string length $::shellrun::runout]} {
if {$nonewline} {
set o [string trimright $::shellrun::runout \r\n]
} else {
set o $::shellrun::runout
}
append chunk "$o"
}
lappend chunklist [list result $chunk]
#set_last_run_display $chunklist
tsv::lappend repl runchunks-[tsv::get repl runid] {*}$chunklist
if {$nonewline} {
return [string trimright $::shellrun::runout \r\n]
} else {
return $::shellrun::runout
}
}
lappend PUNKARGS [list {
@id -id ::shellrun::runerr
@leaders -min 0 -max 0
@opts
-echo -type none
-nonewline -type none
-tcl -type none -default 0
-debug -type none -default 0
--timeout= -type integer
@values -min 1 -max -1
cmdname -type string
cmdarg -type any -multiple 1 -optional 1
}]
proc runerr {args} {
set argd [punk::args::parse $args withid ::shellrun::runerr]
lassign [dict values $argd] leaders opts values received
if {[dict exists $received "-nonewline"]} {
set nonewline 1
} else {
set nonewline 0
}
#set_last_run_display [list]
variable runout
variable runerr
set runout ""
set runerr ""
#set splitargs [get_run_opts $args]
#set runopts [dict get $splitargs runopts]
#set cmdargs [dict get $splitargs cmdargs]
set callopts [dict create]
if {[dict exists $received "-tcl"]} {
dict set callopts -tclscript 1
}
if {[dict exists $received "-debug"]} {
dict set callopts -debug 1
}
if {[dict exists $received --timeout]} {
dict set callopts -timeout [dict get $opts --timeout] ;#convert to single dash
}
set cmdname [dict get $values cmdname]
if {[dict exists $received cmdarg]} {
set cmdarglist [dict get $values cmdarg]
} else {
set cmdarglist {}
}
set cmdargs [concat $cmdname $cmdarglist]
if {[dict exists $received "-tcl"]} {
append callopts " -tclscript 1"
}
if {[dict exists $received "-echo"]} {
set stderr_stackid [shellfilter::stack::add stderr tee_to_var -action float-locked -settings {-varname ::shellrun::runerr}]
set stdout_stackid [shellfilter::stack::add stdout tee_to_var -action float-locked -settings {-varname ::shellrun::runout}]
} else {
set stderr_stackid [shellfilter::stack::add stderr var -action float-locked -settings {-varname ::shellrun::runerr}]
set stdout_stackid [shellfilter::stack::add stdout var -action float-locked -settings {-varname ::shellrun::runout}]
}
set exitinfo [shellfilter::run $cmdargs {*}$callopts -teehandle punksh -inbuffering none -outbuffering none -stdinhandler ::repl::repl_handler]
shellfilter::stack::remove stderr $stderr_stackid
shellfilter::stack::remove stdout $stdout_stackid
flush stderr
flush stdout
#we raise an error because an error during calling is different to collecting stderr from a command, and the caller should be able to wrap in a catch
# to determine something other than just a nonzero exit code or output on stderr.
if {[dict exists $exitinfo error]} {
if {[dict exists $received "-tcl"]} {
} else {
#todo - check errorInfo makes sense.. return -code? tailcall?
error [dict get $exitinfo error]
}
}
set chunklist [list]
set n [a]
set c ""
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]} {
# -tcl (with error)
set c [a+ yellow bold]
lappend chunklist [list "info" "error [dict get $exitinfo error]"]
lappend chunklist [list "info" "errorCode [dict get $exitinfo errorCode]"]
lappend chunklist [list "info" "errorInfo [list [dict get $exitinfo errorInfo]]"]
} else {
# -tcl (without error)
set c [a+ Green white bold]
#lappend chunklist [list "info" "$c$exitinfo$n"]
lappend chunklist [list "info" [punk::ansi::ansiwrap_raw $c "\x1b\[m" "" $exitinfo]]
}
lappend chunklist [list "info" "[a+ white bold]stdout[a]"]
set chunk ""
if {[string length $::shellrun::runout]} {
if {$nonewline} {
set o [string trimright $::shellrun::runout \r\n]
} else {
set o $::shellrun::runout
}
append chunk "[a+ white normal]$o[a]\n" ;#this newline is the display output separator - always there whether data has trailing newline or not.
}
lappend chunklist [list stdout $chunk]
#set c_stderr [punk::config]
set chunk "[a+ red bold]stderr[a]"
lappend chunklist [list "info" $chunk]
set chunk ""
if {[string length $::shellrun::runerr]} {
if {$nonewline} {
set e [string trimright $::shellrun::runerr \r\n]
} else {
set e $::shellrun::runerr
}
append chunk "$e"
}
lappend chunklist [list resulterr $chunk]
#set_last_run_display $chunklist
tsv::lappend repl runchunks-[tsv::get repl runid] {*}$chunklist
if {$nonewline} {
return [string trimright $::shellrun::runerr \r\n]
}
return $::shellrun::runerr
}
proc runx {args} {
#set_last_run_display [list]
variable runout
variable runerr
set runout ""
set runerr ""
set splitargs [get_run_opts $args]
set runopts [dict get $splitargs runopts]
set cmdargs [dict get $splitargs cmdargs]
if {"-nonewline" in $runopts} {
set nonewline 1
} else {
set nonewline 0
}
#shellfilter::stack::remove stdout $::repl::id_outstack
if {"-echo" in $runopts} {
#float to ensure repl transform doesn't interfere with the output data
set stderr_stackid [shellfilter::stack::add stderr tee_to_var -action float -settings {-varname ::shellrun::runerr}]
set stdout_stackid [shellfilter::stack::add stdout tee_to_var -action float -settings {-varname ::shellrun::runout}]
} else {
#set stderr_stackid [shellfilter::stack::add stderr var -action sink-locked -settings {-varname ::shellrun::runerr}]
#set stdout_stackid [shellfilter::stack::add stdout var -action sink-locked -settings {-varname ::shellrun::runout}]
#float above the repl's tee_to_var to deliberately block it.
#a var transform is naturally a junction point because there is no flow-through..
# - but mark it with -junction 1 just to be explicit
set stderr_stackid [shellfilter::stack::add stderr var -action float-locked -junction 1 -settings {-varname ::shellrun::runerr}]
set stdout_stackid [shellfilter::stack::add stdout var -action float-locked -junction 1 -settings {-varname ::shellrun::runout}]
}
set callopts ""
if {"-tcl" in $runopts} {
append callopts " -tclscript 1"
}
#set exitinfo [shellfilter::run $cmdargs -teehandle punksh -inbuffering none -outbuffering none -stdinhandler ::repl::repl_handler]
set exitinfo [shellfilter::run $cmdargs {*}$callopts -teehandle punksh -inbuffering none -outbuffering none]
shellfilter::stack::remove stdout $stdout_stackid
shellfilter::stack::remove stderr $stderr_stackid
flush stderr
flush stdout
if {[dict exists $exitinfo error]} {
if {"-tcl" in $runopts} {
} else {
#todo - check errorInfo makes sense.. return -code? tailcall?
error [dict get $exitinfo error]
}
}
#set x [shellfilter::stack::add stdout var -action sink-locked -settings {-varname ::repl::runxoutput}]
set chunk ""
if {[string length $::shellrun::runout]} {
if {$nonewline} {
set o [string trimright $::shellrun::runout \r\n]
} else {
set o $::shellrun::runout
}
set chunk $o
}
set chunklist [list]
lappend chunklist [list "info" " "]
lappend chunklist [list "result" stdout] ;#key 'stdout' forms part of the resulting dictionary output
lappend chunklist [list "info" "[a+ white bold]stdout[a]"]
lappend chunklist [list result $chunk] ;#value corresponding to 'stdout' key in resulting dict
lappend chunklist [list "info" " "]
set chunk "[a+ red bold]stderr[a]"
lappend chunklist [list "result" $chunk]
lappend chunklist [list "info" stderr]
set chunk ""
if {[string length $::shellrun::runerr]} {
if {$nonewline} {
set e [string trimright $::shellrun::runerr \r\n]
} else {
set e $::shellrun::runerr
}
set chunk $e
}
#stderr is part of the result
lappend chunklist [list "resulterr" $chunk]
set n [a]
set c ""
if {[dict exists $exitinfo exitcode]} {
set code [dict get $exitinfo exitcode]
if {$code == 0} {
set c [a+ green]
} else {
set c [a+ yellow bold]
}
lappend chunklist [list "info" " "]
lappend chunklist [list "result" exitcode]
lappend chunklist [list "info" "exitcode $code"]
lappend chunklist [list "result" "$c$code$n"]
set exitdict [list exitcode $code]
} elseif {[dict exists $exitinfo result]} {
# presumably from a -tcl call
set val [dict get $exitinfo result]
lappend chunklist [list "info" " "]
lappend chunklist [list "result" result]
lappend chunklist [list "info" result]
lappend chunklist [list "result" $val]
set exitdict [list result $val]
} elseif {[dict exists $exitinfo error]} {
# -tcl call with error
#set exitdict [dict create]
lappend chunklist [list "info" " "]
lappend chunklist [list "result" error]
lappend chunklist [list "info" error]
lappend chunklist [list "result" [dict get $exitinfo error]]
lappend chunklist [list "info" " "]
lappend chunklist [list "result" errorCode]
lappend chunklist [list "info" errorCode]
lappend chunklist [list "result" [dict get $exitinfo errorCode]]
lappend chunklist [list "info" " "]
lappend chunklist [list "result" errorInfo]
lappend chunklist [list "info" errorInfo]
lappend chunklist [list "result" [dict get $exitinfo errorInfo]]
set exitdict $exitinfo
} else {
#review - if no exitcode or result. then what is it?
lappend chunklist [list "info" exitinfo]
set c [a+ yellow bold]
lappend chunklist [list result "$c$exitinfo$n"]
set exitdict [list exitinfo $exitinfo]
}
#set_last_run_display $chunklist
tsv::lappend repl runchunks-[tsv::get repl runid] {*}$chunklist
#set ::repl::result_print 0
#return [lindex [list [list stdout $::runout stderr $::runerr {*}$exitinfo] [shellfilter::stack::remove stdout $x][puts -nonewline stdout $pretty][set ::repl::output ""]] 0]
if {$nonewline} {
return [list {*}$exitdict stdout [string trimright $::shellrun::runout \r\n] stderr [string trimright $::shellrun::runerr \r\n]]
}
#always return exitinfo $code at beginning of dict (so that punk unknown can interpret the exit code as a unix-style bool if double evaluated)
return [list {*}$exitdict stdout $::shellrun::runout stderr $::shellrun::runerr]
}
#an experiment
#
#run as raw string instead of tcl-list - no variable subst etc
#
#dummy repl_runraw that repl will intercept
proc repl_runraw {args} {
error "runraw: only available in repl as direct call - not from script"
}
#we can only call runraw with a single (presumably braced) string if we want to use it from both repl and tcl scripts (why? todo with unbalanced quotes/braces?)
proc runraw {commandline} {
#runraw fails as intended - because we can't bypass exec/open interference quoting :/
#set_last_run_display [list]
variable runout
variable runerr
set runout ""
set runerr ""
#return [shellfilter::run [lrange $args 1 end] -teehandle punksh -inbuffering none -outbuffering none -stdinhandler ::repl::repl_handler]
puts stdout ">>runraw got: $commandline"
#run always echoes anyway.. as we aren't diverting stdout/stderr off for capturing
#for consistency with other runxxx commands - we'll just consume it. (review)
set reallyraw 1
if {$reallyraw} {
set wordparts [regexp -inline -all {\S+} $commandline]
set runwords $wordparts
} else {
#shell style args parsing not suitable for windows where we can't assume matched quotes etc.
package require string::token::shell
set parts [string token shell -indices -- $commandline]
puts stdout ">>shellparts: $parts"
set runwords [list]
foreach p $parts {
set ptype [lindex $p 0]
set pval [lindex $p 3]
if {$ptype eq "PLAIN"} {
lappend runwords [lindex $p 3]
} elseif {$ptype eq "D:QUOTED"} {
set v {"}
append v $pval
append v {"}
lappend runwords $v
} elseif {$ptype eq "S:QUOTED"} {
set v {'}
append v $pval
append v {'}
lappend runwords $v
}
}
}
puts stdout ">>runraw runwords: $runwords"
set runwords [lrange $runwords 1 end]
puts stdout ">>runraw runwords: $runwords"
#set args [lrange $args 1 end]
#set runwords [lrange $wordparts 1 end]
set known_runopts [list "-echo" "-e" "-terminal" "-t"]
set aliases [list "-e" "-echo" "-echo" "-echo" "-t" "-terminal" "-terminal" "-terminal"] ;#include map to self
set runopts [list]
set cmdwords [list]
set idx_first_cmdarg [lsearch -not $runwords "-*"]
set runopts [lrange $runwords 0 $idx_first_cmdarg-1]
set cmdwords [lrange $runwords $idx_first_cmdarg end]
foreach o $runopts {
if {$o ni $known_runopts} {
error "runraw: Unknown runoption $o"
}
}
set runopts [lmap o $runopts {dict get $aliases $o}]
set cmd_as_string [join $cmdwords " "]
puts stdout ">>cmd_as_string: $cmd_as_string"
if {"-terminal" in $runopts} {
#fake terminal using 'script' command.
#not ideal: smushes stdout & stderr together amongst other problems
set tcmd [shellfilter::get_scriptrun_from_cmdlist_dquote_if_not $cmdwords]
puts stdout ">>tcmd: $tcmd"
set exitinfo [shellfilter::run $tcmd -teehandle punksh -inbuffering line -outbuffering none ]
set exitinfo "exitcode not-implemented"
} else {
set exitinfo [shellfilter::run $cmdwords -teehandle punksh -inbuffering line -outbuffering none ]
}
if {[dict exists $exitinfo error]} {
#todo - check errorInfo makes sense.. return -code? tailcall?
error [dict get $exitinfo error]
}
set code [dict get $exitinfo exitcode]
if {$code == 0} {
set c [a+ green]
} else {
set c [a+ white bold]
}
puts stderr $c
return $exitinfo
}
proc sh_run {args} {
set splitargs [get_run_opts $args]
set runopts [dict get $splitargs runopts]
set cmdargs [dict get $splitargs cmdargs]
#e.g sh -c "ls -l *"
#we pass cmdargs to sh -c as a list, not individually
tailcall shellrun::run {*}$runopts sh -c $cmdargs
}
proc sh_runout {args} {
set splitargs [get_run_opts $args]
set runopts [dict get $splitargs runopts]
set cmdargs [dict get $splitargs cmdargs]
tailcall shellrun::runout {*}$runopts sh -c $cmdargs
}
proc sh_runerr {args} {
set splitargs [get_run_opts $args]
set runopts [dict get $splitargs runopts]
set cmdargs [dict get $splitargs cmdargs]
tailcall shellrun::runerr {*}$runopts sh -c $cmdargs
}
proc sh_runx {args} {
set splitargs [get_run_opts $args]
set runopts [dict get $splitargs runopts]
set cmdargs [dict get $splitargs cmdargs]
tailcall shellrun::runx {*}$runopts sh -c $cmdargs
}
}
namespace eval shellrun {
interp alias {} run {} shellrun::run
interp alias {} sh_run {} shellrun::sh_run
interp alias {} runout {} shellrun::runout
interp alias {} sh_runout {} shellrun::sh_runout
interp alias {} runerr {} shellrun::runerr
interp alias {} sh_runerr {} shellrun::sh_runerr
interp alias {} runx {} shellrun::runx
interp alias {} sh_runx {} shellrun::sh_runx
interp alias {} runc {} shellrun::runconsole
interp alias {} runraw {} shellrun::runraw
#the shortened versions deliberately don't get pretty output from the repl
interp alias {} r {} shellrun::run
interp alias {} ro {} shellrun::runout
interp alias {} re {} shellrun::runerr
interp alias {} rx {} shellrun::runx
}
namespace eval shellrun {
proc test_cffi {} {
package require test_cffi
cffi::Wrapper create ::shellrun::kernel32 [file join $env(windir) system32 Kernel32.dll]
::shellrun::kernel32 stdcall CreateProcessA
#todo - stuff.
return ::shellrun::kernel32
}
}
namespace eval ::punk::args::register {
#use fully qualified so 8.6 doesn't find existing var in global namespace
lappend ::punk::args::register::NAMESPACES ::shellrun
}
package provide shellrun [namespace eval shellrun {
variable version
set version 0.1.2
}]

BIN
src/vfs/_vfscommon.vfs/modules/test/pattern-1.2.8.tm

Binary file not shown.

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

@ -6475,6 +6475,58 @@ tcl::namespace::eval textblock {
} }
} }
variable framedef_cache [tcl::dict::create] variable framedef_cache [tcl::dict::create]
namespace eval argdoc {
set DYN_FRAME_TYPES {${[set ::textblock::frametypes]}}
punk::args::define {
@dynamic
@id -id ::textblock::framedef
@cmd -name textblock::framedef\
-summary "Return frame graphical elements as a dictionary."\
-help "Return a dict of the elements that make up a frame border.
May return a subset of available elements based on memberglob values."
@leaders -min 0 -max 0
@opts
-joins -default "" -type list\
-help "List of join directions, any of: up down left right
or those combined with another frametype e.g left-heavy down-light."
-boxonly -default 0 -type boolean\
-help "-boxonly true restricts results to the corner,vertical and horizontal box elements
It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj."
@values -min 1 -max -1
frametype -choices "${$DYN_FRAME_TYPES}" -choiceprefix 0 -choicerestricted 0 -type dict\
-help "name from the predefined frametypes or an adhoc dictionary."
memberglob -type globstring -optional 1 -multiple 1 -choiceprefix 0 -choicerestricted 0 -choices {
corner noncorner top bottom vertical horizontal left right
hl hlt hlb vsl vll vlr tlc trc blc brc hltj hlbj vllj vlrj
}\
-help "restrict to keys matching memberglob."
}
#set spec [string map [list <ftlist> $::textblock::frametypes] {
# @id -id ::textblock::framedef
# @cmd -name textblock::framedef\
# -summary "Return frame graphical elements as a dictionary."\
# -help "Return a dict of the elements that make up a frame border.
# May return a subset of available elements based on memberglob values."
# @leaders -min 0 -max 0
# @opts
# -joins -default "" -type list\
# -help "List of join directions, any of: up down left right
# or those combined with another frametype e.g left-heavy down-light."
# -boxonly -default 0 -type boolean\
# -help "-boxonly true restricts results to the corner,vertical and horizontal box elements
# It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj."
# @values -min 1 -max -1
# frametype -choices "<ftlist>" -choiceprefix 0 -choicerestricted 0 -type dict\
# -help "name from the predefined frametypes or an adhoc dictionary."
# memberglob -type globstring -optional 1 -multiple 1 -choiceprefix 0 -choicerestricted 0 -choices {
# corner noncorner top bottom vertical horizontal left right
# hl hlt hlb vsl vll vlr tlc trc blc brc hltj hlbj vllj vlrj
# }\
# -help "restrict to keys matching memberglob."
#}]
}
proc framedef {args} { proc framedef {args} {
#unicode box drawing only provides enough characters for seamless joining of unicode boxes light and heavy. #unicode box drawing only provides enough characters for seamless joining of unicode boxes light and heavy.
#e.g with characters such as \u2539 Box Drawings Right Light and Left Up Heavy. #e.g with characters such as \u2539 Box Drawings Right Light and Left Up Heavy.
@ -6520,6 +6572,9 @@ tcl::namespace::eval textblock {
} }
} }
set f [lindex $values 0] set f [lindex $values 0]
#expect either a known frametype or a dict with known keys
set rawglobs [lrange $values 1 end] set rawglobs [lrange $values 1 end]
if {![llength $rawglobs] || "all" in $rawglobs || "*" in $rawglobs} { if {![llength $rawglobs] || "all" in $rawglobs || "*" in $rawglobs} {
set globs * set globs *
@ -6570,32 +6625,7 @@ tcl::namespace::eval textblock {
} }
if {$bad_option || [llength $values] == 0} { if {$bad_option || [llength $values] == 0} {
#no framedef supplied, or unrecognised opt seen #no framedef supplied, or unrecognised opt seen
set spec [string map [list <ftlist> $::textblock::frametypes] { punk::args::parse $args withid ::textblock::framedef
@id -id ::textblock::framedef
@cmd -name textblock::framedef\
-summary "Return frame graphical elements as a dictionary."\
-help "Return a dict of the elements that make up a frame border.
May return a subset of available elements based on memberglob values."
@leaders -min 0 -max 0
@opts
-joins -default "" -type list\
-help "List of join directions, any of: up down left right
or those combined with another frametype e.g left-heavy down-light."
-boxonly -default 0 -type boolean\
-help "-boxonly true restricts results to the corner,vertical and horizontal box elements
It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj."
@values -min 1 -max -1
frametype -choices "<ftlist>" -choiceprefix 0 -choicerestricted 0 -type dict\
-help "name from the predefined frametypes or an adhoc dictionary."
memberglob -type globstring -optional 1 -multiple 1 -choiceprefix 0 -choicerestricted 0 -choices {
corner noncorner top bottom vertical horizontal left right
hl hlt hlb vsl vll vlr tlc trc blc brc hltj hlbj vllj vlrj
}\
-help "restrict to keys matching memberglob."
}]
#append spec \n "frametype -help \"A predefined \""
punk::args::parse $args withdef $spec
return return
} }
@ -7837,16 +7867,23 @@ tcl::namespace::eval textblock {
set blc \U1fb7c ;#legacy block set blc \U1fb7c ;#legacy block
set brc \U1fb7f ;#legacy block set brc \U1fb7f ;#legacy block
if {(![interp issafe])} {
if {![catch {punk::console::check::has_bug_legacysymbolwidth} symbug] && $symbug} { #------------------------------------------------------------------------------------------------------
#rather than totally fail on some mixed layout that happens to use block2 - just degrade it - but prevent alignment problems #REVIEW - framedef may be called in a context where we don't have a console that can respond to ansi queries.
set sp \u00a0 ;#non breaking space (plain space may act transparent in some use cases) #We should either check has_bug_legacysymbolwidth at initial console detection and set a global var,
set tlc $sp #or find some other way to detect if we are in a terminal that has this problem.
set trc $sp
set blc $sp #if {(![interp issafe])} {
set brc $sp # if {![catch {punk::console::check::has_bug_legacysymbolwidth} symbug] && $symbug} {
} # #rather than totally fail on some mixed layout that happens to use block2 - just degrade it - but prevent alignment problems
} # set sp \u00a0 ;#non breaking space (plain space may act transparent in some use cases)
# set tlc $sp
# set trc $sp
# set blc $sp
# set brc $sp
# }
#}
#------------------------------------------------------------------------------------------------------
#horizontal and vertical bar joins #horizontal and vertical bar joins
set hltj $hlt set hltj $hlt
@ -7909,22 +7946,30 @@ tcl::namespace::eval textblock {
set vlrj $vlr set vlrj $vlr
} }
default { default {
if {[llength $f] % 2 != 0} {
#todo - retrieve usage from punk::args
#error "textblock::frametype frametype '$f' is not one of the predefined frametypes: $::textblock::frametypes and does not appear to be a dictionary for a custom frametype"
punk::args::parse $args withid ::textblock::framedef
return
}
#set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "] ;#only default the general types - these form defaults for more specific types if they're missing #set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "] ;#only default the general types - these form defaults for more specific types if they're missing
set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "] set default_custom [tcl::dict::create hl " " vl " " tlc " " trc " " blc " " brc " "]
if {"all" in [dict keys $f]} { if {"all" in [dict keys $f]} {
set A [dict get $f all] set A [dict get $f all]
set default_custom [tcl::dict::create hl $A vl $A tlc $A trc $A blc $A brc $A] set default_custom [tcl::dict::create hl $A vl $A tlc $A trc $A blc $A brc $A]
} }
if {[llength $f] % 2} { ####
#todo - retrieve usage from punk::args
error "textblock::frametype frametype '$f' is not one of the predefined frametypes: $::textblock::frametypes and does not appear to be a dictionary for a custom frametype"
}
#unknown order of keys specified by user - validate before creating vars as we need more general elements to be available as defaults #unknown order of keys specified by user - validate before creating vars as we need more general elements to be available as defaults
dict for {k v} $f { dict for {k v} $f {
switch -- $k { switch -- $k {
all - hl - vl - tlc - trc - blc - brc - hlt - hlb - vll - vlr - hltj - hlbj - vllj - vlrj {} all - hl - vl - tlc - trc - blc - brc - hlt - hlb - vll - vlr - hltj - hlbj - vllj - vlrj {}
default { default {
error "textblock::frametype '$f' has unknown element '$k'" #error "textblock::frametype '$f' has unknown element '$k'"
set errmsg [punk::args::usage -scheme error ::textblock::framedef]
append errmsg "\ntextblock::frametype frametype '$f' has unknown element '$k'"
error $errmsg
return
} }
} }
} }

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

Binary file not shown.

17
src/vfs/_vfscommon.vfs/modules/zzzload-0.1.0.tm

@ -20,6 +20,7 @@
package require Thread package require Thread
#EXPERIMENTAL.
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval zzzload { namespace eval zzzload {
@ -63,6 +64,8 @@ namespace eval zzzload {
} }
if {$loader_tid eq ""} { if {$loader_tid eq ""} {
set loader_tid [thread::create -joinable -preserved] set loader_tid [thread::create -joinable -preserved]
#todo - set tcl::tm::list and ::auto_path in the loader thread to match the main thread.
#(startup process may have modified these paths)
} }
if {![tsv::exists zzzload_pkg $pkgname]} { if {![tsv::exists zzzload_pkg $pkgname]} {
#puts stderr "zzzload pkg_require $pkgname" #puts stderr "zzzload pkg_require $pkgname"
@ -85,7 +88,7 @@ namespace eval zzzload {
} }
} }
proc pkg_wait {pkgname} { proc pkg_wait {pkgname} {
if {[set ver [package provide twapi]] ne ""} { if {[set ver [package provide $pkgname]] ne ""} {
return $ver return $ver
} }
@ -116,18 +119,6 @@ namespace eval zzzload {
} }
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Ready ## Ready
package provide zzzload [namespace eval zzzload { package provide zzzload [namespace eval zzzload {

Loading…
Cancel
Save