19 changed files with 2395 additions and 1651 deletions
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,501 @@ |
|||||||
|
# -*- tcl -*- |
||||||
|
# Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'pmix make' or bin/punkmake to update from <pkg>-buildversion.txt |
||||||
|
# module template: shellspy/src/decktemplates/vendor/punk/modules/template_module-0.0.2.tm |
||||||
|
# |
||||||
|
# Please consider using a BSD or MIT style license for greatest compatibility with the Tcl ecosystem. |
||||||
|
# Code using preferred Tcl licenses can be eligible for inclusion in Tcllib, Tklib and the punk package repository. |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# (C) 2024 |
||||||
|
# |
||||||
|
# @@ Meta Begin |
||||||
|
# Application punk::experiment 999999.0a1.0 |
||||||
|
# Meta platform tcl |
||||||
|
# Meta license <unspecified> |
||||||
|
# @@ Meta End |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# doctools header |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
#*** !doctools |
||||||
|
#[manpage_begin shellspy_module_punk::experiment 0 999999.0a1.0] |
||||||
|
#[copyright "2024"] |
||||||
|
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}] |
||||||
|
#[moddesc {-}] [comment {-- Description at end of page heading --}] |
||||||
|
#[require punk::experiment] |
||||||
|
#[keywords module] |
||||||
|
#[description] |
||||||
|
#[para] - |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[section Overview] |
||||||
|
#[para] overview of punk::experiment |
||||||
|
#[subsection Concepts] |
||||||
|
#[para] - |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Requirements |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[subsection dependencies] |
||||||
|
#[para] packages used by punk::experiment |
||||||
|
#[list_begin itemized] |
||||||
|
|
||||||
|
package require Tcl 8.6- |
||||||
|
#*** !doctools |
||||||
|
#[item] [package {Tcl 8.6}] |
||||||
|
|
||||||
|
# #package require frobz |
||||||
|
# #*** !doctools |
||||||
|
# #[item] [package {frobz}] |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[section API] |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# oo::class namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval punk::experiment::class { |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace punk::experiment::class}] |
||||||
|
#[para] class definitions |
||||||
|
if {[info commands [namespace current]::interface_sample1] eq ""} { |
||||||
|
#*** !doctools |
||||||
|
#[list_begin enumerated] |
||||||
|
|
||||||
|
# oo::class create interface_sample1 { |
||||||
|
# #*** !doctools |
||||||
|
# #[enum] CLASS [class interface_sample1] |
||||||
|
# #[list_begin definitions] |
||||||
|
|
||||||
|
# method test {arg1} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call class::interface_sample1 [method test] [arg arg1]] |
||||||
|
# #[para] test method |
||||||
|
# puts "test: $arg1" |
||||||
|
# } |
||||||
|
|
||||||
|
# #*** !doctools |
||||||
|
# #[list_end] [comment {-- end definitions interface_sample1}] |
||||||
|
# } |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end class enumeration ---}] |
||||||
|
} |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# Base namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval punk::experiment { |
||||||
|
namespace export {[a-z]*} ;# Convention: export all lowercase |
||||||
|
#variable xyz |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace punk::experiment}] |
||||||
|
#[para] Core API functions for punk::experiment |
||||||
|
#[list_begin definitions] |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#proc sample1 {p1 n args} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call [fun sample1] [arg p1] [arg n] [opt {option value...}]] |
||||||
|
# #[para]Description of sample1 |
||||||
|
# #[para] Arguments: |
||||||
|
# # [list_begin arguments] |
||||||
|
# # [arg_def tring p1] A description of string argument p1. |
||||||
|
# # [arg_def integer n] A description of integer argument n. |
||||||
|
# # [list_end] |
||||||
|
# return "ok" |
||||||
|
#} |
||||||
|
|
||||||
|
variable o_opts_table [dict create\ |
||||||
|
] |
||||||
|
variable o_opts_table_defaults [dict create\ |
||||||
|
-test 1\ |
||||||
|
-test2 etc\ |
||||||
|
-test3 333\ |
||||||
|
-test4 444\ |
||||||
|
] |
||||||
|
set topt_keys [dict keys $o_opts_table_defaults] |
||||||
|
set topt_switchkeys [list -test - -test2 - -test3 - -test4] |
||||||
|
|
||||||
|
proc configure args [string map [list %topt_keys% $topt_keys %topt_switchkeys% $topt_switchkeys] { |
||||||
|
variable o_opts_table |
||||||
|
variable o_opts_table_defaults |
||||||
|
if {![llength $args]} { |
||||||
|
return $o_opts_table |
||||||
|
} |
||||||
|
if {[llength $args] == 1} { |
||||||
|
if {[lindex $args 0] in [list %topt_keys%]} { |
||||||
|
#query single option |
||||||
|
set k [lindex $args 0] |
||||||
|
set val [dict get $o_opts_table $k] |
||||||
|
set returndict [dict create option $k value $val ansireset "\x1b\[m"] |
||||||
|
set infodict [dict create] |
||||||
|
switch -- $k { |
||||||
|
-ansibase_header - -ansibase_body - -ansiborder_header - -ansiborder_body - -ansiborder_footer { |
||||||
|
dict set infodict debug [ansistring VIEW $val] |
||||||
|
} |
||||||
|
-framemap_body - -framemap_header - -framelimits_body - -framelimits_header { |
||||||
|
dict set returndict effective [dict get $o_opts_table_effective $k] |
||||||
|
} |
||||||
|
} |
||||||
|
dict set returndict info $infodict |
||||||
|
return $returndict |
||||||
|
#return [dict create option $k value $val ansireset "\x1b\[m" info $infodict] |
||||||
|
} else { |
||||||
|
error "textblock::table configure - unrecognised option '[lindex $args 0]'. Known values [dict keys $o_opts_table_defaults]" |
||||||
|
} |
||||||
|
} |
||||||
|
if {[llength $args] %2 != 0} { |
||||||
|
error "[namespace current]::table configure - unexpected argument count. Require name value pairs" |
||||||
|
} |
||||||
|
foreach {k v} $args { |
||||||
|
switch -- $k { |
||||||
|
%topt_switchkeys% {} |
||||||
|
default { |
||||||
|
error "[namespace current]::table configure - unrecognised option '$k'. Known values [dict keys $o_opts_table_defaults]" |
||||||
|
} |
||||||
|
} |
||||||
|
#if {$k ni [dict keys $o_opts_table_defaults]} { |
||||||
|
# error "[namespace current]::table configure - unrecognised option '$k'. Known values [dict keys $o_opts_table_defaults]" |
||||||
|
#} |
||||||
|
} |
||||||
|
set checked_opts [list] |
||||||
|
foreach {k v} $args { |
||||||
|
switch -- $k { |
||||||
|
-ansibase_header - -ansibase_body - -ansiborder_header - -ansiborder-body - -ansiborder_footer { |
||||||
|
set parts [punk::ansi::ta::split_codes_single $v] ;#caller may have supplied separated codes eg "[a+ Yellow][a+ red]" |
||||||
|
set ansi_codes [list] ; |
||||||
|
foreach {pt code} $parts { |
||||||
|
if {$pt ne ""} { |
||||||
|
#we don't expect plaintext in an ansibase |
||||||
|
error "Unable to interpret $k value as ansi SGR codes. Plaintext detected. Consider using for example: '\[punk::ansi::a+ green]' (or alias '\[a+ green]') to build ansi. debug view: [punk::ansi::ansistring VIEW $v]" |
||||||
|
} |
||||||
|
if {$code ne ""} { |
||||||
|
lappend ansi_codes $code |
||||||
|
} |
||||||
|
} |
||||||
|
set ansival [punk::ansi::codetype::sgr_merge_singles $ansi_codes] |
||||||
|
lappend checked_opts $k $ansival |
||||||
|
} |
||||||
|
-frametype - -frametype_header - -frametype_body { |
||||||
|
#frametype will raise an error if v is not a valid custom dict or one of the known predefined types such as light,heavy,double etc |
||||||
|
lassign [textblock::frametype $v] _cat category _type ftype |
||||||
|
lappend checked_opts $k $v |
||||||
|
} |
||||||
|
-framemap_body - -framemap_header { |
||||||
|
#upvar ::textblock::class::opts_table_defaults tdefaults |
||||||
|
#set default_bmap [dict get $tdefaults -framemap_body] |
||||||
|
#todo - check keys and map |
||||||
|
if {[llength $v] == 1} { |
||||||
|
if {$v eq "default"} { |
||||||
|
upvar ::textblock::class::opts_table_defaults tdefaults |
||||||
|
set default_map [dict get $tdefaults $k] |
||||||
|
lappend checked_opts $k $default_map |
||||||
|
} else { |
||||||
|
error "textblock::table::configure invalid $k value $v. Expected the value 'default' or a dict e.g topleft {hl *}" |
||||||
|
} |
||||||
|
} else { |
||||||
|
foreach {subk subv} $v { |
||||||
|
switch -- $subk { |
||||||
|
topleft - topinner - topright - topsolo - middleleft - middleinner - middleright - middlesolo - bottomleft - bottominner - bottomright - bottomsolo - onlyleft - onlyinner - onlyright - onlysolo {} |
||||||
|
default { |
||||||
|
error "textblock::table::configure invalid $subk. Known values {topleft topinner topright topsolo middleleft middleinner middleright middlesolo bottomleft bottominner bottomright bottomsolo onlyleft onlyinner onlyright onlysolo}" |
||||||
|
} |
||||||
|
} |
||||||
|
dict for {seg subst} $subv { |
||||||
|
switch -- $seg { |
||||||
|
hl - hlt - hlb - vl - vll - vlr - trc - tlc - blc - brc {} |
||||||
|
default { |
||||||
|
error "textblock::table::configure invalid $subk value $seg. Known values {hl hlt hlb vl vll vlr trc tlc blc brc}" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
lappend checked_opts $k $v |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
-framelimits_body - -framelimits_header { |
||||||
|
set specific_framelimits [list] |
||||||
|
foreach fl $v { |
||||||
|
switch -- $fl { |
||||||
|
"default" { |
||||||
|
lappend specific_framelimits trc hlt tlc vll blc hlb brc vlr |
||||||
|
} |
||||||
|
hl { |
||||||
|
lappend specific_framelimits hlt hlb |
||||||
|
} |
||||||
|
vl { |
||||||
|
lappend specific_framelimits vll vlr |
||||||
|
} |
||||||
|
hlt - hlb - vll - vlr - trc - tlc - blc - brc { |
||||||
|
lappend specific_framelimits $fl |
||||||
|
} |
||||||
|
default { |
||||||
|
error "textblock::table::configure invalid $k '$fl'. Known values {hl hlb hlt vl vll vlr trc tlc blc brc} (or default for all)" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
lappend checked_opts $k $specific_framelimits |
||||||
|
} |
||||||
|
-ansireset { |
||||||
|
if {$v eq "\uFFEF"} { |
||||||
|
set RST "\x1b\[m" ;#[a] |
||||||
|
lappend checked_opts $k $RST |
||||||
|
} else { |
||||||
|
error "textblock::table::configure -ansireset is read-only. It is present only to prevent unwanted colourised output in configure commands" |
||||||
|
} |
||||||
|
} |
||||||
|
-show_hseps { |
||||||
|
if {![string is boolean $v]} { |
||||||
|
error "textblock::table::configure invalid $k '$v'. Must be a boolean or empty string" |
||||||
|
} |
||||||
|
lappend checked_opts $k $v |
||||||
|
#these don't affect column width calculations |
||||||
|
} |
||||||
|
-show_edge { |
||||||
|
if {![string is boolean $v]} { |
||||||
|
error "textblock::table::configure invalid $k '$v'. Must be a boolean or empty string" |
||||||
|
} |
||||||
|
lappend checked_opts $k $v |
||||||
|
#these don't affect column width calculations - except if table -minwidth/-maxwidth come into play |
||||||
|
set o_calculated_column_widths [list] ;#invalidate cached column widths - a recalc will be forced when needed |
||||||
|
} |
||||||
|
-show_vseps { |
||||||
|
#we allow empty string - so don't use -strict boolean check |
||||||
|
if {![string is boolean $v]} { |
||||||
|
error "textblock::table::configure invalid $k '$v'. Must be a boolean or empty string" |
||||||
|
} |
||||||
|
#affects width calculations |
||||||
|
set o_calculated_column_widths [list] |
||||||
|
lappend checked_opts $k $v |
||||||
|
} |
||||||
|
-minwidth - -maxwidth { |
||||||
|
set o_calculated_column_widths [list] |
||||||
|
lappend checked_opts $k $v |
||||||
|
} |
||||||
|
default { |
||||||
|
lappend checked_opts $k $v |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
#all options checked - ok to update o_opts_table and o_opts_table_effective |
||||||
|
|
||||||
|
#set o_opts_table [dict merge $o_opts_table $checked_opts] |
||||||
|
foreach {k v} $args { |
||||||
|
#yes in safe |
||||||
|
switch -- $k { |
||||||
|
-framemap_header - -framemap_body { |
||||||
|
#framemaps don't require setting every key to update. |
||||||
|
#e.g configure -framemaps {topleft <map>} |
||||||
|
#needs to merge with existing unspecified keys such as topright middleleft etc. |
||||||
|
if {$v eq "default"} { |
||||||
|
dict set o_opts_table $k default |
||||||
|
} else { |
||||||
|
if {[dict get $o_opts_table $k] eq "default"} { |
||||||
|
dict set o_opts_table $k $v |
||||||
|
} else { |
||||||
|
dict set o_opts_table $k [dict merge [dict get $o_opts_table $k] $v] |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
default { |
||||||
|
dict set o_opts_table $k $v |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
#use values from checked_opts for the effective opts |
||||||
|
dict for {k v} $checked_opts { |
||||||
|
switch -- $k { |
||||||
|
-framemap_body - -framemap_header { |
||||||
|
set existing [dict get $o_opts_table_effective $k] |
||||||
|
#set updated $existing |
||||||
|
#dict for {subk subv} $v { |
||||||
|
# dict set updated $subk $subv |
||||||
|
#} |
||||||
|
#dict set o_opts_table_effective $k $updated |
||||||
|
dict set o_opts_table_effective $k [dict merge $existing $v] |
||||||
|
} |
||||||
|
-framelimits_body - -framelimits_header { |
||||||
|
#my Set_effective_framelimits |
||||||
|
dict set o_opts_table_effective $k $v |
||||||
|
} |
||||||
|
default { |
||||||
|
dict set o_opts_table_effective $k $v |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
#ansireset exception |
||||||
|
dict set o_opts_table -ansireset [dict get $o_opts_table_effective -ansireset] |
||||||
|
return $o_opts_table |
||||||
|
}] |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
proc test1 {args} { |
||||||
|
set result [list] |
||||||
|
dict for {k v} $args { |
||||||
|
switch -- $k { |
||||||
|
-a - -b - -c - -d - -e - -f - -g - -h - -i - -j - -k - -l - -m - -n - -o - -p - -q - -r - -s - -t - -u - -v - -w - -x - -y - -z { |
||||||
|
switch -- $k { |
||||||
|
-a - -b - -c { |
||||||
|
lappend result "dfor-switcharm1-switcharm1-$k" |
||||||
|
} |
||||||
|
default { |
||||||
|
lappend result "dfor-switcharm1-switchdefault-$k" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
default { |
||||||
|
switch -- $k { |
||||||
|
-1 - -2 - -3 - -4 - -5 - -6 - -7 - -8 - -9 { |
||||||
|
lappend result "dfor-switchdefault-switcharm1-$k" |
||||||
|
} |
||||||
|
default { |
||||||
|
lappend result "dfor-switchdefault-switchdefault-$k" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return $result |
||||||
|
} |
||||||
|
|
||||||
|
proc test2 {args} { |
||||||
|
set result [list] |
||||||
|
foreach {k v} $args { |
||||||
|
switch -- $k { |
||||||
|
-a - -b - -c - -d - -e - -f - -g - -h - -i - -j - -k - -l - -m - -n - -o - -p - -q - -r - -s - -t - -u - -v - -w - -x - -y - -z { |
||||||
|
switch -- $k { |
||||||
|
-a - -b - -c { |
||||||
|
lappend result "dfor-switcharm1-switcharm1-$k" |
||||||
|
} |
||||||
|
default { |
||||||
|
lappend result "dfor-switcharm1-switchdefault-$k" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
default { |
||||||
|
switch -- $k { |
||||||
|
-1 - -2 - -3 - -4 - -5 - -6 - -7 - -8 - -9 { |
||||||
|
lappend result "dfor-switchdefault-switcharm1-$k" |
||||||
|
} |
||||||
|
default { |
||||||
|
lappend result "dfor-switchdefault-switchdefault-$k" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return $result |
||||||
|
} |
||||||
|
|
||||||
|
proc test3 {args} { |
||||||
|
set result [list] |
||||||
|
for {set i 0} {$i < [llength $args]} {incr i} { |
||||||
|
set k [lindex $args $i] |
||||||
|
switch -- $k { |
||||||
|
-a - -b - -c - -d - -e - -f - -g - -h - -i - -j - -k - -l - -m - -n - -o - -p - -q - -r - -s - -t - -u - -v - -w - -x - -y - -z { |
||||||
|
switch -- $k { |
||||||
|
-a - -b - -c { |
||||||
|
lappend result "dfor-switcharm1-switcharm1-$k" |
||||||
|
} |
||||||
|
default { |
||||||
|
lappend result "dfor-switcharm1-switchdefault-$k" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
default { |
||||||
|
switch -- $k { |
||||||
|
-1 - -2 - -3 - -4 - -5 - -6 - -7 - -8 - -9 { |
||||||
|
lappend result "dfor-switchdefault-switcharm1-$k" |
||||||
|
} |
||||||
|
default { |
||||||
|
lappend result "dfor-switchdefault-switchdefault-$k" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return $result |
||||||
|
} |
||||||
|
|
||||||
|
oo::class create c1 { |
||||||
|
method test1 args [info body ::punk::experiment::test1] |
||||||
|
method test2 args [info body ::punk::experiment::test2] |
||||||
|
method test3 args [info body ::punk::experiment::test2] |
||||||
|
} |
||||||
|
c1 create obj1 |
||||||
|
|
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end definitions namespace punk::experiment ---}] |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# Secondary API namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval punk::experiment::lib { |
||||||
|
namespace export {[a-z]*} ;# Convention: export all lowercase |
||||||
|
namespace path [namespace parent] |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace punk::experiment::lib}] |
||||||
|
#[para] Secondary functions that are part of the API |
||||||
|
#[list_begin definitions] |
||||||
|
|
||||||
|
#proc utility1 {p1 args} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call lib::[fun utility1] [arg p1] [opt {?option value...?}]] |
||||||
|
# #[para]Description of utility1 |
||||||
|
# return 1 |
||||||
|
#} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end definitions namespace punk::experiment::lib ---}] |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
#*** !doctools |
||||||
|
#[section Internal] |
||||||
|
namespace eval punk::experiment::system { |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace punk::experiment::system}] |
||||||
|
#[para] Internal functions that are not part of the API |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Ready |
||||||
|
package provide punk::experiment [namespace eval punk::experiment { |
||||||
|
variable pkg punk::experiment |
||||||
|
variable version |
||||||
|
set version 999999.0a1.0 |
||||||
|
}] |
||||||
|
return |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[manpage_end] |
||||||
|
|
@ -0,0 +1,3 @@ |
|||||||
|
0.1.0 |
||||||
|
#First line must be a semantic version number |
||||||
|
#all other lines are ignored. |
Loading…
Reference in new issue