Browse Source

subshell and subprocess work

master
Julian Noble 4 months ago
parent
commit
7c40f63c2a
  1. 2
      src/bootsupport/modules/punk/args/tclcore-0.1.0.tm
  2. 115
      src/bootsupport/modules/punk/mix/commandset/project-0.1.0.tm
  3. 15
      src/lib/app-punk/repl.tcl
  4. 11
      src/make.tcl
  5. 45
      src/modules/picalc-999999.0a1.0.tm
  6. 2
      src/modules/punk/args-999999.0a1.0.tm
  7. 66
      src/modules/punk/imap4-999999.0a1.0.tm
  8. 2
      src/modules/punk/libunknown-0.1.tm
  9. 34
      src/modules/punk/mix/cli-999999.0a1.0.tm
  10. 115
      src/modules/punk/mix/commandset/project-999999.0a1.0.tm
  11. 33
      src/modules/punk/mix/commandset/repo-999999.0a1.0.tm
  12. 2
      src/modules/punk/mix/commandset/scriptwrap-999999.0a1.0.tm
  13. 20
      src/modules/punk/repl-999999.0a1.0.tm
  14. 32
      src/modules/punk/safe-999999.0a1.0.tm
  15. 52
      src/modules/punk/sixel-999999.0a1.0.tm
  16. 67
      src/modules/shellfilter-0.2.tm
  17. 3
      src/modules/test/punk/#modpod-args-999999.0a1.0/args-999999.0a1.0.tm
  18. 1
      src/modules/textblock-999999.0a1.0.tm
  19. 11
      src/project_layouts/custom/_project/punk.basic/src/make.tcl
  20. 2
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/args/tclcore-0.1.0.tm
  21. 115
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/commandset/project-0.1.0.tm
  22. 11
      src/project_layouts/custom/_project/punk.project-0.1/src/make.tcl
  23. 2
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/args/tclcore-0.1.0.tm
  24. 115
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/commandset/project-0.1.0.tm
  25. 11
      src/project_layouts/custom/_project/punk.shell-0.1/src/make.tcl
  26. 13
      src/vendormodules/tomlish-1.1.6.tm
  27. 15
      src/vfs/_vfscommon.vfs/lib/app-punk/repl.tcl
  28. 2
      src/vfs/_vfscommon.vfs/lib/kettle1/kettle.tcl
  29. 45
      src/vfs/_vfscommon.vfs/modules/picalc-0.1.0.tm
  30. 2
      src/vfs/_vfscommon.vfs/modules/punk/args-0.2.tm
  31. 2
      src/vfs/_vfscommon.vfs/modules/punk/args/tclcore-0.1.0.tm
  32. 29
      src/vfs/_vfscommon.vfs/modules/punk/docgen-0.1.0.tm
  33. 66
      src/vfs/_vfscommon.vfs/modules/punk/imap4-0.9.tm
  34. 2
      src/vfs/_vfscommon.vfs/modules/punk/libunknown-0.1.tm
  35. 34
      src/vfs/_vfscommon.vfs/modules/punk/mix/cli-0.3.1.tm
  36. 115
      src/vfs/_vfscommon.vfs/modules/punk/mix/commandset/project-0.1.0.tm
  37. 33
      src/vfs/_vfscommon.vfs/modules/punk/mix/commandset/repo-0.1.0.tm
  38. 2
      src/vfs/_vfscommon.vfs/modules/punk/mix/commandset/scriptwrap-0.1.0.tm
  39. 20
      src/vfs/_vfscommon.vfs/modules/punk/repl-0.1.2.tm
  40. 32
      src/vfs/_vfscommon.vfs/modules/punk/safe-0.1.0.tm
  41. 52
      src/vfs/_vfscommon.vfs/modules/punk/sixel-0.1.0.tm
  42. 67
      src/vfs/_vfscommon.vfs/modules/shellfilter-0.2.tm
  43. BIN
      src/vfs/_vfscommon.vfs/modules/test/punk/args-0.1.5.tm
  44. 1
      src/vfs/_vfscommon.vfs/modules/textblock-0.1.3.tm
  45. 13
      src/vfs/_vfscommon.vfs/modules/tomlish-1.1.6.tm

2
src/bootsupport/modules/punk/args/tclcore-0.1.0.tm

@ -2629,7 +2629,7 @@ tcl::namespace::eval punk::args::tclcore {
"Search for files which match the given patterns starting in the given ${$I}directory${$NI}. "Search for files which match the given patterns starting in the given ${$I}directory${$NI}.
This allows searching of directories whose name contains glob-sensitive characters This allows searching of directories whose name contains glob-sensitive characters
without the need to quote such characters explicitly. This option may not be used without the need to quote such characters explicitly. This option may not be used
in conjunction with ${$B}-path${$NI}, which is used to allow searching for complete file in conjunction with ${$B}-path${$N}, which is used to allow searching for complete file
paths whose names may contain glob-sensitive characters." paths whose names may contain glob-sensitive characters."
-join -type none -help\ -join -type none -help\
"The remaining pattern arguments, after option processing, are treated as a single "The remaining pattern arguments, after option processing, are treated as a single

115
src/bootsupport/modules/punk/mix/commandset/project-0.1.0.tm

@ -776,33 +776,70 @@ namespace eval punk::mix::commandset::project {
return $msg return $msg
#return [list_as_lines [lib::get_projects $glob]] #return [list_as_lines [lib::get_projects $glob]]
} }
proc cd {{glob {}} args} {
dict set args -cd 1
work $glob {*}$args punk::args::define {
@id -id ::punk::mix::commandset::project::collection::work
@cmd -name punk::mix::commandset::project::collection::work\
-summary\
"List projects with checkout directories."\
-help\
"Get project info by opening the central fossil config-db to determine
fossil database files for each project, and the known checkout folders.
If -detail is true, a second operation gathers file state information
for each checkout folder."
@leaders -min 0 -max 0
-cd -type none -help\
"If this flag is provided, after lsting, prompt the user to enter
the row number of the checkout to 'cd' into, or an option to cancel.
If there is only one project with only a single checkout, the
cd operation will occur without prompting unless -prompt was
also supplied."
-prompt -type none -help\
"If there is only one checkout in the result, cause a prompt to be
raised instead of automatically peforming the cd operation.
Has no effect if -cd was not supplied, or if -cd is supplied and
there are multiple checkouts, in which case user is always prompted."
-detail -type boolean -default 0 -help\
"Include file state information for each checkout in the resulting
table. This includes information such as which files are changed,
unchanged,new,missing or extra and can take a little more time to
gather as it must examine the filesystem for each checkout folder.
Note that although the default is false - if only a single project
matches the glob pattern(s) then file state will be gathered for
each of its checkouts. Use an explicit -detail 0 if this is not
desired."
@values -min 0 -max -1
glob -type string -multiple 1 -default * -optional 1 -help\
"glob patterns used to search for project. The glob is applied against
the names of the fossil repository database files - not the project-name,
which is not available in the central fossil config-db.
Case insensitive."
} }
proc work {{glob {}} args} { proc work {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::collection::work]
lassign [dict values $argd] leaders opts values received
package require sqlite3 package require sqlite3
set db_projects [lib::get_projects $glob] set globlist [dict get $values glob]
set db_projects [lib::get_projects {*}$globlist]
#list of lists of the form:
#{fosdb fname workdirlist}
if {[llength $db_projects] == 0} { if {[llength $db_projects] == 0} {
puts stderr "::punk::mix::commandset::project::work No Repo DB name matches found for '$glob'" puts stderr "::punk::mix::commandset::project::work No Repo DB name matches found for '$globlist'"
return "" return ""
} }
#list of lists of the form:
#{fosdb fname workdirlist}
set defaults [dict create\
-cd 0\
-detail "\uFFFF"\
]
set opts [dict merge $defaults $args]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set opt_cd [dict get $opts -cd] set opt_cd [dict exists $received -cd]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set opt_detail [dict get $opts -detail] set opt_detail [dict get $opts -detail]
set opt_detail_explicit_zero 1 ;#default assumption only if {[dict exists $received -detail] && !$opt_detail} {
if {$opt_detail eq "\uFFFF"} { set opt_detail_explicit_zero 1
} else {
set opt_detail_explicit_zero 0 set opt_detail_explicit_zero 0
set opt_detail 0; #default
} }
set opt_prompt [dict exists $received -prompt]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set workdir_dict [dict create] set workdir_dict [dict create]
set all_workdirs [list] set all_workdirs [list]
@ -991,7 +1028,7 @@ namespace eval punk::mix::commandset::project {
set numrows [llength $col_rowids] set numrows [llength $col_rowids]
if {$opt_cd && $numrows >= 1} { if {$opt_cd && $numrows >= 1} {
puts stdout $msg puts stdout $msg
if {$numrows == 1} { if {$numrows == 1 && !$opt_prompt} {
set workingdir [lindex $workdirs 0] set workingdir [lindex $workdirs 0]
puts stdout "1 result. Changing dir to $workingdir" puts stdout "1 result. Changing dir to $workingdir"
if {[file exists $workingdir]} { if {[file exists $workingdir]} {
@ -1014,6 +1051,30 @@ namespace eval punk::mix::commandset::project {
} }
return $msg return $msg
} }
punk::args::define {
@id -id ::punk::mix::commandset::project::collection::cd
@cmd -name punk::mix::commandset::project::collection::cd\
-summary\
"List projects with checkout directories and prompt for which checkout to cd to."\
-help\
"List projects with checkout directories and prompt for which checkout to cd to."
@leaders -min 0 -max 0
}\
[punk::args::resolved_def -types opts ::punk::mix::commandset::project::collection::work -detail]\
{
-prompt -type none -help\
"Prompt even when result contains only one checkout location as a possible cd target.
User will always be prompted if result contains more than one checkout."
@values -min 0 -max -1
}\
[punk::args::resolved_def -types values ::punk::mix::commandset::project::collection::work glob]
proc cd {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::collection::work]
work -cd {*}$args
}
#*** !doctools #*** !doctools
#[list_end] [comment {-- end collection namespace definitions --}] #[list_end] [comment {-- end collection namespace definitions --}]
} }
@ -1029,12 +1090,17 @@ namespace eval punk::mix::commandset::project {
@id -id ::punk::mix::commandset::project::lib::get_projects @id -id ::punk::mix::commandset::project::lib::get_projects
@cmd -name punk::mix::commandset::project::lib::get_projects\ @cmd -name punk::mix::commandset::project::lib::get_projects\
-summary\ -summary\
"List projects referred to by central fossil config-db."\ "Return a 3-element list of projects referred to by central fossil config-db."\
-help\ -help\
"Get project info only by opening the central fossil config-db "Get project info only by opening the central fossil config-db.
(will not have proper project-name etc)" Each member of the returned list is a 3-element list of:
<path_to_fossildb> <shortname> <list_of_checkout_paths>
The shortname is simply the name based on the root name of the fossil database,
it is not necessarily the project-name by which the project is referred to in the fossil
checkout databases."
@values -min 0 -max -1 @values -min 0 -max -1
glob -type string -multiple 1 -default * -optional 1 glob -type string -multiple 1 -default * -optional 1 -help\
"case insensitive glob for the name of the fossil database."
} }
proc get_projects {args} { proc get_projects {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::lib::get_projects] set argd [punk::args::parse $args withid ::punk::mix::commandset::project::lib::get_projects]
@ -1048,6 +1114,9 @@ namespace eval punk::mix::commandset::project {
::sqlite3 fosconf $configdb ::sqlite3 fosconf $configdb
#set testresult [fosconf eval {select name,value from global_config;}] #set testresult [fosconf eval {select name,value from global_config;}]
#puts stderr $testresult #puts stderr $testresult
#list of repositories of the form repo:<path>
#eg repo:C:/Users/someone/.fossils/tcl.fossil
set project_repos [fosconf eval {select name from global_config where name like 'repo:%';}] set project_repos [fosconf eval {select name from global_config where name like 'repo:%';}]
set paths_and_names [list] set paths_and_names [list]
foreach pr $project_repos { foreach pr $project_repos {
@ -1064,7 +1133,7 @@ namespace eval punk::mix::commandset::project {
} }
set filtered_list [list] set filtered_list [list]
foreach glob $globlist { foreach glob $globlist {
set matches [lsearch -all -inline -index 1 $paths_and_names $glob] set matches [lsearch -nocase -all -inline -index 1 $paths_and_names $glob]
foreach m $matches { foreach m $matches {
if {$m ni $filtered_list} { if {$m ni $filtered_list} {
lappend filtered_list $m lappend filtered_list $m

15
src/lib/app-punk/repl.tcl

@ -47,7 +47,20 @@ package require punk::repl
repl::init -safe 0 repl::init -safe 0
#puts stderr "Launching repl::start stdin -title app-punk" #puts stderr "Launching repl::start stdin -title app-punk"
#flush stderr #flush stderr
repl::start stdin -title app-punk set replresult [repl::start stdin -title app-punk]
catch {
puts "app-punk ifneeded: [package ifneeded app-punk 1.0]"
}
#review
if {[string is integer -strict $replresult]} {
puts stdout "repl.tcl exiting with numeric code $replresult"
exit $replresult
} else {
puts stdout "repl.tcl result $replresult"
flush stdout
exit 0
}
#puts "- repl app done -" #puts "- repl app done -"
#flush stdout #flush stdout

11
src/make.tcl

@ -1565,9 +1565,14 @@ if {$::punkboot::command eq "shell"} {
repl::init repl::init
repl::start stdin set replresult [repl::start stdin -title make.tcl]
#review
exit 1 if {[string is integer -strict $replresult]} {
exit $replresult
} else {
puts stdout $replresult
exit 0
}
} }
if {$::punkboot::command eq "vfscommonupdate"} { if {$::punkboot::command eq "vfscommonupdate"} {

45
src/modules/picalc-999999.0a1.0.tm

@ -65,39 +65,6 @@ package require punk::args
#*** !doctools #*** !doctools
#[section API] #[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# oo::class namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#tcl::namespace::eval picalc::class {
#*** !doctools
#[subsection {Namespace picalc::class}]
#[para] class definitions
#if {[tcl::info::commands [tcl::namespace::current]::interface_sample1] eq ""} {
#*** !doctools
#[list_begin enumerated]
# oo::class create interface_sample1 {
# #*** !doctools
# #[enum] CLASS [class interface_sample1]
# #[list_begin definitions]
# method test {arg1} {
# #*** !doctools
# #[call class::interface_sample1 [method test] [arg arg1]]
# #[para] test method
# puts "test: $arg1"
# }
# #*** !doctools
# #[list_end] [comment {-- end definitions interface_sample1}]
# }
#*** !doctools
#[list_end] [comment {--- end class enumeration ---}]
#}
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval picalc { tcl::namespace::eval picalc {
@ -502,18 +469,6 @@ tcl::namespace::eval picalc::lib {
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Internal]
#tcl::namespace::eval picalc::system {
#*** !doctools
#[subsection {Namespace picalc::system}]
#[para] Internal functions that are not part of the API
#}
# == === === === === === === === === === === === === === === # == === === === === === === === === === === === === === ===
# Sample 'about' function with punk::args documentation # Sample 'about' function with punk::args documentation

2
src/modules/punk/args-999999.0a1.0.tm

@ -222,7 +222,7 @@ package require Tcl 8.6-
tcl::namespace::eval punk::args::register { tcl::namespace::eval punk::args::register {
#*** !doctools #*** !doctools
#[subsection {Namespace punk::args}] #[subsection {Namespace punk::args::register}]
#[para] cooperative 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] 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. #[para] The punk::args package will then test for a public list variable <namepace>::PUNKARGS containing argument definitions when it needs to.

66
src/modules/punk/imap4-999999.0a1.0.tm

@ -1,6 +1,6 @@
# -*- tcl -*- # -*- tcl -*-
# Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'dev make' or bin/punkmake to update from <pkg>-buildversion.txt # Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'dev make' or bin/punkmake to update from <pkg>-buildversion.txt
# module template: shellspy/src/decktemplates/vendor/punk/modules/template_module-0.0.3.tm # module template: punkshell/src/decktemplates/vendor/punk/modules/template_module-0.0.3.tm
# #
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
@ -99,7 +99,7 @@
# doctools header # doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools #*** !doctools
#[manpage_begin shellspy_module_punk::imap4 0 999999.0a1.0] #[manpage_begin punkshell_module_punk::imap4 0 999999.0a1.0]
#[copyright "2025"] #[copyright "2025"]
#[titledesc {IMAP4 client}] [comment {-- Name section and table of contents description --}] #[titledesc {IMAP4 client}] [comment {-- Name section and table of contents description --}]
#[moddesc {IMAP4 client}] [comment {-- Description at end of page heading --}] #[moddesc {IMAP4 client}] [comment {-- Description at end of page heading --}]
@ -117,6 +117,15 @@
#[para] - #[para] -
tcl::namespace::eval punk::imap4 { tcl::namespace::eval punk::imap4 {
variable PUNKARGS
lappend PUNKARGS [list {
@id -id "(package)punk::imap4"
@package -name "punk::imap4"\
-title "IMAP4 client library"\
-description "An implementation of IMAP4 (rev1+?) client protocol."\
-copyright "2025"
}]
if {[info exists ::argv0] && [info script] eq $::argv0} { if {[info exists ::argv0] && [info script] eq $::argv0} {
#assert? - if argv0 exists and is same as [info script] - we're not in a safe interp #assert? - if argv0 exists and is same as [info script] - we're not in a safe interp
#when running a tm module as an app - we should calculate the corresponding tm path #when running a tm module as an app - we should calculate the corresponding tm path
@ -173,7 +182,7 @@ package require Tcl 8.6.2-
package require punk::args package require punk::args
package require punk::lib package require punk::lib
#*** !doctools #*** !doctools
#[item] [package {Tcl 8.6}] #[item] [package {Tcl 8.6.2-}]
#[item] [package {punk::args}] #[item] [package {punk::args}]
#[item] [package {punk::lib}] #[item] [package {punk::lib}]
@ -189,38 +198,6 @@ package require punk::lib
#*** !doctools #*** !doctools
#[section API] #[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# oo::class namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#tcl::namespace::eval punk::imap4::class {
#*** !doctools
#[subsection {Namespace punk::imap4::class}]
#[para] class definitions
#if {[tcl::info::commands [tcl::namespace::current]::interface_sample1] eq ""} {
#*** !doctools
#[list_begin enumerated]
# oo::class create interface_sample1 {
# #*** !doctools
# #[enum] CLASS [class interface_sample1]
# #[list_begin definitions]
# method test {arg1} {
# #*** !doctools
# #[call class::interface_sample1 [method test] [arg arg1]]
# #[para] test method
# puts "test: $arg1"
# }
# #*** !doctools
# #[list_end] [comment {-- end definitions interface_sample1}]
# }
#*** !doctools
#[list_end] [comment {--- end class enumeration ---}]
#}
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval punk::imap4::system { tcl::namespace::eval punk::imap4::system {
variable conlog variable conlog
@ -4243,19 +4220,6 @@ tcl::namespace::eval punk::imap4::lib {
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Internal]
#tcl::namespace::eval punk::imap4::system {
#*** !doctools
#[subsection {Namespace punk::imap4::system}]
#[para] Internal functions that are not part of the API
#}
# == === === === === === === === === === === === === === === # == === === === === === === === === === === === === === ===
# Sample 'about' function with punk::args documentation # Sample 'about' function with punk::args documentation
# == === === === === === === === === === === === === === === # == === === === === === === === === === === === === === ===
@ -4264,12 +4228,6 @@ tcl::namespace::eval punk::imap4 {
variable PUNKARGS variable PUNKARGS
variable PUNKARGS_aliases variable PUNKARGS_aliases
lappend PUNKARGS [list {
@id -id "(package)punk::imap4"
@package -name "punk::imap4" -help\
"Package
Description"
}]
namespace eval argdoc { namespace eval argdoc {
#namespace for custom argument documentation #namespace for custom argument documentation

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

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

34
src/modules/punk/mix/cli-999999.0a1.0.tm

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

115
src/modules/punk/mix/commandset/project-999999.0a1.0.tm

@ -776,33 +776,70 @@ namespace eval punk::mix::commandset::project {
return $msg return $msg
#return [list_as_lines [lib::get_projects $glob]] #return [list_as_lines [lib::get_projects $glob]]
} }
proc cd {{glob {}} args} {
dict set args -cd 1
work $glob {*}$args punk::args::define {
@id -id ::punk::mix::commandset::project::collection::work
@cmd -name punk::mix::commandset::project::collection::work\
-summary\
"List projects with checkout directories."\
-help\
"Get project info by opening the central fossil config-db to determine
fossil database files for each project, and the known checkout folders.
If -detail is true, a second operation gathers file state information
for each checkout folder."
@leaders -min 0 -max 0
-cd -type none -help\
"If this flag is provided, after lsting, prompt the user to enter
the row number of the checkout to 'cd' into, or an option to cancel.
If there is only one project with only a single checkout, the
cd operation will occur without prompting unless -prompt was
also supplied."
-prompt -type none -help\
"If there is only one checkout in the result, cause a prompt to be
raised instead of automatically peforming the cd operation.
Has no effect if -cd was not supplied, or if -cd is supplied and
there are multiple checkouts, in which case user is always prompted."
-detail -type boolean -default 0 -help\
"Include file state information for each checkout in the resulting
table. This includes information such as which files are changed,
unchanged,new,missing or extra and can take a little more time to
gather as it must examine the filesystem for each checkout folder.
Note that although the default is false - if only a single project
matches the glob pattern(s) then file state will be gathered for
each of its checkouts. Use an explicit -detail 0 if this is not
desired."
@values -min 0 -max -1
glob -type string -multiple 1 -default * -optional 1 -help\
"glob patterns used to search for project. The glob is applied against
the names of the fossil repository database files - not the project-name,
which is not available in the central fossil config-db.
Case insensitive."
} }
proc work {{glob {}} args} { proc work {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::collection::work]
lassign [dict values $argd] leaders opts values received
package require sqlite3 package require sqlite3
set db_projects [lib::get_projects $glob] set globlist [dict get $values glob]
set db_projects [lib::get_projects {*}$globlist]
#list of lists of the form:
#{fosdb fname workdirlist}
if {[llength $db_projects] == 0} { if {[llength $db_projects] == 0} {
puts stderr "::punk::mix::commandset::project::work No Repo DB name matches found for '$glob'" puts stderr "::punk::mix::commandset::project::work No Repo DB name matches found for '$globlist'"
return "" return ""
} }
#list of lists of the form:
#{fosdb fname workdirlist}
set defaults [dict create\
-cd 0\
-detail "\uFFFF"\
]
set opts [dict merge $defaults $args]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set opt_cd [dict get $opts -cd] set opt_cd [dict exists $received -cd]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set opt_detail [dict get $opts -detail] set opt_detail [dict get $opts -detail]
set opt_detail_explicit_zero 1 ;#default assumption only if {[dict exists $received -detail] && !$opt_detail} {
if {$opt_detail eq "\uFFFF"} { set opt_detail_explicit_zero 1
} else {
set opt_detail_explicit_zero 0 set opt_detail_explicit_zero 0
set opt_detail 0; #default
} }
set opt_prompt [dict exists $received -prompt]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set workdir_dict [dict create] set workdir_dict [dict create]
set all_workdirs [list] set all_workdirs [list]
@ -991,7 +1028,7 @@ namespace eval punk::mix::commandset::project {
set numrows [llength $col_rowids] set numrows [llength $col_rowids]
if {$opt_cd && $numrows >= 1} { if {$opt_cd && $numrows >= 1} {
puts stdout $msg puts stdout $msg
if {$numrows == 1} { if {$numrows == 1 && !$opt_prompt} {
set workingdir [lindex $workdirs 0] set workingdir [lindex $workdirs 0]
puts stdout "1 result. Changing dir to $workingdir" puts stdout "1 result. Changing dir to $workingdir"
if {[file exists $workingdir]} { if {[file exists $workingdir]} {
@ -1014,6 +1051,30 @@ namespace eval punk::mix::commandset::project {
} }
return $msg return $msg
} }
punk::args::define {
@id -id ::punk::mix::commandset::project::collection::cd
@cmd -name punk::mix::commandset::project::collection::cd\
-summary\
"List projects with checkout directories and prompt for which checkout to cd to."\
-help\
"List projects with checkout directories and prompt for which checkout to cd to."
@leaders -min 0 -max 0
}\
[punk::args::resolved_def -types opts ::punk::mix::commandset::project::collection::work -detail]\
{
-prompt -type none -help\
"Prompt even when result contains only one checkout location as a possible cd target.
User will always be prompted if result contains more than one checkout."
@values -min 0 -max -1
}\
[punk::args::resolved_def -types values ::punk::mix::commandset::project::collection::work glob]
proc cd {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::collection::work]
work -cd {*}$args
}
#*** !doctools #*** !doctools
#[list_end] [comment {-- end collection namespace definitions --}] #[list_end] [comment {-- end collection namespace definitions --}]
} }
@ -1029,12 +1090,17 @@ namespace eval punk::mix::commandset::project {
@id -id ::punk::mix::commandset::project::lib::get_projects @id -id ::punk::mix::commandset::project::lib::get_projects
@cmd -name punk::mix::commandset::project::lib::get_projects\ @cmd -name punk::mix::commandset::project::lib::get_projects\
-summary\ -summary\
"List projects referred to by central fossil config-db."\ "Return a 3-element list of projects referred to by central fossil config-db."\
-help\ -help\
"Get project info only by opening the central fossil config-db "Get project info only by opening the central fossil config-db.
(will not have proper project-name etc)" Each member of the returned list is a 3-element list of:
<path_to_fossildb> <shortname> <list_of_checkout_paths>
The shortname is simply the name based on the root name of the fossil database,
it is not necessarily the project-name by which the project is referred to in the fossil
checkout databases."
@values -min 0 -max -1 @values -min 0 -max -1
glob -type string -multiple 1 -default * -optional 1 glob -type string -multiple 1 -default * -optional 1 -help\
"case insensitive glob for the name of the fossil database."
} }
proc get_projects {args} { proc get_projects {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::lib::get_projects] set argd [punk::args::parse $args withid ::punk::mix::commandset::project::lib::get_projects]
@ -1048,6 +1114,9 @@ namespace eval punk::mix::commandset::project {
::sqlite3 fosconf $configdb ::sqlite3 fosconf $configdb
#set testresult [fosconf eval {select name,value from global_config;}] #set testresult [fosconf eval {select name,value from global_config;}]
#puts stderr $testresult #puts stderr $testresult
#list of repositories of the form repo:<path>
#eg repo:C:/Users/someone/.fossils/tcl.fossil
set project_repos [fosconf eval {select name from global_config where name like 'repo:%';}] set project_repos [fosconf eval {select name from global_config where name like 'repo:%';}]
set paths_and_names [list] set paths_and_names [list]
foreach pr $project_repos { foreach pr $project_repos {
@ -1064,7 +1133,7 @@ namespace eval punk::mix::commandset::project {
} }
set filtered_list [list] set filtered_list [list]
foreach glob $globlist { foreach glob $globlist {
set matches [lsearch -all -inline -index 1 $paths_and_names $glob] set matches [lsearch -nocase -all -inline -index 1 $paths_and_names $glob]
foreach m $matches { foreach m $matches {
if {$m ni $filtered_list} { if {$m ni $filtered_list} {
lappend filtered_list $m lappend filtered_list $m

33
src/modules/punk/mix/commandset/repo-999999.0a1.0.tm

@ -41,11 +41,27 @@ namespace eval punk::mix::commandset::repo {
return $result 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} { proc fossilize { args} {
#check if project already managed by fossil.. initialise and check in if not. #check if project already managed by fossil.. initialise and check in if not.
puts stderr "unimplemented" 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} { proc unfossilize {projectname args} {
#remove/archive .fossil #remove/archive .fossil
puts stderr "unimplemented" puts stderr "unimplemented"
@ -76,14 +92,27 @@ namespace eval punk::mix::commandset::repo {
#punk::args #punk::args
lappend PUNKARGS [list { lappend PUNKARGS [list {
@id -id ::punk::mix::commandset::repo::fossil-move-repository @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). "Move the fossil repository file (usually named with .fossil extension).
This is an interactive function which will prompt for answers on stdin This is an interactive function which will prompt for answers on stdin
before proceeding. before proceeding.
The move can be done even if there are open checkouts and will maintain 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 ""}} { 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 searchbase [pwd]
set projectinfo [punk::repo::find_repos $searchbase] set projectinfo [punk::repo::find_repos $searchbase]
set projectbase [dict get $projectinfo closest] set projectbase [dict get $projectinfo closest]

2
src/modules/punk/mix/commandset/scriptwrap-999999.0a1.0.tm

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

20
src/modules/punk/repl-999999.0a1.0.tm

@ -522,7 +522,14 @@ proc repl::start {inchan args} {
set codethread "" set codethread ""
set codethread_cond "" set codethread_cond ""
punk::console::mode line ;#review - revert to line mode on final exit - but we may be exiting a nested repl 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 return 0
} }
proc repl::post_operations {} { proc repl::post_operations {} {
@ -570,7 +577,7 @@ proc repl::reopen_stdin {} {
#todo - avoid putting this in gobal namespace? #todo - avoid putting this in gobal namespace?
#collisions with other libraries apps? #collisions with other libraries apps?
proc punk::repl::quit {args} { proc punk::repl::quit {args} {
set ::repl::done "quit {*}$args" set ::repl::done [list quit {*}$args]
#puts stderr "quit called" #puts stderr "quit called"
return "" ;#make sure to return nothing so "quit" doesn't land on stdout 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 set last_char_info_width 60
#review - string shouldn't be truncated prior to stripcodes - could chop ansi codes! #review - string shouldn't be truncated prior to ansistrip - could chop ansi codes!
#set summary "[::shellfilter::ansi::stripcodes [string range $out 0 $last_char_info_width]]"
set out_plain_text [punk::ansi::ansistrip $out] set out_plain_text [punk::ansi::ansistrip $out]
set summary [string range $out_plain_text 0 $last_char_info_width] set summary [string range $out_plain_text 0 $last_char_info_width]
if {[string length $summary] > $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)]} { if {![llength $input_chunks_waiting($inputchan)]} {
chan event $inputchan readable [list ::repl::repl_handler $inputchan $prompt_config] chan event $inputchan readable [list ::repl::repl_handler $inputchan $prompt_config]
} else { } 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] after idle [list ::repl::repl_handler $inputchan $prompt_config]
} }
#################################################### ####################################################
@ -2695,6 +2703,7 @@ namespace eval repl {
proc init {args} { proc init {args} {
puts stderr "-->repl::init $args"
if {![info exists ::argv0]} { if {![info exists ::argv0]} {
#error out before we create a thread - punk requires this - review #error out before we create a thread - punk requires this - review
error "::argv0 not set" error "::argv0 not set"
@ -2900,7 +2909,7 @@ namespace eval repl {
proc quit {args} { 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 #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 "" # 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 { proc editbuf args {
thread::send %replthread% [list punk::repl::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 #temporary debug aliases - deliberate violation of safety provided by safe interp
code alias escapeeval ::repl::interphelpers::escapeeval code alias escapeeval ::repl::interphelpers::escapeeval
code alias exit ::repl::interphelpers::quit
#experiment #experiment
#code alias ::shellfilter::stack ::shellfilter::stack #code alias ::shellfilter::stack ::shellfilter::stack

32
src/modules/punk/safe-999999.0a1.0.tm

@ -63,38 +63,6 @@ package require punk::args
#*** !doctools #*** !doctools
#[section API] #[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# oo::class namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#tcl::namespace::eval punk::safe::class {
#*** !doctools
#[subsection {Namespace punk::safe::class}]
#[para] class definitions
#if {[tcl::info::commands [tcl::namespace::current]::interface_sample1] eq ""} {
#*** !doctools
#[list_begin enumerated]
# oo::class create interface_sample1 {
# #*** !doctools
# #[enum] CLASS [class interface_sample1]
# #[list_begin definitions]
# method test {arg1} {
# #*** !doctools
# #[call class::interface_sample1 [method test] [arg arg1]]
# #[para] test method
# puts "test: $arg1"
# }
# #*** !doctools
# #[list_end] [comment {-- end definitions interface_sample1}]
# }
#*** !doctools
#[list_end] [comment {--- end class enumeration ---}]
#}
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Secondary API namespace # Secondary API namespace

52
src/modules/punk/sixel-999999.0a1.0.tm

@ -69,38 +69,6 @@ package require punk::ansi
#*** !doctools #*** !doctools
#[section API] #[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# oo::class namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#tcl::namespace::eval punk::sixel::class {
#*** !doctools
#[subsection {Namespace punk::sixel::class}]
#[para] class definitions
#if {[tcl::info::commands [tcl::namespace::current]::interface_sample1] eq ""} {
#*** !doctools
#[list_begin enumerated]
# oo::class create interface_sample1 {
# #*** !doctools
# #[enum] CLASS [class interface_sample1]
# #[list_begin definitions]
# method test {arg1} {
# #*** !doctools
# #[call class::interface_sample1 [method test] [arg arg1]]
# #[para] test method
# puts "test: $arg1"
# }
# #*** !doctools
# #[list_end] [comment {-- end definitions interface_sample1}]
# }
#*** !doctools
#[list_end] [comment {--- end class enumeration ---}]
#}
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#reading #reading
#https://www.reddit.com/r/linux/comments/t3m7zm/quick_roundup_of_bitmap_graphics_availability_in/ #https://www.reddit.com/r/linux/comments/t3m7zm/quick_roundup_of_bitmap_graphics_availability_in/
@ -122,20 +90,6 @@ tcl::namespace::eval punk::sixel {
#proc sample1 {p1 n args} {
# #*** !doctools
# #[call [fun sample1] [arg p1] [arg n] [opt {option value...}]]
# #[para]Description of sample1
# #[para] Arguments:
# # [list_begin arguments]
# # [arg_def tring p1] A description of string argument p1.
# # [arg_def integer n] A description of integer argument n.
# # [list_end]
# return "ok"
#}
#terminated by ST #terminated by ST
#some older terminals may terminate at first other esc encountered. #some older terminals may terminate at first other esc encountered.
#non-sixel characters ignored (? review) #non-sixel characters ignored (? review)
@ -286,12 +240,6 @@ tcl::namespace::eval punk::sixel::lib {
#[para] Secondary functions that are part of the API #[para] Secondary functions that are part of the API
#[list_begin definitions] #[list_begin definitions]
#proc utility1 {p1 args} {
# #*** !doctools
# #[call lib::[fun utility1] [arg p1] [opt {?option value...?}]]
# #[para]Description of utility1
# return 1
#}
proc ascii_to_sixelvalue {a} { proc ascii_to_sixelvalue {a} {
set dec [scan $a %c] set dec [scan $a %c]
if {$dec < 63 || $dec > 127} {error "ascii character to convert to sixel value must be from 63 to 126 (chars '?' through to '~')"} if {$dec < 63 || $dec > 127} {error "ascii character to convert to sixel value must be from 63 to 126 (chars '?' through to '~')"}

67
src/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 { namespace eval shellfilter::chan {
set testobj ::shellfilter::chan::var set testobj ::shellfilter::chan::var
if {$testobj ni [info commands $testobj]} { 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 $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 $errchan -buffering $errbuffering
#chan configure $outchan -blocking 0 #chan configure $outchan -blocking 0
chan configure $outchan -buffering $outbuffering ;#don't configure non-blocking. weird duplicate of *second* line occurs if you do. chan configure $outchan -buffering $outbuffering ;#don't configure non-blocking. weird duplicate of *second* line occurs if you do.
@ -2889,7 +2832,9 @@ namespace eval shellfilter {
# - and that at least appears like a terminal to the called command. # - and that at least appears like a terminal to the called command.
#set rdout [open |[concat $commandlist [list 2>@stderr <@$inchan]] [list RDONLY]] #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)
set rdout [open |[concat $commandlist [list 2>@$wrerr <@$inchan]] [list RDONLY]] set rdout [open |[concat $commandlist [list 2>@$wrerr <@$inchan]] [list RDONLY]]
chan configure $rderr -buffering $errbuffering -blocking 0 chan configure $rderr -buffering $errbuffering -blocking 0

3
src/modules/test/punk/#modpod-args-999999.0a1.0/args-999999.0a1.0.tm

@ -119,8 +119,7 @@ tcl::namespace::eval test::punk::args {
lappend PUNKARGS [list { lappend PUNKARGS [list {
@id -id "(package)test::punk::args" @id -id "(package)test::punk::args"
@package -name "test::punk::args" -help\ @package -name "test::punk::args" -help\
"Package "Test suites for punk::args"
Description"
}] }]
namespace eval argdoc { namespace eval argdoc {

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

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

11
src/project_layouts/custom/_project/punk.basic/src/make.tcl

@ -1565,9 +1565,14 @@ if {$::punkboot::command eq "shell"} {
repl::init repl::init
repl::start stdin set replresult [repl::start stdin -title make.tcl]
#review
exit 1 if {[string is integer -strict $replresult]} {
exit $replresult
} else {
puts stdout $replresult
exit 0
}
} }
if {$::punkboot::command eq "vfscommonupdate"} { if {$::punkboot::command eq "vfscommonupdate"} {

2
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/args/tclcore-0.1.0.tm

@ -2629,7 +2629,7 @@ tcl::namespace::eval punk::args::tclcore {
"Search for files which match the given patterns starting in the given ${$I}directory${$NI}. "Search for files which match the given patterns starting in the given ${$I}directory${$NI}.
This allows searching of directories whose name contains glob-sensitive characters This allows searching of directories whose name contains glob-sensitive characters
without the need to quote such characters explicitly. This option may not be used without the need to quote such characters explicitly. This option may not be used
in conjunction with ${$B}-path${$NI}, which is used to allow searching for complete file in conjunction with ${$B}-path${$N}, which is used to allow searching for complete file
paths whose names may contain glob-sensitive characters." paths whose names may contain glob-sensitive characters."
-join -type none -help\ -join -type none -help\
"The remaining pattern arguments, after option processing, are treated as a single "The remaining pattern arguments, after option processing, are treated as a single

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

@ -776,33 +776,70 @@ namespace eval punk::mix::commandset::project {
return $msg return $msg
#return [list_as_lines [lib::get_projects $glob]] #return [list_as_lines [lib::get_projects $glob]]
} }
proc cd {{glob {}} args} {
dict set args -cd 1
work $glob {*}$args punk::args::define {
@id -id ::punk::mix::commandset::project::collection::work
@cmd -name punk::mix::commandset::project::collection::work\
-summary\
"List projects with checkout directories."\
-help\
"Get project info by opening the central fossil config-db to determine
fossil database files for each project, and the known checkout folders.
If -detail is true, a second operation gathers file state information
for each checkout folder."
@leaders -min 0 -max 0
-cd -type none -help\
"If this flag is provided, after lsting, prompt the user to enter
the row number of the checkout to 'cd' into, or an option to cancel.
If there is only one project with only a single checkout, the
cd operation will occur without prompting unless -prompt was
also supplied."
-prompt -type none -help\
"If there is only one checkout in the result, cause a prompt to be
raised instead of automatically peforming the cd operation.
Has no effect if -cd was not supplied, or if -cd is supplied and
there are multiple checkouts, in which case user is always prompted."
-detail -type boolean -default 0 -help\
"Include file state information for each checkout in the resulting
table. This includes information such as which files are changed,
unchanged,new,missing or extra and can take a little more time to
gather as it must examine the filesystem for each checkout folder.
Note that although the default is false - if only a single project
matches the glob pattern(s) then file state will be gathered for
each of its checkouts. Use an explicit -detail 0 if this is not
desired."
@values -min 0 -max -1
glob -type string -multiple 1 -default * -optional 1 -help\
"glob patterns used to search for project. The glob is applied against
the names of the fossil repository database files - not the project-name,
which is not available in the central fossil config-db.
Case insensitive."
} }
proc work {{glob {}} args} { proc work {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::collection::work]
lassign [dict values $argd] leaders opts values received
package require sqlite3 package require sqlite3
set db_projects [lib::get_projects $glob] set globlist [dict get $values glob]
set db_projects [lib::get_projects {*}$globlist]
#list of lists of the form:
#{fosdb fname workdirlist}
if {[llength $db_projects] == 0} { if {[llength $db_projects] == 0} {
puts stderr "::punk::mix::commandset::project::work No Repo DB name matches found for '$glob'" puts stderr "::punk::mix::commandset::project::work No Repo DB name matches found for '$globlist'"
return "" return ""
} }
#list of lists of the form:
#{fosdb fname workdirlist}
set defaults [dict create\
-cd 0\
-detail "\uFFFF"\
]
set opts [dict merge $defaults $args]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set opt_cd [dict get $opts -cd] set opt_cd [dict exists $received -cd]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set opt_detail [dict get $opts -detail] set opt_detail [dict get $opts -detail]
set opt_detail_explicit_zero 1 ;#default assumption only if {[dict exists $received -detail] && !$opt_detail} {
if {$opt_detail eq "\uFFFF"} { set opt_detail_explicit_zero 1
} else {
set opt_detail_explicit_zero 0 set opt_detail_explicit_zero 0
set opt_detail 0; #default
} }
set opt_prompt [dict exists $received -prompt]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set workdir_dict [dict create] set workdir_dict [dict create]
set all_workdirs [list] set all_workdirs [list]
@ -991,7 +1028,7 @@ namespace eval punk::mix::commandset::project {
set numrows [llength $col_rowids] set numrows [llength $col_rowids]
if {$opt_cd && $numrows >= 1} { if {$opt_cd && $numrows >= 1} {
puts stdout $msg puts stdout $msg
if {$numrows == 1} { if {$numrows == 1 && !$opt_prompt} {
set workingdir [lindex $workdirs 0] set workingdir [lindex $workdirs 0]
puts stdout "1 result. Changing dir to $workingdir" puts stdout "1 result. Changing dir to $workingdir"
if {[file exists $workingdir]} { if {[file exists $workingdir]} {
@ -1014,6 +1051,30 @@ namespace eval punk::mix::commandset::project {
} }
return $msg return $msg
} }
punk::args::define {
@id -id ::punk::mix::commandset::project::collection::cd
@cmd -name punk::mix::commandset::project::collection::cd\
-summary\
"List projects with checkout directories and prompt for which checkout to cd to."\
-help\
"List projects with checkout directories and prompt for which checkout to cd to."
@leaders -min 0 -max 0
}\
[punk::args::resolved_def -types opts ::punk::mix::commandset::project::collection::work -detail]\
{
-prompt -type none -help\
"Prompt even when result contains only one checkout location as a possible cd target.
User will always be prompted if result contains more than one checkout."
@values -min 0 -max -1
}\
[punk::args::resolved_def -types values ::punk::mix::commandset::project::collection::work glob]
proc cd {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::collection::work]
work -cd {*}$args
}
#*** !doctools #*** !doctools
#[list_end] [comment {-- end collection namespace definitions --}] #[list_end] [comment {-- end collection namespace definitions --}]
} }
@ -1029,12 +1090,17 @@ namespace eval punk::mix::commandset::project {
@id -id ::punk::mix::commandset::project::lib::get_projects @id -id ::punk::mix::commandset::project::lib::get_projects
@cmd -name punk::mix::commandset::project::lib::get_projects\ @cmd -name punk::mix::commandset::project::lib::get_projects\
-summary\ -summary\
"List projects referred to by central fossil config-db."\ "Return a 3-element list of projects referred to by central fossil config-db."\
-help\ -help\
"Get project info only by opening the central fossil config-db "Get project info only by opening the central fossil config-db.
(will not have proper project-name etc)" Each member of the returned list is a 3-element list of:
<path_to_fossildb> <shortname> <list_of_checkout_paths>
The shortname is simply the name based on the root name of the fossil database,
it is not necessarily the project-name by which the project is referred to in the fossil
checkout databases."
@values -min 0 -max -1 @values -min 0 -max -1
glob -type string -multiple 1 -default * -optional 1 glob -type string -multiple 1 -default * -optional 1 -help\
"case insensitive glob for the name of the fossil database."
} }
proc get_projects {args} { proc get_projects {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::lib::get_projects] set argd [punk::args::parse $args withid ::punk::mix::commandset::project::lib::get_projects]
@ -1048,6 +1114,9 @@ namespace eval punk::mix::commandset::project {
::sqlite3 fosconf $configdb ::sqlite3 fosconf $configdb
#set testresult [fosconf eval {select name,value from global_config;}] #set testresult [fosconf eval {select name,value from global_config;}]
#puts stderr $testresult #puts stderr $testresult
#list of repositories of the form repo:<path>
#eg repo:C:/Users/someone/.fossils/tcl.fossil
set project_repos [fosconf eval {select name from global_config where name like 'repo:%';}] set project_repos [fosconf eval {select name from global_config where name like 'repo:%';}]
set paths_and_names [list] set paths_and_names [list]
foreach pr $project_repos { foreach pr $project_repos {
@ -1064,7 +1133,7 @@ namespace eval punk::mix::commandset::project {
} }
set filtered_list [list] set filtered_list [list]
foreach glob $globlist { foreach glob $globlist {
set matches [lsearch -all -inline -index 1 $paths_and_names $glob] set matches [lsearch -nocase -all -inline -index 1 $paths_and_names $glob]
foreach m $matches { foreach m $matches {
if {$m ni $filtered_list} { if {$m ni $filtered_list} {
lappend filtered_list $m lappend filtered_list $m

11
src/project_layouts/custom/_project/punk.project-0.1/src/make.tcl

@ -1565,9 +1565,14 @@ if {$::punkboot::command eq "shell"} {
repl::init repl::init
repl::start stdin set replresult [repl::start stdin -title make.tcl]
#review
exit 1 if {[string is integer -strict $replresult]} {
exit $replresult
} else {
puts stdout $replresult
exit 0
}
} }
if {$::punkboot::command eq "vfscommonupdate"} { if {$::punkboot::command eq "vfscommonupdate"} {

2
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/args/tclcore-0.1.0.tm

@ -2629,7 +2629,7 @@ tcl::namespace::eval punk::args::tclcore {
"Search for files which match the given patterns starting in the given ${$I}directory${$NI}. "Search for files which match the given patterns starting in the given ${$I}directory${$NI}.
This allows searching of directories whose name contains glob-sensitive characters This allows searching of directories whose name contains glob-sensitive characters
without the need to quote such characters explicitly. This option may not be used without the need to quote such characters explicitly. This option may not be used
in conjunction with ${$B}-path${$NI}, which is used to allow searching for complete file in conjunction with ${$B}-path${$N}, which is used to allow searching for complete file
paths whose names may contain glob-sensitive characters." paths whose names may contain glob-sensitive characters."
-join -type none -help\ -join -type none -help\
"The remaining pattern arguments, after option processing, are treated as a single "The remaining pattern arguments, after option processing, are treated as a single

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

@ -776,33 +776,70 @@ namespace eval punk::mix::commandset::project {
return $msg return $msg
#return [list_as_lines [lib::get_projects $glob]] #return [list_as_lines [lib::get_projects $glob]]
} }
proc cd {{glob {}} args} {
dict set args -cd 1
work $glob {*}$args punk::args::define {
@id -id ::punk::mix::commandset::project::collection::work
@cmd -name punk::mix::commandset::project::collection::work\
-summary\
"List projects with checkout directories."\
-help\
"Get project info by opening the central fossil config-db to determine
fossil database files for each project, and the known checkout folders.
If -detail is true, a second operation gathers file state information
for each checkout folder."
@leaders -min 0 -max 0
-cd -type none -help\
"If this flag is provided, after lsting, prompt the user to enter
the row number of the checkout to 'cd' into, or an option to cancel.
If there is only one project with only a single checkout, the
cd operation will occur without prompting unless -prompt was
also supplied."
-prompt -type none -help\
"If there is only one checkout in the result, cause a prompt to be
raised instead of automatically peforming the cd operation.
Has no effect if -cd was not supplied, or if -cd is supplied and
there are multiple checkouts, in which case user is always prompted."
-detail -type boolean -default 0 -help\
"Include file state information for each checkout in the resulting
table. This includes information such as which files are changed,
unchanged,new,missing or extra and can take a little more time to
gather as it must examine the filesystem for each checkout folder.
Note that although the default is false - if only a single project
matches the glob pattern(s) then file state will be gathered for
each of its checkouts. Use an explicit -detail 0 if this is not
desired."
@values -min 0 -max -1
glob -type string -multiple 1 -default * -optional 1 -help\
"glob patterns used to search for project. The glob is applied against
the names of the fossil repository database files - not the project-name,
which is not available in the central fossil config-db.
Case insensitive."
} }
proc work {{glob {}} args} { proc work {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::collection::work]
lassign [dict values $argd] leaders opts values received
package require sqlite3 package require sqlite3
set db_projects [lib::get_projects $glob] set globlist [dict get $values glob]
set db_projects [lib::get_projects {*}$globlist]
#list of lists of the form:
#{fosdb fname workdirlist}
if {[llength $db_projects] == 0} { if {[llength $db_projects] == 0} {
puts stderr "::punk::mix::commandset::project::work No Repo DB name matches found for '$glob'" puts stderr "::punk::mix::commandset::project::work No Repo DB name matches found for '$globlist'"
return "" return ""
} }
#list of lists of the form:
#{fosdb fname workdirlist}
set defaults [dict create\
-cd 0\
-detail "\uFFFF"\
]
set opts [dict merge $defaults $args]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set opt_cd [dict get $opts -cd] set opt_cd [dict exists $received -cd]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set opt_detail [dict get $opts -detail] set opt_detail [dict get $opts -detail]
set opt_detail_explicit_zero 1 ;#default assumption only if {[dict exists $received -detail] && !$opt_detail} {
if {$opt_detail eq "\uFFFF"} { set opt_detail_explicit_zero 1
} else {
set opt_detail_explicit_zero 0 set opt_detail_explicit_zero 0
set opt_detail 0; #default
} }
set opt_prompt [dict exists $received -prompt]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set workdir_dict [dict create] set workdir_dict [dict create]
set all_workdirs [list] set all_workdirs [list]
@ -991,7 +1028,7 @@ namespace eval punk::mix::commandset::project {
set numrows [llength $col_rowids] set numrows [llength $col_rowids]
if {$opt_cd && $numrows >= 1} { if {$opt_cd && $numrows >= 1} {
puts stdout $msg puts stdout $msg
if {$numrows == 1} { if {$numrows == 1 && !$opt_prompt} {
set workingdir [lindex $workdirs 0] set workingdir [lindex $workdirs 0]
puts stdout "1 result. Changing dir to $workingdir" puts stdout "1 result. Changing dir to $workingdir"
if {[file exists $workingdir]} { if {[file exists $workingdir]} {
@ -1014,6 +1051,30 @@ namespace eval punk::mix::commandset::project {
} }
return $msg return $msg
} }
punk::args::define {
@id -id ::punk::mix::commandset::project::collection::cd
@cmd -name punk::mix::commandset::project::collection::cd\
-summary\
"List projects with checkout directories and prompt for which checkout to cd to."\
-help\
"List projects with checkout directories and prompt for which checkout to cd to."
@leaders -min 0 -max 0
}\
[punk::args::resolved_def -types opts ::punk::mix::commandset::project::collection::work -detail]\
{
-prompt -type none -help\
"Prompt even when result contains only one checkout location as a possible cd target.
User will always be prompted if result contains more than one checkout."
@values -min 0 -max -1
}\
[punk::args::resolved_def -types values ::punk::mix::commandset::project::collection::work glob]
proc cd {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::collection::work]
work -cd {*}$args
}
#*** !doctools #*** !doctools
#[list_end] [comment {-- end collection namespace definitions --}] #[list_end] [comment {-- end collection namespace definitions --}]
} }
@ -1029,12 +1090,17 @@ namespace eval punk::mix::commandset::project {
@id -id ::punk::mix::commandset::project::lib::get_projects @id -id ::punk::mix::commandset::project::lib::get_projects
@cmd -name punk::mix::commandset::project::lib::get_projects\ @cmd -name punk::mix::commandset::project::lib::get_projects\
-summary\ -summary\
"List projects referred to by central fossil config-db."\ "Return a 3-element list of projects referred to by central fossil config-db."\
-help\ -help\
"Get project info only by opening the central fossil config-db "Get project info only by opening the central fossil config-db.
(will not have proper project-name etc)" Each member of the returned list is a 3-element list of:
<path_to_fossildb> <shortname> <list_of_checkout_paths>
The shortname is simply the name based on the root name of the fossil database,
it is not necessarily the project-name by which the project is referred to in the fossil
checkout databases."
@values -min 0 -max -1 @values -min 0 -max -1
glob -type string -multiple 1 -default * -optional 1 glob -type string -multiple 1 -default * -optional 1 -help\
"case insensitive glob for the name of the fossil database."
} }
proc get_projects {args} { proc get_projects {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::lib::get_projects] set argd [punk::args::parse $args withid ::punk::mix::commandset::project::lib::get_projects]
@ -1048,6 +1114,9 @@ namespace eval punk::mix::commandset::project {
::sqlite3 fosconf $configdb ::sqlite3 fosconf $configdb
#set testresult [fosconf eval {select name,value from global_config;}] #set testresult [fosconf eval {select name,value from global_config;}]
#puts stderr $testresult #puts stderr $testresult
#list of repositories of the form repo:<path>
#eg repo:C:/Users/someone/.fossils/tcl.fossil
set project_repos [fosconf eval {select name from global_config where name like 'repo:%';}] set project_repos [fosconf eval {select name from global_config where name like 'repo:%';}]
set paths_and_names [list] set paths_and_names [list]
foreach pr $project_repos { foreach pr $project_repos {
@ -1064,7 +1133,7 @@ namespace eval punk::mix::commandset::project {
} }
set filtered_list [list] set filtered_list [list]
foreach glob $globlist { foreach glob $globlist {
set matches [lsearch -all -inline -index 1 $paths_and_names $glob] set matches [lsearch -nocase -all -inline -index 1 $paths_and_names $glob]
foreach m $matches { foreach m $matches {
if {$m ni $filtered_list} { if {$m ni $filtered_list} {
lappend filtered_list $m lappend filtered_list $m

11
src/project_layouts/custom/_project/punk.shell-0.1/src/make.tcl

@ -1565,9 +1565,14 @@ if {$::punkboot::command eq "shell"} {
repl::init repl::init
repl::start stdin set replresult [repl::start stdin -title make.tcl]
#review
exit 1 if {[string is integer -strict $replresult]} {
exit $replresult
} else {
puts stdout $replresult
exit 0
}
} }
if {$::punkboot::command eq "vfscommonupdate"} { if {$::punkboot::command eq "vfscommonupdate"} {

13
src/vendormodules/tomlish-1.1.6.tm

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

15
src/vfs/_vfscommon.vfs/lib/app-punk/repl.tcl

@ -47,7 +47,20 @@ package require punk::repl
repl::init -safe 0 repl::init -safe 0
#puts stderr "Launching repl::start stdin -title app-punk" #puts stderr "Launching repl::start stdin -title app-punk"
#flush stderr #flush stderr
repl::start stdin -title app-punk set replresult [repl::start stdin -title app-punk]
catch {
puts "app-punk ifneeded: [package ifneeded app-punk 1.0]"
}
#review
if {[string is integer -strict $replresult]} {
puts stdout "repl.tcl exiting with numeric code $replresult"
exit $replresult
} else {
puts stdout "repl.tcl result $replresult"
flush stdout
exit 0
}
#puts "- repl app done -" #puts "- repl app done -"
#flush stdout #flush stdout

2
src/vfs/_vfscommon.vfs/lib/kettle1/kettle.tcl

@ -27,7 +27,7 @@
# # ## ### ##### ######## ############# ##################### # # ## ### ##### ######## ############# #####################
## Requisites ## Requisites
package require Tcl 8.5 package require Tcl 8.5-
namespace eval ::kettle {} namespace eval ::kettle {}
# # ## ### ##### ######## ############# ##################### # # ## ### ##### ######## ############# #####################

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

@ -65,39 +65,6 @@ package require punk::args
#*** !doctools #*** !doctools
#[section API] #[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# oo::class namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#tcl::namespace::eval picalc::class {
#*** !doctools
#[subsection {Namespace picalc::class}]
#[para] class definitions
#if {[tcl::info::commands [tcl::namespace::current]::interface_sample1] eq ""} {
#*** !doctools
#[list_begin enumerated]
# oo::class create interface_sample1 {
# #*** !doctools
# #[enum] CLASS [class interface_sample1]
# #[list_begin definitions]
# method test {arg1} {
# #*** !doctools
# #[call class::interface_sample1 [method test] [arg arg1]]
# #[para] test method
# puts "test: $arg1"
# }
# #*** !doctools
# #[list_end] [comment {-- end definitions interface_sample1}]
# }
#*** !doctools
#[list_end] [comment {--- end class enumeration ---}]
#}
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval picalc { tcl::namespace::eval picalc {
@ -502,18 +469,6 @@ tcl::namespace::eval picalc::lib {
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Internal]
#tcl::namespace::eval picalc::system {
#*** !doctools
#[subsection {Namespace picalc::system}]
#[para] Internal functions that are not part of the API
#}
# == === === === === === === === === === === === === === === # == === === === === === === === === === === === === === ===
# Sample 'about' function with punk::args documentation # Sample 'about' function with punk::args documentation

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

@ -222,7 +222,7 @@ package require Tcl 8.6-
tcl::namespace::eval punk::args::register { tcl::namespace::eval punk::args::register {
#*** !doctools #*** !doctools
#[subsection {Namespace punk::args}] #[subsection {Namespace punk::args::register}]
#[para] cooperative 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] 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. #[para] The punk::args package will then test for a public list variable <namepace>::PUNKARGS containing argument definitions when it needs to.

2
src/vfs/_vfscommon.vfs/modules/punk/args/tclcore-0.1.0.tm

@ -2629,7 +2629,7 @@ tcl::namespace::eval punk::args::tclcore {
"Search for files which match the given patterns starting in the given ${$I}directory${$NI}. "Search for files which match the given patterns starting in the given ${$I}directory${$NI}.
This allows searching of directories whose name contains glob-sensitive characters This allows searching of directories whose name contains glob-sensitive characters
without the need to quote such characters explicitly. This option may not be used without the need to quote such characters explicitly. This option may not be used
in conjunction with ${$B}-path${$NI}, which is used to allow searching for complete file in conjunction with ${$B}-path${$N}, which is used to allow searching for complete file
paths whose names may contain glob-sensitive characters." paths whose names may contain glob-sensitive characters."
-join -type none -help\ -join -type none -help\
"The remaining pattern arguments, after option processing, are treated as a single "The remaining pattern arguments, after option processing, are treated as a single

29
src/vfs/_vfscommon.vfs/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 data [string map [list \r\n \n] $data]
set in_doctools 0 set in_doctools 0
set doctools "" 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] { foreach ln [split $data \n] {
set ln [string trim $ln] set ln [string trim $ln]
if {$in_doctools && [string index $ln 0] != "#"} { if {$in_doctools} {
set in_doctools 0 if {[string index $ln 0] != "#"} {
} elseif {[string range $ln 0 1] == "#*"} { set in_doctools 0
#todo - process doctools ordering hints in tail of line } else {
set in_doctools 1 append doctools [string range $ln 1 end] \n
} elseif {$in_doctools} { }
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 return $doctools

66
src/vfs/_vfscommon.vfs/modules/punk/imap4-0.9.tm

@ -1,6 +1,6 @@
# -*- tcl -*- # -*- tcl -*-
# Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'dev make' or bin/punkmake to update from <pkg>-buildversion.txt # Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'dev make' or bin/punkmake to update from <pkg>-buildversion.txt
# module template: shellspy/src/decktemplates/vendor/punk/modules/template_module-0.0.3.tm # module template: punkshell/src/decktemplates/vendor/punk/modules/template_module-0.0.3.tm
# #
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
@ -99,7 +99,7 @@
# doctools header # doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools #*** !doctools
#[manpage_begin shellspy_module_punk::imap4 0 0.9] #[manpage_begin punkshell_module_punk::imap4 0 0.9]
#[copyright "2025"] #[copyright "2025"]
#[titledesc {IMAP4 client}] [comment {-- Name section and table of contents description --}] #[titledesc {IMAP4 client}] [comment {-- Name section and table of contents description --}]
#[moddesc {IMAP4 client}] [comment {-- Description at end of page heading --}] #[moddesc {IMAP4 client}] [comment {-- Description at end of page heading --}]
@ -117,6 +117,15 @@
#[para] - #[para] -
tcl::namespace::eval punk::imap4 { tcl::namespace::eval punk::imap4 {
variable PUNKARGS
lappend PUNKARGS [list {
@id -id "(package)punk::imap4"
@package -name "punk::imap4"\
-title "IMAP4 client library"\
-description "An implementation of IMAP4 (rev1+?) client protocol."\
-copyright "2025"
}]
if {[info exists ::argv0] && [info script] eq $::argv0} { if {[info exists ::argv0] && [info script] eq $::argv0} {
#assert? - if argv0 exists and is same as [info script] - we're not in a safe interp #assert? - if argv0 exists and is same as [info script] - we're not in a safe interp
#when running a tm module as an app - we should calculate the corresponding tm path #when running a tm module as an app - we should calculate the corresponding tm path
@ -173,7 +182,7 @@ package require Tcl 8.6.2-
package require punk::args package require punk::args
package require punk::lib package require punk::lib
#*** !doctools #*** !doctools
#[item] [package {Tcl 8.6}] #[item] [package {Tcl 8.6.2-}]
#[item] [package {punk::args}] #[item] [package {punk::args}]
#[item] [package {punk::lib}] #[item] [package {punk::lib}]
@ -189,38 +198,6 @@ package require punk::lib
#*** !doctools #*** !doctools
#[section API] #[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# oo::class namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#tcl::namespace::eval punk::imap4::class {
#*** !doctools
#[subsection {Namespace punk::imap4::class}]
#[para] class definitions
#if {[tcl::info::commands [tcl::namespace::current]::interface_sample1] eq ""} {
#*** !doctools
#[list_begin enumerated]
# oo::class create interface_sample1 {
# #*** !doctools
# #[enum] CLASS [class interface_sample1]
# #[list_begin definitions]
# method test {arg1} {
# #*** !doctools
# #[call class::interface_sample1 [method test] [arg arg1]]
# #[para] test method
# puts "test: $arg1"
# }
# #*** !doctools
# #[list_end] [comment {-- end definitions interface_sample1}]
# }
#*** !doctools
#[list_end] [comment {--- end class enumeration ---}]
#}
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval punk::imap4::system { tcl::namespace::eval punk::imap4::system {
variable conlog variable conlog
@ -4243,19 +4220,6 @@ tcl::namespace::eval punk::imap4::lib {
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Internal]
#tcl::namespace::eval punk::imap4::system {
#*** !doctools
#[subsection {Namespace punk::imap4::system}]
#[para] Internal functions that are not part of the API
#}
# == === === === === === === === === === === === === === === # == === === === === === === === === === === === === === ===
# Sample 'about' function with punk::args documentation # Sample 'about' function with punk::args documentation
# == === === === === === === === === === === === === === === # == === === === === === === === === === === === === === ===
@ -4264,12 +4228,6 @@ tcl::namespace::eval punk::imap4 {
variable PUNKARGS variable PUNKARGS
variable PUNKARGS_aliases variable PUNKARGS_aliases
lappend PUNKARGS [list {
@id -id "(package)punk::imap4"
@package -name "punk::imap4" -help\
"Package
Description"
}]
namespace eval argdoc { namespace eval argdoc {
#namespace for custom argument documentation #namespace for custom argument documentation

2
src/vfs/_vfscommon.vfs/modules/punk/libunknown-0.1.tm

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

34
src/vfs/_vfscommon.vfs/modules/punk/mix/cli-0.3.1.tm

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

115
src/vfs/_vfscommon.vfs/modules/punk/mix/commandset/project-0.1.0.tm

@ -776,33 +776,70 @@ namespace eval punk::mix::commandset::project {
return $msg return $msg
#return [list_as_lines [lib::get_projects $glob]] #return [list_as_lines [lib::get_projects $glob]]
} }
proc cd {{glob {}} args} {
dict set args -cd 1
work $glob {*}$args punk::args::define {
@id -id ::punk::mix::commandset::project::collection::work
@cmd -name punk::mix::commandset::project::collection::work\
-summary\
"List projects with checkout directories."\
-help\
"Get project info by opening the central fossil config-db to determine
fossil database files for each project, and the known checkout folders.
If -detail is true, a second operation gathers file state information
for each checkout folder."
@leaders -min 0 -max 0
-cd -type none -help\
"If this flag is provided, after lsting, prompt the user to enter
the row number of the checkout to 'cd' into, or an option to cancel.
If there is only one project with only a single checkout, the
cd operation will occur without prompting unless -prompt was
also supplied."
-prompt -type none -help\
"If there is only one checkout in the result, cause a prompt to be
raised instead of automatically peforming the cd operation.
Has no effect if -cd was not supplied, or if -cd is supplied and
there are multiple checkouts, in which case user is always prompted."
-detail -type boolean -default 0 -help\
"Include file state information for each checkout in the resulting
table. This includes information such as which files are changed,
unchanged,new,missing or extra and can take a little more time to
gather as it must examine the filesystem for each checkout folder.
Note that although the default is false - if only a single project
matches the glob pattern(s) then file state will be gathered for
each of its checkouts. Use an explicit -detail 0 if this is not
desired."
@values -min 0 -max -1
glob -type string -multiple 1 -default * -optional 1 -help\
"glob patterns used to search for project. The glob is applied against
the names of the fossil repository database files - not the project-name,
which is not available in the central fossil config-db.
Case insensitive."
} }
proc work {{glob {}} args} { proc work {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::collection::work]
lassign [dict values $argd] leaders opts values received
package require sqlite3 package require sqlite3
set db_projects [lib::get_projects $glob] set globlist [dict get $values glob]
set db_projects [lib::get_projects {*}$globlist]
#list of lists of the form:
#{fosdb fname workdirlist}
if {[llength $db_projects] == 0} { if {[llength $db_projects] == 0} {
puts stderr "::punk::mix::commandset::project::work No Repo DB name matches found for '$glob'" puts stderr "::punk::mix::commandset::project::work No Repo DB name matches found for '$globlist'"
return "" return ""
} }
#list of lists of the form:
#{fosdb fname workdirlist}
set defaults [dict create\
-cd 0\
-detail "\uFFFF"\
]
set opts [dict merge $defaults $args]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set opt_cd [dict get $opts -cd] set opt_cd [dict exists $received -cd]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set opt_detail [dict get $opts -detail] set opt_detail [dict get $opts -detail]
set opt_detail_explicit_zero 1 ;#default assumption only if {[dict exists $received -detail] && !$opt_detail} {
if {$opt_detail eq "\uFFFF"} { set opt_detail_explicit_zero 1
} else {
set opt_detail_explicit_zero 0 set opt_detail_explicit_zero 0
set opt_detail 0; #default
} }
set opt_prompt [dict exists $received -prompt]
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
set workdir_dict [dict create] set workdir_dict [dict create]
set all_workdirs [list] set all_workdirs [list]
@ -991,7 +1028,7 @@ namespace eval punk::mix::commandset::project {
set numrows [llength $col_rowids] set numrows [llength $col_rowids]
if {$opt_cd && $numrows >= 1} { if {$opt_cd && $numrows >= 1} {
puts stdout $msg puts stdout $msg
if {$numrows == 1} { if {$numrows == 1 && !$opt_prompt} {
set workingdir [lindex $workdirs 0] set workingdir [lindex $workdirs 0]
puts stdout "1 result. Changing dir to $workingdir" puts stdout "1 result. Changing dir to $workingdir"
if {[file exists $workingdir]} { if {[file exists $workingdir]} {
@ -1014,6 +1051,30 @@ namespace eval punk::mix::commandset::project {
} }
return $msg return $msg
} }
punk::args::define {
@id -id ::punk::mix::commandset::project::collection::cd
@cmd -name punk::mix::commandset::project::collection::cd\
-summary\
"List projects with checkout directories and prompt for which checkout to cd to."\
-help\
"List projects with checkout directories and prompt for which checkout to cd to."
@leaders -min 0 -max 0
}\
[punk::args::resolved_def -types opts ::punk::mix::commandset::project::collection::work -detail]\
{
-prompt -type none -help\
"Prompt even when result contains only one checkout location as a possible cd target.
User will always be prompted if result contains more than one checkout."
@values -min 0 -max -1
}\
[punk::args::resolved_def -types values ::punk::mix::commandset::project::collection::work glob]
proc cd {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::collection::work]
work -cd {*}$args
}
#*** !doctools #*** !doctools
#[list_end] [comment {-- end collection namespace definitions --}] #[list_end] [comment {-- end collection namespace definitions --}]
} }
@ -1029,12 +1090,17 @@ namespace eval punk::mix::commandset::project {
@id -id ::punk::mix::commandset::project::lib::get_projects @id -id ::punk::mix::commandset::project::lib::get_projects
@cmd -name punk::mix::commandset::project::lib::get_projects\ @cmd -name punk::mix::commandset::project::lib::get_projects\
-summary\ -summary\
"List projects referred to by central fossil config-db."\ "Return a 3-element list of projects referred to by central fossil config-db."\
-help\ -help\
"Get project info only by opening the central fossil config-db "Get project info only by opening the central fossil config-db.
(will not have proper project-name etc)" Each member of the returned list is a 3-element list of:
<path_to_fossildb> <shortname> <list_of_checkout_paths>
The shortname is simply the name based on the root name of the fossil database,
it is not necessarily the project-name by which the project is referred to in the fossil
checkout databases."
@values -min 0 -max -1 @values -min 0 -max -1
glob -type string -multiple 1 -default * -optional 1 glob -type string -multiple 1 -default * -optional 1 -help\
"case insensitive glob for the name of the fossil database."
} }
proc get_projects {args} { proc get_projects {args} {
set argd [punk::args::parse $args withid ::punk::mix::commandset::project::lib::get_projects] set argd [punk::args::parse $args withid ::punk::mix::commandset::project::lib::get_projects]
@ -1048,6 +1114,9 @@ namespace eval punk::mix::commandset::project {
::sqlite3 fosconf $configdb ::sqlite3 fosconf $configdb
#set testresult [fosconf eval {select name,value from global_config;}] #set testresult [fosconf eval {select name,value from global_config;}]
#puts stderr $testresult #puts stderr $testresult
#list of repositories of the form repo:<path>
#eg repo:C:/Users/someone/.fossils/tcl.fossil
set project_repos [fosconf eval {select name from global_config where name like 'repo:%';}] set project_repos [fosconf eval {select name from global_config where name like 'repo:%';}]
set paths_and_names [list] set paths_and_names [list]
foreach pr $project_repos { foreach pr $project_repos {
@ -1064,7 +1133,7 @@ namespace eval punk::mix::commandset::project {
} }
set filtered_list [list] set filtered_list [list]
foreach glob $globlist { foreach glob $globlist {
set matches [lsearch -all -inline -index 1 $paths_and_names $glob] set matches [lsearch -nocase -all -inline -index 1 $paths_and_names $glob]
foreach m $matches { foreach m $matches {
if {$m ni $filtered_list} { if {$m ni $filtered_list} {
lappend filtered_list $m lappend filtered_list $m

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

@ -41,11 +41,27 @@ namespace eval punk::mix::commandset::repo {
return $result 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} { proc fossilize { args} {
#check if project already managed by fossil.. initialise and check in if not. #check if project already managed by fossil.. initialise and check in if not.
puts stderr "unimplemented" 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} { proc unfossilize {projectname args} {
#remove/archive .fossil #remove/archive .fossil
puts stderr "unimplemented" puts stderr "unimplemented"
@ -76,14 +92,27 @@ namespace eval punk::mix::commandset::repo {
#punk::args #punk::args
lappend PUNKARGS [list { lappend PUNKARGS [list {
@id -id ::punk::mix::commandset::repo::fossil-move-repository @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). "Move the fossil repository file (usually named with .fossil extension).
This is an interactive function which will prompt for answers on stdin This is an interactive function which will prompt for answers on stdin
before proceeding. before proceeding.
The move can be done even if there are open checkouts and will maintain 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 ""}} { 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 searchbase [pwd]
set projectinfo [punk::repo::find_repos $searchbase] set projectinfo [punk::repo::find_repos $searchbase]
set projectbase [dict get $projectinfo closest] set projectbase [dict get $projectinfo closest]

2
src/vfs/_vfscommon.vfs/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 #[para] Core API functions for punk::mix::commandset::scriptwrap
#[list_begin definitions] #[list_begin definitions]
namespace export * namespace export {[a-z]*}
namespace eval fileline { namespace eval fileline {
namespace import ::punk::fileline::lib::* namespace import ::punk::fileline::lib::*

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

@ -522,7 +522,14 @@ proc repl::start {inchan args} {
set codethread "" set codethread ""
set codethread_cond "" set codethread_cond ""
punk::console::mode line ;#review - revert to line mode on final exit - but we may be exiting a nested repl 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 return 0
} }
proc repl::post_operations {} { proc repl::post_operations {} {
@ -570,7 +577,7 @@ proc repl::reopen_stdin {} {
#todo - avoid putting this in gobal namespace? #todo - avoid putting this in gobal namespace?
#collisions with other libraries apps? #collisions with other libraries apps?
proc punk::repl::quit {args} { proc punk::repl::quit {args} {
set ::repl::done "quit {*}$args" set ::repl::done [list quit {*}$args]
#puts stderr "quit called" #puts stderr "quit called"
return "" ;#make sure to return nothing so "quit" doesn't land on stdout 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 set last_char_info_width 60
#review - string shouldn't be truncated prior to stripcodes - could chop ansi codes! #review - string shouldn't be truncated prior to ansistrip - could chop ansi codes!
#set summary "[::shellfilter::ansi::stripcodes [string range $out 0 $last_char_info_width]]"
set out_plain_text [punk::ansi::ansistrip $out] set out_plain_text [punk::ansi::ansistrip $out]
set summary [string range $out_plain_text 0 $last_char_info_width] set summary [string range $out_plain_text 0 $last_char_info_width]
if {[string length $summary] > $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)]} { if {![llength $input_chunks_waiting($inputchan)]} {
chan event $inputchan readable [list ::repl::repl_handler $inputchan $prompt_config] chan event $inputchan readable [list ::repl::repl_handler $inputchan $prompt_config]
} else { } 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] after idle [list ::repl::repl_handler $inputchan $prompt_config]
} }
#################################################### ####################################################
@ -2695,6 +2703,7 @@ namespace eval repl {
proc init {args} { proc init {args} {
puts stderr "-->repl::init $args"
if {![info exists ::argv0]} { if {![info exists ::argv0]} {
#error out before we create a thread - punk requires this - review #error out before we create a thread - punk requires this - review
error "::argv0 not set" error "::argv0 not set"
@ -2900,7 +2909,7 @@ namespace eval repl {
proc quit {args} { 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 #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 "" # 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 { proc editbuf args {
thread::send %replthread% [list punk::repl::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 #temporary debug aliases - deliberate violation of safety provided by safe interp
code alias escapeeval ::repl::interphelpers::escapeeval code alias escapeeval ::repl::interphelpers::escapeeval
code alias exit ::repl::interphelpers::quit
#experiment #experiment
#code alias ::shellfilter::stack ::shellfilter::stack #code alias ::shellfilter::stack ::shellfilter::stack

32
src/vfs/_vfscommon.vfs/modules/punk/safe-0.1.0.tm

@ -63,38 +63,6 @@ package require punk::args
#*** !doctools #*** !doctools
#[section API] #[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# oo::class namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#tcl::namespace::eval punk::safe::class {
#*** !doctools
#[subsection {Namespace punk::safe::class}]
#[para] class definitions
#if {[tcl::info::commands [tcl::namespace::current]::interface_sample1] eq ""} {
#*** !doctools
#[list_begin enumerated]
# oo::class create interface_sample1 {
# #*** !doctools
# #[enum] CLASS [class interface_sample1]
# #[list_begin definitions]
# method test {arg1} {
# #*** !doctools
# #[call class::interface_sample1 [method test] [arg arg1]]
# #[para] test method
# puts "test: $arg1"
# }
# #*** !doctools
# #[list_end] [comment {-- end definitions interface_sample1}]
# }
#*** !doctools
#[list_end] [comment {--- end class enumeration ---}]
#}
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Secondary API namespace # Secondary API namespace

52
src/vfs/_vfscommon.vfs/modules/punk/sixel-0.1.0.tm

@ -69,38 +69,6 @@ package require punk::ansi
#*** !doctools #*** !doctools
#[section API] #[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# oo::class namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#tcl::namespace::eval punk::sixel::class {
#*** !doctools
#[subsection {Namespace punk::sixel::class}]
#[para] class definitions
#if {[tcl::info::commands [tcl::namespace::current]::interface_sample1] eq ""} {
#*** !doctools
#[list_begin enumerated]
# oo::class create interface_sample1 {
# #*** !doctools
# #[enum] CLASS [class interface_sample1]
# #[list_begin definitions]
# method test {arg1} {
# #*** !doctools
# #[call class::interface_sample1 [method test] [arg arg1]]
# #[para] test method
# puts "test: $arg1"
# }
# #*** !doctools
# #[list_end] [comment {-- end definitions interface_sample1}]
# }
#*** !doctools
#[list_end] [comment {--- end class enumeration ---}]
#}
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#reading #reading
#https://www.reddit.com/r/linux/comments/t3m7zm/quick_roundup_of_bitmap_graphics_availability_in/ #https://www.reddit.com/r/linux/comments/t3m7zm/quick_roundup_of_bitmap_graphics_availability_in/
@ -122,20 +90,6 @@ tcl::namespace::eval punk::sixel {
#proc sample1 {p1 n args} {
# #*** !doctools
# #[call [fun sample1] [arg p1] [arg n] [opt {option value...}]]
# #[para]Description of sample1
# #[para] Arguments:
# # [list_begin arguments]
# # [arg_def tring p1] A description of string argument p1.
# # [arg_def integer n] A description of integer argument n.
# # [list_end]
# return "ok"
#}
#terminated by ST #terminated by ST
#some older terminals may terminate at first other esc encountered. #some older terminals may terminate at first other esc encountered.
#non-sixel characters ignored (? review) #non-sixel characters ignored (? review)
@ -286,12 +240,6 @@ tcl::namespace::eval punk::sixel::lib {
#[para] Secondary functions that are part of the API #[para] Secondary functions that are part of the API
#[list_begin definitions] #[list_begin definitions]
#proc utility1 {p1 args} {
# #*** !doctools
# #[call lib::[fun utility1] [arg p1] [opt {?option value...?}]]
# #[para]Description of utility1
# return 1
#}
proc ascii_to_sixelvalue {a} { proc ascii_to_sixelvalue {a} {
set dec [scan $a %c] set dec [scan $a %c]
if {$dec < 63 || $dec > 127} {error "ascii character to convert to sixel value must be from 63 to 126 (chars '?' through to '~')"} if {$dec < 63 || $dec > 127} {error "ascii character to convert to sixel value must be from 63 to 126 (chars '?' through to '~')"}

67
src/vfs/_vfscommon.vfs/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 { namespace eval shellfilter::chan {
set testobj ::shellfilter::chan::var set testobj ::shellfilter::chan::var
if {$testobj ni [info commands $testobj]} { 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 $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 $errchan -buffering $errbuffering
#chan configure $outchan -blocking 0 #chan configure $outchan -blocking 0
chan configure $outchan -buffering $outbuffering ;#don't configure non-blocking. weird duplicate of *second* line occurs if you do. chan configure $outchan -buffering $outbuffering ;#don't configure non-blocking. weird duplicate of *second* line occurs if you do.
@ -2889,7 +2832,9 @@ namespace eval shellfilter {
# - and that at least appears like a terminal to the called command. # - and that at least appears like a terminal to the called command.
#set rdout [open |[concat $commandlist [list 2>@stderr <@$inchan]] [list RDONLY]] #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)
set rdout [open |[concat $commandlist [list 2>@$wrerr <@$inchan]] [list RDONLY]] set rdout [open |[concat $commandlist [list 2>@$wrerr <@$inchan]] [list RDONLY]]
chan configure $rderr -buffering $errbuffering -blocking 0 chan configure $rderr -buffering $errbuffering -blocking 0

BIN
src/vfs/_vfscommon.vfs/modules/test/punk/args-0.1.5.tm

Binary file not shown.

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

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

13
src/vfs/_vfscommon.vfs/modules/tomlish-1.1.6.tm

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

Loading…
Cancel
Save