Browse Source

project_layouts sync

master
Julian Noble 1 month ago
parent
commit
cc3380a70e
  1. 1293
      src/project_layouts/custom/_project/punk.basic/src/make.tcl
  2. 10
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/fauxlink-0.1.0.tm
  3. 1
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/include_modules.config
  4. 35
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk-0.1.tm
  5. 141
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/args-0.1.0.tm
  6. 5
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/config-0.1.tm
  7. 39
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/console-0.1.1.tm
  8. 108
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/du-0.1.0.tm
  9. 1
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/fileline-0.1.0.tm
  10. 171
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/lib-0.1.1.tm
  11. 23
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/base-0.1.tm
  12. 7
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/commandset/doc-0.1.0.tm
  13. 2
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/util-0.1.0.tm
  14. 44
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/nav/fs-0.1.0.tm
  15. 24
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/packagepreference-0.1.0.tm
  16. 24
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/repl/codethread-0.1.0.tm
  17. 5
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/repo-0.1.1.tm
  18. 6
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/textblock-0.1.1.tm
  19. 2
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/textutil-0.9.tm
  20. 1293
      src/project_layouts/custom/_project/punk.project-0.1/src/make.tcl
  21. 10
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/fauxlink-0.1.0.tm
  22. 1
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/include_modules.config
  23. 35
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk-0.1.tm
  24. 141
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/args-0.1.0.tm
  25. 5
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/config-0.1.tm
  26. 39
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/console-0.1.1.tm
  27. 108
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/du-0.1.0.tm
  28. 1
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/fileline-0.1.0.tm
  29. 171
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/lib-0.1.1.tm
  30. 23
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/base-0.1.tm
  31. 7
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/commandset/doc-0.1.0.tm
  32. 2
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/util-0.1.0.tm
  33. 44
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/nav/fs-0.1.0.tm
  34. 24
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/packagepreference-0.1.0.tm
  35. 24
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/repl/codethread-0.1.0.tm
  36. 5
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/repo-0.1.1.tm
  37. 6
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/textblock-0.1.1.tm
  38. 2
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/textutil-0.9.tm
  39. 1293
      src/project_layouts/custom/_project/punk.shell-0.1/src/make.tcl

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

File diff suppressed because it is too large Load Diff

10
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/fauxlink-0.1.0.tm

@ -66,6 +66,16 @@
# "my-program-files#++server+c+Program%20Files.fxlnk"
#If we needed the old-style literal %20 it would become
# "my-program-files#++server+c+Program%2520Files.fxlnk"
#
# The file:// scheme on windows supposedly *does* decode %xx (for use in a browser)
# e.g
# pfiles#file%3a++++localhost+c+Program%2520files
# The browser will work with literal spaces too though - so it could just as well be:
# pfiles#file%3a++++localhost+c+Program%20files
#windows may default to using explorer.exe instead of a browser for file:// urls though
#and explorer doesn't want the literal %20. It probably depends what API the file:// url is to be passed to?
#in a .url shortcut either literal space or %20 will work ie %xx values are decoded
#*** !doctools

1
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/include_modules.config

@ -14,7 +14,6 @@ set bootsupport_modules [list\
src/vendormodules debug\
src/vendormodules dictutils\
src/vendormodules fauxlink\
src/vendormodules fileutil\
src/vendormodules http\
src/vendormodules md5\
src/vendormodules metaface\

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

@ -213,6 +213,13 @@ namespace eval punk {
proc objclone {obj} {
append obj2 $obj {}
}
proc set_clone {varname obj} {
#maintenance: also punk::lib::set_clone
#e.g used by repl's codeinterp. Maintains internal rep, easier to call e.g interp eval code [list punk::set_clone varnmame $val]
append obj2 $obj {}
uplevel 1 [list set $varname $obj2]
}
interp alias "" strlen "" ::punk::strlen
interp alias "" str_len "" ::punk::strlen
interp alias "" objclone "" ::punk::objclone
@ -2122,7 +2129,7 @@ namespace eval punk {
}
{@V\*@*} - {@v\*@*} {
#dict value glob - return values
set active_key_type "dict"
set active_key_type dict
set keyglob [string range $index 4 end]
append script [tstr -return string -allowcommands {
if {[catch {dict size $leveldata}]} {
@ -2132,7 +2139,7 @@ namespace eval punk {
if {$get_not} {
lappend INDEX_OPERATIONS globvalue-get-values-not
append script \n [string map [list <keyglob> $keyglob] {
# set active_key_type "dict" index_operation: globvalue-get-values-not"
# set active_key_type "dict" ;# index_operation: globvalue-get-values-not
set assigned [list]
tcl::dict::for {k v} $leveldata {
if {![string match <keyglob> $v]} {
@ -2144,7 +2151,7 @@ namespace eval punk {
} else {
lappend INDEX_OPERATIONS globvalue-get-values
append script \n [string map [list <keyglob> $keyglob] {
# set active_key_type "dict" index_operation: globvalue-get-value
# set active_key_type "dict" ;#index_operation: globvalue-get-value
set assigned [dict values $leveldata <keyglob>]
}]
}
@ -2166,7 +2173,7 @@ namespace eval punk {
} else {
lappend INDEX_OPERATIONS globkeyvalue-get-pairs
append script \n [string map [list <keyvalglob> $keyvalglob] {
# set active_key_type "dict" index_operation: globkeyvalue-get-pairs-not"
# set active_key_type "dict" ;# index_operation: globkeyvalue-get-pairs-not
set assigned [dict create]
tcl::dict::for {k v} $leveldata {
if {[string match <keyvalglob> $k] || [string match <keyvalglob> $v]} {
@ -4952,10 +4959,7 @@ namespace eval punk {
} else {
#tags ?
#debug.punk.pipe {>>raw commandline: [concat $rhs $segment_members_filled]} 5
if 0 {
if {false} {
#set s [list uplevel 1 [concat $rhs $segment_members_filled]]
if {![info exists pscript]} {
upvar ::_pipescript pscript
@ -4972,6 +4976,7 @@ namespace eval punk {
}
}
set cmdlist_result [uplevel 1 $segment_members_filled]
#set d [_multi_bind_result $returnvarspec [punk::K $segment_members_filled [unset segment_members_filled]]]
set d [_multi_bind_result $returnvarspec [lindex [list $cmdlist_result [unset cmdlist_result]] 0 ]]
@ -7321,16 +7326,22 @@ namespace eval punk {
if {$topic in [list tcl]} {
if {[punk::lib::system::has_script_var_bug]} {
append warningblock \n "minor warning: punk::lib::system::has_script_var_bug returned true! (string rep for list variable in script generated when script changed)"
if {[punk::lib::system::has_tclbug_script_var]} {
append warningblock \n "minor warning: punk::lib::system::has_tclbug_script_var returned true! (string rep for list variable in script generated when script changed)"
}
if {[punk::lib::system::has_safeinterp_compile_bug]} {
if {[punk::lib::system::has_tclbug_safeinterp_compile]} {
set indent " "
append warningblock \n "[a+ web-red]warning: punk::lib::system::has_safeinterp_compile_bug returned true!" \n
append warningblock \n "[a+ web-red]warning: punk::lib::system::has_tclbug_safeinterp returned true!" \n
append warningblock "${indent}(ensemble commands not compiled in safe interps - heavy performance impact in safe interps)" \n
append warningblock "${indent}see https://core.tcl-lang.org/tcl/tktview/1095bf7f75"
append warningblock [a]
}
if {[punk::lib::system::has_tclbug_list_quoting_emptyjoin]} {
set indent " "
append warningblock \n "[a+ web-red]warning: punk::lib::system::has_tclbug_list_quoting returned true!" \n
append warningblock "${indent}lists elements not properly quoted in some cases. e.g 'list {*}[lindex {etc #foo} 1] {*}[list]' (#foo not braced)" \n
append warningblock "${indent}see https://core.tcl-lang.org/tcl/tktview/e38dce74e2"
}
}
set text ""

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

@ -201,6 +201,7 @@
#[para] packages used by punk::args
#[list_begin itemized]
package require Tcl 8.6-
#optional? punk::trie
#*** !doctools
#[item] [package {Tcl 8.6-}]
@ -293,6 +294,7 @@ tcl::namespace::eval punk::args {
-validate_without_ansi 0\
-strip_ansi 0\
-nocase 0\
-choiceprefix 1\
-multiple 0\
]
set valspec_defaults [tcl::dict::create\
@ -301,8 +303,12 @@ tcl::namespace::eval punk::args {
-allow_ansi 1\
-validate_without_ansi 0\
-strip_ansi 0\
-nocase 0\
-choiceprefix 1\
-multiple 0\
]
#we need a -choiceprefix default even though it often doesn't apply so we can look it up to display in Help if there are -choices
#default to 1 for convenience
#checks with no default
#-minlen -maxlen -range
@ -415,11 +421,11 @@ tcl::namespace::eval punk::args {
-anyopts {
set opt_any $v
}
-minlen - -maxlen - -range - -choices - -choicelabels {
-minlen - -maxlen - -range - -choices - -choicelabels - -choiceprefix {
#review - only apply to certain types?
tcl::dict::set optspec_defaults $k $v
}
-nominlen - -nomaxlen - -norange - -nochoices - -nochoicelabels {
-nominlen - -nomaxlen - -norange - -nochoices - -nochoicelabels - -nocase {
if {$v} {
tcl::dict::unset optspec_defaults $k
}
@ -459,7 +465,7 @@ tcl::namespace::eval punk::args {
tcl::dict::set optspec_defaults $k $v
}
default {
set known { -any -anyopts -minlen -maxlen -range -choices -choicelabels\
set known { -any -anyopts -minlen -maxlen -range -choices -choicelabels -choiceprefix -nocase\
-nominlen -nomaxlen -norange -nochoices -nochoicelabels\
-type -optional -allow_ansi -validate_without_ansi -strip_ansi -multiple\
}
@ -479,7 +485,7 @@ tcl::namespace::eval punk::args {
-maxvalues {
set val_max $v
}
-minlen - -maxlen - -range - -choices - -choicelabels {
-minlen - -maxlen - -range - -choices - -choicelabels - -choiceprefix - -nocase {
#review - only apply to certain types?
tcl::dict::set valspec_defaults $k $v
}
@ -520,7 +526,7 @@ tcl::namespace::eval punk::args {
}
default {
set known { -min -minvalues -max -maxvalues\
-minlen -maxlen -range -choices -choicelabels\
-minlen -maxlen -range -choices -choicelabels -choiceprefix -nocase\
-nominlen -nomaxlen -norange -nochoices -nochoicelabels\
-type -optional -allow_ansi -validate_without_ansi -strip_ansi -multiple\
}
@ -596,12 +602,12 @@ tcl::namespace::eval punk::args {
}
}
}
-default - -solo - -range - -choices - -choicelabels - -minlen - -maxlen - -nocase - -optional - -multiple - -validate_without_ansi - -allow_ansi - -strip_ansi - -help - -ARGTYPE {
-default - -solo - -range - -choices - -choiceprefix - -choicelabels - -choiceprefix - -minlen - -maxlen - -nocase - -optional - -multiple - -validate_without_ansi - -allow_ansi - -strip_ansi - -help - -ARGTYPE {
#review -solo 1 vs -type none ?
tcl::dict::set spec_merged $spec $specval
}
default {
set known_argspecs [list -default -type -range -choices -nocase -optional -multiple -validate_without_ansi -allow_ansi -strip_ansi -help]
set known_argspecs [list -default -type -range -choices -choiceprefix -nocase -optional -multiple -validate_without_ansi -allow_ansi -strip_ansi -help]
error "punk::args::get_dict - unrecognised key '$spec' in specifications for argument '$argname' Known option specification keys: $known_argspecs"
}
}
@ -752,7 +758,28 @@ tcl::namespace::eval punk::args {
#set greencheck [a+ web-limegreen]\u2713[a]
set greencheck [a+ brightgreen]\u2713[a]
foreach arg [dict get $spec_dict opt_names] {
if {![catch {package require punk::trie}]} {
set opt_names_display [list]
set trie [punk::trie::trieclass new {*}[dict get $spec_dict opt_names]]
set idents [dict get [$trie shortest_idents ""] scanned]
$trie destroy
set M "\x1b\[32m" ;#mark in green
set RST "\x1b\[m"
foreach c [dict get $spec_dict opt_names] {
set id [dict get $idents $c]
if {$id eq $c} {
lappend opt_names_display $M$c$RST
} else {
set idlen [string length $id]
lappend opt_names_display "$M[string range $c 0 $idlen-1]$RST[string range $c $idlen end]"
}
}
} else {
set opt_names_display [dict get $spec_dict opt_names]
}
foreach argshow $opt_names_display arg [dict get $spec_dict opt_names] {
set arginfo [dict get $spec_dict arg_info $arg]
if {[dict exists $arginfo -default]} {
#set default $c_default[dict get $arginfo -default]
@ -763,14 +790,47 @@ tcl::namespace::eval punk::args {
set help [punk::lib::dict_getdef $arginfo -help ""]
if {[dict exists $arginfo -choices]} {
if {$help ne ""} {append help \n}
append help "Choices: [dict get $arginfo -choices]"
if {[dict get $arginfo -nocase]} {
set casemsg " (case insensitive)"
} else {
set casemsg " (case sensitive)"
}
if {[dict get $arginfo -choiceprefix]} {
set prefixmsg " (choice prefix allowed)"
} else {
set prefixmsg ""
}
append help "Choices$prefixmsg$casemsg"
if {[catch {package require punk::trie}]} {
append help "\n " [join [dict get $arginfo -choices] "\n "]
} else {
if {[catch {
set trie [punk::trie::trieclass new {*}[dict get $arginfo -choices]]
set idents [dict get [$trie shortest_idents ""] scanned]
$trie destroy
set M "\x1b\[32m" ;#mark in green
set RST "\x1b\[m"
foreach c [dict get $arginfo -choices] {
set id [dict get $idents $c]
if {$id eq $c} {
append help "\n " "$M$c$RST"
} else {
set idlen [string length $id]
append help "\n " "$M[string range $c 0 $idlen-1]$RST[string range $c $idlen end]"
}
}
} errM]} {
puts stderr "prefix marking failed\n$errM"
append help "\n " [join [dict get $arginfo -choices] "\n "]
}
}
}
if {[punk::lib::dict_getdef $arginfo -multiple 0]} {
set multiple $greencheck
} else {
set multiple ""
}
$t add_row [list $arg [dict get $arginfo -type] $default $multiple $help]
$t add_row [list $argshow [dict get $arginfo -type] $default $multiple $help]
if {$arg eq $badarg} {
$t configure_row [expr {[$t row_count]-1}] -ansibase $c_badarg
}
@ -785,7 +845,40 @@ tcl::namespace::eval punk::args {
set help [punk::lib::dict_getdef $arginfo -help ""]
if {[dict exists $arginfo -choices]} {
if {$help ne ""} {append help \n}
append help "Choices: [dict get $arginfo -choices]"
if {[dict get $arginfo -nocase]} {
set casemsg " (case insensitive)"
} else {
set casemsg " (case sensitive)"
}
if {[dict get $arginfo -choiceprefix]} {
set prefixmsg " (choice prefix allowed)"
} else {
set prefixmsg ""
}
append help "Choices$prefixmsg$casemsg"
if {[catch {package require punk::trie}]} {
append help "\n " [join [dict get $arginfo -choices] "\n "]
} else {
if {[catch {
set trie [punk::trie::trieclass new {*}[dict get $arginfo -choices]]
set idents [dict get [$trie shortest_idents ""] scanned]
$trie destroy
set M "\x1b\[32m" ;#mark in green
set RST "\x1b\[m"
foreach c [dict get $arginfo -choices] {
set id [dict get $idents $c]
if {$id eq $c} {
append help "\n " "$M$c$RST"
} else {
set idlen [string length $id]
append help "\n " "$M[string range $c 0 $idlen-1]$RST[string range $c $idlen end]"
}
}
} errM]} {
puts stderr "prefix marking failed\n$errM"
append help "\n " [join [dict get $arginfo -choices] "\n "]
}
}
}
if {[punk::lib::dict_getdef $arginfo -multiple 0]} {
set multiple $greencheck
@ -1430,19 +1523,37 @@ tcl::namespace::eval punk::args {
if {$has_choices} {
#todo -choicelabels
set choices [tcl::dict::get $thisarg -choices]
set choiceprefix [tcl::dict::get $thisarg -choiceprefix]
set nocase [tcl::dict::get $thisarg -nocase]
foreach e $vlist e_check $vlist_check {
if {$nocase} {
set casemsg "(case insensitive)"
set casemsg " (case insensitive)"
set choices_test [tcl::string::tolower $choices]
set v_test [tcl::string::tolower $e_check]
} else {
set casemsg "(case sensitive)"
set casemsg " (case sensitive)"
set v_test $e_check
set choices_test $choices
}
if {$v_test ni $choices_test} {
arg_error "Option $argname for [Get_caller] must be one of the listed values $choices $casemsg. Received: '$e'" $argspecs $argname
set choice_ok 0
if {$choiceprefix} {
if {![catch {tcl::prefix::match $choices_test $v_test} chosen]} {
set choice_ok 1
#can we handle empty string as a choice? It should just work - REVIEW/test
set choice [lsearch -inline -nocase $choices $chosen] ;#map possibly lcased choice back to original case in choices list
if {[tcl::dict::get $thisarg -ARGTYPE] eq "option"} {
tcl::dict::set opts $argname $choice
} else {
tcl::dict::set values_dict $argname $choice
}
}
set prefixmsg " (or a unique prefix of a value)"
} else {
set prefixmsg ""
set choice_ok [expr {$v_test in $choices_test}]
}
if {!$choice_ok} {
arg_error "Option $argname for [Get_caller] must be one of the listed values:\n [join $choices "\n "]\n$casemsg$prefixmsg. Received: '$e'" $argspecs $argname
}
}
}

5
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/config-0.1.tm

@ -362,10 +362,11 @@ tcl::namespace::eval punk::config {
proc configure {args} {
set argd [punk::args::get_dict {
whichconfig -type string -choices {startup running}
*values -min 1 -max 1
whichconfig -type string -choices {startup running stop}
} $args]
return "unimplemented - $argd"
}
proc show {whichconfig {globfor *}} {

39
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/console-0.1.1.tm

@ -44,6 +44,7 @@
#[list_begin itemized]
package require Tcl 8.6-
package require Thread ;#tsv required to sync is_raw
package require punk::ansi
#*** !doctools
#[item] [package {Tcl 8.6-}]
@ -84,7 +85,12 @@ namespace eval punk::console {
variable previous_stty_state_stdin ""
variable previous_stty_state_stdout ""
variable previous_stty_state_stderr ""
variable is_raw 0
#variable is_raw 0
if {![tsv::exists console is_raw]} {
tsv::set console is_raw 0
}
variable input_chunks_waiting
if {![info exists input_chunks_waiting(stdin)]} {
set input_chunks_waiting(stdin) [list]
@ -183,7 +189,8 @@ namespace eval punk::console {
#NOTE - the is_raw is only being set in current interp - but the channel is shared.
#this is problematic with the repl thread being separate. - must be a tsv? REVIEW
proc enableRaw {{channel stdin}} {
variable is_raw
#variable is_raw
variable previous_stty_state_$channel
set sttycmd [auto_execok stty]
if {[set previous_stty_state_$channel] eq ""} {
@ -193,21 +200,21 @@ namespace eval punk::console {
}
exec {*}$sttycmd raw -echo <@$channel
set is_raw 1
tsv::set console is_raw 1
return [dict create previous [set previous_stty_state_$channel]]
}
proc disableRaw {{channel stdin}} {
variable is_raw
#variable is_raw
variable previous_stty_state_$channel
set sttycmd [auto_execok stty]
if {[set previous_stty_state_$channel] ne ""} {
exec {*}$sttycmd [set previous_stty_state_$channel]
set previous_stty_state_$channel ""
set is_raw 0
tsv::set console is_raw 0
return restored
}
exec {*}$sttycmd -raw echo <@$channel
set is_raw 0
tsv::set console is_raw 0
return done
}
proc enableVirtualTerminal {{channels {input output}}} {
@ -249,11 +256,11 @@ namespace eval punk::console {
}
proc mode {{raw_or_line query}} {
variable is_raw
#variable is_raw
variable ansi_available
set raw_or_line [string tolower $raw_or_line]
if {$raw_or_line eq "query"} {
if {$is_raw} {
if {[tsv::get console is_raw]} {
return "raw"
} else {
return "line"
@ -493,7 +500,7 @@ namespace eval punk::console {
}
proc [namespace parent]::enableRaw {{channel stdin}} {
variable is_raw
#variable is_raw
variable previous_stty_state_$channel
if {[package provide twapi] ne ""} {
@ -506,7 +513,7 @@ namespace eval punk::console {
#set newmode [dict merge $oldmode [dict create -lineinput 0 -echoinput 0]]
set newmode [twapi::get_console_input_mode]
set is_raw 1
tsv::set console is_raw 1
#don't disable handler - it will detect is_raw
### twapi::set_console_control_handler {}
return [list stdin [list from $oldmode to $newmode]]
@ -516,7 +523,7 @@ namespace eval punk::console {
}
exec {*}$sttycmd raw -echo <@$channel
set is_raw 1
tsv::set console is_raw 1
#review - inconsistent return dict
return [dict create stdin [list from [set previous_stty_state_$channel] to "" note "fixme - to state not shown"]]
} else {
@ -528,7 +535,7 @@ namespace eval punk::console {
#could be we were missing a step in reopening stdin and console configuration?
proc [namespace parent]::disableRaw {{channel stdin}} {
variable is_raw
#variable is_raw
variable previous_stty_state_$channel
if {[package provide twapi] ne ""} {
@ -537,7 +544,7 @@ namespace eval punk::console {
# Turn on the echo and line-editing bits
twapi::modify_console_input_mode $console_handle -lineinput 1 -echoinput 1
set newmode [twapi::get_console_input_mode]
set is_raw 0
tsv::set console is_raw 0
return [list stdin [list from $oldmode to $newmode]]
} elseif {[set sttycmd [auto_execok stty]] ne ""} {
#stty can return info on windows - but doesn't seem to be able to set anything.
@ -550,7 +557,7 @@ namespace eval punk::console {
return restored
}
exec {*}$sttycmd -raw echo <@$channel
set is_raw 0
tsv::set console is_raw 0
#do we really want to exec stty yet again to show final 'to' state?
#probably not. We should work out how to read the stty result flags and set a result.. or just limit from,to to showing echo and lineedit states.
return [list stdin [list from "[set previous_stty_state_$channel]" to "" note "fixme - to state not shown"]]
@ -634,7 +641,7 @@ namespace eval punk::console {
puts -nonewline $output $query;flush $output
#todo - test and save rawstate so we don't disableRaw if console was already raw
if {!$::punk::console::is_raw} {
if {![tsv::get console is_raw]} {
set was_raw 0
punk::console::enableRaw
} else {
@ -1378,7 +1385,7 @@ namespace eval punk::console {
#todo - compare speed with get_cursor_pos - work out why the big difference
proc test_cursor_pos {} {
if {!$::punk::console::is_raw} {
if {![tsv::get console is_raw]} {
set was_raw 0
enableRaw
} else {

108
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/du-0.1.0.tm

@ -1065,56 +1065,65 @@ namespace eval punk::du {
#note - with this design, we can't glob for all except dotfiles - this is for cross-platform consistency and efficiency (Review).
#dotfiles aren't considered hidden on all platforms
#some sort of antiglob is a possible enhancement and more consistent with the view that leading dot should be treated as any other filename character in this context.
if {"windows" eq $::tcl_platform(platform)} {
if {$opt_glob eq "*"} {
#Note - glob operations seem to be faster than looped tests like 'file isdirectory' & 'file readlink'
#set parent [lindex $folders $folderidx]
set hdirs [glob -nocomplain -dir $folderpath -types {hidden d} * .*]
#set hdirs {}
set dirs [glob -nocomplain -dir $folderpath -types d * .*]
set hlinks [glob -nocomplain -dir $folderpath -types {hidden l} * .*]
#set hlinks {}
set links [glob -nocomplain -dir $folderpath -types l * .*] ;#links may have dupes - we don't care. struct::set difference will remove (?)
#set links [lsort -unique [concat $hlinks $links[unset links]]]
set links [glob -nocomplain -dir $folderpath -types l * .*] ;#links may have dupes - we don't care. punk::lib::struct_set_diff_unique
set hfiles [glob -nocomplain -dir $folderpath -types {hidden f} * .*]
#set hfiles {}
set files [glob -nocomplain -dir $folderpath -types f * .*]
#set files {}
} else {
set hdirs [glob -nocomplain -dir $folderpath -types {hidden d} $opt_glob]
set dirs [glob -nocomplain -dir $folderpath -types d $opt_glob]
set hlinks [glob -nocomplain -dir $folderpath -types {hidden l} $opt_glob]
set links [glob -nocomplain -dir $folderpath -types l $opt_glob] ;#links may have dupes - we don't care. struct::set difference will remove (?)
set links [glob -nocomplain -dir $folderpath -types l $opt_glob] ;#links may have dupes - we don't care. punk::lib::struct_set_diff_unique
set hfiles [glob -nocomplain -dir $folderpath -types {hidden f} $opt_glob]
set files [glob -nocomplain -dir $folderpath -types f $opt_glob]
}
} else {
set hdirs {}
set hfiles {}
set hlinks {}
if {$opt_glob eq "*"} {
#Note - glob operations seem to be faster than looped tests like 'file isdirectory' & 'file readlink'
#set parent [lindex $folders $folderidx]
set dirs [glob -nocomplain -dir $folderpath -types d * .*]
set links [glob -nocomplain -dir $folderpath -types l * .*] ;#links may have dupes - we don't care. punk::lib::struct_set_diff_unique
set files [glob -nocomplain -dir $folderpath -types f * .*]
} else {
set dirs [glob -nocomplain -dir $folderpath -types d $opt_glob]
set links [glob -nocomplain -dir $folderpath -types l $opt_glob] ;#links may have dupes - we don't care. punk::lib::struct_set_diff_unique
set files [glob -nocomplain -dir $folderpath -types f $opt_glob]
}
}
#note struct::set difference produces unordered result
#struct::set difference removes duplicates (but not always.. e.g if using tcl impl and 2nd element empty!)
#relying on struct::set to remove dupes is somewhat risky. It is not well documented - and behaviour of dupes in inputs is underspecified as it appears to be intended for mathematical 'sets'
#relying on struct::set to remove dupes is somewhat risky.
#It is not well documented - and behaviour of dupes in inputs is underspecified as it appears to be intended for mathematical 'sets' ie lists without dupes
#for this reason we must use the wrapper punk::lib::struct_set_diff_unique, which will use the well behaved critcl for speed if avail, but fall back to a deduping tcl version
#remove links and . .. from directories, remove links from files
#ideally we would like to classify links by whether they point to files vs dirs - but there are enough cross-platform differences that we will have to leave it to the caller to sort out for now.
#struct::set will affect order: tcl vs critcl give different ordering!
set files [struct::set difference [concat $hfiles $files[unset files]] $links]
set dirs [struct::set difference [concat $hdirs $dirs[unset dirs]] [concat $links [list [file join $folderpath .] [file join $folderpath ..] ]]]
#set links [lsort -unique [concat $links $hlinks]]
set files [punk::lib::struct_set_diff_unique [list {*}$hfiles {*}$files[unset files]] $links]
set dirs [punk::lib::struct_set_diff_unique [list {*}$hdirs {*}$dirs[unset dirs] ] [list {*}$links [file join $folderpath .] [file join $folderpath ..]]]
#----
set mdata_lists [du_get_metadata_lists $sized_types $timed_types $files $dirs $links]
if {"windows" eq $::tcl_platform(platform)} {
set flaggedhidden [concat $hdirs $hfiles $hlinks]
} else {
set flaggedhidden [list {*}$hdirs {*}$hfiles {*}$hlinks]
#unix dotted files/folders are not 'flagged' as such - it's a convention - so the client can use the same convention to decide if something is hidden
#this allows us to return less data - but more importantly - reserve flaggedhidden for systems where such a flag exists and avoid conflating the different concepts of what is hidden
set flaggedhidden {}
}
set vfsmounts [get_vfsmounts_in_folder $folderpath]
@ -1223,21 +1232,21 @@ namespace eval punk::du {
#if {[punk::mix::base::lib::path_a_above_b $folderpath "//zipfs:/"]} {}
#zipfs files also reported as links by glob - review - should we preserve this in response?
#todo - hidden? not returned in attributes on windows at least.
#zipfs files also reported as links by glob - review - should we preserve this in response? (2024 unable to duplicate)
if {$opt_glob eq "*"} {
set dirs [glob -nocomplain -dir $folderpath -types d * .*] ;# also returns links to dirs
#set links [glob -nocomplain -dir $folderpath -types l * .*] ;# links may have dupes - we don't care. struct::set difference will remove
set links [list]
set links [glob -nocomplain -dir $folderpath -types l * .*] ;# links may have dupes - we don't care. struct::set difference will remove
set files [glob -nocomplain -dir $folderpath -types f * .*] ;# also returns links to files
} else {
set dirs [glob -nocomplain -dir $folderpath -types d $opt_glob]
#set links [glob -nocomplain -dir $folderpath -types l $opt_glob]
set links [list]
set links [glob -nocomplain -dir $folderpath -types l $opt_glob]
set files [glob -nocomplain -dir $folderpath -types f $opt_glob]
}
#remove any links from our dirs and files collections
set dirs [struct::set difference $dirs[unset dirs] [concat $links [list [file join $folderpath .] [file join $folderpath ..] ]]]
set files [struct::set difference $files[unset files] $links]
#see du_dirlisting_generic re struct::set difference issues
set dirs [punk::lib::struct_set_diff_unique $dirs[unset dirs] [list {*}$links [file join $folderpath .] [file join $folderpath ..]]]
set files [punk::lib::struct_set_diff_unique $files[unset files] $links]
#nested vfs mount.. REVIEW - does anything need special handling?
@ -1300,34 +1309,63 @@ namespace eval punk::du {
}
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
#at least some vfs on windows seem to support the -hidden attribute
#we are presuming glob will accept the -types hidden option for all vfs - even if it doesn't really apply REVIEW
#The extra globs aren't nice - but hopefully the vfs is reasonably performant (?)
set errors [dict create]
if {"windows" eq $::tcl_platform(platform)} {
if {$opt_glob eq "*"} {
set hdirs [glob -nocomplain -dir $folderpath -types {hidden d} * .*]
set dirs [glob -nocomplain -dir $folderpath -types d * .*] ;# also returns links to dirs
#review - how are links handled in vfs? presumably if the vfs is a full implementation they should work at least within the vfs?
set hlinks [glob -nocomplain -dir $folderpath -types {hidden l} * .*]
set links [glob -nocomplain -dir $folderpath -types l * .*] ;# links may have dupes - we don't care. struct::set difference will remove
set hfiles [glob -nocomplain -dir $folderpath -types {hidden l} * .*]
set files [glob -nocomplain -dir $folderpath -types f * .*] ;# also returns links to files
} else {
set hdirs [glob -nocomplain -dir $folderpath -types {hidden d} $opt_glob]
set dirs [glob -nocomplain -dir $folderpath -types d $opt_glob]
set hlinks [glob -nocomplain -dir $folderpath -types {hidden l} $opt_glob]
set links [glob -nocomplain -dir $folderpath -types l $opt_glob]
set hfiles [glob -nocomplain -dir $folderpath -types {hidden f} $opt_glob]
set files [glob -nocomplain -dir $folderpath -types f $opt_glob]
}
} else {
#we leave it to the ui on unix to classify dotfiles as hidden
set hdirs {}
set hfiles {}
set hlinks {}
if {$opt_glob eq "*"} {
set dirs [glob -nocomplain -dir $folderpath -types d * .*] ;# also returns links to dirs
#review - how are links handled in vfs? presumably if the vfs is a full implementation they should work at least within the vfs?
set links [glob -nocomplain -dir $folderpath -types l * .*] ;# links may have dupes - we don't care. struct::set difference will remove
set files [glob -nocomplain -dir $folderpath -types f * .*] ;# also returns links to files
} else {
set dirs [glob -nocomplain -dir $folderpath -types d $opt_glob]
set links [glob -nocomplain -dir $folderpath -types l $opt_glob]
set files [glob -nocomplain -dir $folderpath -types f $opt_glob]
}
}
#remove any links from our dirs and files collections
set dirs [struct::set difference $dirs[unset dirs] [concat $links [list [file join $folderpath .] [file join $folderpath ..] ]]]
set files [struct::set difference $files[unset files] $links]
#see du_dirlisting_generic re struct::set difference issues
set dirs [punk::lib::struct_set_diff_unique $dirs[unset dirs] [list {*}$links [file join $folderpath .] [file join $folderpath ..] ]]
set files [punk::lib::struct_set_diff_unique $files[unset files] $links]
#nested vfs mount.. REVIEW - does anything need special handling?
set vfsmounts [get_vfsmounts_in_folder $folderpath]
set mdata_lists [du_get_metadata_lists $sized_types $timed_types $files $dirs $links]
set flaggedhidden [list {*}$hdirs {*}$hfiles {*}$hlinks]
set effective_opts $opts
dict set effective_opts -with_times $timed_types
dict set effective_opts -with_sizes $sized_types
return [list dirs $dirs vfsmounts $vfsmounts links $links files $files filesizes [dict get $mdata_lists fsizes] sizes [dict get $mdata_lists allsizes] times [dict get $mdata_lists alltimes] flaggedhidden {} flaggedsystem {} flaggedreadonly {} altname {} opts $effective_opts errors $errors]
return [list dirs $dirs vfsmounts $vfsmounts links $links files $files filesizes [dict get $mdata_lists fsizes] sizes [dict get $mdata_lists allsizes] times [dict get $mdata_lists alltimes] flaggedhidden $flaggedhidden flaggedsystem {} flaggedreadonly {} altname {} opts $effective_opts errors $errors]
}
#we can halve the number of round trips on unix-like systems, where 'hidden' always corresponds to dotted files
#but we don't classify as such anyway. (leave for UI)
proc du_dirlisting_unix {folderpath args} {
set defaults [dict create\
-glob *\
@ -1379,6 +1417,9 @@ namespace eval punk::du {
}
#this is not consistent with standard way * works for unix folders - but it is consistent with behaviour of this facility on windows
#we don't classify anything as 'flaggedhidden' on unix.
#it is a convention for dotfiles rather than a flag - and we'll leave the distinction for the display library
#This
if {$opt_glob eq "*"} {
set dirs [glob -nocomplain -dir $folderpath -types d * .*] ;# also returns links to dirs
set links [glob -nocomplain -dir $folderpath -types l * .*] ;# links may have dupes - we don't care. struct::set difference will remove
@ -1389,8 +1430,9 @@ namespace eval punk::du {
set files [glob -nocomplain -dir $folderpath -types f $opt_glob]
}
#remove any links from our dirs and files collections
set dirs [struct::set difference $dirs[unset dirs] [concat $links [list [file join $folderpath .] [file join $folderpath ..] ]]]
set files [struct::set difference $files[unset files] $links]
#see du_dirlisting_generic re struct::set difference issues
set dirs [punk::lib::struct_set_diff_unique $dirs[unset dirs] [list {*}$links [file join $folderpath .] [file join $folderpath ..] ]]
set files [punk::lib::struct_set_diff_unique $files[unset files] $links]
set vfsmounts [get_vfsmounts_in_folder $folderpath]
set mdata_lists [du_get_metadata_lists $sized_types $timed_types $files $dirs $links]
@ -1406,7 +1448,7 @@ namespace eval punk::du {
#return fsizes,allsizes,alltimes metadata in same order as files,dirs,links lists - if specified in sized_types
proc du_get_metadata_lists {sized_types timed_types files dirs links} {
set meta_dict [dict create]
set meta_types [concat $sized_types $timed_types]
set meta_types [list {*}$sized_types {*}$timed_types]
#known tcl stat keys 2023 - review
set empty_stat_dict [dict create atime {} ctime {} dev {} gid {} ino {} mode {} mtime {} nlink {} size {} type {} uid {}]
#make sure we call file stat only once per item
@ -1419,6 +1461,7 @@ namespace eval punk::du {
if {![catch {file stat $path arrstat} errM]} {
dict set meta_dict $path [dict create shorttype $ft {*}[array get arrstat]]
} else {
puts stderr "du_get_metadata_lists: file stat $path error: $errM"
dict lappend errors $path "file stat error: $errM"
dict set meta_dict $path [dict create shorttype $ft {*}$empty_stat_dict]
}
@ -1437,6 +1480,9 @@ namespace eval punk::du {
if {$ft eq "f"} {
#subst with na if empty?
lappend fsizes [dict get $pathinfo size]
if {[dict get $pathinfo size] eq ""} {
puts stderr "du_get_metadata_lists: fsize $path is empty!"
}
}
}
if {$ft in $timed_types} {
@ -1446,7 +1492,7 @@ namespace eval punk::du {
#todo - fix . The list lengths will presumably match but have empty values if failed to stat
if {"f" in $sized_types} {
if {[llength $fsizes] ne [llength $files]} {
dict lappend errors $folderpath "failed to retrieve all file sizes"
dict lappend errors general "failed to retrieve all file sizes"
}
}
return [dict create fsizes $fsizes allsizes $allsizes alltimes $alltimes]

1
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/fileline-0.1.0.tm

@ -290,7 +290,6 @@ namespace eval punk::fileline::class {
-showconfig 0\
-boundaryheader {Boundary %i% at %b%}\
]
set known_opts [dict keys $defaults]
foreach {k v} $args {
switch -- $k {
-ansi - -offset - -displaybytes - -truncatedmark - -completemark - -moremark - -continuemark - -linemaxwidth - -linebase - -limit - -boundaries - -showconfig - -boundaryheader {

171
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/lib-0.1.1.tm

@ -339,6 +339,144 @@ namespace eval punk::lib {
set has_twapi [expr {![catch {package require twapi}]}]
}
# == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==
# Maintenance - This is the primary source for tm_version... functions
# - certain packages script require these but without package dependency
# - 1 punk boot script
# - 2 packagetrace module
# - These should be updated to sync with this
# == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==
proc tm_version_isvalid {versionpart} {
#Needs to be suitable for use with Tcl's 'package vcompare'
if {![catch [list package vcompare $versionpart $versionpart]]} {
return 1
} else {
return 0
}
}
proc tm_version_major {version} {
if {![tm_version_isvalid $version]} {
error "Invalid version '$version' is not a proper Tcl module version number"
}
set firstpart [lindex [split $version .] 0]
#check for a/b in first segment
if {[string is integer -strict $firstpart]} {
return $firstpart
}
if {[string first a $firstpart] > 0} {
return [lindex [split $firstpart a] 0]
}
if {[string first b $firstpart] > 0} {
return [lindex [split $firstpart b] 0]
}
error "tm_version_major unable to determine major version from version number '$version'"
}
proc tm_version_canonical {ver} {
#accepts a single valid version only - not a bounded or unbounded spec
if {![tm_version_isvalid $ver]} {
error "tm_version_canonical version '$ver' is not valid for a package version"
}
set parts [split $ver .]
set newparts [list]
foreach o $parts {
set trimmed [string trimleft $o 0]
set firstnonzero [string index $trimmed 0]
switch -exact -- $firstnonzero {
"" {
lappend newparts 0
}
a - b {
#e.g 000bnnnn -> bnnnnn
set tailtrimmed [string trimleft [string range $trimmed 1 end] 0]
if {$tailtrimmed eq ""} {
set tailtrimmed 0
}
lappend newparts 0$firstnonzero$tailtrimmed
}
default {
#digit
if {[string is integer -strict $trimmed]} {
#e.g 0100 -> 100
lappend newparts $trimmed
} else {
#e.g 0100b003 -> 100b003 (still need to process tail)
if {[set apos [string first a $trimmed]] > 0} {
set lhs [string range $trimmed 0 $apos-1] ;#assert lhs non-empty and only digits or wouldn't be in this branch
set rhs [string range $trimmed $apos+1 end] ;#assert rhs non-empty and only digits
set rhs [string trimleft $rhs 0]
if {$rhs eq ""} {
set rhs 0
}
lappend newparts ${lhs}a${rhs}
} elseif {[set bpos [string first b $trimmed]] > 0} {
set lhs [string range $trimmed 0 $bpos-1] ;#assert lhs non-empty and only digits or wouldn't be in this branch
set rhs [string range $trimmed $bpos+1 end] ;#assert rhs non-empty and only digits
set rhs [string trimleft $rhs 0]
if {$rhs eq ""} {
set rhs 0
}
lappend newparts ${lhs}b${rhs}
} else {
#assert - shouldn't get here trimmed val should have been empty, an int or contained an a or b
error "tm_version_canonical error - trimfail - unexpected"
}
}
}
}
}
return [join $newparts .]
}
proc tm_version_required_canonical {versionspec} {
#also trim leading zero from any dottedpart?
#Tcl *allows* leading zeros in any of the dotted parts - but they are not significant.
#e.g 1.01 is equivalent to 1.1 and 01.001
#also 1b3 == 1b0003
if {[string trim $versionspec] eq ""} {return ""} ;#unspecified = any version
set errmsg "tm_version_required_canonical - invalid version specification"
if {[string first - $versionspec] < 0} {
#no dash
#looks like a minbounded version (ie a single version with no dash) convert to min-max form
set from $versionspec
if {![tm_version_isvalid $from]} {
error "$errmsg '$versionpec'"
}
if {![catch {tm_version_major $from} majorv]} {
set from [tm_version_canonical $from]
return "${from}-[expr {$majorv +1}]"
} else {
error "$errmsg '$versionspec'"
}
} else {
# min- or min-max
#validation and canonicalisation (strip leading zeroes from each segment, including either side of a or b)
set parts [split $versionspec -] ;#we expect only 2 parts
lassign $parts from to
if {![tm_version_isvalid $from]} {
error "$errmsg '$versionspec'"
}
set from [tm_version_canonical $from]
if {[llength $parts] == 2} {
if {$to ne ""} {
if {![tm_version_isvalid $to]} {
error "$errmsg '$versionspec'"
}
set to [tm_version_canonical $to]
return $from-$to
} else {
return $from-
}
} else {
error "$errmsg '$versionspec'"
}
error "tm_version_required_canonical should have already returned a canonicalised versionspec - or produced an error with reason before this point"
}
}
# end tm_version... functions
# == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==
# -- ---
#https://stackoverflow.com/questions/17631269/whats-the-best-way-to-join-two-lists
#DKF's 2013 recommendation of using list {*}$first {*}$second seems not to apply in 2024
@ -1575,8 +1713,20 @@ namespace eval punk::lib {
lremove $fromlist {*}$doomed
}
#fix for tcl impl of struct::set::diff which doesn't dedupe
proc struct_set_diff_unique {A B} {
package require struct::set ;#require even if tcl impl - so the dependency isn't missed accidentally due to Loaded state of programmers machine.
if {[struct::set::Loaded] eq "tcl"} {
return [punk::lib::setdiff $A $B]
} else {
#use (presumably critcl) implementation for speed
return [struct::set difference $A $B]
}
}
#non-dupe preserving - for consistency in dedupe behaviour we don't shortcircuit empty B
#consistent dedupe and order-maintenance of remaining items in A differentiate this from struct::set difference
#consistent dedupe and order-maintenance of remaining items in A differentiate this from struct::set difference (dedupes with critcl, doesn't with tcl implementation 2024)
#also struct::set difference with critcl is faster
proc setdiff {A B} {
if {[llength $A] == 0} {return {}}
@ -2387,7 +2537,7 @@ namespace eval punk::lib {
set stdin_state [fconfigure stdin]
if {[catch {
package require punk::console
set console_raw [set ::punk::console::is_raw]
set console_raw [tsv::get console is_raw]
} err_console]} {
#assume normal line mode
set console_raw 0
@ -3032,6 +3182,11 @@ namespace eval punk::lib {
proc objclone {obj} {
append obj2 $obj {}
}
proc set_clone {varname obj} {
#used by repl's codeinterp. Maintains internal rep, easier to call e.g interp eval code [list punk::set_clone varnmame $val]
append obj2 $obj {}
uplevel 1 [list set $varname $obj2]
}
@ -3175,7 +3330,7 @@ tcl::namespace::eval punk::lib::system {
#[para] Internal functions that are not part of the API
#[list_begin definitions]
proc has_script_var_bug {} {
proc has_tclbug_script_var {} {
set script {set j [list spud] ; list}
append script \n
uplevel #0 $script
@ -3194,7 +3349,15 @@ tcl::namespace::eval punk::lib::system {
return false
}
}
proc has_safeinterp_compile_bug {{show 0}} {
proc has_tclbug_list_quoting_emptyjoin {} {
#https://core.tcl-lang.org/tcl/tktview/e38dce74e2
set v1 [list {*}[lindex #foo] {*}[]] ;#can return "#foo" instead of "{#foo}" under some beta 9 releases
set v2 [list #foo] ;#normal tcl list quoting for 1st element that looks like a comment -> "{#foo}"
return [expr {![string equal $v1 $v2]}] ;#if they're not equal - we have the bug.
}
proc has_tclbug_safeinterp_compile {{show 0}} {
#ensemble calls within safe interp not compiled
namespace eval [namespace current]::testcompile {
proc ensembletest {} {string index a 0}

23
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/base-0.1.tm

@ -473,13 +473,26 @@ namespace eval punk::mix::base {
#set data [fileutil::cat -translation binary $filename] ;#no significant performance diff on windows - and doesn't handle win-illegal names
zlib adler32 $data
}
#zlib crc vie file-slurp
#zlib crc via file-slurp
proc cksum_crc_file {filename} {
package require zlib
set data [punk::mix::util::fcat -translation binary -encoding iso8859-1 $filename]
zlib crc $data
}
proc cksum_md5_data {data} {
if {[package vsatisfies [package present md5] 2-]} {
return [md5::md5 -hex $data]
} else {
return [md5::md5 $data]
}
}
#fallback md5 via file-slurp - shouldn't be needed if have md5 2-
proc cksum_md5_file {filename} {
set data [punk::mix::util::fcat -translation binary -encoding iso8859-1 $filename]
cksum_md5_data $data
}
#required to be able to accept relative paths
#for full cksum - using tar could reduce number of hashes to be made..
@ -624,7 +637,11 @@ namespace eval punk::mix::base {
}
md5 {
package require md5
if {[package vsatisfies [package present md5] 2- ] } {
set cksum_command [list md5::md5 -hex -file]
} else {
set cksum_comand [list cksum_md5_file]
}
}
cksum {
package require cksum ;#tcllib
@ -637,7 +654,7 @@ namespace eval punk::mix::base {
set cksum_command [list cksum_adler32_file]
}
sha3 - sha3-256 {
#todo - replace with something that doesn't call another process
#todo - replace with something that doesn't call another process - only if tcllibc not available!
#set cksum_command [list apply {{file} {lindex [exec fossil sha3sum -256 $file] 0}}]
set cksum_command [list $sha3_implementation 256]
}
@ -684,7 +701,7 @@ namespace eval punk::mix::base {
set sizeinfo "(file type $ftype - tarred size [punk::lib::format_number [file size $archivename]] bytes)"
}
set tsstart [clock millis]
puts -nonewline stdout "cksum_path: calculating cksum for $target $sizeinfo ... "
puts -nonewline stdout "cksum_path: calculating cksum using $opt_cksum_algorithm for $target $sizeinfo ... "
set cksum [{*}$cksum_command $archivename]
set tsend [clock millis]
set ms [expr {$tsend - $tsstart}]

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

@ -271,7 +271,12 @@ namespace eval punk::mix::commandset::doc {
#this case only came up because docgen used to path munge to long filenames - but left because we know there is a limit and renaming fixes it - even if it's ugly - but still allows doc generation.
#review - if we're checking fname - should also test length of whole path and determine limits for tar
package require md5
set target_docname [md5::md5 -hex [encoding convertto utf-8 $fullpath]]_overlongfilename.man
if {[package vsatisfies [package present md5] 2- ] } {
set md5opt "-hex"
} else {
set md5opt ""
}
set target_docname [md5::md5 {*}$md5opt [encoding convertto utf-8 $fullpath]]_overlongfilename.man
puts stderr "WARNING - overlong file name - renaming $fullpath"
puts stderr " to [file dirname $fullpath]/$target_docname"
}

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

@ -261,6 +261,8 @@ namespace eval punk::mix::util {
return
}
# review punk::lib::tm_version.. functions
proc is_valid_tm_version {versionpart} {
#Needs to be suitable for use with Tcl's 'package vcompare'
if {![catch [list package vcompare $versionpart $versionpart]]} {

44
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/nav/fs-0.1.0.tm

@ -821,9 +821,12 @@ tcl::namespace::eval punk::nav::fs {
set match_contents $opt_tailglob
}
}
puts stdout "searchbase: $searchbase searchspec:$searchspec"
#puts stdout "searchbase: $searchbase searchspec:$searchspec"
set in_vfs 0
#file attr //cookit:/ returns {-vfs 1 -handle {}}
#we will treat it differently for now - use generic handler REVIEW
set in_vfs 0 ;#we use this only for a vfs which is reported to have a mountpoint by vfs::filesystem info - not all that have -vfs 1 attr like cookit.
if {[llength [package provide vfs]]} {
foreach mount [vfs::filesystem info] {
if {[punk::mix::base::lib::path_a_atorbelow_b $location $mount]} {
@ -849,20 +852,43 @@ tcl::namespace::eval punk::nav::fs {
set listing [punk::du::lib::du_dirlisting_tclvfs $location -glob $match_contents {*}$next_opt_with_sizes {*}$next_opt_with_times]
} else {
set in_zipfs 0
set in_cookit 1
set in_other_pseudovol 1
switch -glob -- $location {
//zipfs:/* {
if {[info commands ::tcl::zipfs::mount] ne ""} {
if {[string match //zipfs:/* $location]} {
set in_zipfs 1
}
#dict for {zmount zpath} [zipfs mount] {
# if {[punk::mix::base::lib::path_a_atorbelow_b $location $zmount]} {
# set in_zipfs 1
# break
# }
#}
}
//cookit:/* {
set in_cookit 1
}
default {
#handle 'other/unknown' that mounts at a volume-like path //pseudovol:/
if {[regexp {//((?:(?!:|/).)+):/.*} $location _match pseudovol]} {
#pseudovol probably more than one char long
#we don't really expect something like //c:/ , but anyway, it's not the same as c:/ and for all we know someone could use that as a volume name?
set in_other_pseudovol 1 ;#flag so we don't use twapi - hope generic can handle it (uses tcl glob)
} else {
#we could use 'file attr' here to test if {-vfs 1}
#but it's an extra filesystem hit on all normal paths too (which can be expensive on some systems)
#instead for now we'll assume any reasonable vfs should have been found by vfs::filesystem::info or mounted as a pseudovolume
}
}
}
if {$in_zipfs} {
#relative vs absolute? review - cwd valid for //zipfs:/ ??
set listing [punk::du::lib::du_dirlisting_zipfs $location -glob $match_contents {*}$next_opt_with_sizes {*}$next_opt_with_times]
} elseif {$in_cookit} {
#seems to be a vfs - except it mounts on a pseudo-volume path //cookit:/
#don't use twapi
#could possibly use du_dirlisting_tclvfs REVIEW
#files and folders are all returned with the -types hidden option for glob on windows
set listing [punk::du::lib::du_dirlisting_generic $location -glob $match_contents {*}$next_opt_with_sizes {*}$next_opt_with_times]
} elseif {$in_other} {
set listing [punk::du::lib::du_dirlisting_generic $location -glob $match_contents {*}$next_opt_with_sizes {*}$next_opt_with_times]
} else {
set listing [punk::du::dirlisting $location -glob $match_contents {*}$next_opt_with_sizes {*}$next_opt_with_times]
}

24
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/packagepreference-0.1.0.tm

@ -155,18 +155,26 @@ tcl::namespace::eval punk::packagepreference {
if {[lindex $args 1] eq "-exact"} {
set pkg [lindex $args 2]
set vwant [lindex $args 3]
if {[set ver [package provide $pkg]] ne ""} {
if {$ver eq $vwant} {
return $vwant
} else {
#package already provided with a different version.. we will defer to underlying implementation to return the standard error
if {[set ver [$COMMANDSTACKNEXT_ORIGINAL provide $pkg]] ne ""} {
#although we could shortcircuit using vsatisfies to return the ver
#we should instead pass through to COMMANDSTACKNEXT so as not to interfere with whatever it does.
return [$COMMANDSTACKNEXT {*}$args]
}
#if {$vwant eq "" || [$COMMANDSTACKNEXT vsatisfies $ver $vwant]} {
# return $ver
#} else {
# #package already provided with a different version.. we will defer to underlying implementation to return the standard error
# return [$COMMANDSTACKNEXT {*}$args]
#}
}
} else {
set pkg [lindex $args 1]
if {[set ver [package provide $pkg]] ne ""} {
return $ver
set vwant [lindex $args 2]
if {[set ver [$COMMANDSTACKNEXT_ORIGINAL provide $pkg]] ne ""} {
return [$COMMANDSTACKNEXT {*}$args]
#if {$vwant eq "" || [$COMMANDSTACKNEXT vsatisfies $ver $vwant]} {
# return $ver
#}
}
}
if {[regexp {[A-Z]} $pkg]} {

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

@ -20,12 +20,12 @@
#*** !doctools
#[manpage_begin shellspy_module_punk::repl::codethread 0 0.1.0]
#[copyright "2024"]
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}]
#[moddesc {-}] [comment {-- Description at end of page heading --}]
#[titledesc {Module repl codethread}] [comment {-- Name section and table of contents description --}]
#[moddesc {codethread for repl - root interpreter}] [comment {-- Description at end of page heading --}]
#[require punk::repl::codethread]
#[keywords module]
#[keywords module repl]
#[description]
#[para] -
#[para] This is part of the infrastructure required for the punk::repl to operate
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
@ -131,11 +131,14 @@ tcl::namespace::eval punk::repl::codethread {
# return "ok"
#}
variable run_command_cache
proc is_running {} {
variable running
return $running
}
proc runscript {script} {
#puts stderr "->runscript"
variable replthread_cond
variable output_stdout ""
@ -169,9 +172,18 @@ tcl::namespace::eval punk::repl::codethread {
#set errhandle [shellfilter::stack::item_tophandle stderr]
#interp transfer "" $errhandle code
set scope [interp eval code [list set ::punk::ns::ns_current]]
set status [catch {
interp eval code [list tcl::namespace::inscope $scope $script]
#shennanigans to keep compiled script around after call.
#otherwise when $script goes out of scope - internal rep of vars set in script changes.
#The shimmering may be no big deal(?) - but debug/analysis using tcl::unsupported::representation becomes impossible.
interp eval code [list ::punk::lib::set_clone ::codeinterp::clonescript $script] ;#like objclone
interp eval code {
lappend ::codeinterp::run_command_cache $::codeinterp::clonescript
if {[llength $::codeinterp::run_command_cache] > 2000} {
set ::codeinterp::run_command_cache [lrange $::codeinterp::run_command_cache 1750 end][unset ::codeinterp::run_command_cache]
}
tcl::namespace::inscope $::punk::ns::ns_current $::codeinterp::clonescript
}
} result]

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

@ -27,6 +27,11 @@
#
# path/repo functions
#
#REVIEW punk::repo required early by punk boot script to find projectdir
#todo - split off basic find_project chain of functions to a smaller package and import as necessary here
#Then we can reduce early dependencies in punk boot
if {$::tcl_platform(platform) eq "windows"} {
package require punk::winpath
} else {

6
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/textblock-0.1.1.tm

@ -5280,7 +5280,7 @@ tcl::namespace::eval textblock {
It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj"
*values -min 1 -max 1
frametype -help "name from the predefined frametypes:<ftlist>
or an adhoc
or an adhoc "
}]
append spec \n "frametype -help \"A predefined \""
punk::args::get_dict $spec $args
@ -6804,7 +6804,11 @@ tcl::namespace::eval textblock {
if {$use_md5} {
#package require md5 ;#already required at package load
if {[package vsatisfies [package present md5] 2- ] } {
set hash [md5::md5 -hex [encoding convertto utf-8 $hashables]] ;#need fast and unique to content - not cryptographic - review
} else {
set hash [md5::md5 [encoding convertto utf-8 $hashables]]
}
} else {
set hash $hashables
}

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

@ -16,7 +16,7 @@
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
package require Tcl 8.2-
namespace eval ::textutil {}

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

File diff suppressed because it is too large Load Diff

10
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/fauxlink-0.1.0.tm

@ -66,6 +66,16 @@
# "my-program-files#++server+c+Program%20Files.fxlnk"
#If we needed the old-style literal %20 it would become
# "my-program-files#++server+c+Program%2520Files.fxlnk"
#
# The file:// scheme on windows supposedly *does* decode %xx (for use in a browser)
# e.g
# pfiles#file%3a++++localhost+c+Program%2520files
# The browser will work with literal spaces too though - so it could just as well be:
# pfiles#file%3a++++localhost+c+Program%20files
#windows may default to using explorer.exe instead of a browser for file:// urls though
#and explorer doesn't want the literal %20. It probably depends what API the file:// url is to be passed to?
#in a .url shortcut either literal space or %20 will work ie %xx values are decoded
#*** !doctools

1
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/include_modules.config

@ -14,7 +14,6 @@ set bootsupport_modules [list\
src/vendormodules debug\
src/vendormodules dictutils\
src/vendormodules fauxlink\
src/vendormodules fileutil\
src/vendormodules http\
src/vendormodules md5\
src/vendormodules metaface\

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

@ -213,6 +213,13 @@ namespace eval punk {
proc objclone {obj} {
append obj2 $obj {}
}
proc set_clone {varname obj} {
#maintenance: also punk::lib::set_clone
#e.g used by repl's codeinterp. Maintains internal rep, easier to call e.g interp eval code [list punk::set_clone varnmame $val]
append obj2 $obj {}
uplevel 1 [list set $varname $obj2]
}
interp alias "" strlen "" ::punk::strlen
interp alias "" str_len "" ::punk::strlen
interp alias "" objclone "" ::punk::objclone
@ -2122,7 +2129,7 @@ namespace eval punk {
}
{@V\*@*} - {@v\*@*} {
#dict value glob - return values
set active_key_type "dict"
set active_key_type dict
set keyglob [string range $index 4 end]
append script [tstr -return string -allowcommands {
if {[catch {dict size $leveldata}]} {
@ -2132,7 +2139,7 @@ namespace eval punk {
if {$get_not} {
lappend INDEX_OPERATIONS globvalue-get-values-not
append script \n [string map [list <keyglob> $keyglob] {
# set active_key_type "dict" index_operation: globvalue-get-values-not"
# set active_key_type "dict" ;# index_operation: globvalue-get-values-not
set assigned [list]
tcl::dict::for {k v} $leveldata {
if {![string match <keyglob> $v]} {
@ -2144,7 +2151,7 @@ namespace eval punk {
} else {
lappend INDEX_OPERATIONS globvalue-get-values
append script \n [string map [list <keyglob> $keyglob] {
# set active_key_type "dict" index_operation: globvalue-get-value
# set active_key_type "dict" ;#index_operation: globvalue-get-value
set assigned [dict values $leveldata <keyglob>]
}]
}
@ -2166,7 +2173,7 @@ namespace eval punk {
} else {
lappend INDEX_OPERATIONS globkeyvalue-get-pairs
append script \n [string map [list <keyvalglob> $keyvalglob] {
# set active_key_type "dict" index_operation: globkeyvalue-get-pairs-not"
# set active_key_type "dict" ;# index_operation: globkeyvalue-get-pairs-not
set assigned [dict create]
tcl::dict::for {k v} $leveldata {
if {[string match <keyvalglob> $k] || [string match <keyvalglob> $v]} {
@ -4952,10 +4959,7 @@ namespace eval punk {
} else {
#tags ?
#debug.punk.pipe {>>raw commandline: [concat $rhs $segment_members_filled]} 5
if 0 {
if {false} {
#set s [list uplevel 1 [concat $rhs $segment_members_filled]]
if {![info exists pscript]} {
upvar ::_pipescript pscript
@ -4972,6 +4976,7 @@ namespace eval punk {
}
}
set cmdlist_result [uplevel 1 $segment_members_filled]
#set d [_multi_bind_result $returnvarspec [punk::K $segment_members_filled [unset segment_members_filled]]]
set d [_multi_bind_result $returnvarspec [lindex [list $cmdlist_result [unset cmdlist_result]] 0 ]]
@ -7321,16 +7326,22 @@ namespace eval punk {
if {$topic in [list tcl]} {
if {[punk::lib::system::has_script_var_bug]} {
append warningblock \n "minor warning: punk::lib::system::has_script_var_bug returned true! (string rep for list variable in script generated when script changed)"
if {[punk::lib::system::has_tclbug_script_var]} {
append warningblock \n "minor warning: punk::lib::system::has_tclbug_script_var returned true! (string rep for list variable in script generated when script changed)"
}
if {[punk::lib::system::has_safeinterp_compile_bug]} {
if {[punk::lib::system::has_tclbug_safeinterp_compile]} {
set indent " "
append warningblock \n "[a+ web-red]warning: punk::lib::system::has_safeinterp_compile_bug returned true!" \n
append warningblock \n "[a+ web-red]warning: punk::lib::system::has_tclbug_safeinterp returned true!" \n
append warningblock "${indent}(ensemble commands not compiled in safe interps - heavy performance impact in safe interps)" \n
append warningblock "${indent}see https://core.tcl-lang.org/tcl/tktview/1095bf7f75"
append warningblock [a]
}
if {[punk::lib::system::has_tclbug_list_quoting_emptyjoin]} {
set indent " "
append warningblock \n "[a+ web-red]warning: punk::lib::system::has_tclbug_list_quoting returned true!" \n
append warningblock "${indent}lists elements not properly quoted in some cases. e.g 'list {*}[lindex {etc #foo} 1] {*}[list]' (#foo not braced)" \n
append warningblock "${indent}see https://core.tcl-lang.org/tcl/tktview/e38dce74e2"
}
}
set text ""

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

@ -201,6 +201,7 @@
#[para] packages used by punk::args
#[list_begin itemized]
package require Tcl 8.6-
#optional? punk::trie
#*** !doctools
#[item] [package {Tcl 8.6-}]
@ -293,6 +294,7 @@ tcl::namespace::eval punk::args {
-validate_without_ansi 0\
-strip_ansi 0\
-nocase 0\
-choiceprefix 1\
-multiple 0\
]
set valspec_defaults [tcl::dict::create\
@ -301,8 +303,12 @@ tcl::namespace::eval punk::args {
-allow_ansi 1\
-validate_without_ansi 0\
-strip_ansi 0\
-nocase 0\
-choiceprefix 1\
-multiple 0\
]
#we need a -choiceprefix default even though it often doesn't apply so we can look it up to display in Help if there are -choices
#default to 1 for convenience
#checks with no default
#-minlen -maxlen -range
@ -415,11 +421,11 @@ tcl::namespace::eval punk::args {
-anyopts {
set opt_any $v
}
-minlen - -maxlen - -range - -choices - -choicelabels {
-minlen - -maxlen - -range - -choices - -choicelabels - -choiceprefix {
#review - only apply to certain types?
tcl::dict::set optspec_defaults $k $v
}
-nominlen - -nomaxlen - -norange - -nochoices - -nochoicelabels {
-nominlen - -nomaxlen - -norange - -nochoices - -nochoicelabels - -nocase {
if {$v} {
tcl::dict::unset optspec_defaults $k
}
@ -459,7 +465,7 @@ tcl::namespace::eval punk::args {
tcl::dict::set optspec_defaults $k $v
}
default {
set known { -any -anyopts -minlen -maxlen -range -choices -choicelabels\
set known { -any -anyopts -minlen -maxlen -range -choices -choicelabels -choiceprefix -nocase\
-nominlen -nomaxlen -norange -nochoices -nochoicelabels\
-type -optional -allow_ansi -validate_without_ansi -strip_ansi -multiple\
}
@ -479,7 +485,7 @@ tcl::namespace::eval punk::args {
-maxvalues {
set val_max $v
}
-minlen - -maxlen - -range - -choices - -choicelabels {
-minlen - -maxlen - -range - -choices - -choicelabels - -choiceprefix - -nocase {
#review - only apply to certain types?
tcl::dict::set valspec_defaults $k $v
}
@ -520,7 +526,7 @@ tcl::namespace::eval punk::args {
}
default {
set known { -min -minvalues -max -maxvalues\
-minlen -maxlen -range -choices -choicelabels\
-minlen -maxlen -range -choices -choicelabels -choiceprefix -nocase\
-nominlen -nomaxlen -norange -nochoices -nochoicelabels\
-type -optional -allow_ansi -validate_without_ansi -strip_ansi -multiple\
}
@ -596,12 +602,12 @@ tcl::namespace::eval punk::args {
}
}
}
-default - -solo - -range - -choices - -choicelabels - -minlen - -maxlen - -nocase - -optional - -multiple - -validate_without_ansi - -allow_ansi - -strip_ansi - -help - -ARGTYPE {
-default - -solo - -range - -choices - -choiceprefix - -choicelabels - -choiceprefix - -minlen - -maxlen - -nocase - -optional - -multiple - -validate_without_ansi - -allow_ansi - -strip_ansi - -help - -ARGTYPE {
#review -solo 1 vs -type none ?
tcl::dict::set spec_merged $spec $specval
}
default {
set known_argspecs [list -default -type -range -choices -nocase -optional -multiple -validate_without_ansi -allow_ansi -strip_ansi -help]
set known_argspecs [list -default -type -range -choices -choiceprefix -nocase -optional -multiple -validate_without_ansi -allow_ansi -strip_ansi -help]
error "punk::args::get_dict - unrecognised key '$spec' in specifications for argument '$argname' Known option specification keys: $known_argspecs"
}
}
@ -752,7 +758,28 @@ tcl::namespace::eval punk::args {
#set greencheck [a+ web-limegreen]\u2713[a]
set greencheck [a+ brightgreen]\u2713[a]
foreach arg [dict get $spec_dict opt_names] {
if {![catch {package require punk::trie}]} {
set opt_names_display [list]
set trie [punk::trie::trieclass new {*}[dict get $spec_dict opt_names]]
set idents [dict get [$trie shortest_idents ""] scanned]
$trie destroy
set M "\x1b\[32m" ;#mark in green
set RST "\x1b\[m"
foreach c [dict get $spec_dict opt_names] {
set id [dict get $idents $c]
if {$id eq $c} {
lappend opt_names_display $M$c$RST
} else {
set idlen [string length $id]
lappend opt_names_display "$M[string range $c 0 $idlen-1]$RST[string range $c $idlen end]"
}
}
} else {
set opt_names_display [dict get $spec_dict opt_names]
}
foreach argshow $opt_names_display arg [dict get $spec_dict opt_names] {
set arginfo [dict get $spec_dict arg_info $arg]
if {[dict exists $arginfo -default]} {
#set default $c_default[dict get $arginfo -default]
@ -763,14 +790,47 @@ tcl::namespace::eval punk::args {
set help [punk::lib::dict_getdef $arginfo -help ""]
if {[dict exists $arginfo -choices]} {
if {$help ne ""} {append help \n}
append help "Choices: [dict get $arginfo -choices]"
if {[dict get $arginfo -nocase]} {
set casemsg " (case insensitive)"
} else {
set casemsg " (case sensitive)"
}
if {[dict get $arginfo -choiceprefix]} {
set prefixmsg " (choice prefix allowed)"
} else {
set prefixmsg ""
}
append help "Choices$prefixmsg$casemsg"
if {[catch {package require punk::trie}]} {
append help "\n " [join [dict get $arginfo -choices] "\n "]
} else {
if {[catch {
set trie [punk::trie::trieclass new {*}[dict get $arginfo -choices]]
set idents [dict get [$trie shortest_idents ""] scanned]
$trie destroy
set M "\x1b\[32m" ;#mark in green
set RST "\x1b\[m"
foreach c [dict get $arginfo -choices] {
set id [dict get $idents $c]
if {$id eq $c} {
append help "\n " "$M$c$RST"
} else {
set idlen [string length $id]
append help "\n " "$M[string range $c 0 $idlen-1]$RST[string range $c $idlen end]"
}
}
} errM]} {
puts stderr "prefix marking failed\n$errM"
append help "\n " [join [dict get $arginfo -choices] "\n "]
}
}
}
if {[punk::lib::dict_getdef $arginfo -multiple 0]} {
set multiple $greencheck
} else {
set multiple ""
}
$t add_row [list $arg [dict get $arginfo -type] $default $multiple $help]
$t add_row [list $argshow [dict get $arginfo -type] $default $multiple $help]
if {$arg eq $badarg} {
$t configure_row [expr {[$t row_count]-1}] -ansibase $c_badarg
}
@ -785,7 +845,40 @@ tcl::namespace::eval punk::args {
set help [punk::lib::dict_getdef $arginfo -help ""]
if {[dict exists $arginfo -choices]} {
if {$help ne ""} {append help \n}
append help "Choices: [dict get $arginfo -choices]"
if {[dict get $arginfo -nocase]} {
set casemsg " (case insensitive)"
} else {
set casemsg " (case sensitive)"
}
if {[dict get $arginfo -choiceprefix]} {
set prefixmsg " (choice prefix allowed)"
} else {
set prefixmsg ""
}
append help "Choices$prefixmsg$casemsg"
if {[catch {package require punk::trie}]} {
append help "\n " [join [dict get $arginfo -choices] "\n "]
} else {
if {[catch {
set trie [punk::trie::trieclass new {*}[dict get $arginfo -choices]]
set idents [dict get [$trie shortest_idents ""] scanned]
$trie destroy
set M "\x1b\[32m" ;#mark in green
set RST "\x1b\[m"
foreach c [dict get $arginfo -choices] {
set id [dict get $idents $c]
if {$id eq $c} {
append help "\n " "$M$c$RST"
} else {
set idlen [string length $id]
append help "\n " "$M[string range $c 0 $idlen-1]$RST[string range $c $idlen end]"
}
}
} errM]} {
puts stderr "prefix marking failed\n$errM"
append help "\n " [join [dict get $arginfo -choices] "\n "]
}
}
}
if {[punk::lib::dict_getdef $arginfo -multiple 0]} {
set multiple $greencheck
@ -1430,19 +1523,37 @@ tcl::namespace::eval punk::args {
if {$has_choices} {
#todo -choicelabels
set choices [tcl::dict::get $thisarg -choices]
set choiceprefix [tcl::dict::get $thisarg -choiceprefix]
set nocase [tcl::dict::get $thisarg -nocase]
foreach e $vlist e_check $vlist_check {
if {$nocase} {
set casemsg "(case insensitive)"
set casemsg " (case insensitive)"
set choices_test [tcl::string::tolower $choices]
set v_test [tcl::string::tolower $e_check]
} else {
set casemsg "(case sensitive)"
set casemsg " (case sensitive)"
set v_test $e_check
set choices_test $choices
}
if {$v_test ni $choices_test} {
arg_error "Option $argname for [Get_caller] must be one of the listed values $choices $casemsg. Received: '$e'" $argspecs $argname
set choice_ok 0
if {$choiceprefix} {
if {![catch {tcl::prefix::match $choices_test $v_test} chosen]} {
set choice_ok 1
#can we handle empty string as a choice? It should just work - REVIEW/test
set choice [lsearch -inline -nocase $choices $chosen] ;#map possibly lcased choice back to original case in choices list
if {[tcl::dict::get $thisarg -ARGTYPE] eq "option"} {
tcl::dict::set opts $argname $choice
} else {
tcl::dict::set values_dict $argname $choice
}
}
set prefixmsg " (or a unique prefix of a value)"
} else {
set prefixmsg ""
set choice_ok [expr {$v_test in $choices_test}]
}
if {!$choice_ok} {
arg_error "Option $argname for [Get_caller] must be one of the listed values:\n [join $choices "\n "]\n$casemsg$prefixmsg. Received: '$e'" $argspecs $argname
}
}
}

5
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/config-0.1.tm

@ -362,10 +362,11 @@ tcl::namespace::eval punk::config {
proc configure {args} {
set argd [punk::args::get_dict {
whichconfig -type string -choices {startup running}
*values -min 1 -max 1
whichconfig -type string -choices {startup running stop}
} $args]
return "unimplemented - $argd"
}
proc show {whichconfig {globfor *}} {

39
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/console-0.1.1.tm

@ -44,6 +44,7 @@
#[list_begin itemized]
package require Tcl 8.6-
package require Thread ;#tsv required to sync is_raw
package require punk::ansi
#*** !doctools
#[item] [package {Tcl 8.6-}]
@ -84,7 +85,12 @@ namespace eval punk::console {
variable previous_stty_state_stdin ""
variable previous_stty_state_stdout ""
variable previous_stty_state_stderr ""
variable is_raw 0
#variable is_raw 0
if {![tsv::exists console is_raw]} {
tsv::set console is_raw 0
}
variable input_chunks_waiting
if {![info exists input_chunks_waiting(stdin)]} {
set input_chunks_waiting(stdin) [list]
@ -183,7 +189,8 @@ namespace eval punk::console {
#NOTE - the is_raw is only being set in current interp - but the channel is shared.
#this is problematic with the repl thread being separate. - must be a tsv? REVIEW
proc enableRaw {{channel stdin}} {
variable is_raw
#variable is_raw
variable previous_stty_state_$channel
set sttycmd [auto_execok stty]
if {[set previous_stty_state_$channel] eq ""} {
@ -193,21 +200,21 @@ namespace eval punk::console {
}
exec {*}$sttycmd raw -echo <@$channel
set is_raw 1
tsv::set console is_raw 1
return [dict create previous [set previous_stty_state_$channel]]
}
proc disableRaw {{channel stdin}} {
variable is_raw
#variable is_raw
variable previous_stty_state_$channel
set sttycmd [auto_execok stty]
if {[set previous_stty_state_$channel] ne ""} {
exec {*}$sttycmd [set previous_stty_state_$channel]
set previous_stty_state_$channel ""
set is_raw 0
tsv::set console is_raw 0
return restored
}
exec {*}$sttycmd -raw echo <@$channel
set is_raw 0
tsv::set console is_raw 0
return done
}
proc enableVirtualTerminal {{channels {input output}}} {
@ -249,11 +256,11 @@ namespace eval punk::console {
}
proc mode {{raw_or_line query}} {
variable is_raw
#variable is_raw
variable ansi_available
set raw_or_line [string tolower $raw_or_line]
if {$raw_or_line eq "query"} {
if {$is_raw} {
if {[tsv::get console is_raw]} {
return "raw"
} else {
return "line"
@ -493,7 +500,7 @@ namespace eval punk::console {
}
proc [namespace parent]::enableRaw {{channel stdin}} {
variable is_raw
#variable is_raw
variable previous_stty_state_$channel
if {[package provide twapi] ne ""} {
@ -506,7 +513,7 @@ namespace eval punk::console {
#set newmode [dict merge $oldmode [dict create -lineinput 0 -echoinput 0]]
set newmode [twapi::get_console_input_mode]
set is_raw 1
tsv::set console is_raw 1
#don't disable handler - it will detect is_raw
### twapi::set_console_control_handler {}
return [list stdin [list from $oldmode to $newmode]]
@ -516,7 +523,7 @@ namespace eval punk::console {
}
exec {*}$sttycmd raw -echo <@$channel
set is_raw 1
tsv::set console is_raw 1
#review - inconsistent return dict
return [dict create stdin [list from [set previous_stty_state_$channel] to "" note "fixme - to state not shown"]]
} else {
@ -528,7 +535,7 @@ namespace eval punk::console {
#could be we were missing a step in reopening stdin and console configuration?
proc [namespace parent]::disableRaw {{channel stdin}} {
variable is_raw
#variable is_raw
variable previous_stty_state_$channel
if {[package provide twapi] ne ""} {
@ -537,7 +544,7 @@ namespace eval punk::console {
# Turn on the echo and line-editing bits
twapi::modify_console_input_mode $console_handle -lineinput 1 -echoinput 1
set newmode [twapi::get_console_input_mode]
set is_raw 0
tsv::set console is_raw 0
return [list stdin [list from $oldmode to $newmode]]
} elseif {[set sttycmd [auto_execok stty]] ne ""} {
#stty can return info on windows - but doesn't seem to be able to set anything.
@ -550,7 +557,7 @@ namespace eval punk::console {
return restored
}
exec {*}$sttycmd -raw echo <@$channel
set is_raw 0
tsv::set console is_raw 0
#do we really want to exec stty yet again to show final 'to' state?
#probably not. We should work out how to read the stty result flags and set a result.. or just limit from,to to showing echo and lineedit states.
return [list stdin [list from "[set previous_stty_state_$channel]" to "" note "fixme - to state not shown"]]
@ -634,7 +641,7 @@ namespace eval punk::console {
puts -nonewline $output $query;flush $output
#todo - test and save rawstate so we don't disableRaw if console was already raw
if {!$::punk::console::is_raw} {
if {![tsv::get console is_raw]} {
set was_raw 0
punk::console::enableRaw
} else {
@ -1378,7 +1385,7 @@ namespace eval punk::console {
#todo - compare speed with get_cursor_pos - work out why the big difference
proc test_cursor_pos {} {
if {!$::punk::console::is_raw} {
if {![tsv::get console is_raw]} {
set was_raw 0
enableRaw
} else {

108
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/du-0.1.0.tm

@ -1065,56 +1065,65 @@ namespace eval punk::du {
#note - with this design, we can't glob for all except dotfiles - this is for cross-platform consistency and efficiency (Review).
#dotfiles aren't considered hidden on all platforms
#some sort of antiglob is a possible enhancement and more consistent with the view that leading dot should be treated as any other filename character in this context.
if {"windows" eq $::tcl_platform(platform)} {
if {$opt_glob eq "*"} {
#Note - glob operations seem to be faster than looped tests like 'file isdirectory' & 'file readlink'
#set parent [lindex $folders $folderidx]
set hdirs [glob -nocomplain -dir $folderpath -types {hidden d} * .*]
#set hdirs {}
set dirs [glob -nocomplain -dir $folderpath -types d * .*]
set hlinks [glob -nocomplain -dir $folderpath -types {hidden l} * .*]
#set hlinks {}
set links [glob -nocomplain -dir $folderpath -types l * .*] ;#links may have dupes - we don't care. struct::set difference will remove (?)
#set links [lsort -unique [concat $hlinks $links[unset links]]]
set links [glob -nocomplain -dir $folderpath -types l * .*] ;#links may have dupes - we don't care. punk::lib::struct_set_diff_unique
set hfiles [glob -nocomplain -dir $folderpath -types {hidden f} * .*]
#set hfiles {}
set files [glob -nocomplain -dir $folderpath -types f * .*]
#set files {}
} else {
set hdirs [glob -nocomplain -dir $folderpath -types {hidden d} $opt_glob]
set dirs [glob -nocomplain -dir $folderpath -types d $opt_glob]
set hlinks [glob -nocomplain -dir $folderpath -types {hidden l} $opt_glob]
set links [glob -nocomplain -dir $folderpath -types l $opt_glob] ;#links may have dupes - we don't care. struct::set difference will remove (?)
set links [glob -nocomplain -dir $folderpath -types l $opt_glob] ;#links may have dupes - we don't care. punk::lib::struct_set_diff_unique
set hfiles [glob -nocomplain -dir $folderpath -types {hidden f} $opt_glob]
set files [glob -nocomplain -dir $folderpath -types f $opt_glob]
}
} else {
set hdirs {}
set hfiles {}
set hlinks {}
if {$opt_glob eq "*"} {
#Note - glob operations seem to be faster than looped tests like 'file isdirectory' & 'file readlink'
#set parent [lindex $folders $folderidx]
set dirs [glob -nocomplain -dir $folderpath -types d * .*]
set links [glob -nocomplain -dir $folderpath -types l * .*] ;#links may have dupes - we don't care. punk::lib::struct_set_diff_unique
set files [glob -nocomplain -dir $folderpath -types f * .*]
} else {
set dirs [glob -nocomplain -dir $folderpath -types d $opt_glob]
set links [glob -nocomplain -dir $folderpath -types l $opt_glob] ;#links may have dupes - we don't care. punk::lib::struct_set_diff_unique
set files [glob -nocomplain -dir $folderpath -types f $opt_glob]
}
}
#note struct::set difference produces unordered result
#struct::set difference removes duplicates (but not always.. e.g if using tcl impl and 2nd element empty!)
#relying on struct::set to remove dupes is somewhat risky. It is not well documented - and behaviour of dupes in inputs is underspecified as it appears to be intended for mathematical 'sets'
#relying on struct::set to remove dupes is somewhat risky.
#It is not well documented - and behaviour of dupes in inputs is underspecified as it appears to be intended for mathematical 'sets' ie lists without dupes
#for this reason we must use the wrapper punk::lib::struct_set_diff_unique, which will use the well behaved critcl for speed if avail, but fall back to a deduping tcl version
#remove links and . .. from directories, remove links from files
#ideally we would like to classify links by whether they point to files vs dirs - but there are enough cross-platform differences that we will have to leave it to the caller to sort out for now.
#struct::set will affect order: tcl vs critcl give different ordering!
set files [struct::set difference [concat $hfiles $files[unset files]] $links]
set dirs [struct::set difference [concat $hdirs $dirs[unset dirs]] [concat $links [list [file join $folderpath .] [file join $folderpath ..] ]]]
#set links [lsort -unique [concat $links $hlinks]]
set files [punk::lib::struct_set_diff_unique [list {*}$hfiles {*}$files[unset files]] $links]
set dirs [punk::lib::struct_set_diff_unique [list {*}$hdirs {*}$dirs[unset dirs] ] [list {*}$links [file join $folderpath .] [file join $folderpath ..]]]
#----
set mdata_lists [du_get_metadata_lists $sized_types $timed_types $files $dirs $links]
if {"windows" eq $::tcl_platform(platform)} {
set flaggedhidden [concat $hdirs $hfiles $hlinks]
} else {
set flaggedhidden [list {*}$hdirs {*}$hfiles {*}$hlinks]
#unix dotted files/folders are not 'flagged' as such - it's a convention - so the client can use the same convention to decide if something is hidden
#this allows us to return less data - but more importantly - reserve flaggedhidden for systems where such a flag exists and avoid conflating the different concepts of what is hidden
set flaggedhidden {}
}
set vfsmounts [get_vfsmounts_in_folder $folderpath]
@ -1223,21 +1232,21 @@ namespace eval punk::du {
#if {[punk::mix::base::lib::path_a_above_b $folderpath "//zipfs:/"]} {}
#zipfs files also reported as links by glob - review - should we preserve this in response?
#todo - hidden? not returned in attributes on windows at least.
#zipfs files also reported as links by glob - review - should we preserve this in response? (2024 unable to duplicate)
if {$opt_glob eq "*"} {
set dirs [glob -nocomplain -dir $folderpath -types d * .*] ;# also returns links to dirs
#set links [glob -nocomplain -dir $folderpath -types l * .*] ;# links may have dupes - we don't care. struct::set difference will remove
set links [list]
set links [glob -nocomplain -dir $folderpath -types l * .*] ;# links may have dupes - we don't care. struct::set difference will remove
set files [glob -nocomplain -dir $folderpath -types f * .*] ;# also returns links to files
} else {
set dirs [glob -nocomplain -dir $folderpath -types d $opt_glob]
#set links [glob -nocomplain -dir $folderpath -types l $opt_glob]
set links [list]
set links [glob -nocomplain -dir $folderpath -types l $opt_glob]
set files [glob -nocomplain -dir $folderpath -types f $opt_glob]
}
#remove any links from our dirs and files collections
set dirs [struct::set difference $dirs[unset dirs] [concat $links [list [file join $folderpath .] [file join $folderpath ..] ]]]
set files [struct::set difference $files[unset files] $links]
#see du_dirlisting_generic re struct::set difference issues
set dirs [punk::lib::struct_set_diff_unique $dirs[unset dirs] [list {*}$links [file join $folderpath .] [file join $folderpath ..]]]
set files [punk::lib::struct_set_diff_unique $files[unset files] $links]
#nested vfs mount.. REVIEW - does anything need special handling?
@ -1300,34 +1309,63 @@ namespace eval punk::du {
}
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
#at least some vfs on windows seem to support the -hidden attribute
#we are presuming glob will accept the -types hidden option for all vfs - even if it doesn't really apply REVIEW
#The extra globs aren't nice - but hopefully the vfs is reasonably performant (?)
set errors [dict create]
if {"windows" eq $::tcl_platform(platform)} {
if {$opt_glob eq "*"} {
set hdirs [glob -nocomplain -dir $folderpath -types {hidden d} * .*]
set dirs [glob -nocomplain -dir $folderpath -types d * .*] ;# also returns links to dirs
#review - how are links handled in vfs? presumably if the vfs is a full implementation they should work at least within the vfs?
set hlinks [glob -nocomplain -dir $folderpath -types {hidden l} * .*]
set links [glob -nocomplain -dir $folderpath -types l * .*] ;# links may have dupes - we don't care. struct::set difference will remove
set hfiles [glob -nocomplain -dir $folderpath -types {hidden l} * .*]
set files [glob -nocomplain -dir $folderpath -types f * .*] ;# also returns links to files
} else {
set hdirs [glob -nocomplain -dir $folderpath -types {hidden d} $opt_glob]
set dirs [glob -nocomplain -dir $folderpath -types d $opt_glob]
set hlinks [glob -nocomplain -dir $folderpath -types {hidden l} $opt_glob]
set links [glob -nocomplain -dir $folderpath -types l $opt_glob]
set hfiles [glob -nocomplain -dir $folderpath -types {hidden f} $opt_glob]
set files [glob -nocomplain -dir $folderpath -types f $opt_glob]
}
} else {
#we leave it to the ui on unix to classify dotfiles as hidden
set hdirs {}
set hfiles {}
set hlinks {}
if {$opt_glob eq "*"} {
set dirs [glob -nocomplain -dir $folderpath -types d * .*] ;# also returns links to dirs
#review - how are links handled in vfs? presumably if the vfs is a full implementation they should work at least within the vfs?
set links [glob -nocomplain -dir $folderpath -types l * .*] ;# links may have dupes - we don't care. struct::set difference will remove
set files [glob -nocomplain -dir $folderpath -types f * .*] ;# also returns links to files
} else {
set dirs [glob -nocomplain -dir $folderpath -types d $opt_glob]
set links [glob -nocomplain -dir $folderpath -types l $opt_glob]
set files [glob -nocomplain -dir $folderpath -types f $opt_glob]
}
}
#remove any links from our dirs and files collections
set dirs [struct::set difference $dirs[unset dirs] [concat $links [list [file join $folderpath .] [file join $folderpath ..] ]]]
set files [struct::set difference $files[unset files] $links]
#see du_dirlisting_generic re struct::set difference issues
set dirs [punk::lib::struct_set_diff_unique $dirs[unset dirs] [list {*}$links [file join $folderpath .] [file join $folderpath ..] ]]
set files [punk::lib::struct_set_diff_unique $files[unset files] $links]
#nested vfs mount.. REVIEW - does anything need special handling?
set vfsmounts [get_vfsmounts_in_folder $folderpath]
set mdata_lists [du_get_metadata_lists $sized_types $timed_types $files $dirs $links]
set flaggedhidden [list {*}$hdirs {*}$hfiles {*}$hlinks]
set effective_opts $opts
dict set effective_opts -with_times $timed_types
dict set effective_opts -with_sizes $sized_types
return [list dirs $dirs vfsmounts $vfsmounts links $links files $files filesizes [dict get $mdata_lists fsizes] sizes [dict get $mdata_lists allsizes] times [dict get $mdata_lists alltimes] flaggedhidden {} flaggedsystem {} flaggedreadonly {} altname {} opts $effective_opts errors $errors]
return [list dirs $dirs vfsmounts $vfsmounts links $links files $files filesizes [dict get $mdata_lists fsizes] sizes [dict get $mdata_lists allsizes] times [dict get $mdata_lists alltimes] flaggedhidden $flaggedhidden flaggedsystem {} flaggedreadonly {} altname {} opts $effective_opts errors $errors]
}
#we can halve the number of round trips on unix-like systems, where 'hidden' always corresponds to dotted files
#but we don't classify as such anyway. (leave for UI)
proc du_dirlisting_unix {folderpath args} {
set defaults [dict create\
-glob *\
@ -1379,6 +1417,9 @@ namespace eval punk::du {
}
#this is not consistent with standard way * works for unix folders - but it is consistent with behaviour of this facility on windows
#we don't classify anything as 'flaggedhidden' on unix.
#it is a convention for dotfiles rather than a flag - and we'll leave the distinction for the display library
#This
if {$opt_glob eq "*"} {
set dirs [glob -nocomplain -dir $folderpath -types d * .*] ;# also returns links to dirs
set links [glob -nocomplain -dir $folderpath -types l * .*] ;# links may have dupes - we don't care. struct::set difference will remove
@ -1389,8 +1430,9 @@ namespace eval punk::du {
set files [glob -nocomplain -dir $folderpath -types f $opt_glob]
}
#remove any links from our dirs and files collections
set dirs [struct::set difference $dirs[unset dirs] [concat $links [list [file join $folderpath .] [file join $folderpath ..] ]]]
set files [struct::set difference $files[unset files] $links]
#see du_dirlisting_generic re struct::set difference issues
set dirs [punk::lib::struct_set_diff_unique $dirs[unset dirs] [list {*}$links [file join $folderpath .] [file join $folderpath ..] ]]
set files [punk::lib::struct_set_diff_unique $files[unset files] $links]
set vfsmounts [get_vfsmounts_in_folder $folderpath]
set mdata_lists [du_get_metadata_lists $sized_types $timed_types $files $dirs $links]
@ -1406,7 +1448,7 @@ namespace eval punk::du {
#return fsizes,allsizes,alltimes metadata in same order as files,dirs,links lists - if specified in sized_types
proc du_get_metadata_lists {sized_types timed_types files dirs links} {
set meta_dict [dict create]
set meta_types [concat $sized_types $timed_types]
set meta_types [list {*}$sized_types {*}$timed_types]
#known tcl stat keys 2023 - review
set empty_stat_dict [dict create atime {} ctime {} dev {} gid {} ino {} mode {} mtime {} nlink {} size {} type {} uid {}]
#make sure we call file stat only once per item
@ -1419,6 +1461,7 @@ namespace eval punk::du {
if {![catch {file stat $path arrstat} errM]} {
dict set meta_dict $path [dict create shorttype $ft {*}[array get arrstat]]
} else {
puts stderr "du_get_metadata_lists: file stat $path error: $errM"
dict lappend errors $path "file stat error: $errM"
dict set meta_dict $path [dict create shorttype $ft {*}$empty_stat_dict]
}
@ -1437,6 +1480,9 @@ namespace eval punk::du {
if {$ft eq "f"} {
#subst with na if empty?
lappend fsizes [dict get $pathinfo size]
if {[dict get $pathinfo size] eq ""} {
puts stderr "du_get_metadata_lists: fsize $path is empty!"
}
}
}
if {$ft in $timed_types} {
@ -1446,7 +1492,7 @@ namespace eval punk::du {
#todo - fix . The list lengths will presumably match but have empty values if failed to stat
if {"f" in $sized_types} {
if {[llength $fsizes] ne [llength $files]} {
dict lappend errors $folderpath "failed to retrieve all file sizes"
dict lappend errors general "failed to retrieve all file sizes"
}
}
return [dict create fsizes $fsizes allsizes $allsizes alltimes $alltimes]

1
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/fileline-0.1.0.tm

@ -290,7 +290,6 @@ namespace eval punk::fileline::class {
-showconfig 0\
-boundaryheader {Boundary %i% at %b%}\
]
set known_opts [dict keys $defaults]
foreach {k v} $args {
switch -- $k {
-ansi - -offset - -displaybytes - -truncatedmark - -completemark - -moremark - -continuemark - -linemaxwidth - -linebase - -limit - -boundaries - -showconfig - -boundaryheader {

171
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/lib-0.1.1.tm

@ -339,6 +339,144 @@ namespace eval punk::lib {
set has_twapi [expr {![catch {package require twapi}]}]
}
# == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==
# Maintenance - This is the primary source for tm_version... functions
# - certain packages script require these but without package dependency
# - 1 punk boot script
# - 2 packagetrace module
# - These should be updated to sync with this
# == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==
proc tm_version_isvalid {versionpart} {
#Needs to be suitable for use with Tcl's 'package vcompare'
if {![catch [list package vcompare $versionpart $versionpart]]} {
return 1
} else {
return 0
}
}
proc tm_version_major {version} {
if {![tm_version_isvalid $version]} {
error "Invalid version '$version' is not a proper Tcl module version number"
}
set firstpart [lindex [split $version .] 0]
#check for a/b in first segment
if {[string is integer -strict $firstpart]} {
return $firstpart
}
if {[string first a $firstpart] > 0} {
return [lindex [split $firstpart a] 0]
}
if {[string first b $firstpart] > 0} {
return [lindex [split $firstpart b] 0]
}
error "tm_version_major unable to determine major version from version number '$version'"
}
proc tm_version_canonical {ver} {
#accepts a single valid version only - not a bounded or unbounded spec
if {![tm_version_isvalid $ver]} {
error "tm_version_canonical version '$ver' is not valid for a package version"
}
set parts [split $ver .]
set newparts [list]
foreach o $parts {
set trimmed [string trimleft $o 0]
set firstnonzero [string index $trimmed 0]
switch -exact -- $firstnonzero {
"" {
lappend newparts 0
}
a - b {
#e.g 000bnnnn -> bnnnnn
set tailtrimmed [string trimleft [string range $trimmed 1 end] 0]
if {$tailtrimmed eq ""} {
set tailtrimmed 0
}
lappend newparts 0$firstnonzero$tailtrimmed
}
default {
#digit
if {[string is integer -strict $trimmed]} {
#e.g 0100 -> 100
lappend newparts $trimmed
} else {
#e.g 0100b003 -> 100b003 (still need to process tail)
if {[set apos [string first a $trimmed]] > 0} {
set lhs [string range $trimmed 0 $apos-1] ;#assert lhs non-empty and only digits or wouldn't be in this branch
set rhs [string range $trimmed $apos+1 end] ;#assert rhs non-empty and only digits
set rhs [string trimleft $rhs 0]
if {$rhs eq ""} {
set rhs 0
}
lappend newparts ${lhs}a${rhs}
} elseif {[set bpos [string first b $trimmed]] > 0} {
set lhs [string range $trimmed 0 $bpos-1] ;#assert lhs non-empty and only digits or wouldn't be in this branch
set rhs [string range $trimmed $bpos+1 end] ;#assert rhs non-empty and only digits
set rhs [string trimleft $rhs 0]
if {$rhs eq ""} {
set rhs 0
}
lappend newparts ${lhs}b${rhs}
} else {
#assert - shouldn't get here trimmed val should have been empty, an int or contained an a or b
error "tm_version_canonical error - trimfail - unexpected"
}
}
}
}
}
return [join $newparts .]
}
proc tm_version_required_canonical {versionspec} {
#also trim leading zero from any dottedpart?
#Tcl *allows* leading zeros in any of the dotted parts - but they are not significant.
#e.g 1.01 is equivalent to 1.1 and 01.001
#also 1b3 == 1b0003
if {[string trim $versionspec] eq ""} {return ""} ;#unspecified = any version
set errmsg "tm_version_required_canonical - invalid version specification"
if {[string first - $versionspec] < 0} {
#no dash
#looks like a minbounded version (ie a single version with no dash) convert to min-max form
set from $versionspec
if {![tm_version_isvalid $from]} {
error "$errmsg '$versionpec'"
}
if {![catch {tm_version_major $from} majorv]} {
set from [tm_version_canonical $from]
return "${from}-[expr {$majorv +1}]"
} else {
error "$errmsg '$versionspec'"
}
} else {
# min- or min-max
#validation and canonicalisation (strip leading zeroes from each segment, including either side of a or b)
set parts [split $versionspec -] ;#we expect only 2 parts
lassign $parts from to
if {![tm_version_isvalid $from]} {
error "$errmsg '$versionspec'"
}
set from [tm_version_canonical $from]
if {[llength $parts] == 2} {
if {$to ne ""} {
if {![tm_version_isvalid $to]} {
error "$errmsg '$versionspec'"
}
set to [tm_version_canonical $to]
return $from-$to
} else {
return $from-
}
} else {
error "$errmsg '$versionspec'"
}
error "tm_version_required_canonical should have already returned a canonicalised versionspec - or produced an error with reason before this point"
}
}
# end tm_version... functions
# == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==
# -- ---
#https://stackoverflow.com/questions/17631269/whats-the-best-way-to-join-two-lists
#DKF's 2013 recommendation of using list {*}$first {*}$second seems not to apply in 2024
@ -1575,8 +1713,20 @@ namespace eval punk::lib {
lremove $fromlist {*}$doomed
}
#fix for tcl impl of struct::set::diff which doesn't dedupe
proc struct_set_diff_unique {A B} {
package require struct::set ;#require even if tcl impl - so the dependency isn't missed accidentally due to Loaded state of programmers machine.
if {[struct::set::Loaded] eq "tcl"} {
return [punk::lib::setdiff $A $B]
} else {
#use (presumably critcl) implementation for speed
return [struct::set difference $A $B]
}
}
#non-dupe preserving - for consistency in dedupe behaviour we don't shortcircuit empty B
#consistent dedupe and order-maintenance of remaining items in A differentiate this from struct::set difference
#consistent dedupe and order-maintenance of remaining items in A differentiate this from struct::set difference (dedupes with critcl, doesn't with tcl implementation 2024)
#also struct::set difference with critcl is faster
proc setdiff {A B} {
if {[llength $A] == 0} {return {}}
@ -2387,7 +2537,7 @@ namespace eval punk::lib {
set stdin_state [fconfigure stdin]
if {[catch {
package require punk::console
set console_raw [set ::punk::console::is_raw]
set console_raw [tsv::get console is_raw]
} err_console]} {
#assume normal line mode
set console_raw 0
@ -3032,6 +3182,11 @@ namespace eval punk::lib {
proc objclone {obj} {
append obj2 $obj {}
}
proc set_clone {varname obj} {
#used by repl's codeinterp. Maintains internal rep, easier to call e.g interp eval code [list punk::set_clone varnmame $val]
append obj2 $obj {}
uplevel 1 [list set $varname $obj2]
}
@ -3175,7 +3330,7 @@ tcl::namespace::eval punk::lib::system {
#[para] Internal functions that are not part of the API
#[list_begin definitions]
proc has_script_var_bug {} {
proc has_tclbug_script_var {} {
set script {set j [list spud] ; list}
append script \n
uplevel #0 $script
@ -3194,7 +3349,15 @@ tcl::namespace::eval punk::lib::system {
return false
}
}
proc has_safeinterp_compile_bug {{show 0}} {
proc has_tclbug_list_quoting_emptyjoin {} {
#https://core.tcl-lang.org/tcl/tktview/e38dce74e2
set v1 [list {*}[lindex #foo] {*}[]] ;#can return "#foo" instead of "{#foo}" under some beta 9 releases
set v2 [list #foo] ;#normal tcl list quoting for 1st element that looks like a comment -> "{#foo}"
return [expr {![string equal $v1 $v2]}] ;#if they're not equal - we have the bug.
}
proc has_tclbug_safeinterp_compile {{show 0}} {
#ensemble calls within safe interp not compiled
namespace eval [namespace current]::testcompile {
proc ensembletest {} {string index a 0}

23
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/base-0.1.tm

@ -473,13 +473,26 @@ namespace eval punk::mix::base {
#set data [fileutil::cat -translation binary $filename] ;#no significant performance diff on windows - and doesn't handle win-illegal names
zlib adler32 $data
}
#zlib crc vie file-slurp
#zlib crc via file-slurp
proc cksum_crc_file {filename} {
package require zlib
set data [punk::mix::util::fcat -translation binary -encoding iso8859-1 $filename]
zlib crc $data
}
proc cksum_md5_data {data} {
if {[package vsatisfies [package present md5] 2-]} {
return [md5::md5 -hex $data]
} else {
return [md5::md5 $data]
}
}
#fallback md5 via file-slurp - shouldn't be needed if have md5 2-
proc cksum_md5_file {filename} {
set data [punk::mix::util::fcat -translation binary -encoding iso8859-1 $filename]
cksum_md5_data $data
}
#required to be able to accept relative paths
#for full cksum - using tar could reduce number of hashes to be made..
@ -624,7 +637,11 @@ namespace eval punk::mix::base {
}
md5 {
package require md5
if {[package vsatisfies [package present md5] 2- ] } {
set cksum_command [list md5::md5 -hex -file]
} else {
set cksum_comand [list cksum_md5_file]
}
}
cksum {
package require cksum ;#tcllib
@ -637,7 +654,7 @@ namespace eval punk::mix::base {
set cksum_command [list cksum_adler32_file]
}
sha3 - sha3-256 {
#todo - replace with something that doesn't call another process
#todo - replace with something that doesn't call another process - only if tcllibc not available!
#set cksum_command [list apply {{file} {lindex [exec fossil sha3sum -256 $file] 0}}]
set cksum_command [list $sha3_implementation 256]
}
@ -684,7 +701,7 @@ namespace eval punk::mix::base {
set sizeinfo "(file type $ftype - tarred size [punk::lib::format_number [file size $archivename]] bytes)"
}
set tsstart [clock millis]
puts -nonewline stdout "cksum_path: calculating cksum for $target $sizeinfo ... "
puts -nonewline stdout "cksum_path: calculating cksum using $opt_cksum_algorithm for $target $sizeinfo ... "
set cksum [{*}$cksum_command $archivename]
set tsend [clock millis]
set ms [expr {$tsend - $tsstart}]

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

@ -271,7 +271,12 @@ namespace eval punk::mix::commandset::doc {
#this case only came up because docgen used to path munge to long filenames - but left because we know there is a limit and renaming fixes it - even if it's ugly - but still allows doc generation.
#review - if we're checking fname - should also test length of whole path and determine limits for tar
package require md5
set target_docname [md5::md5 -hex [encoding convertto utf-8 $fullpath]]_overlongfilename.man
if {[package vsatisfies [package present md5] 2- ] } {
set md5opt "-hex"
} else {
set md5opt ""
}
set target_docname [md5::md5 {*}$md5opt [encoding convertto utf-8 $fullpath]]_overlongfilename.man
puts stderr "WARNING - overlong file name - renaming $fullpath"
puts stderr " to [file dirname $fullpath]/$target_docname"
}

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

@ -261,6 +261,8 @@ namespace eval punk::mix::util {
return
}
# review punk::lib::tm_version.. functions
proc is_valid_tm_version {versionpart} {
#Needs to be suitable for use with Tcl's 'package vcompare'
if {![catch [list package vcompare $versionpart $versionpart]]} {

44
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/nav/fs-0.1.0.tm

@ -821,9 +821,12 @@ tcl::namespace::eval punk::nav::fs {
set match_contents $opt_tailglob
}
}
puts stdout "searchbase: $searchbase searchspec:$searchspec"
#puts stdout "searchbase: $searchbase searchspec:$searchspec"
set in_vfs 0
#file attr //cookit:/ returns {-vfs 1 -handle {}}
#we will treat it differently for now - use generic handler REVIEW
set in_vfs 0 ;#we use this only for a vfs which is reported to have a mountpoint by vfs::filesystem info - not all that have -vfs 1 attr like cookit.
if {[llength [package provide vfs]]} {
foreach mount [vfs::filesystem info] {
if {[punk::mix::base::lib::path_a_atorbelow_b $location $mount]} {
@ -849,20 +852,43 @@ tcl::namespace::eval punk::nav::fs {
set listing [punk::du::lib::du_dirlisting_tclvfs $location -glob $match_contents {*}$next_opt_with_sizes {*}$next_opt_with_times]
} else {
set in_zipfs 0
set in_cookit 1
set in_other_pseudovol 1
switch -glob -- $location {
//zipfs:/* {
if {[info commands ::tcl::zipfs::mount] ne ""} {
if {[string match //zipfs:/* $location]} {
set in_zipfs 1
}
#dict for {zmount zpath} [zipfs mount] {
# if {[punk::mix::base::lib::path_a_atorbelow_b $location $zmount]} {
# set in_zipfs 1
# break
# }
#}
}
//cookit:/* {
set in_cookit 1
}
default {
#handle 'other/unknown' that mounts at a volume-like path //pseudovol:/
if {[regexp {//((?:(?!:|/).)+):/.*} $location _match pseudovol]} {
#pseudovol probably more than one char long
#we don't really expect something like //c:/ , but anyway, it's not the same as c:/ and for all we know someone could use that as a volume name?
set in_other_pseudovol 1 ;#flag so we don't use twapi - hope generic can handle it (uses tcl glob)
} else {
#we could use 'file attr' here to test if {-vfs 1}
#but it's an extra filesystem hit on all normal paths too (which can be expensive on some systems)
#instead for now we'll assume any reasonable vfs should have been found by vfs::filesystem::info or mounted as a pseudovolume
}
}
}
if {$in_zipfs} {
#relative vs absolute? review - cwd valid for //zipfs:/ ??
set listing [punk::du::lib::du_dirlisting_zipfs $location -glob $match_contents {*}$next_opt_with_sizes {*}$next_opt_with_times]
} elseif {$in_cookit} {
#seems to be a vfs - except it mounts on a pseudo-volume path //cookit:/
#don't use twapi
#could possibly use du_dirlisting_tclvfs REVIEW
#files and folders are all returned with the -types hidden option for glob on windows
set listing [punk::du::lib::du_dirlisting_generic $location -glob $match_contents {*}$next_opt_with_sizes {*}$next_opt_with_times]
} elseif {$in_other} {
set listing [punk::du::lib::du_dirlisting_generic $location -glob $match_contents {*}$next_opt_with_sizes {*}$next_opt_with_times]
} else {
set listing [punk::du::dirlisting $location -glob $match_contents {*}$next_opt_with_sizes {*}$next_opt_with_times]
}

24
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/packagepreference-0.1.0.tm

@ -155,18 +155,26 @@ tcl::namespace::eval punk::packagepreference {
if {[lindex $args 1] eq "-exact"} {
set pkg [lindex $args 2]
set vwant [lindex $args 3]
if {[set ver [package provide $pkg]] ne ""} {
if {$ver eq $vwant} {
return $vwant
} else {
#package already provided with a different version.. we will defer to underlying implementation to return the standard error
if {[set ver [$COMMANDSTACKNEXT_ORIGINAL provide $pkg]] ne ""} {
#although we could shortcircuit using vsatisfies to return the ver
#we should instead pass through to COMMANDSTACKNEXT so as not to interfere with whatever it does.
return [$COMMANDSTACKNEXT {*}$args]
}
#if {$vwant eq "" || [$COMMANDSTACKNEXT vsatisfies $ver $vwant]} {
# return $ver
#} else {
# #package already provided with a different version.. we will defer to underlying implementation to return the standard error
# return [$COMMANDSTACKNEXT {*}$args]
#}
}
} else {
set pkg [lindex $args 1]
if {[set ver [package provide $pkg]] ne ""} {
return $ver
set vwant [lindex $args 2]
if {[set ver [$COMMANDSTACKNEXT_ORIGINAL provide $pkg]] ne ""} {
return [$COMMANDSTACKNEXT {*}$args]
#if {$vwant eq "" || [$COMMANDSTACKNEXT vsatisfies $ver $vwant]} {
# return $ver
#}
}
}
if {[regexp {[A-Z]} $pkg]} {

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

@ -20,12 +20,12 @@
#*** !doctools
#[manpage_begin shellspy_module_punk::repl::codethread 0 0.1.0]
#[copyright "2024"]
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}]
#[moddesc {-}] [comment {-- Description at end of page heading --}]
#[titledesc {Module repl codethread}] [comment {-- Name section and table of contents description --}]
#[moddesc {codethread for repl - root interpreter}] [comment {-- Description at end of page heading --}]
#[require punk::repl::codethread]
#[keywords module]
#[keywords module repl]
#[description]
#[para] -
#[para] This is part of the infrastructure required for the punk::repl to operate
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
@ -131,11 +131,14 @@ tcl::namespace::eval punk::repl::codethread {
# return "ok"
#}
variable run_command_cache
proc is_running {} {
variable running
return $running
}
proc runscript {script} {
#puts stderr "->runscript"
variable replthread_cond
variable output_stdout ""
@ -169,9 +172,18 @@ tcl::namespace::eval punk::repl::codethread {
#set errhandle [shellfilter::stack::item_tophandle stderr]
#interp transfer "" $errhandle code
set scope [interp eval code [list set ::punk::ns::ns_current]]
set status [catch {
interp eval code [list tcl::namespace::inscope $scope $script]
#shennanigans to keep compiled script around after call.
#otherwise when $script goes out of scope - internal rep of vars set in script changes.
#The shimmering may be no big deal(?) - but debug/analysis using tcl::unsupported::representation becomes impossible.
interp eval code [list ::punk::lib::set_clone ::codeinterp::clonescript $script] ;#like objclone
interp eval code {
lappend ::codeinterp::run_command_cache $::codeinterp::clonescript
if {[llength $::codeinterp::run_command_cache] > 2000} {
set ::codeinterp::run_command_cache [lrange $::codeinterp::run_command_cache 1750 end][unset ::codeinterp::run_command_cache]
}
tcl::namespace::inscope $::punk::ns::ns_current $::codeinterp::clonescript
}
} result]

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

@ -27,6 +27,11 @@
#
# path/repo functions
#
#REVIEW punk::repo required early by punk boot script to find projectdir
#todo - split off basic find_project chain of functions to a smaller package and import as necessary here
#Then we can reduce early dependencies in punk boot
if {$::tcl_platform(platform) eq "windows"} {
package require punk::winpath
} else {

6
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/textblock-0.1.1.tm

@ -5280,7 +5280,7 @@ tcl::namespace::eval textblock {
It excludes the extra top and side join elements htlj,hlbj,vllj,vlrj"
*values -min 1 -max 1
frametype -help "name from the predefined frametypes:<ftlist>
or an adhoc
or an adhoc "
}]
append spec \n "frametype -help \"A predefined \""
punk::args::get_dict $spec $args
@ -6804,7 +6804,11 @@ tcl::namespace::eval textblock {
if {$use_md5} {
#package require md5 ;#already required at package load
if {[package vsatisfies [package present md5] 2- ] } {
set hash [md5::md5 -hex [encoding convertto utf-8 $hashables]] ;#need fast and unique to content - not cryptographic - review
} else {
set hash [md5::md5 [encoding convertto utf-8 $hashables]]
}
} else {
set hash $hashables
}

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

@ -16,7 +16,7 @@
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
package require Tcl 8.2-
namespace eval ::textutil {}

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

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