Browse Source

punk::ansi work in progress, punk::assertion

master
Julian Noble 9 months ago
parent
commit
27b7695fee
  1. 2
      src/modules/#tarjar-tarjar-2.3/#tarjar-loadscript-tarjar.tcl
  2. 7
      src/modules/flagfilter-0.3.tm
  3. 174
      src/modules/punk-0.1.tm
  4. 818
      src/modules/punk/ansi-999999.0a1.0.tm
  5. 2
      src/modules/punk/args-999999.0a1.0.tm
  6. 412
      src/modules/punk/assertion-999999.0a1.0.tm
  7. 3
      src/modules/punk/assertion-buildversion.txt
  8. 2
      src/modules/punk/cap-999999.0a1.0.tm
  9. 4
      src/modules/punk/cap/handlers/templates-999999.0a1.0.tm
  10. 5
      src/modules/punk/char-999999.0a1.0.tm
  11. 16
      src/modules/punk/console-999999.0a1.0.tm
  12. 8
      src/modules/punk/fileline-999999.0a1.0.tm
  13. 2
      src/modules/punk/lib-999999.0a1.0.tm
  14. 2
      src/modules/punk/mix/commandset/scriptwrap-999999.0a1.0.tm
  15. 2
      src/modules/punk/mix/templates/layouts/project/src/make.tcl
  16. 24
      src/modules/punk/ns-999999.0a1.0.tm
  17. 12
      src/modules/punk/repl-0.1.tm
  18. 2
      src/modules/punk/winrun-999999.0a1.0.tm
  19. 100
      src/testansi/belinda.ans
  20. 62
      src/testansi/timebend.ans
  21. 1160
      src/vendormodules/overtype-1.6.0.tm

2
src/modules/#tarjar-tarjar-2.3/#tarjar-loadscript-tarjar.tcl

@ -1447,7 +1447,7 @@ proc ::tarjar::wrap {scriptfile args} {
catch {unset create_args($k)}
}
#assert: $versionpart now has a value
#assertion: versionpart now has a value
if {![string length [string trim $tm_version]]} {
error "Missing value for 'tm_version'"
}

7
src/modules/flagfilter-0.3.tm

@ -591,7 +591,8 @@ namespace eval flagfilter {
#review - should we be using control::assert here?
#It depends if this is intended to raise error at runtime - would using control::assert and disabling assertions cause problems?
#todo - show caller info
proc assert_equal {a b} {
if {![expr {$a eq $b}]} {
@ -1360,7 +1361,7 @@ namespace eval flagfilter {
}
}
#assert - should be none?
#assertion - should be none?
#set remaining_values [lrange $source_values $a_index end]
#do_debug 3 $debugc "-------->________>end of processing - remaining vals $remaining_values"
@ -2138,7 +2139,7 @@ namespace eval flagfilter {
}
}
set classifications [dict get $processed_arguments classifications] ;#assert - ordered by numerically increasing key representing positions in supplied argument list
set classifications [dict get $processed_arguments classifications] ;#assertion - ordered by numerically increasing key representing positions in supplied argument list
set rangesets [$RETURNED_VMAP get_ranges_from_classifications $classifications]
set ranges [dict get $rangesets -ranges]
set rangesbytype [dict get $rangesets -rangesbytype] ;#unallocated are split into flag,operand and endofoptions - further splitting is easy enough to do by looking up the classifications list for each position in the supplied arg list.

174
src/modules/punk-0.1.tm

@ -88,6 +88,20 @@ package require punk::du
package require punk::mix::base
namespace eval punk {
# -- --- ---
#namespace import ::control::assert ;#according to tcllib doc - assert can be enabled/disabled per namespace
# using control::control assert enabled within a namespace for which ::control::assert wasn't imported can produce surprising results.
#e.g setting to zero may keep asserts enabled - (e.g if the assert command is still available due to namespace path etc) - but.. querying the enabled status may show zero even in the parent namespace where asserts also still work.
#package require control
#control::control assert enabled 1
#We will use punk::assertion instead
package require punk::assertion
namespace import ::punk::assertion::assert
punk::assertion::active on
# -- --- ---
interp alias {} purelist {} lreplace x 0 0 ;#required by pipe system
if {[catch {
package require pattern
@ -97,9 +111,7 @@ namespace eval punk {
package require shellfilter
package require punkapp
package require funcl
package require control
control::control assert enabled 1
namespace import ::control::assert
package require struct::list
package require fileutil
#package require punk::lib
@ -133,8 +145,153 @@ namespace eval punk {
debug header "dbg> "
if {"::lremove" ne [info commands ::lremove]} {
puts stderr "Warning - no built-in lremove"
proc ::lremove {list args} {
set data [lmap v $list {list data $v}]
foreach doomed_index $args {
if {[llength $doomed_index] != 1} {error "bad index \"$doomed_index\": must be integer?\[+-]integer? or end?\[+-]integer?"}
lset data $doomed_index x ;#x won't collide as all our data has been mapped to 2 elements per value
}
set keep [lsearch -all -inline -not -exact $data x]
return [lsearch -all -inline -index 1 -subindices $keep *]
}
#not significantly different in performance over test of 100 elements - getting somewhere near 10% for 1k integers
proc ::lremove2 {list args} {
set data [lmap v $list {list data $v}]
foreach doomed_index $args {
if {[llength $doomed_index] != 1} {error "bad index \"$doomed_index\": must be integer?\[+-]integer? or end?\[+-]integer?"}
lset data $doomed_index x ;#x won't collide as all our data has been mapped to 2 elements per value
}
set keep [lsearch -all -inline -not -exact $data x]
return [lmap v $keep {lindex $v 1}]
}
#outside of lmap - don't know of any particularly nice ways to flatten to subindex 1 of each element..
#flattening then lsearch with -stride and * would be nice - but it's not avail in 8.6 - and even in 8.7 it doesn't seem to allow returning one index of the stridden 'group'
}
if {"::lpop" ne [info commands ::lpop]} {
puts stderr "Warning - no built-in lpop"
interp alias {} lpop {} ::punk::lpop
}
proc lpop {lvar args} {
upvar $lvar l
if {![llength $args]} {
set args [list end]
}
set v [lindex $l {*}$args]
set newlist $l
set path [list]
set subl $l
for {set i 0} {$i < [llength $args]} {incr i} {
set idx [lindex $args $i]
if {![llength [lrange $subl $idx $idx]]} {
error "tcl_lpop index \"$idx\" out of range"
}
#if {[list_index_get $subl $idx] == -1} {
# error "tcl_lpop index \"$idx\" out of range"
#}
lappend path [lindex $args $i]
set subl [lindex $l {*}$path]
}
set sublist_path [lrange $args 0 end-1]
set tailidx [lindex $args end]
if {![llength $sublist_path]} {
#set newlist [lremove $newlist $tailidx]
set newlist [lreplace $newlist $tailidx $tailidx]
} else {
set sublist [lindex $newlist {*}$sublist_path]
#set sublist [lremove $sublist $tailidx]
set sublist [lreplace $sublist $tailidx $tailidx]
lset newlist {*}$sublist_path $sublist
}
#puts "[set l] -> $newlist"
set l $newlist
return $v
}
proc list_index_resolve {list index} {
#Note that for an index such as $x+1 - we never see the '$x' as it is substituted in the calling command. We will get something like 10+1 - which we will resolve (hopefully safely) with expr
if {![llength $list]} {
return -1
}
set index [string map [list _ ""] $index] ;#forward compatibility with integers such as 1_000
if {[string is integer -strict $index]} {
#can match +i -i
if {$index < 0} {
return -1
} elseif {$index >= [llength $list]} {
return -1
} else {
#integer may still have + sign - normalize with expr
return [expr {$index}]
}
} else {
if {[string match end* $index]} {
if {$index ne "end"} {
set op [string index $index 3]
set offset [string range $index 4 end]
if {$op ni {+ -} || ![string is integer -strict $offset]} {error "bad index '$index': must be integer?\[+-\]integer? or end?\[+-\]integer?"}
if {$op eq "+" && $offset != 0} {
return -1
}
} else {
set offset 0
}
#by now, if op = + then offset = 0 so we only need to handle the minus case
if {$offset == 0} {
set index [expr {[llength $list]-1}]
} else {
set index [expr {([llength $list]-1) - $offset}]
}
if {$index < 0} {
return -1
} else {
return $index
}
} else {
#plain +-<int> already handled above.
#we are trying to avoid evaluating unbraced expr of potentially insecure origin
if {[regexp {(.*)([+-])(.*)} $index _match a op b]} {
if {[string is integer -strict $a] && [string is integer -strict $b]} {
if {$op eq "-"} {
set index [expr {$a - $b}]
} else {
set index [expr {$a + $b}]
}
} else {
error "bad index '$index': must be integer?\[+-\]integer? or end?\[+-\]integer?"
}
} else {
error "bad index '$index': must be integer?\[+-\]integer? or end?\[+-\]integer?"
}
if {$index < 0 || $index >= [llength $list]} {return -1}
return $index
}
}
}
proc list_index_resolve2 {list index} {
set indices [list] ;#building this may be somewhat expensive in terms of storage and compute for large lists - we could use lseq in Tcl 8.7+ but that's likely unavailable here.
for {set i 0} {$i < [llength $list]} {incr i} {
lappend indices $i
}
set idx [lindex $indices $index]
if {$idx eq ""} {
return -1
} else {
return $idx
}
}
proc list_index_get {list index} {
set resultlist [lrange $list $index $index]
if {![llength $resultlist]} {
return -1
} else {
#we still don't know the actual integer index for an index such as end-x or int-int without parsing and evaluating ourself.
#we can return the value - but only in a way that won't collide with our -1 out-of-range indicator
return [dict create value [lindex $resultlist 0]]
}
}
variable last_run_display [list]
@ -2179,7 +2336,7 @@ namespace eval punk {
set returnval ""
set i 0
#assert i incremented at each continue and at each end of loop - at end i == list length + 1
#assertion i incremented at each continue and at each end of loop - at end i == list length + 1
#always use 'assigned' var in each loop
# (for consistency and to assist with returnval)
# ^var means a pinned variable - compare value of $var to rhs - don't assign
@ -2222,7 +2379,7 @@ namespace eval punk {
#For booleans the final val may later be normalised to 0 or 1
#assert all var_actions were set with leading question mark
#assertion all var_actions were set with leading question mark
#perform assignments only if matched ok
debug.punk.pipe.var {VAR_CLASS: $var_class} 5
@ -2709,13 +2866,13 @@ namespace eval punk {
}
default {
set first_bound [lsearch -index 0 $var_actions $varname]
#assert first_bound >=0, we will always find something - usually self
#assertion first_bound >=0, we will always find something - usually self
if {$first_bound == $i} {
lset match_state $i 1
lset var_actions $i 1 [string range $act 1 end] ;# ?set -> set
lset expected_values $i [list var $varname spec $lhsspec info "match-any-lhs" lhs - rhs $val]
} else {
#assert - first_bound < $i
assert {$first_bound < $i} assertion_fail: _multi_bind_result condition: [list $first_bound < $i]
set expectedinfo [lindex $expected_values $first_bound]
set expected_earlier [dict get $expectedinfo rhs]
if {$expected_earlier ne $val} {
@ -2856,8 +3013,7 @@ namespace eval punk {
#var_name entries can be blank - but it will still be a list
dict set returndict result $data
} else {
#punk::assert {$i == [llength $var_names]}
assert {$i == [llength $var_names]} assertion_fail _multi_bind_result condition {$i == [llength $var_names]}
dict set returndict result $returnval
}
return $returndict

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

File diff suppressed because it is too large Load Diff

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

@ -391,7 +391,7 @@ namespace eval punk::args {
}
}
set opts [dict merge $defaults_dict_opts $checked_args]
#assert - checked_args keys are full-length option names if -anyopts was false or if the supplied option as a shortname matched one of our defined options
#assertion - checked_args keys are full-length option names if -anyopts was false or if the supplied option as a shortname matched one of our defined options
set values [dict merge $defaults_dict_values $values_dict]

412
src/modules/punk/assertion-999999.0a1.0.tm

@ -0,0 +1,412 @@
# -*- 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::assertion 999999.0a1.0
# Meta platform tcl
# Meta license <unspecified>
# @@ Meta End
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[manpage_begin shellspy_module_punk::assertion 0 999999.0a1.0]
#[copyright "2024"]
#[titledesc {assertion alternative to control::assert}] [comment {-- Name section and table of contents description --}]
#[moddesc {per-namespace assertions with }] [comment {-- Description at end of page heading --}]
#[require punk::assertion]
#[keywords module assertion assert debug]
#[description]
#[para] The punk::assertion library has the same semantics as Tcllib's control::assert library for the assert command itself.
#[para] The main difference is the way in which assert is enabled/disabled in namespaces.
#[para] Due to commands such as 'namespace path' - the assert command could be available in arbitrary namespaces unrelated by tree structure to namespaces where assert has been directly imported.
#[para] punk::assertion::active 0|1 allows activating and deactivating assertions in any namespace where the assert command is available - but only affecting the activations state of the namespace in which it is called.
#[para] If such a non-primary assertion namespace never had active set to 0 or 1 - then it will activate/deactivate when the namespace corresponding to the found assert command (primary) is activated/deactivated.
#[para] Once marked active or inactive - such a non-primary namespace will no longer follow the primary
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Overview]
#[para] overview of punk::assertion
#[subsection Concepts]
#[para] -
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Requirements
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[subsection dependencies]
#[para] packages used by punk::assertion
#[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::assertion::class {
#*** !doctools
#[subsection {Namespace punk::assertion::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 ---}]
}
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#keep 2 namespaces for assertActive and assertInactive so there is introspection available via namespace origin
namespace eval punk::assertion::primary {
namespace export *
proc assertActive {expr args} {
set code [catch {uplevel 1 [list expr $expr]} res]
if {$code} {
return -code $code $res
}
if {![string is boolean -strict $res]} {
return -code error "invalid boolean expression: $expr"
}
if {$res} {return}
if {[llength $args]} {
#set msg "[join $args]"
set msg "$args punk::assertion failed expr $expr"
} else {
set msg "punk::assertion failed expr $expr" ;#give a clue in the default msg about which assert lib is in use
}
upvar ::punk::assertion::CallbackCmd CallbackCmd
# Might want to catch this
namespace eval :: $CallbackCmd [list $msg]
}
proc assertInactive args {}
}
namespace eval punk::assertion::secondary {
namespace export *
#we need to actually define these procs here, (not import then re-export) - or namespace origin will report the original source namespace - which isn't what we want.
proc assertActive {expr args} [info body ::punk::assertion::primary::assertActive]
proc assertInactive args {}
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Base namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval punk::assertion {
variable CallbackCmd [list return -code error]
namespace import ::punk::assertion::primary::assertActive
rename assertActive assert
namespace export *
#variable xyz
#*** !doctools
#[subsection {Namespace punk::assertion}]
#[para] Core API functions for punk::assertion
#[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"
#}
#like tcllib's control::assert - we are limited to the same callback for all namespaces.
#review - a per namespace - or per assert command callback may be tricky to do performantly.
#Would probably involve rewriting the proc body - otherwise we have a runtime penalty in the assert of looking it up.
proc callback {args} {
#set nscaller [uplevel 1 [list namespace current]]
#set which_assert [namespace eval $nscaller {namespace which assert}]
upvar ::punk::assertion::CallbackCmd cb
set n [llength $args]
if {$n > 1} {
return -code error "wrong # args: should be\
\"[lindex [info level 0] 0] ?command?\""
}
if {$n} {
set cb [lindex $args 0]
return
}
return $cb
}
proc active {{on_off ""}} {
set nscaller [uplevel 1 [list namespace current]]
set which_assert [namespace eval $nscaller {namespace which assert}]
#puts "nscaller:'$nscaller'"
#puts "which_assert: $which_assert"
if {$on_off eq ""} {
if {$which_assert eq ""} {return 0}
set assertorigin [namespace origin $which_assert]
#puts "ns which assert: $which_assert"
#puts "ns origin assert: $assertorigin"
return [expr {"assertActive" eq [namespace tail $assertorigin]}]
}
if {![string is boolean -strict $on_off]} {
error "invalid boolean value : $on_off"
} else {
set info_command [namespace eval $nscaller {info commands assert}]
if {$on_off} {
#Enable it in calling namespace
if {"assert" eq $info_command} {
#There is an assert command reachable - due to namespace path etc, it could be in another namespace entirely - (not necessarily in an ancestor namespace of the namespace's tree structure)
if {$which_assert eq [punk::assertion::system::nsjoin ${nscaller} assert]} {
namespace eval $nscaller {
set assertorigin [namespace origin assert]
set assertorigin_ns [punk::assertion::system::nsprefix $assertorigin]
switch -- $assertorigin_ns {
::punk::assertion {
#original import - switch to primary origin
rename assert {}
namespace import ::punk::assertion::primary::assertActive
rename assertActive assert
}
::punk::assertion::primary - ::punk::assertion::secondary {
#keep using from same origin ns
rename assert {}
namespace import ${assertorigin_ns}::assertActive
rename assertActive assert
}
default {
error "The assert command in this namespace is not from punk::assertion package. Use the enable mechanism from the package associated with $assertorigin or remove the existing assert command and namespace import punk::assertion::assert"
}
}
}
return 1
} else {
#assert is available, but isn't in the calling namespace - we should enable it in a way that is distinguishable from case where assert was explicitly imported to this namespace
namespace eval $nscaller {
set assertorigin [namespace origin assert]
if {[string match ::punk::assertion::* $assertorigin]} {
namespace import ::punk::assertion::secondary::assertActive
rename assertActive assert
} else {
error "The reachable assert command at '$which_assert' is not from punk::assertion package. Import punk::assertion::assert - or use the enable mechanism from the package associated with $assertorigin"
}
}
return 1
}
} else {
#no assert command reachable
puts stderr "no assert command visible from namespace '$nscaller' - use: namespace import ::punk::assertion::assert"
return 0
}
} else {
#Disable
if {"assert" eq $info_command} {
if {$which_assert eq [punk::assertion::system::nsjoin ${nscaller} assert]} {
#assert is present in callers NS
namespace eval $nscaller {
set assertorigin [namespace origin assert]
set assertorigin_ns [punk::assertion::system::nsprefix $assertorigin]
switch -glob -- $assertorigin_ns {
::punk::assertion {
#original import
rename assert {}
namespace import punk::assertion::primary::assertInactive
rename assertInactive assert
}
::punk::assertion::primary - ::punk::assertion::secondary {
#keep using from same origin ns
rename assert {}
namespace import ${assertorigin_ns}::assertInactive
rename assertInactive assert
}
default {
error "The assert command in this namespace is not from punk::assertion package. Use the disable mechanism from the package associated with $assertorigin or remove the existing assert command and namespace import punk::assertion::assert"
}
}
}
return 0
} else {
#assert not present in callers NS - first install of secondary (if assert is from punk::assertion::*)
namespace eval $nscaller {
set assertorigin [namespace origin assert]
set assertorigin_ns [punk::assertion::system::nsprefix $assertorigin]
if {[string match ::punk::assertion::* $assertorigin]} {
namespace import ::punk::assertion::secondary::assertInactive
rename assertInactive assert
} else {
error "The reachable assert command at '$which_assert' is not from punk::assertion package. Import punk::assertion::assert - or use the enable mechanism from the package associated with $assertorigin"
}
}
return 0
}
} else {
#no assert command reachable
#If caller is using assert in this namespace - they should have imported it, or ensured it was reachable via namespace path
puts stderr "no assert command visible from namespace '$nscaller' - use: namespace import ::punk::assertion::assert"
return 0
}
}
}
}
#*** !doctools
#[list_end] [comment {--- end definitions namespace punk::assertion ---}]
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Secondary API namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval punk::assertion::lib {
namespace export *
namespace path [namespace parent]
#*** !doctools
#[subsection {Namespace punk::assertion::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::assertion::lib ---}]
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Internal]
namespace eval punk::assertion::system {
#*** !doctools
#[subsection {Namespace punk::assertion::system}]
#[para] Internal functions that are not part of the API
#Maintenance - snarfed from punk::ns to reduce dependencies - punk::ns::nsprefix is the master version
#nsprefix/nstail are string functions - they do not concern themselves with what namespaces are present in the system
proc nsprefix {{nspath {}}} {
#normalize the common case of ::::
set nspath [string map [list :::: ::] $nspath]
set rawprefix [string range $nspath 0 end-[string length [nstail $nspath]]]
if {$rawprefix eq "::"} {
return $rawprefix
} else {
if {[string match *:: $rawprefix]} {
return [string range $rawprefix 0 end-2]
} else {
return $rawprefix
}
#return [string trimright $rawprefix :]
}
}
#see also punk::ns - keep in sync
proc nstail {nspath args} {
#normalize the common case of ::::
set nspath [string map [list :::: ::] $nspath]
set mapped [string map [list :: \u0FFF] $nspath]
set parts [split $mapped \u0FFF]
set defaults [list -strict 0]
set opts [dict merge $defaults $args]
set strict [dict get $opts -strict]
if {$strict} {
foreach p $parts {
if {[string match :* $p]} {
error "nstail unpaired colon ':' in $nspath"
}
}
}
#e.g ::x::y:::z should return ":z" despite it being a bad idea for a command name.
return [lindex $parts end]
}
proc nsjoin {prefix name} {
if {[string match ::* $name]} {
if {"$prefix" ne ""} {
error "nsjoin: won't join non-empty prefix to absolute namespace path '$name'"
}
return $name
}
if {"$prefix" eq "::"} {
return ::$name
}
#if {"$name" eq ""} {
# return $prefix
#}
#nsjoin ::x::y "" should return ::x::y:: - this is the correct fully qualified form used to call a command that is the empty string
return ${prefix}::$name
}
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Ready
package provide punk::assertion [namespace eval punk::assertion {
variable pkg punk::assertion
variable version
set version 999999.0a1.0
}]
return
#*** !doctools
#[manpage_end]

3
src/modules/punk/assertion-buildversion.txt

@ -0,0 +1,3 @@
0.1.0
#First line must be a semantic version number
#all other lines are ignored.

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

@ -249,7 +249,7 @@ namespace eval punk::cap {
puts stderr "register_capabilityname cannot register capability:$capname with handler:$capnamespace. There is already a registered handler:$hdlr"
return
}
#assert: capnamespace may or may not be empty string, capname may or may not already exist in caps dict, caps $capname providers may have existing entries.
#assertion: capnamespace may or may not be empty string, capname may or may not already exist in caps dict, caps $capname providers may have existing entries.
dict set caps $capname handler $capnamespace
if {![dict exists $caps $capname providers]} {
dict set caps $capname providers [list]

4
src/modules/punk/cap/handlers/templates-999999.0a1.0.tm

@ -698,8 +698,8 @@ namespace eval punk::cap::handlers::templates {
}
}
#assert path is first key of itemdict {callers are allowed to rely on it being first}
#assert itemdict has keys path,basefolder,sourceinfo
#assertion path is first key of itemdict {callers are allowed to rely on it being first}
#assertion itemdict has keys path,basefolder,sourceinfo
set result [dict create]
set keys [lreverse [dict keys $itemdict]]
foreach k $keys {

5
src/modules/punk/char-999999.0a1.0.tm

@ -57,6 +57,7 @@
package require Tcl 8.6-
#dependency on tcllib not ideal for bootstrapping as punk::char is core to many features.. (textutil::wcswidth is therefore included in bootsupport/include_modules.config) review
package require textutil
package require textutil::wcswidth
#*** !doctools
@ -921,7 +922,7 @@ namespace eval punk::char {
set start [dict get [lindex $ranges 0] start]
set end [dict get [lindex $ranges 0] end]
if {![dict exists $charset_extents_startpoints $start] || $end ni [dict get $charset_extents_startpoints $start]} {
#assert if end wasn't in startpoits list - then start won't be in endpoints list
#assertion if end wasn't in startpoits list - then start won't be in endpoints list
dict lappend charset_extents_startpoints $start $end
dict lappend charset_extents_endpoints $end $start
}
@ -934,7 +935,7 @@ namespace eval punk::char {
set start [dict get $range start]
set end [dict get $range end]
if {![dict exists $charset_extents_startpoints $start] || $end ni [dict get $charset_extents_startpoints $start]} {
#assert if end wasn't in startpoits list - then start won't be in endpoints list
#assertion if end wasn't in startpoits list - then start won't be in endpoints list
dict lappend charset_extents_startpoints $start $end
dict lappend charset_extents_endpoints $end $start
}

16
src/modules/punk/console-999999.0a1.0.tm

@ -981,6 +981,22 @@ namespace eval punk::console {
lassign [split $payload {;}] rows cols
return [list columns $cols rows $rows]
}
proc get_mode_line_wrap {{inoutchannels {stdin stdout}}} {
set capturingregex {(.*)(\x1b\[\?7;([0-9]+)\$y)$} ;#must capture prefix,entire-response,response-payload
set request "\x1b\[?7\$p"
set payload [punk::console::internal::get_ansi_response_payload $request $capturingregex $inoutchannels]
return $payload
}
#Terminals generally default to LNM being reset (off) ie enter key sends a lone <cr>
#Terminals tested on windows either don't respond to this query, or respond with 0 (meaning mode not understood)
#I presume from this that almost nobody is using LNM 1 (which sends both <cr> and <lf>)
proc get_mode_LNM {{inoutchannels {stdin stdout}}} {
set capturingregex {(.*)(\x1b\[\?20;([0-9]+)\$y)$} ;#must capture prefix,entire-response,response-payload
set request "\x1b\[?20\$p"
set payload [punk::console::internal::get_ansi_response_payload $request $capturingregex $inoutchannels]
return $payload
}
#terminals lie. This should be a reasonable (albeit relatively slow) test of actual width - but some terminals seem to miscalculate.
#todo - a visual interactive test/questionnaire to ask user if things are lining up or if the terminal is telling fibs about cursor position.

8
src/modules/punk/fileline-999999.0a1.0.tm

@ -745,7 +745,7 @@ namespace eval punk::fileline::class {
lassign [my numeric_linerange $startidx $endidx] startidx endidx
set chunkstart [dict get $o_linemap $startidx start]
set chunkend [dict get $o_linemap $endidx end]
set line_list [my chunkrange_to_lineinfolist $chunkstart $chunkend] ;# assert - no need to view truncations as we've picked start and end of complete lines
set line_list [my chunkrange_to_lineinfolist $chunkstart $chunkend] ;# assertion - no need to view truncations as we've picked start and end of complete lines
#verify sanity
set l_start [lindex $line_list 0]
if {[set idx_start [dict get $l_start lineindex]] ne $startidx} {
@ -983,9 +983,9 @@ namespace eval punk::fileline::class {
lappend infolist $last
}
###########################
#assert all records have is_truncated key.
#assert if is_truncated == 1 truncatedside should contain a list of either left, right or both left and right
#assert If not opt_show_truncated - then truncated records will not have truncated,truncatedleft,truncatedright keys.
#assertion all records have is_truncated key.
#assertion if is_truncated == 1 truncatedside should contain a list of either left, right or both left and right
#assertion If not opt_show_truncated - then truncated records will not have truncated,truncatedleft,truncatedright keys.
return $infolist
}

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

@ -1270,7 +1270,7 @@ namespace eval punk::lib {
}
}
set opts [dict merge $defaults_dict_opts $checked_args]
#assert - checked_args keys are full-length option names if -anyopts was false or if the supplied option as a shortname matched one of our defined options
#assertion - checked_args keys are full-length option names if -anyopts was false or if the supplied option as a shortname matched one of our defined options
set values [dict merge $defaults_dict_values $values_dict]

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

@ -892,7 +892,7 @@ namespace eval punk::mix::commandset::scriptwrap {
return false
}
}
#assert - customwrapper_folder var exists - but might be empty
#assertion - customwrapper_folder var exists - but might be empty
if {[string length $ext]} {

2
src/modules/punk/mix/templates/layouts/project/src/make.tcl

@ -777,7 +777,7 @@ foreach vfs $vfs_folders {
}
}
}
#assert $runtimes is a list of executable names suffixed with .exe if on windows - whether or not specified with .exe in the mapvfs.config
#assertion $runtimes is a list of executable names suffixed with .exe if on windows - whether or not specified with .exe in the mapvfs.config
#todo - non kit based - zipkit?

24
src/modules/punk/ns-999999.0a1.0.tm

@ -215,7 +215,7 @@ namespace eval punk::ns {
}
proc nschildren {fqns} {
if {![string match ::* $fqns]} {
error "nschildren only accespts a fully qualified namespace"
error "nschildren only accepts a fully qualified namespace"
}
set parent [nsprefix $fqns]
set tail [nstail $fqns]
@ -225,6 +225,9 @@ namespace eval punk::ns {
return [lsort $nslist]
}
#Note nsjoin,nsjoinall,nsprefix,nstail are string functions that don't care about namespaces in existence.
#Some functions in punk::ns are
proc nsjoin {prefix name} {
if {[string match ::* $name]} {
if {"$prefix" ne ""} {
@ -265,6 +268,17 @@ namespace eval punk::ns {
}
return [join $nonempty_segments ::]
}
#REVIEW - the combination of nsprefix & nstail are designed to *almost* always be able to reassemble the input, and to be independent of what namespaces actually exist
#The main difference being collapsing (or ignoring) repeated double-colons
#we need to distinguish unprefixed from prefixed ie ::x vs x
#There is an apparent inconsistency with nstail ::a:::x being able to return :x
#whereas nsprefix :::a will return just a
#This is because :x (or even just : ) can in theory be the name of a command and we may need to see it (although it is not a good idea)
#and a namespace can exist with leading colon - but is even worse - as default Tcl commands will misreport e.g namespace current within namespace eval
#The view is taken that a namespace with leading/trailing colons is so error-prone that even introspection is unreliable so we will rule that out.
#
proc nsprefix {{nspath ""}} {
#normalize the common case of ::::
set nspath [string map [list :::: ::] $nspath]
@ -281,8 +295,8 @@ namespace eval punk::ns {
}
}
#namespace tail which handles :::cmd ::x:::y ::x:::/y etc
#todo - raise error for unexpected sequences such as :::: or more than 2 colons together.
#namespace tail which handles :::cmd ::x:::y ::x:::/y etc in a specific manner for string processing
#review - consider making -strict raise an error for unexpected sequences such as :::: or any situation with more than 2 colons together.
proc nstail {nspath args} {
#normalize the common case of ::::
set nspath [string map [list :::: ::] $nspath]
@ -301,7 +315,7 @@ namespace eval punk::ns {
}
}
#e.g ::x::y:::z should return ":z"
#e.g ::x::y:::z should return ":z" despite it being a bad idea for a command name.
return [lindex $parts end]
}
@ -792,7 +806,7 @@ namespace eval punk::ns {
}
if {$cmd in $aliases && $cmd in $seencmds} {
#masked commandless-alias
#assert member of masked - but we use seencmds instead to detect.
#assertion member of masked - but we use seencmds instead to detect.
set c [a+ yellow bold]
set prefix "${a}als "
set prefix [overtype::right $prefix "-R"]

12
src/modules/punk/repl-0.1.tm

@ -1383,7 +1383,8 @@ namespace eval punk::repl::class {
set prefix [string repeat " " [expr {$col0 -1}]]
set linecols [punk::ansi::printing_length $cursorline]
set suffix [string repeat " " [expr {$linecols -$col1}]]
set char_at_cursor [ansistring index $cursorline $charindex_at_cursor] ;#this is the char with appropriate ansireset codes
#capitalised INDEX - for grapheme/control-char index e.g a with diacritic a\u0300 has a single index
set char_at_cursor [ansistring INDEX $cursorline $charindex_at_cursor] ;#this is the char with appropriate ansireset codes
set rawchar [punk::ansi::stripansi $char_at_cursor]
if {$rawchar eq " "} {
set charhighlight "[punk::ansi::a+ White]_[a]"
@ -1633,6 +1634,7 @@ proc repl::repl_handler {inputchan prompt_config} {
uplevel #0 [list repl::repl_process_data $inputchan raw-waiting $ch [list] $prompt_config]
} else {
repl_handler_checkchannel $inputchan
if {[dict get $original_input_conf -blocking] ne "0" || [dict get $original_input_conf -translation] ne "lf"} {
chan configure $inputchan -blocking 0
@ -1752,7 +1754,11 @@ proc repl::repl_process_data {inputchan type chunk stdinlines prompt_config} {
#punk::console::move_emitblock_return 20 120 $chunklen-->[chan conf stdin]<--
if {$chunklen > 0} {
set info1 "read $chunklen bytes->[ansistring VIEW -lf 1 -vt 1 $chunk]"
#it's strange - but apparently terminals use a lone cr to represent enter
#consider also the terminal linefeed mode.
#https://vt100.net/docs/vt510-rm/LNM.html
# terminals (by default) generally use a lone cr to represent enter (LNM reset ie CSI 20l)
#(as per above doc: "For compatibility with Digital's software you should keep LNM reset (line feed)")
#You can insert an lf using ctrl-j - and of course stdin could have crlf or lf
#pasting from notepad++ with mixed line endings seems to paste everything ok
#we don't really know the source of input keyboard vs paste vs pipe - and whether a read has potentially chopped a crl in half..
@ -2242,7 +2248,7 @@ proc repl::repl_process_data {inputchan type chunk stdinlines prompt_config} {
foreach cinfo $::repl::screen_last_char_list {
lassign $cinfo c whatinfo whyinfo
set cdisplay [punk::ansi::ansistring::VIEW -lf 1 -vt 1 $c]
#assert cdisplay has no raw newlines
#assertion cdisplay has no raw newlines
if {[punk::char::ansifreestring_width $cdisplay] == 1} {
set cdisplay "$cdisplay " ;#make 2 wide
}

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

@ -153,7 +153,7 @@ namespace eval punk::winrun {
}
# -----------------
#tw_run $cmdline
#assert - can be treated as tcl list ?
#assertion - can be treated as tcl list ?
return $cmdline
}
interp alias "" [namespace current]::quote_wintcl "" ::punk::winrun::quote_win ;#just for symmetry with unquote_wintcl

100
src/testansi/belinda.ans

@ -0,0 +1,100 @@
ロ イイアアーーーーーレチトルツトレツ
タツツツツツトツナナナナツチトトト
ツソトナナツトト゚゚ソロロロロロ
ロロロロロロ ゙ンメトキ イイアアアーーーーー
トチテルチナツチナトテナツトナトチナナエ
ワワワロロワチチツナナナトレソタ
エロロロロロロロロロロロ ゙ンヌトミキ
 イイアアーーーーーーー ナ レツルナ
レナチロワワワワワロロロロロロロロロロウタナ
゙ソテナツナソロロロロロロロロロロ ゙ン
ミトトス イイアアーーーーーーーウウ ソル
タツトルテナロロロロロロロロロロロロロロロロロロ
ロ タナ゙ウウウタエソロロロロロロロロロ 
゙ンメトトキ イイアアーーーーーーーレナエ
トエウウウトツナナ゚゚ロロロロロロロロロロロロロロロロロン
トナ゙タルテソウタトソロロロロロロロ
 ゙ンヌト イイアアーーーーーーーウテエ
トエウウウトツナナワロロロロロロロロロロロロロロロロロロロ 
ナ゙タルテソウ ウ ロロロロロロロ 
゙ンミトトス イイアアーーーーーーーーレ
ルウルウテソレルウウロロロロロロロロロロ
ロ゚゚ワワワワ゚ロロンチソレドウ
ウソウタソロロロロロロ ゙ンメ
 イイアアーーーーーーーレナチエウレナル 
ウウタタル゚゚ロロロロワ゚ワ ワ
 ワ゚ロロロロ ウウヴ
トソタソ テソロロロロロ ゙ンコ
 イイアアーーーーー トソエテナエウウウテ
ルテツエ゙ワワ ワ ゚ロロロロワワワロロ
ロロロロロ テエテゾチソタソウ
ウロロロロロ ゙ンミトトスイイアアーーーーーーー
レナツナチエテエウウウウウ
ウウロロロロ ロロロロロロロロロロロロロロ エ
゙ウヴウタソタソウ
ロロロロロ ゙ントメトトイイアアーーーーレツトエ
ウテエレナチエレナツチナチ
タ ロ゚ ロロロロ゚゚ロロロロロロロン ゙
ウタツエレルウタトソロロロ ゙
ンコイイアアーーーーウウレエ ナ
ナエテトタエウウトチトウウ 
゚ロワロロロワワ゚ロロロロロン
テル゙エウウウタツソテソ 
ウロロロ ゙ントミトトイアアーーーー
トルレル ナナナナナツツルナルトツツナ
ル ロワ゚゚゚ロ゚゚ヷワロロロ゚
レチソデテルテソウウウテソ
ウソロロ ゙ンメトキキイアアーーーーー
レエエナナウウウウナ
エタソウテエ ア ゚゚゚゚
゚ワロロロロロロ゚レトウウテエ゙
タソテナ゙タソウウウウロロ ゙
ンコ ココイアアーーーーーテナウナ
ナツルテナルウウウテソタエ
ウ ワワワワロロロロロロ゚レトル
レルウウウテトチルウ
゙トナトソウロロ ゙ン
ミ モスイアアーーーーレエウルナチナ
ツナトツナチナナナソウウ 
ロロ゚ロロロロロ゚ソレエ ツヂ
トルウテツトウデト
ナツルトツロロ ゙ンメトトキ
イアアーーーーウウテナルウテエ
ウウウウテルウウタナ
ツソ゚ ワ゚゚ レエテナナ
エナナソウトチタチツチ
ルレソタチトソテソロ ゙ン
コ コイアーーーーウテナナ トチエ
テエウテエウレテ
ソウタナソタルエテナナチ
エウテツツソウタ
トゾチヅテナトチロ 
゙ンミトトスアアーーレツチチ
ナナナトレエウウテナエ
ウテナテエテトナエトツ 
゚レトルウウテテエウ
ウウタチナソレナ゙ツエ゙
チチトツツツソンヨトトキアアー
レエテツツウテレトウチトル
ウテトチチルウテソタエ
ウタソア  ツソテナエウ
タトルウテトヴウデナ
ツトトソ テチチチソヌトトカアーーウレエ
ウチツナルウウタトツトルテトツ
ツナエウトナナソタソ
テア ウウテチナチトツトウウ
レル゙ナナ タチソ ウ
ロロロロ タツソミアー
レエナトエウチソウレツツチナトナ
ツチナルテナナツチナ
ナソタナナエ タルウタツソウ
レナソテツヅナ
ロロ タソロロロロロロ タエ
Michaelアータエルトエ ア
テツナルナツナツタルテナト
ルタチナツナナルツエテエ イ 
トチツナエテエウタエタ
ル タソロロ ウロロロロロ
ロロ ウArnett


62
src/testansi/timebend.ans

@ -0,0 +1,62 @@
ÛÛÛÛÛÛÛÛÛÛÛÛÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
ßßßßßßßßßßßßßßßßÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Û Û Û ÛÛ ÛÛ
ÛßÛ ÛßÛßÛ ÛßÛÛßÛ ÛßÛßÛ ÛÛßÛ ÛßÛ ÛÛ ÛÛ Û Û Û ÛÛÛÛÛÛÛÛÛÛ
ÛÛÛÛÛÛÛÛÛÛÛÛÛÜÜÜ ÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜ ÜÜÜ
ÜÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Û Û 
Ü ÛÛÛÛÛÛÛÛ ²ÜÛÛÛÛÛÛÛÛÛ Û ÛÛÛÛÛÛ
ÛÛÛÛÛ Û Û Û ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
 Û ÛÜ ßÛÛÛÛÛÛÛÛÛß²ÛÛÛÛÛÛÛÛÛ 
 Û ÛÛÛÛÛÛÛÛÛÛßÜßÜÛ Û ÛÛSc
reen ByÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Û ÛÛÜßÜß
ÜÛÛÛÛÛÛ ²ßÛÛÛÛÛßÛßÛ Û ÛÛÛÛÛÛÛÛÛßÜß
ÜÛÛ Û ÛÛPretty ÛÛÛÛÛÛÛÛÛÛÛÛÛ
ÛÛÛÛ Û ÛÛÛÜ ÜßÛÛÛÛÛÛ ²ßßß ß
 Ü ÛÜ Û ÛÛÛÛÛÛÛÛßÜßÜÛÛÛ Û ÛÛ
Please ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Û ÛÛÛÛÛÜ 
ßÛÛßßßÜ ßÛÜ Û ßÜÛßÛÛßÜß
ÜÛÛÛÛÛ Û ÛÛ(c) 1991 ÛÛÛÛÛÛÛÛÛÛ
ÛÛÛÛÛÛÛ Û ÛÛÛÛÛÛÛÜß Üß Üß ßÜß Û 
ßÜÜßÛÜßÜÛÛÛÛÛÛÛ Û ÛÛ"Accept 
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Û ÛÛÛÛÛÛÛÛÛÜÜßßÜ
Ü Ü Üß ßÜÛ Û ÛÜßßÜÜÛÛÛÛÛÛÛÛÛ Û ÛÛ
 No ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Û ÛÛÛÛÛÛÛ
ÛÛÛÛÛÛ ßßÜÜ Û ßÜß Û ÜÜÛÛÛÛÛÛÛÛÛÛÛÛÛ Û 
ÛÛ Substi- ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Û 
ÛÛÛÛÛÛÛÛÛÛÛÛÛ Û ÜßÛÜ ßÛ Û ÛÛÛÛÛÛÛÛÛ
ÛÛÛÛÛÛ Û ÛÛ tutes!" ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
Û Û ÛÛÛÛÛÛÛÛÛÛÛÛÛ Û ÛÛ Û ÜÛ Û
 ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Û ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
TimeÛÛÛÛÛÛÛÛÛ Û ÛÛÛÛÛÛÛÛÛÛÛÛÛ Û 
ÛßÜ Û ßÜ Û ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Û 
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛBender-LongÛÛ Û 
ÛÛÛÛÛÛÛÛÛÛÛÛÛ ß ÜßÜÛÜ ÛÜ Û ÛÛÛÛÛÛÛÛÛ
ÛÛÛÛÛÛ Û ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ916-342-9
239Û Û ÛÛÛÛÛÛÛÛÛÛÛßßܲ
ÛÛÛÛÛÜßÛÛ Û ÜÜßßÛÛÛÛÛÛÛÛÛÛ
Û Û ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ 
Û ÛÛÛÛÛÛÛÛßÜ ÛÜܲÛÛÛÛÛÜÛßÛ 
Û ÛÜÛßÜÜßÛÛÛÛÛÛÛÛ Û ÛÛÛÛÛÛÛÛÛÛÛÛÛ
ÛÛScreen ByÛÛÛÛ Û ÛÛÛÛÛÛßÜßÜÛÛÛ 
²ßÛ_ÛÛÛÛßÛÛ Û ÛÛÛÛÛÜßÜßÛÛÛÛÛ
Û Û ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛPretty ÛÛÛÛ 
Û ÛÛÛÛß ÜÛÛÛÛÛܲÛÛÛÛßÛßÛß 
Û ÛÛÛÛÛÛÛÜßÜßÛÛÛÛ Û ÛÛÛÛÛÛÛÛÛÛÛÛÛ
ÛÛPlease ÛÛÛÛ Û ÛÛÛ Ü ÛÛÛÛÛÛÛ 
²Ûß ßÜ ÜßÜß Û ÛÛÛÛÛÛÛÛÛ Û 
ÛÛÛ Û ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ(c) 1991
 ÛÛÛÛ Û ÛÛ Ü ßÜÛÛÛÛÛÛ ²
ß Ü ßÜÜßÜ Û ÜßÛÛÛÛÛÛÛÛ Û ÛÛ 
Û ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ"Accept ÛÛÛÛ 
Û Û Ü ßÛßÛÛßß Ü ß ßÜ ÜßÜÛß Û ÛÛÜÜ
ßÛÛÛÛÛÛ Û Û Û ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
 No ÛÛÛÛ Û ßÜß ß Üßß Üß ÛÛ
Üß Û ÜÛÛÜÛßÜÛÛÛÛÜßÜß Û ÛÛÛ
Screen:ÛÛÛÛÛ Substi- ÛÛßß 
ß ß ßß ßß ß ß ß ß ßßß ß 
ßß ß ß ßßÛPrettyÛÛÛÛÛÛ
 tutes!" Û Û Û Û ÛÛ ÛÛ ÛßÛ ÛßÛßÛ ÛÛßÛßÛ ÛßÛßÛ ÛÛß
Û ÛßÛ ÛÛ ÛÛ Û Û Û Please ÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
 (c) 1991Û
Downloaded From P-80 International Information Systems 304-744-2253

1160
src/vendormodules/overtype-1.6.0.tm

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