Browse Source

update bootsupport and vfs

master
Julian Noble 3 months ago
parent
commit
39ce3b7f5b
  1. 23
      src/bootsupport/modules/punk/args-0.2.tm
  2. 29
      src/bootsupport/modules/punk/docgen-0.1.0.tm
  3. 2
      src/bootsupport/modules/punk/libunknown-0.1.tm
  4. 34
      src/bootsupport/modules/punk/mix/cli-0.3.1.tm
  5. 56
      src/bootsupport/modules/punk/mix/commandset/loadedlib-0.1.0.tm
  6. 33
      src/bootsupport/modules/punk/mix/commandset/repo-0.1.0.tm
  7. 2
      src/bootsupport/modules/punk/mix/commandset/scriptwrap-0.1.0.tm
  8. 37
      src/bootsupport/modules/punk/path-0.1.0.tm
  9. 20
      src/bootsupport/modules/punk/repl-0.1.2.tm
  10. 72
      src/bootsupport/modules/shellfilter-0.2.tm
  11. 1
      src/bootsupport/modules/textblock-0.1.3.tm
  12. 13
      src/bootsupport/modules/tomlish-1.1.6.tm
  13. 23
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/args-0.2.tm
  14. 29
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/docgen-0.1.0.tm
  15. 2
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/libunknown-0.1.tm
  16. 34
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/cli-0.3.1.tm
  17. 56
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/commandset/loadedlib-0.1.0.tm
  18. 33
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/commandset/repo-0.1.0.tm
  19. 2
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/commandset/scriptwrap-0.1.0.tm
  20. 37
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/path-0.1.0.tm
  21. 20
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/repl-0.1.2.tm
  22. 72
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/shellfilter-0.2.tm
  23. 1
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/textblock-0.1.3.tm
  24. 13
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/tomlish-1.1.6.tm
  25. 23
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/args-0.2.tm
  26. 29
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/docgen-0.1.0.tm
  27. 2
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/libunknown-0.1.tm
  28. 34
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/cli-0.3.1.tm
  29. 56
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/commandset/loadedlib-0.1.0.tm
  30. 33
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/commandset/repo-0.1.0.tm
  31. 2
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/commandset/scriptwrap-0.1.0.tm
  32. 37
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/path-0.1.0.tm
  33. 20
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/repl-0.1.2.tm
  34. 72
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/shellfilter-0.2.tm
  35. 1
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/textblock-0.1.3.tm
  36. 13
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/tomlish-1.1.6.tm
  37. 21
      src/vfs/_vfscommon.vfs/modules/picalc-0.1.0.tm
  38. 39
      src/vfs/_vfscommon.vfs/modules/poshinfo-0.1.0.tm
  39. 21
      src/vfs/_vfscommon.vfs/modules/punk/args-0.2.tm
  40. 56
      src/vfs/_vfscommon.vfs/modules/punk/mix/commandset/loadedlib-0.1.0.tm
  41. 37
      src/vfs/_vfscommon.vfs/modules/punk/path-0.1.0.tm
  42. 9
      src/vfs/_vfscommon.vfs/modules/shellfilter-0.2.tm

23
src/bootsupport/modules/punk/args-0.2.tm

@ -222,7 +222,7 @@ package require Tcl 8.6-
tcl::namespace::eval punk::args::register {
#*** !doctools
#[subsection {Namespace punk::args}]
#[subsection {Namespace punk::args::register}]
#[para] cooperative namespace punk::args::register
#[para] punk::args aware packages may add their own namespace to the public list variable NAMESPACES before or after punk::args is loaded
#[para] The punk::args package will then test for a public list variable <namepace>::PUNKARGS containing argument definitions when it needs to.
@ -2606,11 +2606,11 @@ tcl::namespace::eval punk::args {
@values {set defaults_key VALSPEC_DEFAULTS}
}
if {[dict exists $opt_override $type]} {
append result \n "$type [dict merge [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS] [dict get $opt_override $type]]"
dict set resultdict $type [dict merge [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS] [dict get $opt_override $type]]
append result \n "$type [dict merge [dict get $specdict FORMS $formname $defaults_key] [dict get $opt_override $type]]"
dict set resultdict $type [dict merge [dict get $specdict FORMS $formname $defaults_key] [dict get $opt_override $type]]
} else {
append result \n "$type [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS]"
dict set resultdict $type [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS]
append result \n "$type [dict get $specdict FORMS $formname $defaults_key]"
dict set resultdict $type [dict get $specdict FORMS $formname $defaults_key]
}
}
}
@ -2856,6 +2856,19 @@ tcl::namespace::eval punk::args {
return $result
}
lappend PUNKARGS [list {
@id -id ::punk::args::update_definitions
@cmd -name punk::args::update_definitions\
-summary\
""\
-help\
""
@values -min 1
id
arglist -type list -help\
"list containing arguments to be parsed as per the
argument specification identified by the supplied id."
}]
#scanned_packages (list)
#namespace_docpackages (dict)
proc update_definitions {{nslist *}} {

29
src/bootsupport/modules/punk/docgen-0.1.0.tm

@ -40,15 +40,30 @@ namespace eval punk::docgen {
set data [string map [list \r\n \n] $data]
set in_doctools 0
set doctools ""
#foreach ln [split $data \n] {
# set ln [string trim $ln]
# if {$in_doctools && [string index $ln 0] != "#"} {
# set in_doctools 0
# } elseif {[string range $ln 0 1] == "#*"} {
# #todo - process doctools ordering hints in tail of line
# set in_doctools 1
# } elseif {$in_doctools} {
# append doctools [string range $ln 1 end] \n
# }
#}
foreach ln [split $data \n] {
set ln [string trim $ln]
if {$in_doctools && [string index $ln 0] != "#"} {
set in_doctools 0
} elseif {[string range $ln 0 1] == "#*"} {
#todo - process doctools ordering hints in tail of line
set in_doctools 1
} elseif {$in_doctools} {
append doctools [string range $ln 1 end] \n
if {$in_doctools} {
if {[string index $ln 0] != "#"} {
set in_doctools 0
} else {
append doctools [string range $ln 1 end] \n
}
} else {
if {[string range $ln 0 1] == "#*" && [string first "!doctools" $ln] >=2} {
#todo - process doctools ordering hints in tail of line
set in_doctools 1
}
}
}
return $doctools

2
src/bootsupport/modules/punk/libunknown-0.1.tm

@ -17,7 +17,7 @@
# doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[manpage_begin shellspy_module_punk::libunknown 0.1]
#[manpage_begin shellspy_module_punk::libunknown 0 0.1]
#[copyright "2025"]
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}]
#[moddesc {-}] [comment {-- Description at end of page heading --}]

34
src/bootsupport/modules/punk/mix/cli-0.3.1.tm

@ -1083,20 +1083,28 @@ namespace eval punk::mix::cli {
switch -- $calltype {
lib {}
shell {
set kettleappfile [file dirname [info nameofexecutable]]/kettle
set kettlebatfile [file dirname [info nameofexecutable]]/kettle.bat
if {(![file exists $kettleappfile]) && (![file exists $kettlebatfile])} {
error "deck kettle_call unable to find installed kettle application file '$kettleappfile' (or '$kettlebatfile' if on windows)"
}
if {[file exists $kettleappfile]} {
set kettlescript $kettleappfile
}
if {$::tcl_platform(platform) eq "windows"} {
if {[file exists $kettlebatfile]} {
set kettlescript $kettlebatfile
}
#on windows - could be kettle.bat or kettle.cmd - use auto_execok to find, whatever the platform.
#for now, restrict to version sitting next to exe - REVIEW
set exedir [file dirname [info nameofexecutable]]
set kettlescript [auto_execok $exedir/kettle]
if {$kettlescript eq ""} {
error "kettle_call unable to find installed kettle application file in '$exedir'"
}
#set kettleappfile [file dirname [info nameofexecutable]]/kettle
#set kettlebatfile [file dirname [info nameofexecutable]]/kettle.bat
#if {(![file exists $kettleappfile]) && (![file exists $kettlebatfile])} {
# error "deck kettle_call unable to find installed kettle application file '$kettleappfile' (or '$kettlebatfile' if on windows)"
#}
#if {[file exists $kettleappfile]} {
# set kettlescript $kettleappfile
#}
#if {$::tcl_platform(platform) eq "windows"} {
# if {[file exists $kettlebatfile]} {
# set kettlescript $kettlebatfile
# }
#}
}
default {
error "deck kettle_call 1st argument must be one of: 'lib' for direct use of kettle module or 'shell' to call as separate process"

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

@ -35,23 +35,39 @@ namespace eval punk::mix::commandset::loadedlib {
-highlight -type boolean -default 1 -help\
"Highlight which version is present with ansi underline and colour"
-refresh -default 0 -type boolean -help "Re-scan the tm and library folders"
searchstrings -default * -multiple 1 -help\
searchstring -default * -multiple 1 -help\
"Names to search for, may contain glob chars (* ?) e.g *lib*
If no glob chars are explicitly specified, the searchstring will be wrapped with star globs.
eg name -> *name*
To search for an exact name prefix it with =
e.g =name -> name
"
If no glob chars are explicitly specified, the searchstring will be wrapped with star globs.
eg name -> *name*
To search for an exact name prefix it with =
e.g =name -> name
If search is not prefixed with '=' the search is case insensitive."
}
proc search {args} {
set argd [punk::args::get_by_id ::punk::mix::commandset::loadedlib::search $args]
set searchstrings [dict get $argd values searchstrings]
set searchstrings [dict get $argd values searchstring]
set opts [dict get $argd opts]
set opt_return [dict get $opts -return]
set opt_highlight [dict get $opts -highlight]
set opt_refresh [dict get $opts -refresh]
if {$opt_refresh} {
catch {package require frobznodule666} ;#ensure pkg system has loaded/searched for everything REVIEW - this doesn't result in full scans
foreach tm_path [tcl::tm::list] {
set paths_below [punk::path::subfolders -recursive $tm_path]
foreach folder $paths_below {
set tail [file tail $folder]
if {[string match #modpod-* $tail] || [string match #tarjar-* $tail]} {
continue
}
if {[string match */_build/* $folder]} {continue}
set relpath [string tolower [punk::path::relative $tm_path $folder]]
set modpath [string map {/ ::} $relpath]
catch {package require ${modpath}::flobrudder99}
}
}
}
#REVIEW - this doesn't result in full scans
catch {package require frobznodule666} ;#ensure pkg system has loaded/searched for everything
set packages [package names]
set matches [list]
@ -122,9 +138,25 @@ namespace eval punk::mix::commandset::loadedlib {
}
}
}
proc loaded.search {searchstring} {
set search_result [search $searchstring]
set all_libs [split $search_result \n]
punk::args::define {
@id -id ::punk::mix::commandset::loadedlib::loaded.search
@cmd -name "punk::mix::commandset::loadedlib loaded.search"\
-summary\
"Search loaded libraries."\
-help "search all Tcl libraries currently loaded in your local interpreter.
ie those that have been loaded directly or indirectly by 'package require'."
}\
@values\
[punk::args::resolved_def -types values ::punk::mix::commandset::loadedlib::search searchstring]
proc loaded.search {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::loadedlib::loaded.search]
lassign [dict values $argd] leaders opts values
set searchstrings [dict get $values searchstring]
set all_libs [search -return list -highlight 0 {*}$searchstrings]
set col1items [list]
set col2items [list]
set col3items [list]

33
src/bootsupport/modules/punk/mix/commandset/repo-0.1.0.tm

@ -41,11 +41,27 @@ namespace eval punk::mix::commandset::repo {
return $result
}
lappend PUNKARGS [list {
@id -id ::punk::mix::commandset::repo::fossilize
@cmd -name punk::mix::commandset::repo::fossilize
-summary\
"Initialise and check in a project to fossil (unimplemented)."\
-help\
"(unimplemented)"
}]
proc fossilize { args} {
#check if project already managed by fossil.. initialise and check in if not.
puts stderr "unimplemented"
}
lappend PUNKARGS [list {
@id -id ::punk::mix::commandset::repo::unfossilize
@cmd -name punk::mix::commandset::repo::unfossilize
-summary\
"Remove/archive .fossil (unimplemented)."\
-help\
"(unimplemented)"
}]
proc unfossilize {projectname args} {
#remove/archive .fossil
puts stderr "unimplemented"
@ -76,14 +92,27 @@ namespace eval punk::mix::commandset::repo {
#punk::args
lappend PUNKARGS [list {
@id -id ::punk::mix::commandset::repo::fossil-move-repository
@cmd -name punk::mix::commandset::repo::fossil-move-repository -help\
@cmd -name punk::mix::commandset::repo::fossil-move-repository
-summary\
"Move a fossil repository database file."\
-help\
"Move the fossil repository file (usually named with .fossil extension).
This is an interactive function which will prompt for answers on stdin
before proceeding.
The move can be done even if there are open checkouts and will maintain
the link between checkout databases and the repository file."
the link between checkout databases and the repository file.
The call can be made from within a folder containing fossil databases,
or from within one of the checkouts of the fossil database that is to
be moved.
"
#todo?
#@values -min 0 -max 1
#path
}]
proc fossil-move-repository {{path ""}} {
#path unused for now - todo - allow calling with a specific target rather than relying on cwd?
set searchbase [pwd]
set projectinfo [punk::repo::find_repos $searchbase]
set projectbase [dict get $projectinfo closest]

2
src/bootsupport/modules/punk/mix/commandset/scriptwrap-0.1.0.tm

@ -77,7 +77,7 @@ namespace eval punk::mix::commandset::scriptwrap {
#[para] Core API functions for punk::mix::commandset::scriptwrap
#[list_begin definitions]
namespace export *
namespace export {[a-z]*}
namespace eval fileline {
namespace import ::punk::fileline::lib::*

37
src/bootsupport/modules/punk/path-0.1.0.tm

@ -99,7 +99,7 @@ package require punk::args
# Base namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval punk::path {
namespace export *
namespace export {[a-z]*}
#variable xyz
#*** !doctools
@ -645,6 +645,41 @@ namespace eval punk::path {
}
return $ismatch
}
punk::args::define {
@id -id ::punk::path::subfolders
@cmd -name punk::path::subfolders\
-summary\
"Listing of directories within supplied path."\
-help\
"List of folders below path.
The resulting list is unsorted."
@opts
-recursive -type none -help\
""
#todo -depth
@values -min 0 -max 1
path -type directory -optional 1 -help\
"Path of folder. If not supplied current directory is used."
}
proc subfolders {args} {
set argd [punk::args::parse $args withid ::punk::path::subfolders]
lassign [dict values $argd] leaders opts values received
set do_recursion [dict exists $received -recursive]
if {[dict exists $received path]} {
set path [dict get $values path]
} else {
set path [pwd]
}
set folders [glob -nocomplain -directory $path -types d *]
if {$do_recursion} {
foreach subdir $folders {
lappend folders {*}[subfolders -recursive $subdir]
}
}
return $folders
}
#todo - treefolders with similar search caps as treefilenames
punk::args::define {
@id -id ::punk::path::treefilenames

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

@ -522,7 +522,14 @@ proc repl::start {inchan args} {
set codethread ""
set codethread_cond ""
punk::console::mode line ;#review - revert to line mode on final exit - but we may be exiting a nested repl
puts "end repl::start"
set donevalue [set [namespace current]::done]
if {[lindex $donevalue 0] eq "quit"} {
puts "-->repl::start end $inchan $args result:'$donevalue'"
puts stderr "--> returning [lindex $donevalue 1]"
return [lindex $donevalue 1]
}
puts "-->repl::start end $inchan $args result:'$donevalue'"
puts stderr "__> returning 0"
return 0
}
proc repl::post_operations {} {
@ -570,7 +577,7 @@ proc repl::reopen_stdin {} {
#todo - avoid putting this in gobal namespace?
#collisions with other libraries apps?
proc punk::repl::quit {args} {
set ::repl::done "quit {*}$args"
set ::repl::done [list quit {*}$args]
#puts stderr "quit called"
return "" ;#make sure to return nothing so "quit" doesn't land on stdout
}
@ -800,8 +807,7 @@ proc repl::rputs {args} {
}
}
set last_char_info_width 60
#review - string shouldn't be truncated prior to stripcodes - could chop ansi codes!
#set summary "[::shellfilter::ansi::stripcodes [string range $out 0 $last_char_info_width]]"
#review - string shouldn't be truncated prior to ansistrip - could chop ansi codes!
set out_plain_text [punk::ansi::ansistrip $out]
set summary [string range $out_plain_text 0 $last_char_info_width]
if {[string length $summary] > $last_char_info_width} {
@ -1610,6 +1616,8 @@ proc repl::repl_handler {inputchan prompt_config} {
if {![llength $input_chunks_waiting($inputchan)]} {
chan event $inputchan readable [list ::repl::repl_handler $inputchan $prompt_config]
} else {
#review
#puts stderr "warning: after idle re-enable repl::repl_handler in thread: [thread::id]"
after idle [list ::repl::repl_handler $inputchan $prompt_config]
}
####################################################
@ -2695,6 +2703,7 @@ namespace eval repl {
proc init {args} {
puts stderr "-->repl::init $args"
if {![info exists ::argv0]} {
#error out before we create a thread - punk requires this - review
error "::argv0 not set"
@ -2900,7 +2909,7 @@ namespace eval repl {
proc quit {args} {
#child codethreads run in a 'code' interp therefore if they started another repl - it is within the 'code' interp in that thread
# whereas the first repl launched in the process runs in root interp ""
thread::send -async %replthread% [list interp eval %replthread_interp% ::punk::repl::quit]
thread::send -async %replthread% [list interp eval %replthread_interp% [list ::punk::repl::quit {*}$args]]
}
proc editbuf args {
thread::send %replthread% [list punk::repl::editbuf {*}$args]
@ -3623,6 +3632,7 @@ namespace eval repl {
#temporary debug aliases - deliberate violation of safety provided by safe interp
code alias escapeeval ::repl::interphelpers::escapeeval
code alias exit ::repl::interphelpers::quit
#experiment
#code alias ::shellfilter::stack ::shellfilter::stack

72
src/bootsupport/modules/shellfilter-0.2.tm

@ -152,65 +152,6 @@ namespace eval shellfilter::pipe {
}
namespace eval shellfilter::ansi {
#maint warning -
#ansistrip from punk::ansi is better/more comprehensive
proc stripcodes {text} {
#obsolete?
#single "final byte" in the range 0x40–0x7E (ASCII @A–Z[\]^_`a–z{|}~).
dict set escape_terminals CSI [list @ \\ ^ _ ` | ~ a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z "\{" "\}"]
#dict set escape_terminals CSI [list J K m n A B C D E F G s u] ;#basic
dict set escape_terminals OSC [list \007 \033\\] ;#note mix of 1 and 2-byte terminals
#we process char by char - line-endings whether \r\n or \n should be processed as per any other character.
#line endings can theoretically occur within an ansi escape sequence (review e.g title?)
set inputlist [split $text ""]
set outputlist [list]
#self-contained 2 byte ansi escape sequences - review more?
set 2bytecodes_dict [dict create\
"reset_terminal" "\033c"\
"save_cursor_posn" "\u001b7"\
"restore_cursor_posn" "\u001b8"\
"cursor_up_one" "\u001bM"\
]
set 2bytecodes [dict values $2bytecodes_dict]
set in_escapesequence 0
#assumption - undertext already 'rendered' - ie no backspaces or carriagereturns or other cursor movement controls
set i 0
foreach u $inputlist {
set v [lindex $inputlist $i+1]
set uv ${u}${v}
if {$in_escapesequence eq "2b"} {
#2nd byte - done.
set in_escapesequence 0
} elseif {$in_escapesequence != 0} {
set escseq [dict get $escape_terminals $in_escapesequence]
if {$u in $escseq} {
set in_escapesequence 0
} elseif {$uv in $escseq} {
set in_escapseequence 2b ;#flag next byte as last in sequence
}
} else {
#handle both 7-bit and 8-bit CSI and OSC
if {[regexp {^(?:\033\[|\u009b)} $uv]} {
set in_escapesequence CSI
} elseif {[regexp {^(?:\033\]|\u009c)} $uv]} {
set in_escapesequence OSC
} elseif {$uv in $2bytecodes} {
#self-contained e.g terminal reset - don't pass through.
set in_escapesequence 2b
} else {
lappend outputlist $u
}
}
incr i
}
return [join $outputlist ""]
}
}
namespace eval shellfilter::chan {
set testobj ::shellfilter::chan::var
if {$testobj ni [info commands $testobj]} {
@ -2851,8 +2792,10 @@ namespace eval shellfilter {
#chan configure $inchan -buffering none -blocking 1 ;#test
chan configure $inchan -buffering $inbuffering -blocking 0 ;#we are setting up a readable handler for this - so non-blocking ok
chan configure $errchan -buffering $errbuffering
#chan configure $outchan -blocking 0
chan configure $outchan -buffering $outbuffering ;#don't configure non-blocking. weird duplicate of *second* line occurs if you do.
@ -2888,7 +2831,14 @@ namespace eval shellfilter {
# Ideally we need something like exec,open in tcl that interacts with transformed channels directly and emits as it runs, not only at termination
# - and that at least appears like a terminal to the called command.
#set rdout [open |[concat $commandlist [list 2>@stderr <@$inchan]] [list RDONLY]]
#REVIEW!
#if the child process takes a while to begin reading stdin - the data on stdin between when we stopped the parent chan event handler and when the child gets data,
#seems to stay buffered somewhere. It is then read by the parent, after the child returns. (ie not lost, but out-of-order)
#This can be apparent sometimes even with fast typing upon calling an executable. (e.g occasionally even vim - but seems to be timing based so might only happen first time if at all)
# see scriptlib/stdin_race.tcl etc test files.
#similar problem with python & perl - issue seems to be in libc or OS buffering behaviour for standard channels.
#note that zig (repo/jn/zig/stdin_race) seems to avoid this issue - todo - make zig based binary extension for open/exec?
set rdout [open |[concat $commandlist [list 2>@$wrerr <@$inchan]] [list RDONLY]]

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

@ -4899,7 +4899,6 @@ tcl::namespace::eval textblock {
set textblock [punk::ansi::ansistripraw $textblock]
}
if {[tcl::string::last \n $textblock] >= 0} {
#return [tcl::mathfunc::max {*}[lmap v [split $textblock \n] {::punk::char::ansifreestring_width $v}]]
set widths [lmap v [split $textblock \n] {::punk::char::ansifreestring_width $v}]
set max [tcl::mathfunc::max {*}$widths]
set min [tcl::mathfunc::min {*}$widths]

13
src/bootsupport/modules/tomlish-1.1.6.tm

@ -2012,6 +2012,8 @@ namespace eval tomlish {
#updatables
#review - type changes from existing value??
set sourcedata [lindex $source_d_elements $arridx]
#todo - what happens when less source elements than in existing array? ie sourcedata is empty.
#
switch -- $arrchild_type {
STRING - LITERAL - FLOAT - INT - DATETIME - DATETIME-LOCAL - DATE-LOCAL - TIME-LOCAL {
#basic types - no recursion needed
@ -2036,7 +2038,7 @@ namespace eval tomlish {
}
ITABLE - ARRAY {
#recurse
puts stderr "update $tomlish_type within array"
puts stderr "update $arrchild_type within array"
set nextd [tomlish::dict::path::get $d $arridx]
set subrecord_tomlish [list $arrchild]
set newsubrecord_tomlish [update_tomlish_from_dict $subrecord_tomlish $nextd]
@ -9240,8 +9242,15 @@ namespace eval tomlish::lib {
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval tomlish::system {
#*** !doctools
#[subsection {Namespace tomlish::system}]
#[para]
#[list_begin definitions]
#taken from punk::lib
#todo - change list argument to integer length
proc lindex_resolve_basic {list index} {
#*** !doctools
#[call [fun lindex_resolve_basic] [arg list] [arg index]]
@ -9360,6 +9369,8 @@ namespace eval tomlish::system {
}
}
#*** !doctools
#[list_end] [comment {--- end definitions namespace tomlish::system ---}]
}
if {[info exists ::argc] && $::argc > 0} {

23
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/args-0.2.tm

@ -222,7 +222,7 @@ package require Tcl 8.6-
tcl::namespace::eval punk::args::register {
#*** !doctools
#[subsection {Namespace punk::args}]
#[subsection {Namespace punk::args::register}]
#[para] cooperative namespace punk::args::register
#[para] punk::args aware packages may add their own namespace to the public list variable NAMESPACES before or after punk::args is loaded
#[para] The punk::args package will then test for a public list variable <namepace>::PUNKARGS containing argument definitions when it needs to.
@ -2606,11 +2606,11 @@ tcl::namespace::eval punk::args {
@values {set defaults_key VALSPEC_DEFAULTS}
}
if {[dict exists $opt_override $type]} {
append result \n "$type [dict merge [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS] [dict get $opt_override $type]]"
dict set resultdict $type [dict merge [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS] [dict get $opt_override $type]]
append result \n "$type [dict merge [dict get $specdict FORMS $formname $defaults_key] [dict get $opt_override $type]]"
dict set resultdict $type [dict merge [dict get $specdict FORMS $formname $defaults_key] [dict get $opt_override $type]]
} else {
append result \n "$type [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS]"
dict set resultdict $type [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS]
append result \n "$type [dict get $specdict FORMS $formname $defaults_key]"
dict set resultdict $type [dict get $specdict FORMS $formname $defaults_key]
}
}
}
@ -2856,6 +2856,19 @@ tcl::namespace::eval punk::args {
return $result
}
lappend PUNKARGS [list {
@id -id ::punk::args::update_definitions
@cmd -name punk::args::update_definitions\
-summary\
""\
-help\
""
@values -min 1
id
arglist -type list -help\
"list containing arguments to be parsed as per the
argument specification identified by the supplied id."
}]
#scanned_packages (list)
#namespace_docpackages (dict)
proc update_definitions {{nslist *}} {

29
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/docgen-0.1.0.tm

@ -40,15 +40,30 @@ namespace eval punk::docgen {
set data [string map [list \r\n \n] $data]
set in_doctools 0
set doctools ""
#foreach ln [split $data \n] {
# set ln [string trim $ln]
# if {$in_doctools && [string index $ln 0] != "#"} {
# set in_doctools 0
# } elseif {[string range $ln 0 1] == "#*"} {
# #todo - process doctools ordering hints in tail of line
# set in_doctools 1
# } elseif {$in_doctools} {
# append doctools [string range $ln 1 end] \n
# }
#}
foreach ln [split $data \n] {
set ln [string trim $ln]
if {$in_doctools && [string index $ln 0] != "#"} {
set in_doctools 0
} elseif {[string range $ln 0 1] == "#*"} {
#todo - process doctools ordering hints in tail of line
set in_doctools 1
} elseif {$in_doctools} {
append doctools [string range $ln 1 end] \n
if {$in_doctools} {
if {[string index $ln 0] != "#"} {
set in_doctools 0
} else {
append doctools [string range $ln 1 end] \n
}
} else {
if {[string range $ln 0 1] == "#*" && [string first "!doctools" $ln] >=2} {
#todo - process doctools ordering hints in tail of line
set in_doctools 1
}
}
}
return $doctools

2
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/libunknown-0.1.tm

@ -17,7 +17,7 @@
# doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[manpage_begin shellspy_module_punk::libunknown 0.1]
#[manpage_begin shellspy_module_punk::libunknown 0 0.1]
#[copyright "2025"]
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}]
#[moddesc {-}] [comment {-- Description at end of page heading --}]

34
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/cli-0.3.1.tm

@ -1083,20 +1083,28 @@ namespace eval punk::mix::cli {
switch -- $calltype {
lib {}
shell {
set kettleappfile [file dirname [info nameofexecutable]]/kettle
set kettlebatfile [file dirname [info nameofexecutable]]/kettle.bat
if {(![file exists $kettleappfile]) && (![file exists $kettlebatfile])} {
error "deck kettle_call unable to find installed kettle application file '$kettleappfile' (or '$kettlebatfile' if on windows)"
}
if {[file exists $kettleappfile]} {
set kettlescript $kettleappfile
}
if {$::tcl_platform(platform) eq "windows"} {
if {[file exists $kettlebatfile]} {
set kettlescript $kettlebatfile
}
#on windows - could be kettle.bat or kettle.cmd - use auto_execok to find, whatever the platform.
#for now, restrict to version sitting next to exe - REVIEW
set exedir [file dirname [info nameofexecutable]]
set kettlescript [auto_execok $exedir/kettle]
if {$kettlescript eq ""} {
error "kettle_call unable to find installed kettle application file in '$exedir'"
}
#set kettleappfile [file dirname [info nameofexecutable]]/kettle
#set kettlebatfile [file dirname [info nameofexecutable]]/kettle.bat
#if {(![file exists $kettleappfile]) && (![file exists $kettlebatfile])} {
# error "deck kettle_call unable to find installed kettle application file '$kettleappfile' (or '$kettlebatfile' if on windows)"
#}
#if {[file exists $kettleappfile]} {
# set kettlescript $kettleappfile
#}
#if {$::tcl_platform(platform) eq "windows"} {
# if {[file exists $kettlebatfile]} {
# set kettlescript $kettlebatfile
# }
#}
}
default {
error "deck kettle_call 1st argument must be one of: 'lib' for direct use of kettle module or 'shell' to call as separate process"

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

@ -35,23 +35,39 @@ namespace eval punk::mix::commandset::loadedlib {
-highlight -type boolean -default 1 -help\
"Highlight which version is present with ansi underline and colour"
-refresh -default 0 -type boolean -help "Re-scan the tm and library folders"
searchstrings -default * -multiple 1 -help\
searchstring -default * -multiple 1 -help\
"Names to search for, may contain glob chars (* ?) e.g *lib*
If no glob chars are explicitly specified, the searchstring will be wrapped with star globs.
eg name -> *name*
To search for an exact name prefix it with =
e.g =name -> name
"
If no glob chars are explicitly specified, the searchstring will be wrapped with star globs.
eg name -> *name*
To search for an exact name prefix it with =
e.g =name -> name
If search is not prefixed with '=' the search is case insensitive."
}
proc search {args} {
set argd [punk::args::get_by_id ::punk::mix::commandset::loadedlib::search $args]
set searchstrings [dict get $argd values searchstrings]
set searchstrings [dict get $argd values searchstring]
set opts [dict get $argd opts]
set opt_return [dict get $opts -return]
set opt_highlight [dict get $opts -highlight]
set opt_refresh [dict get $opts -refresh]
if {$opt_refresh} {
catch {package require frobznodule666} ;#ensure pkg system has loaded/searched for everything REVIEW - this doesn't result in full scans
foreach tm_path [tcl::tm::list] {
set paths_below [punk::path::subfolders -recursive $tm_path]
foreach folder $paths_below {
set tail [file tail $folder]
if {[string match #modpod-* $tail] || [string match #tarjar-* $tail]} {
continue
}
if {[string match */_build/* $folder]} {continue}
set relpath [string tolower [punk::path::relative $tm_path $folder]]
set modpath [string map {/ ::} $relpath]
catch {package require ${modpath}::flobrudder99}
}
}
}
#REVIEW - this doesn't result in full scans
catch {package require frobznodule666} ;#ensure pkg system has loaded/searched for everything
set packages [package names]
set matches [list]
@ -122,9 +138,25 @@ namespace eval punk::mix::commandset::loadedlib {
}
}
}
proc loaded.search {searchstring} {
set search_result [search $searchstring]
set all_libs [split $search_result \n]
punk::args::define {
@id -id ::punk::mix::commandset::loadedlib::loaded.search
@cmd -name "punk::mix::commandset::loadedlib loaded.search"\
-summary\
"Search loaded libraries."\
-help "search all Tcl libraries currently loaded in your local interpreter.
ie those that have been loaded directly or indirectly by 'package require'."
}\
@values\
[punk::args::resolved_def -types values ::punk::mix::commandset::loadedlib::search searchstring]
proc loaded.search {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::loadedlib::loaded.search]
lassign [dict values $argd] leaders opts values
set searchstrings [dict get $values searchstring]
set all_libs [search -return list -highlight 0 {*}$searchstrings]
set col1items [list]
set col2items [list]
set col3items [list]

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

@ -41,11 +41,27 @@ namespace eval punk::mix::commandset::repo {
return $result
}
lappend PUNKARGS [list {
@id -id ::punk::mix::commandset::repo::fossilize
@cmd -name punk::mix::commandset::repo::fossilize
-summary\
"Initialise and check in a project to fossil (unimplemented)."\
-help\
"(unimplemented)"
}]
proc fossilize { args} {
#check if project already managed by fossil.. initialise and check in if not.
puts stderr "unimplemented"
}
lappend PUNKARGS [list {
@id -id ::punk::mix::commandset::repo::unfossilize
@cmd -name punk::mix::commandset::repo::unfossilize
-summary\
"Remove/archive .fossil (unimplemented)."\
-help\
"(unimplemented)"
}]
proc unfossilize {projectname args} {
#remove/archive .fossil
puts stderr "unimplemented"
@ -76,14 +92,27 @@ namespace eval punk::mix::commandset::repo {
#punk::args
lappend PUNKARGS [list {
@id -id ::punk::mix::commandset::repo::fossil-move-repository
@cmd -name punk::mix::commandset::repo::fossil-move-repository -help\
@cmd -name punk::mix::commandset::repo::fossil-move-repository
-summary\
"Move a fossil repository database file."\
-help\
"Move the fossil repository file (usually named with .fossil extension).
This is an interactive function which will prompt for answers on stdin
before proceeding.
The move can be done even if there are open checkouts and will maintain
the link between checkout databases and the repository file."
the link between checkout databases and the repository file.
The call can be made from within a folder containing fossil databases,
or from within one of the checkouts of the fossil database that is to
be moved.
"
#todo?
#@values -min 0 -max 1
#path
}]
proc fossil-move-repository {{path ""}} {
#path unused for now - todo - allow calling with a specific target rather than relying on cwd?
set searchbase [pwd]
set projectinfo [punk::repo::find_repos $searchbase]
set projectbase [dict get $projectinfo closest]

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

@ -77,7 +77,7 @@ namespace eval punk::mix::commandset::scriptwrap {
#[para] Core API functions for punk::mix::commandset::scriptwrap
#[list_begin definitions]
namespace export *
namespace export {[a-z]*}
namespace eval fileline {
namespace import ::punk::fileline::lib::*

37
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/path-0.1.0.tm

@ -99,7 +99,7 @@ package require punk::args
# Base namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval punk::path {
namespace export *
namespace export {[a-z]*}
#variable xyz
#*** !doctools
@ -645,6 +645,41 @@ namespace eval punk::path {
}
return $ismatch
}
punk::args::define {
@id -id ::punk::path::subfolders
@cmd -name punk::path::subfolders\
-summary\
"Listing of directories within supplied path."\
-help\
"List of folders below path.
The resulting list is unsorted."
@opts
-recursive -type none -help\
""
#todo -depth
@values -min 0 -max 1
path -type directory -optional 1 -help\
"Path of folder. If not supplied current directory is used."
}
proc subfolders {args} {
set argd [punk::args::parse $args withid ::punk::path::subfolders]
lassign [dict values $argd] leaders opts values received
set do_recursion [dict exists $received -recursive]
if {[dict exists $received path]} {
set path [dict get $values path]
} else {
set path [pwd]
}
set folders [glob -nocomplain -directory $path -types d *]
if {$do_recursion} {
foreach subdir $folders {
lappend folders {*}[subfolders -recursive $subdir]
}
}
return $folders
}
#todo - treefolders with similar search caps as treefilenames
punk::args::define {
@id -id ::punk::path::treefilenames

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

@ -522,7 +522,14 @@ proc repl::start {inchan args} {
set codethread ""
set codethread_cond ""
punk::console::mode line ;#review - revert to line mode on final exit - but we may be exiting a nested repl
puts "end repl::start"
set donevalue [set [namespace current]::done]
if {[lindex $donevalue 0] eq "quit"} {
puts "-->repl::start end $inchan $args result:'$donevalue'"
puts stderr "--> returning [lindex $donevalue 1]"
return [lindex $donevalue 1]
}
puts "-->repl::start end $inchan $args result:'$donevalue'"
puts stderr "__> returning 0"
return 0
}
proc repl::post_operations {} {
@ -570,7 +577,7 @@ proc repl::reopen_stdin {} {
#todo - avoid putting this in gobal namespace?
#collisions with other libraries apps?
proc punk::repl::quit {args} {
set ::repl::done "quit {*}$args"
set ::repl::done [list quit {*}$args]
#puts stderr "quit called"
return "" ;#make sure to return nothing so "quit" doesn't land on stdout
}
@ -800,8 +807,7 @@ proc repl::rputs {args} {
}
}
set last_char_info_width 60
#review - string shouldn't be truncated prior to stripcodes - could chop ansi codes!
#set summary "[::shellfilter::ansi::stripcodes [string range $out 0 $last_char_info_width]]"
#review - string shouldn't be truncated prior to ansistrip - could chop ansi codes!
set out_plain_text [punk::ansi::ansistrip $out]
set summary [string range $out_plain_text 0 $last_char_info_width]
if {[string length $summary] > $last_char_info_width} {
@ -1610,6 +1616,8 @@ proc repl::repl_handler {inputchan prompt_config} {
if {![llength $input_chunks_waiting($inputchan)]} {
chan event $inputchan readable [list ::repl::repl_handler $inputchan $prompt_config]
} else {
#review
#puts stderr "warning: after idle re-enable repl::repl_handler in thread: [thread::id]"
after idle [list ::repl::repl_handler $inputchan $prompt_config]
}
####################################################
@ -2695,6 +2703,7 @@ namespace eval repl {
proc init {args} {
puts stderr "-->repl::init $args"
if {![info exists ::argv0]} {
#error out before we create a thread - punk requires this - review
error "::argv0 not set"
@ -2900,7 +2909,7 @@ namespace eval repl {
proc quit {args} {
#child codethreads run in a 'code' interp therefore if they started another repl - it is within the 'code' interp in that thread
# whereas the first repl launched in the process runs in root interp ""
thread::send -async %replthread% [list interp eval %replthread_interp% ::punk::repl::quit]
thread::send -async %replthread% [list interp eval %replthread_interp% [list ::punk::repl::quit {*}$args]]
}
proc editbuf args {
thread::send %replthread% [list punk::repl::editbuf {*}$args]
@ -3623,6 +3632,7 @@ namespace eval repl {
#temporary debug aliases - deliberate violation of safety provided by safe interp
code alias escapeeval ::repl::interphelpers::escapeeval
code alias exit ::repl::interphelpers::quit
#experiment
#code alias ::shellfilter::stack ::shellfilter::stack

72
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/shellfilter-0.2.tm

@ -152,65 +152,6 @@ namespace eval shellfilter::pipe {
}
namespace eval shellfilter::ansi {
#maint warning -
#ansistrip from punk::ansi is better/more comprehensive
proc stripcodes {text} {
#obsolete?
#single "final byte" in the range 0x40–0x7E (ASCII @A–Z[\]^_`a–z{|}~).
dict set escape_terminals CSI [list @ \\ ^ _ ` | ~ a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z "\{" "\}"]
#dict set escape_terminals CSI [list J K m n A B C D E F G s u] ;#basic
dict set escape_terminals OSC [list \007 \033\\] ;#note mix of 1 and 2-byte terminals
#we process char by char - line-endings whether \r\n or \n should be processed as per any other character.
#line endings can theoretically occur within an ansi escape sequence (review e.g title?)
set inputlist [split $text ""]
set outputlist [list]
#self-contained 2 byte ansi escape sequences - review more?
set 2bytecodes_dict [dict create\
"reset_terminal" "\033c"\
"save_cursor_posn" "\u001b7"\
"restore_cursor_posn" "\u001b8"\
"cursor_up_one" "\u001bM"\
]
set 2bytecodes [dict values $2bytecodes_dict]
set in_escapesequence 0
#assumption - undertext already 'rendered' - ie no backspaces or carriagereturns or other cursor movement controls
set i 0
foreach u $inputlist {
set v [lindex $inputlist $i+1]
set uv ${u}${v}
if {$in_escapesequence eq "2b"} {
#2nd byte - done.
set in_escapesequence 0
} elseif {$in_escapesequence != 0} {
set escseq [dict get $escape_terminals $in_escapesequence]
if {$u in $escseq} {
set in_escapesequence 0
} elseif {$uv in $escseq} {
set in_escapseequence 2b ;#flag next byte as last in sequence
}
} else {
#handle both 7-bit and 8-bit CSI and OSC
if {[regexp {^(?:\033\[|\u009b)} $uv]} {
set in_escapesequence CSI
} elseif {[regexp {^(?:\033\]|\u009c)} $uv]} {
set in_escapesequence OSC
} elseif {$uv in $2bytecodes} {
#self-contained e.g terminal reset - don't pass through.
set in_escapesequence 2b
} else {
lappend outputlist $u
}
}
incr i
}
return [join $outputlist ""]
}
}
namespace eval shellfilter::chan {
set testobj ::shellfilter::chan::var
if {$testobj ni [info commands $testobj]} {
@ -2851,8 +2792,10 @@ namespace eval shellfilter {
#chan configure $inchan -buffering none -blocking 1 ;#test
chan configure $inchan -buffering $inbuffering -blocking 0 ;#we are setting up a readable handler for this - so non-blocking ok
chan configure $errchan -buffering $errbuffering
#chan configure $outchan -blocking 0
chan configure $outchan -buffering $outbuffering ;#don't configure non-blocking. weird duplicate of *second* line occurs if you do.
@ -2888,7 +2831,14 @@ namespace eval shellfilter {
# Ideally we need something like exec,open in tcl that interacts with transformed channels directly and emits as it runs, not only at termination
# - and that at least appears like a terminal to the called command.
#set rdout [open |[concat $commandlist [list 2>@stderr <@$inchan]] [list RDONLY]]
#REVIEW!
#if the child process takes a while to begin reading stdin - the data on stdin between when we stopped the parent chan event handler and when the child gets data,
#seems to stay buffered somewhere. It is then read by the parent, after the child returns. (ie not lost, but out-of-order)
#This can be apparent sometimes even with fast typing upon calling an executable. (e.g occasionally even vim - but seems to be timing based so might only happen first time if at all)
# see scriptlib/stdin_race.tcl etc test files.
#similar problem with python & perl - issue seems to be in libc or OS buffering behaviour for standard channels.
#note that zig (repo/jn/zig/stdin_race) seems to avoid this issue - todo - make zig based binary extension for open/exec?
set rdout [open |[concat $commandlist [list 2>@$wrerr <@$inchan]] [list RDONLY]]

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

@ -4899,7 +4899,6 @@ tcl::namespace::eval textblock {
set textblock [punk::ansi::ansistripraw $textblock]
}
if {[tcl::string::last \n $textblock] >= 0} {
#return [tcl::mathfunc::max {*}[lmap v [split $textblock \n] {::punk::char::ansifreestring_width $v}]]
set widths [lmap v [split $textblock \n] {::punk::char::ansifreestring_width $v}]
set max [tcl::mathfunc::max {*}$widths]
set min [tcl::mathfunc::min {*}$widths]

13
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/tomlish-1.1.6.tm

@ -2012,6 +2012,8 @@ namespace eval tomlish {
#updatables
#review - type changes from existing value??
set sourcedata [lindex $source_d_elements $arridx]
#todo - what happens when less source elements than in existing array? ie sourcedata is empty.
#
switch -- $arrchild_type {
STRING - LITERAL - FLOAT - INT - DATETIME - DATETIME-LOCAL - DATE-LOCAL - TIME-LOCAL {
#basic types - no recursion needed
@ -2036,7 +2038,7 @@ namespace eval tomlish {
}
ITABLE - ARRAY {
#recurse
puts stderr "update $tomlish_type within array"
puts stderr "update $arrchild_type within array"
set nextd [tomlish::dict::path::get $d $arridx]
set subrecord_tomlish [list $arrchild]
set newsubrecord_tomlish [update_tomlish_from_dict $subrecord_tomlish $nextd]
@ -9240,8 +9242,15 @@ namespace eval tomlish::lib {
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval tomlish::system {
#*** !doctools
#[subsection {Namespace tomlish::system}]
#[para]
#[list_begin definitions]
#taken from punk::lib
#todo - change list argument to integer length
proc lindex_resolve_basic {list index} {
#*** !doctools
#[call [fun lindex_resolve_basic] [arg list] [arg index]]
@ -9360,6 +9369,8 @@ namespace eval tomlish::system {
}
}
#*** !doctools
#[list_end] [comment {--- end definitions namespace tomlish::system ---}]
}
if {[info exists ::argc] && $::argc > 0} {

23
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/args-0.2.tm

@ -222,7 +222,7 @@ package require Tcl 8.6-
tcl::namespace::eval punk::args::register {
#*** !doctools
#[subsection {Namespace punk::args}]
#[subsection {Namespace punk::args::register}]
#[para] cooperative namespace punk::args::register
#[para] punk::args aware packages may add their own namespace to the public list variable NAMESPACES before or after punk::args is loaded
#[para] The punk::args package will then test for a public list variable <namepace>::PUNKARGS containing argument definitions when it needs to.
@ -2606,11 +2606,11 @@ tcl::namespace::eval punk::args {
@values {set defaults_key VALSPEC_DEFAULTS}
}
if {[dict exists $opt_override $type]} {
append result \n "$type [dict merge [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS] [dict get $opt_override $type]]"
dict set resultdict $type [dict merge [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS] [dict get $opt_override $type]]
append result \n "$type [dict merge [dict get $specdict FORMS $formname $defaults_key] [dict get $opt_override $type]]"
dict set resultdict $type [dict merge [dict get $specdict FORMS $formname $defaults_key] [dict get $opt_override $type]]
} else {
append result \n "$type [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS]"
dict set resultdict $type [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS]
append result \n "$type [dict get $specdict FORMS $formname $defaults_key]"
dict set resultdict $type [dict get $specdict FORMS $formname $defaults_key]
}
}
}
@ -2856,6 +2856,19 @@ tcl::namespace::eval punk::args {
return $result
}
lappend PUNKARGS [list {
@id -id ::punk::args::update_definitions
@cmd -name punk::args::update_definitions\
-summary\
""\
-help\
""
@values -min 1
id
arglist -type list -help\
"list containing arguments to be parsed as per the
argument specification identified by the supplied id."
}]
#scanned_packages (list)
#namespace_docpackages (dict)
proc update_definitions {{nslist *}} {

29
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/docgen-0.1.0.tm

@ -40,15 +40,30 @@ namespace eval punk::docgen {
set data [string map [list \r\n \n] $data]
set in_doctools 0
set doctools ""
#foreach ln [split $data \n] {
# set ln [string trim $ln]
# if {$in_doctools && [string index $ln 0] != "#"} {
# set in_doctools 0
# } elseif {[string range $ln 0 1] == "#*"} {
# #todo - process doctools ordering hints in tail of line
# set in_doctools 1
# } elseif {$in_doctools} {
# append doctools [string range $ln 1 end] \n
# }
#}
foreach ln [split $data \n] {
set ln [string trim $ln]
if {$in_doctools && [string index $ln 0] != "#"} {
set in_doctools 0
} elseif {[string range $ln 0 1] == "#*"} {
#todo - process doctools ordering hints in tail of line
set in_doctools 1
} elseif {$in_doctools} {
append doctools [string range $ln 1 end] \n
if {$in_doctools} {
if {[string index $ln 0] != "#"} {
set in_doctools 0
} else {
append doctools [string range $ln 1 end] \n
}
} else {
if {[string range $ln 0 1] == "#*" && [string first "!doctools" $ln] >=2} {
#todo - process doctools ordering hints in tail of line
set in_doctools 1
}
}
}
return $doctools

2
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/libunknown-0.1.tm

@ -17,7 +17,7 @@
# doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[manpage_begin shellspy_module_punk::libunknown 0.1]
#[manpage_begin shellspy_module_punk::libunknown 0 0.1]
#[copyright "2025"]
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}]
#[moddesc {-}] [comment {-- Description at end of page heading --}]

34
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/cli-0.3.1.tm

@ -1083,20 +1083,28 @@ namespace eval punk::mix::cli {
switch -- $calltype {
lib {}
shell {
set kettleappfile [file dirname [info nameofexecutable]]/kettle
set kettlebatfile [file dirname [info nameofexecutable]]/kettle.bat
if {(![file exists $kettleappfile]) && (![file exists $kettlebatfile])} {
error "deck kettle_call unable to find installed kettle application file '$kettleappfile' (or '$kettlebatfile' if on windows)"
}
if {[file exists $kettleappfile]} {
set kettlescript $kettleappfile
}
if {$::tcl_platform(platform) eq "windows"} {
if {[file exists $kettlebatfile]} {
set kettlescript $kettlebatfile
}
#on windows - could be kettle.bat or kettle.cmd - use auto_execok to find, whatever the platform.
#for now, restrict to version sitting next to exe - REVIEW
set exedir [file dirname [info nameofexecutable]]
set kettlescript [auto_execok $exedir/kettle]
if {$kettlescript eq ""} {
error "kettle_call unable to find installed kettle application file in '$exedir'"
}
#set kettleappfile [file dirname [info nameofexecutable]]/kettle
#set kettlebatfile [file dirname [info nameofexecutable]]/kettle.bat
#if {(![file exists $kettleappfile]) && (![file exists $kettlebatfile])} {
# error "deck kettle_call unable to find installed kettle application file '$kettleappfile' (or '$kettlebatfile' if on windows)"
#}
#if {[file exists $kettleappfile]} {
# set kettlescript $kettleappfile
#}
#if {$::tcl_platform(platform) eq "windows"} {
# if {[file exists $kettlebatfile]} {
# set kettlescript $kettlebatfile
# }
#}
}
default {
error "deck kettle_call 1st argument must be one of: 'lib' for direct use of kettle module or 'shell' to call as separate process"

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

@ -35,23 +35,39 @@ namespace eval punk::mix::commandset::loadedlib {
-highlight -type boolean -default 1 -help\
"Highlight which version is present with ansi underline and colour"
-refresh -default 0 -type boolean -help "Re-scan the tm and library folders"
searchstrings -default * -multiple 1 -help\
searchstring -default * -multiple 1 -help\
"Names to search for, may contain glob chars (* ?) e.g *lib*
If no glob chars are explicitly specified, the searchstring will be wrapped with star globs.
eg name -> *name*
To search for an exact name prefix it with =
e.g =name -> name
"
If no glob chars are explicitly specified, the searchstring will be wrapped with star globs.
eg name -> *name*
To search for an exact name prefix it with =
e.g =name -> name
If search is not prefixed with '=' the search is case insensitive."
}
proc search {args} {
set argd [punk::args::get_by_id ::punk::mix::commandset::loadedlib::search $args]
set searchstrings [dict get $argd values searchstrings]
set searchstrings [dict get $argd values searchstring]
set opts [dict get $argd opts]
set opt_return [dict get $opts -return]
set opt_highlight [dict get $opts -highlight]
set opt_refresh [dict get $opts -refresh]
if {$opt_refresh} {
catch {package require frobznodule666} ;#ensure pkg system has loaded/searched for everything REVIEW - this doesn't result in full scans
foreach tm_path [tcl::tm::list] {
set paths_below [punk::path::subfolders -recursive $tm_path]
foreach folder $paths_below {
set tail [file tail $folder]
if {[string match #modpod-* $tail] || [string match #tarjar-* $tail]} {
continue
}
if {[string match */_build/* $folder]} {continue}
set relpath [string tolower [punk::path::relative $tm_path $folder]]
set modpath [string map {/ ::} $relpath]
catch {package require ${modpath}::flobrudder99}
}
}
}
#REVIEW - this doesn't result in full scans
catch {package require frobznodule666} ;#ensure pkg system has loaded/searched for everything
set packages [package names]
set matches [list]
@ -122,9 +138,25 @@ namespace eval punk::mix::commandset::loadedlib {
}
}
}
proc loaded.search {searchstring} {
set search_result [search $searchstring]
set all_libs [split $search_result \n]
punk::args::define {
@id -id ::punk::mix::commandset::loadedlib::loaded.search
@cmd -name "punk::mix::commandset::loadedlib loaded.search"\
-summary\
"Search loaded libraries."\
-help "search all Tcl libraries currently loaded in your local interpreter.
ie those that have been loaded directly or indirectly by 'package require'."
}\
@values\
[punk::args::resolved_def -types values ::punk::mix::commandset::loadedlib::search searchstring]
proc loaded.search {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::loadedlib::loaded.search]
lassign [dict values $argd] leaders opts values
set searchstrings [dict get $values searchstring]
set all_libs [search -return list -highlight 0 {*}$searchstrings]
set col1items [list]
set col2items [list]
set col3items [list]

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

@ -41,11 +41,27 @@ namespace eval punk::mix::commandset::repo {
return $result
}
lappend PUNKARGS [list {
@id -id ::punk::mix::commandset::repo::fossilize
@cmd -name punk::mix::commandset::repo::fossilize
-summary\
"Initialise and check in a project to fossil (unimplemented)."\
-help\
"(unimplemented)"
}]
proc fossilize { args} {
#check if project already managed by fossil.. initialise and check in if not.
puts stderr "unimplemented"
}
lappend PUNKARGS [list {
@id -id ::punk::mix::commandset::repo::unfossilize
@cmd -name punk::mix::commandset::repo::unfossilize
-summary\
"Remove/archive .fossil (unimplemented)."\
-help\
"(unimplemented)"
}]
proc unfossilize {projectname args} {
#remove/archive .fossil
puts stderr "unimplemented"
@ -76,14 +92,27 @@ namespace eval punk::mix::commandset::repo {
#punk::args
lappend PUNKARGS [list {
@id -id ::punk::mix::commandset::repo::fossil-move-repository
@cmd -name punk::mix::commandset::repo::fossil-move-repository -help\
@cmd -name punk::mix::commandset::repo::fossil-move-repository
-summary\
"Move a fossil repository database file."\
-help\
"Move the fossil repository file (usually named with .fossil extension).
This is an interactive function which will prompt for answers on stdin
before proceeding.
The move can be done even if there are open checkouts and will maintain
the link between checkout databases and the repository file."
the link between checkout databases and the repository file.
The call can be made from within a folder containing fossil databases,
or from within one of the checkouts of the fossil database that is to
be moved.
"
#todo?
#@values -min 0 -max 1
#path
}]
proc fossil-move-repository {{path ""}} {
#path unused for now - todo - allow calling with a specific target rather than relying on cwd?
set searchbase [pwd]
set projectinfo [punk::repo::find_repos $searchbase]
set projectbase [dict get $projectinfo closest]

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

@ -77,7 +77,7 @@ namespace eval punk::mix::commandset::scriptwrap {
#[para] Core API functions for punk::mix::commandset::scriptwrap
#[list_begin definitions]
namespace export *
namespace export {[a-z]*}
namespace eval fileline {
namespace import ::punk::fileline::lib::*

37
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/path-0.1.0.tm

@ -99,7 +99,7 @@ package require punk::args
# Base namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval punk::path {
namespace export *
namespace export {[a-z]*}
#variable xyz
#*** !doctools
@ -645,6 +645,41 @@ namespace eval punk::path {
}
return $ismatch
}
punk::args::define {
@id -id ::punk::path::subfolders
@cmd -name punk::path::subfolders\
-summary\
"Listing of directories within supplied path."\
-help\
"List of folders below path.
The resulting list is unsorted."
@opts
-recursive -type none -help\
""
#todo -depth
@values -min 0 -max 1
path -type directory -optional 1 -help\
"Path of folder. If not supplied current directory is used."
}
proc subfolders {args} {
set argd [punk::args::parse $args withid ::punk::path::subfolders]
lassign [dict values $argd] leaders opts values received
set do_recursion [dict exists $received -recursive]
if {[dict exists $received path]} {
set path [dict get $values path]
} else {
set path [pwd]
}
set folders [glob -nocomplain -directory $path -types d *]
if {$do_recursion} {
foreach subdir $folders {
lappend folders {*}[subfolders -recursive $subdir]
}
}
return $folders
}
#todo - treefolders with similar search caps as treefilenames
punk::args::define {
@id -id ::punk::path::treefilenames

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

@ -522,7 +522,14 @@ proc repl::start {inchan args} {
set codethread ""
set codethread_cond ""
punk::console::mode line ;#review - revert to line mode on final exit - but we may be exiting a nested repl
puts "end repl::start"
set donevalue [set [namespace current]::done]
if {[lindex $donevalue 0] eq "quit"} {
puts "-->repl::start end $inchan $args result:'$donevalue'"
puts stderr "--> returning [lindex $donevalue 1]"
return [lindex $donevalue 1]
}
puts "-->repl::start end $inchan $args result:'$donevalue'"
puts stderr "__> returning 0"
return 0
}
proc repl::post_operations {} {
@ -570,7 +577,7 @@ proc repl::reopen_stdin {} {
#todo - avoid putting this in gobal namespace?
#collisions with other libraries apps?
proc punk::repl::quit {args} {
set ::repl::done "quit {*}$args"
set ::repl::done [list quit {*}$args]
#puts stderr "quit called"
return "" ;#make sure to return nothing so "quit" doesn't land on stdout
}
@ -800,8 +807,7 @@ proc repl::rputs {args} {
}
}
set last_char_info_width 60
#review - string shouldn't be truncated prior to stripcodes - could chop ansi codes!
#set summary "[::shellfilter::ansi::stripcodes [string range $out 0 $last_char_info_width]]"
#review - string shouldn't be truncated prior to ansistrip - could chop ansi codes!
set out_plain_text [punk::ansi::ansistrip $out]
set summary [string range $out_plain_text 0 $last_char_info_width]
if {[string length $summary] > $last_char_info_width} {
@ -1610,6 +1616,8 @@ proc repl::repl_handler {inputchan prompt_config} {
if {![llength $input_chunks_waiting($inputchan)]} {
chan event $inputchan readable [list ::repl::repl_handler $inputchan $prompt_config]
} else {
#review
#puts stderr "warning: after idle re-enable repl::repl_handler in thread: [thread::id]"
after idle [list ::repl::repl_handler $inputchan $prompt_config]
}
####################################################
@ -2695,6 +2703,7 @@ namespace eval repl {
proc init {args} {
puts stderr "-->repl::init $args"
if {![info exists ::argv0]} {
#error out before we create a thread - punk requires this - review
error "::argv0 not set"
@ -2900,7 +2909,7 @@ namespace eval repl {
proc quit {args} {
#child codethreads run in a 'code' interp therefore if they started another repl - it is within the 'code' interp in that thread
# whereas the first repl launched in the process runs in root interp ""
thread::send -async %replthread% [list interp eval %replthread_interp% ::punk::repl::quit]
thread::send -async %replthread% [list interp eval %replthread_interp% [list ::punk::repl::quit {*}$args]]
}
proc editbuf args {
thread::send %replthread% [list punk::repl::editbuf {*}$args]
@ -3623,6 +3632,7 @@ namespace eval repl {
#temporary debug aliases - deliberate violation of safety provided by safe interp
code alias escapeeval ::repl::interphelpers::escapeeval
code alias exit ::repl::interphelpers::quit
#experiment
#code alias ::shellfilter::stack ::shellfilter::stack

72
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/shellfilter-0.2.tm

@ -152,65 +152,6 @@ namespace eval shellfilter::pipe {
}
namespace eval shellfilter::ansi {
#maint warning -
#ansistrip from punk::ansi is better/more comprehensive
proc stripcodes {text} {
#obsolete?
#single "final byte" in the range 0x40–0x7E (ASCII @A–Z[\]^_`a–z{|}~).
dict set escape_terminals CSI [list @ \\ ^ _ ` | ~ a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z "\{" "\}"]
#dict set escape_terminals CSI [list J K m n A B C D E F G s u] ;#basic
dict set escape_terminals OSC [list \007 \033\\] ;#note mix of 1 and 2-byte terminals
#we process char by char - line-endings whether \r\n or \n should be processed as per any other character.
#line endings can theoretically occur within an ansi escape sequence (review e.g title?)
set inputlist [split $text ""]
set outputlist [list]
#self-contained 2 byte ansi escape sequences - review more?
set 2bytecodes_dict [dict create\
"reset_terminal" "\033c"\
"save_cursor_posn" "\u001b7"\
"restore_cursor_posn" "\u001b8"\
"cursor_up_one" "\u001bM"\
]
set 2bytecodes [dict values $2bytecodes_dict]
set in_escapesequence 0
#assumption - undertext already 'rendered' - ie no backspaces or carriagereturns or other cursor movement controls
set i 0
foreach u $inputlist {
set v [lindex $inputlist $i+1]
set uv ${u}${v}
if {$in_escapesequence eq "2b"} {
#2nd byte - done.
set in_escapesequence 0
} elseif {$in_escapesequence != 0} {
set escseq [dict get $escape_terminals $in_escapesequence]
if {$u in $escseq} {
set in_escapesequence 0
} elseif {$uv in $escseq} {
set in_escapseequence 2b ;#flag next byte as last in sequence
}
} else {
#handle both 7-bit and 8-bit CSI and OSC
if {[regexp {^(?:\033\[|\u009b)} $uv]} {
set in_escapesequence CSI
} elseif {[regexp {^(?:\033\]|\u009c)} $uv]} {
set in_escapesequence OSC
} elseif {$uv in $2bytecodes} {
#self-contained e.g terminal reset - don't pass through.
set in_escapesequence 2b
} else {
lappend outputlist $u
}
}
incr i
}
return [join $outputlist ""]
}
}
namespace eval shellfilter::chan {
set testobj ::shellfilter::chan::var
if {$testobj ni [info commands $testobj]} {
@ -2851,8 +2792,10 @@ namespace eval shellfilter {
#chan configure $inchan -buffering none -blocking 1 ;#test
chan configure $inchan -buffering $inbuffering -blocking 0 ;#we are setting up a readable handler for this - so non-blocking ok
chan configure $errchan -buffering $errbuffering
#chan configure $outchan -blocking 0
chan configure $outchan -buffering $outbuffering ;#don't configure non-blocking. weird duplicate of *second* line occurs if you do.
@ -2888,7 +2831,14 @@ namespace eval shellfilter {
# Ideally we need something like exec,open in tcl that interacts with transformed channels directly and emits as it runs, not only at termination
# - and that at least appears like a terminal to the called command.
#set rdout [open |[concat $commandlist [list 2>@stderr <@$inchan]] [list RDONLY]]
#REVIEW!
#if the child process takes a while to begin reading stdin - the data on stdin between when we stopped the parent chan event handler and when the child gets data,
#seems to stay buffered somewhere. It is then read by the parent, after the child returns. (ie not lost, but out-of-order)
#This can be apparent sometimes even with fast typing upon calling an executable. (e.g occasionally even vim - but seems to be timing based so might only happen first time if at all)
# see scriptlib/stdin_race.tcl etc test files.
#similar problem with python & perl - issue seems to be in libc or OS buffering behaviour for standard channels.
#note that zig (repo/jn/zig/stdin_race) seems to avoid this issue - todo - make zig based binary extension for open/exec?
set rdout [open |[concat $commandlist [list 2>@$wrerr <@$inchan]] [list RDONLY]]

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

@ -4899,7 +4899,6 @@ tcl::namespace::eval textblock {
set textblock [punk::ansi::ansistripraw $textblock]
}
if {[tcl::string::last \n $textblock] >= 0} {
#return [tcl::mathfunc::max {*}[lmap v [split $textblock \n] {::punk::char::ansifreestring_width $v}]]
set widths [lmap v [split $textblock \n] {::punk::char::ansifreestring_width $v}]
set max [tcl::mathfunc::max {*}$widths]
set min [tcl::mathfunc::min {*}$widths]

13
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/tomlish-1.1.6.tm

@ -2012,6 +2012,8 @@ namespace eval tomlish {
#updatables
#review - type changes from existing value??
set sourcedata [lindex $source_d_elements $arridx]
#todo - what happens when less source elements than in existing array? ie sourcedata is empty.
#
switch -- $arrchild_type {
STRING - LITERAL - FLOAT - INT - DATETIME - DATETIME-LOCAL - DATE-LOCAL - TIME-LOCAL {
#basic types - no recursion needed
@ -2036,7 +2038,7 @@ namespace eval tomlish {
}
ITABLE - ARRAY {
#recurse
puts stderr "update $tomlish_type within array"
puts stderr "update $arrchild_type within array"
set nextd [tomlish::dict::path::get $d $arridx]
set subrecord_tomlish [list $arrchild]
set newsubrecord_tomlish [update_tomlish_from_dict $subrecord_tomlish $nextd]
@ -9240,8 +9242,15 @@ namespace eval tomlish::lib {
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval tomlish::system {
#*** !doctools
#[subsection {Namespace tomlish::system}]
#[para]
#[list_begin definitions]
#taken from punk::lib
#todo - change list argument to integer length
proc lindex_resolve_basic {list index} {
#*** !doctools
#[call [fun lindex_resolve_basic] [arg list] [arg index]]
@ -9360,6 +9369,8 @@ namespace eval tomlish::system {
}
}
#*** !doctools
#[list_end] [comment {--- end definitions namespace tomlish::system ---}]
}
if {[info exists ::argc] && $::argc > 0} {

21
src/vfs/_vfscommon.vfs/modules/picalc-0.1.0.tm

@ -46,7 +46,7 @@
#[list_begin itemized]
package require Tcl 8.6-
package require punk::lib
package require punk::lib
package require punk::args
#*** !doctools
#[item] [package {Tcl 8.6}]
@ -73,10 +73,18 @@ tcl::namespace::eval picalc {
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[subsection {Namespace picalc}]
#[para] Core API functions for picalc
#[para] Core API functions for picalc
#[list_begin definitions]
variable PUNKARGS
variable PUNKARGS_aliases
lappend PUNKARGS [list {
@id -id "(package)picalc"
@package -name "picalc"\
-help\
"A test/learning experimental package for pi calculation"
}]
@ -475,15 +483,6 @@ tcl::namespace::eval picalc::lib {
# == === === === === === === === === === === === === === ===
tcl::namespace::eval picalc {
tcl::namespace::export {[a-z]*} ;# Convention: export all lowercase
variable PUNKARGS
variable PUNKARGS_aliases
lappend PUNKARGS [list {
@id -id "(package)picalc"
@package -name "picalc" -help\
"Package
Description"
}]
namespace eval argdoc {
#namespace for custom argument documentation

39
src/vfs/_vfscommon.vfs/modules/poshinfo-0.1.0.tm

@ -21,7 +21,7 @@
#[manpage_begin punkshell_module_poshinfo 0 0.1.0]
#[copyright "2024"]
#[titledesc {poshinfo prompt theme tool}] [comment {-- Name section and table of contents description --}]
#[moddesc {POSH-related prompt tool}] [comment {-- Description at end of page heading --}]
#[moddesc {POSH-related prompt tool}] [comment {-- Description at end of page heading --}]
#[require poshinfo]
#[keywords module terminal console theme prompt {prompt theme} POSH]
#[description]
@ -113,7 +113,7 @@ tcl::namespace::eval poshinfo {
#*** !doctools
#[subsection {Namespace poshinfo}]
#[para] Core API functions for poshinfo
#[para] Core API functions for poshinfo
#[list_begin definitions]
@ -121,11 +121,11 @@ tcl::namespace::eval poshinfo {
proc info_from_filename {fname} {
#string based filename processing: we are deliberately avoiding test of file existence etc here
if {$fname eq ""} {
error "poshinfo::info_from_filename unable to determine name from empty string"
error "poshinfo::info_from_filename unable to determine name from empty string"
}
if {[string first . $fname] < 0} {
#theoretically we could have a file without dots - but it's more likely an error in this context
error "poshinfo::info_from_filename supplied value '$fname' doesn't look like a filename. Cowardly refusing to guess a shortname."
error "poshinfo::info_from_filename supplied value '$fname' doesn't look like a filename. Cowardly refusing to guess a shortname."
}
set ftail [file tail $fname]
set rootname [file rootname $ftail]
@ -141,7 +141,7 @@ tcl::namespace::eval poshinfo {
set shortname [join [lrange $parts 0 end-1] .]
} else {
if {$rootname eq "schema"} {
set type schema
set type schema
} else {
#review - we can't tell diff betw <themename_with_dots>.<format> and <themename>.<unknowntype>.<format>
set type unknown
@ -181,7 +181,7 @@ tcl::namespace::eval poshinfo {
dict lappend themes_dict $shortname $themeinfo
}
}
}
}
}
}
return $themes_dict
@ -204,10 +204,10 @@ tcl::namespace::eval poshinfo {
-format -default all -multiple 1 -choices {all yaml json}\
-help "File format of posh theme - based on file extension"
-type -default all -multiple 1\
-help "e.g omp"
-help "e.g omp"
-as -default "table" -choices {list showlist dict showdict table tableobject plaintext}\
-help "return type of result"
@values -min 0
@values -min 0
globs -multiple 1 -default * -help ""
}
proc themes {args} {
@ -226,7 +226,7 @@ tcl::namespace::eval poshinfo {
set themeinfo [lindex $themeinfolist 0]
if {("all" in $formats || [dict get $themeinfo format] in $formats) && ("all" in $types || [dict get $themeinfo type] in $types)} {
dict set restricted_themes_dict $shortname $themeinfolist
}
}
}
unset themes_dict
switch -- $return_as {
@ -266,7 +266,7 @@ tcl::namespace::eval poshinfo {
omp {}
unknown {
set bg Web-red
}
}
default {
#we shouldn't be getting other values
set bg Web-yellow
@ -274,7 +274,7 @@ tcl::namespace::eval poshinfo {
}
if {$posh_theme eq [file normalize $path]} {
set fg web-limegreen
}
}
if {"$fg$bg" ne ""} {
$t configure_row [expr {[$t row_count]-1}] -ansibase [a+ {*}$fg {*}$bg]
}
@ -287,7 +287,7 @@ tcl::namespace::eval poshinfo {
return [join [lines_as_list -line trimline $pt] \n]
}
table {
set tabletext [$t print]
set tabletext [$t print]
$t destroy
return $tabletext
}
@ -313,16 +313,9 @@ tcl::namespace::eval poshinfo::lib {
#*** !doctools
#[subsection {Namespace poshinfo::lib}]
#[para] Secondary functions that are part of the API
#[para] Secondary functions that are part of the API
#[list_begin definitions]
#proc utility1 {p1 args} {
# #*** !doctools
# #[call lib::[fun utility1] [arg p1] [opt {?option value...?}]]
# #[para]Description of utility1
# return 1
#}
#*** !doctools
@ -340,17 +333,17 @@ tcl::namespace::eval poshinfo::lib {
#*** !doctools
#[subsection {Namespace poshinfo::system}]
#[para] Internal functions that are not part of the API
#[para] Internal functions that are not part of the API
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Ready
## Ready
package provide poshinfo [tcl::namespace::eval poshinfo {
variable pkg poshinfo
variable version
set version 0.1.0
set version 0.1.0
}]
return

21
src/vfs/_vfscommon.vfs/modules/punk/args-0.2.tm

@ -2606,11 +2606,11 @@ tcl::namespace::eval punk::args {
@values {set defaults_key VALSPEC_DEFAULTS}
}
if {[dict exists $opt_override $type]} {
append result \n "$type [dict merge [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS] [dict get $opt_override $type]]"
dict set resultdict $type [dict merge [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS] [dict get $opt_override $type]]
append result \n "$type [dict merge [dict get $specdict FORMS $formname $defaults_key] [dict get $opt_override $type]]"
dict set resultdict $type [dict merge [dict get $specdict FORMS $formname $defaults_key] [dict get $opt_override $type]]
} else {
append result \n "$type [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS]"
dict set resultdict $type [dict get $specdict FORMS $formname LEADERSPEC_DEFAULTS]
append result \n "$type [dict get $specdict FORMS $formname $defaults_key]"
dict set resultdict $type [dict get $specdict FORMS $formname $defaults_key]
}
}
}
@ -2856,6 +2856,19 @@ tcl::namespace::eval punk::args {
return $result
}
lappend PUNKARGS [list {
@id -id ::punk::args::update_definitions
@cmd -name punk::args::update_definitions\
-summary\
""\
-help\
""
@values -min 1
id
arglist -type list -help\
"list containing arguments to be parsed as per the
argument specification identified by the supplied id."
}]
#scanned_packages (list)
#namespace_docpackages (dict)
proc update_definitions {{nslist *}} {

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

@ -35,23 +35,39 @@ namespace eval punk::mix::commandset::loadedlib {
-highlight -type boolean -default 1 -help\
"Highlight which version is present with ansi underline and colour"
-refresh -default 0 -type boolean -help "Re-scan the tm and library folders"
searchstrings -default * -multiple 1 -help\
searchstring -default * -multiple 1 -help\
"Names to search for, may contain glob chars (* ?) e.g *lib*
If no glob chars are explicitly specified, the searchstring will be wrapped with star globs.
eg name -> *name*
To search for an exact name prefix it with =
e.g =name -> name
"
If no glob chars are explicitly specified, the searchstring will be wrapped with star globs.
eg name -> *name*
To search for an exact name prefix it with =
e.g =name -> name
If search is not prefixed with '=' the search is case insensitive."
}
proc search {args} {
set argd [punk::args::get_by_id ::punk::mix::commandset::loadedlib::search $args]
set searchstrings [dict get $argd values searchstrings]
set searchstrings [dict get $argd values searchstring]
set opts [dict get $argd opts]
set opt_return [dict get $opts -return]
set opt_highlight [dict get $opts -highlight]
set opt_refresh [dict get $opts -refresh]
if {$opt_refresh} {
catch {package require frobznodule666} ;#ensure pkg system has loaded/searched for everything REVIEW - this doesn't result in full scans
foreach tm_path [tcl::tm::list] {
set paths_below [punk::path::subfolders -recursive $tm_path]
foreach folder $paths_below {
set tail [file tail $folder]
if {[string match #modpod-* $tail] || [string match #tarjar-* $tail]} {
continue
}
if {[string match */_build/* $folder]} {continue}
set relpath [string tolower [punk::path::relative $tm_path $folder]]
set modpath [string map {/ ::} $relpath]
catch {package require ${modpath}::flobrudder99}
}
}
}
#REVIEW - this doesn't result in full scans
catch {package require frobznodule666} ;#ensure pkg system has loaded/searched for everything
set packages [package names]
set matches [list]
@ -122,9 +138,25 @@ namespace eval punk::mix::commandset::loadedlib {
}
}
}
proc loaded.search {searchstring} {
set search_result [search $searchstring]
set all_libs [split $search_result \n]
punk::args::define {
@id -id ::punk::mix::commandset::loadedlib::loaded.search
@cmd -name "punk::mix::commandset::loadedlib loaded.search"\
-summary\
"Search loaded libraries."\
-help "search all Tcl libraries currently loaded in your local interpreter.
ie those that have been loaded directly or indirectly by 'package require'."
}\
@values\
[punk::args::resolved_def -types values ::punk::mix::commandset::loadedlib::search searchstring]
proc loaded.search {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::loadedlib::loaded.search]
lassign [dict values $argd] leaders opts values
set searchstrings [dict get $values searchstring]
set all_libs [search -return list -highlight 0 {*}$searchstrings]
set col1items [list]
set col2items [list]
set col3items [list]

37
src/vfs/_vfscommon.vfs/modules/punk/path-0.1.0.tm

@ -99,7 +99,7 @@ package require punk::args
# Base namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval punk::path {
namespace export *
namespace export {[a-z]*}
#variable xyz
#*** !doctools
@ -645,6 +645,41 @@ namespace eval punk::path {
}
return $ismatch
}
punk::args::define {
@id -id ::punk::path::subfolders
@cmd -name punk::path::subfolders\
-summary\
"Listing of directories within supplied path."\
-help\
"List of folders below path.
The resulting list is unsorted."
@opts
-recursive -type none -help\
""
#todo -depth
@values -min 0 -max 1
path -type directory -optional 1 -help\
"Path of folder. If not supplied current directory is used."
}
proc subfolders {args} {
set argd [punk::args::parse $args withid ::punk::path::subfolders]
lassign [dict values $argd] leaders opts values received
set do_recursion [dict exists $received -recursive]
if {[dict exists $received path]} {
set path [dict get $values path]
} else {
set path [pwd]
}
set folders [glob -nocomplain -directory $path -types d *]
if {$do_recursion} {
foreach subdir $folders {
lappend folders {*}[subfolders -recursive $subdir]
}
}
return $folders
}
#todo - treefolders with similar search caps as treefilenames
punk::args::define {
@id -id ::punk::path::treefilenames

9
src/vfs/_vfscommon.vfs/modules/shellfilter-0.2.tm

@ -2792,7 +2792,7 @@ namespace eval shellfilter {
#chan configure $inchan -buffering none -blocking 1 ;test
#chan configure $inchan -buffering none -blocking 1 ;#test
chan configure $inchan -buffering $inbuffering -blocking 0 ;#we are setting up a readable handler for this - so non-blocking ok
@ -2831,10 +2831,15 @@ namespace eval shellfilter {
# Ideally we need something like exec,open in tcl that interacts with transformed channels directly and emits as it runs, not only at termination
# - and that at least appears like a terminal to the called command.
#set rdout [open |[concat $commandlist [list 2>@stderr <@$inchan]] [list RDONLY]]
#REVIEW!
#if the child process takes a while to begin reading stdin - the data on stdin between when we stopped the parent chan event handler and when the child gets data,
#seems to stay buffered somewhere. It is then read by the parent, after the child returns. (ie not lost, but out-of-order)
#This can be apparent sometimes even with fast typing upon calling an executable. (e.g occasionally even vim - but seems to be timing based so might only happen first time if at all)
# see scriptlib/stdin_race.tcl etc test files.
#similar problem with python & perl - issue seems to be in libc or OS buffering behaviour for standard channels.
#note that zig (repo/jn/zig/stdin_race) seems to avoid this issue - todo - make zig based binary extension for open/exec?
set rdout [open |[concat $commandlist [list 2>@$wrerr <@$inchan]] [list RDONLY]]
chan configure $rderr -buffering $errbuffering -blocking 0

Loading…
Cancel
Save