Browse Source

punk::cap capability system + docgen doctools

master
Julian Noble 1 year ago
parent
commit
3efeaf95d7
  1. 3942
      src/bootsupport/modules/mime-1.7.0.tm
  2. 228
      src/bootsupport/modules/punk/cap-0.1.0.tm
  3. 74
      src/bootsupport/modules/punk/cap/handlers/templates-0.1.0.tm
  4. 2
      src/bootsupport/modules/punk/mix-0.2.tm
  5. 3
      src/bootsupport/modules/punk/mix/cli-0.3.tm
  6. 74
      src/bootsupport/modules/punk/mix/commandset/doc-0.1.0.tm
  7. 16
      src/bootsupport/modules/punk/mix/templates-0.1.0.tm
  8. 32
      src/bootsupport/modules/punkcheck-0.1.0.tm
  9. 80
      src/bootsupport/modules/textutil-0.9.tm
  10. 761
      src/bootsupport/modules/textutil/adjust-0.7.3.tm
  11. 902
      src/bootsupport/modules/textutil/dehypht.tex
  12. 1104
      src/bootsupport/modules/textutil/eshyph_vo.tex
  13. 1122
      src/bootsupport/modules/textutil/expander-1.3.1.tm
  14. 223
      src/bootsupport/modules/textutil/ithyph.tex
  15. 180
      src/bootsupport/modules/textutil/patch-0.1.tm
  16. 91
      src/bootsupport/modules/textutil/repeat-0.7.tm
  17. 176
      src/bootsupport/modules/textutil/split-0.8.tm
  18. 144
      src/bootsupport/modules/textutil/string-0.8.tm
  19. 289
      src/bootsupport/modules/textutil/tabify-0.7.tm
  20. 112
      src/bootsupport/modules/textutil/trim-0.7.tm
  21. 772
      src/bootsupport/modules/textutil/wcswidth-35.1.tm
  22. 140
      src/doc/_module_punk_cap-0.1.0.tm.man
  23. 23
      src/doc/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.man
  24. 11
      src/doc/_module_punk_mix_templates_modules_template_module-0.0.1.tm.man
  25. 140
      src/docgen/punk_cap-0.1.0.tm.man
  26. 23
      src/docgen/punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.man
  27. 40
      src/docgen/punk_mix_templates_modules_template_module-0.0.1.tm.man
  28. 489
      src/embedded/man/files/_module_punk_cap-0.1.0.tm.n
  29. 318
      src/embedded/man/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.n
  30. 286
      src/embedded/man/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.n
  31. 9
      src/embedded/man/toc.n
  32. 5
      src/embedded/md/.doc/tocdoc
  33. 2
      src/embedded/md/.toc
  34. 2
      src/embedded/md/.xrf
  35. 262
      src/embedded/md/doc/files/_module_punk_cap-0.1.0.tm.md
  36. 64
      src/embedded/md/doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.md
  37. 33
      src/embedded/md/doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.md
  38. 6
      src/embedded/md/doc/toc.md
  39. 6
      src/embedded/md/toc.md
  40. 5
      src/embedded/www/.doc/tocdoc
  41. 2
      src/embedded/www/.toc
  42. 2
      src/embedded/www/.xrf
  43. 301
      src/embedded/www/doc/files/_module_punk_cap-0.1.0.tm.html
  44. 156
      src/embedded/www/doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.html
  45. 132
      src/embedded/www/doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.html
  46. 12
      src/embedded/www/doc/toc.html
  47. 12
      src/embedded/www/toc.html
  48. 16
      src/make.tcl
  49. 3942
      src/mixtemplates/layouts/basic/src/bootsupport/modules/mime-1.7.0.tm
  50. 228
      src/mixtemplates/layouts/basic/src/bootsupport/modules/punk/cap-0.1.0.tm
  51. 74
      src/mixtemplates/layouts/basic/src/bootsupport/modules/punk/cap/handlers/templates-0.1.0.tm
  52. 2
      src/mixtemplates/layouts/basic/src/bootsupport/modules/punk/mix-0.2.tm
  53. 3
      src/mixtemplates/layouts/basic/src/bootsupport/modules/punk/mix/cli-0.3.tm
  54. 74
      src/mixtemplates/layouts/basic/src/bootsupport/modules/punk/mix/commandset/doc-0.1.0.tm
  55. 16
      src/mixtemplates/layouts/basic/src/bootsupport/modules/punk/mix/templates-0.1.0.tm
  56. 32
      src/mixtemplates/layouts/basic/src/bootsupport/modules/punkcheck-0.1.0.tm
  57. 80
      src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil-0.9.tm
  58. 761
      src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/adjust-0.7.3.tm
  59. 902
      src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/dehypht.tex
  60. 1104
      src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/eshyph_vo.tex
  61. 1122
      src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/expander-1.3.1.tm
  62. 223
      src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/ithyph.tex
  63. 180
      src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/patch-0.1.tm
  64. 91
      src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/repeat-0.7.tm
  65. 176
      src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/split-0.8.tm
  66. 144
      src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/string-0.8.tm
  67. 289
      src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/tabify-0.7.tm
  68. 112
      src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/trim-0.7.tm
  69. 772
      src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/wcswidth-35.1.tm
  70. 16
      src/mixtemplates/layouts/basic/src/make.tcl
  71. 18
      src/modules/punk-0.1.tm
  72. 520
      src/modules/punk/cap-999999.0a1.0.tm
  73. 123
      src/modules/punk/cap.html
  74. 29
      src/modules/punk/cap.md
  75. 73
      src/modules/punk/cap/handlers/templates-999999.0a1.0.tm
  76. 71
      src/modules/punk/docgen-999999.0a1.0.tm
  77. 3
      src/modules/punk/docgen-buildversion.txt
  78. 17
      src/modules/punk/mix/cli-0.3.tm
  79. 74
      src/modules/punk/mix/commandset/doc-999999.0a1.0.tm
  80. 6
      src/modules/punk/mix/commandset/project-999999.0a1.0.tm
  81. 4
      src/modules/punk/mix/templates-999999.0a1.0.tm
  82. 3942
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/mime-1.7.0.tm
  83. 228
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punk/cap-0.1.0.tm
  84. 74
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punk/cap/handlers/templates-0.1.0.tm
  85. 2
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punk/mix-0.2.tm
  86. 3
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punk/mix/cli-0.3.tm
  87. 74
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punk/mix/commandset/doc-0.1.0.tm
  88. 16
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punk/mix/templates-0.1.0.tm
  89. 32
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punkcheck-0.1.0.tm
  90. 80
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil-0.9.tm
  91. 761
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/adjust-0.7.3.tm
  92. 902
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/dehypht.tex
  93. 1104
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/eshyph_vo.tex
  94. 1122
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/expander-1.3.1.tm
  95. 223
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/ithyph.tex
  96. 180
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/patch-0.1.tm
  97. 91
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/repeat-0.7.tm
  98. 176
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/split-0.8.tm
  99. 144
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/string-0.8.tm
  100. 289
      src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/tabify-0.7.tm
  101. Some files were not shown because too many files have changed in this diff Show More

3942
src/bootsupport/modules/mime-1.7.0.tm

File diff suppressed because it is too large Load Diff

228
src/bootsupport/modules/punk/cap-0.1.0.tm

@ -14,20 +14,36 @@
# @@ Meta End # @@ Meta End
#*** !doctools
#[manpage_begin punk::cap 0 0.1.0]
#[copyright "2023 JMNoble - BSD licensed"]
#[titledesc {Module API}]
#[moddesc {punk capabilities plugin system}]
#[require punk::cap]
#[description]
#[list_begin definitions]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Requirements ## Requirements
##e.g package require frobz ##e.g package require frobz
package require oolib
#concepts:
# A capability may be something like providing a folder of files, or just a data dictionary, and/or an API # mkdoc markdown
# #' ---
# capability handler - a package/namespace which may provide validation and standardised ways of looking up provider data #' author: JMNoble
# registered (or not) using register_capabilityname <capname> <capnamespace> #' ---
# capability provider - a package which registers as providing one or more capablities. #' ## Concepts:
# registered using register_package <pkg> <capabilitylist> #' > A **capability** may be something like providing a folder of files, or just a data dictionary, and/or an API
# the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability #'
# A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets. #' > **capability handler** - a package/namespace which may provide validation and standardised ways of looking up provider data
#' registered (or not) using register_capabilityname <capname> <capnamespace>
#'
#' > **capability provider** - a package which registers as providing one or more capablities.
#' registered using register_package <pkg> <capabilitylist>
#' the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability
#' A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets.
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
@ -35,32 +51,99 @@ namespace eval punk::cap {
variable pkgcapsdeclared [dict create] variable pkgcapsdeclared [dict create]
variable pkgcapsaccepted [dict create] variable pkgcapsaccepted [dict create]
variable caps [dict create] variable caps [dict create]
if {[info commands [namespace current]::interface_caphandler.registry] eq ""} {
oo::class create [namespace current]::interface_caphandler.registry { namespace eval class {
method pkg_register {pkg capname capdict fullcapabilitylist} { if {[info commands [namespace current]::interface_caphandler.registry] eq ""} {
#handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid #Handler classes
#overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes. oo::class create [namespace current]::interface_caphandler.registry {
return 1 ;#default to permit method pkg_register {pkg capname capdict fullcapabilitylist} {
} #***
method pkg_unregister {pkg} { #[call [class interface_caphandler.registry] [method pkg_register] [arg pkg] [arg capname] [arg capdict] [arg fullcapabilitylist]]
return ;#unregistration return is ignored - review #handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid
#overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes.
return 1 ;#default to permit
}
method pkg_unregister {pkg} {
#***
#[call [class interface_caphandler.registry] [method pkg_unregister] [arg pkg]]
return ;#unregistration return is ignored - review
}
} }
} oo::class create [namespace current]::interface_caphandler.sysapi {
oo::class create [namespace current]::interface_capprovider.registration {
method get_declarations {} {
error "interface_capprovider.registration not implemented by provider"
} }
}
oo::class create [namespace current]::interface_capprovider.provider {
method register {{capabilityname_glob *}} {
#Provider classes
oo::class create [namespace current]::interface_capprovider.registration {
method get_declarations {} {
#***
#[call [class interface_capprovider.registration] [method pkg_unregister] [arg pkg]]
error "interface_capprovider.registration not implemented by provider"
}
} }
method capabilities {} { oo::class create [namespace current]::interface_capprovider.provider {
variable provider_pkg
variable registrationobj
constructor {providerpkg} {
variable provider_pkg
if {$providerpkg in [list "" "::"]} {
error "interface_capprovider.provider constructor error. Invalid provider '$providerpkg'"
}
if {![namespace exists ::$providerpkg]} {
error "interface_capprovider.provider constructor error. Invalid provider '$providerpkg' - matching namespace not found"
}
set registrationobj ::${providerpkg}::capsystem::capprovider.registration
if {[info commands $registrationobj] eq ""} {
error "capprovider.provider constructor error. Missing capprovider.registration interface at '$obj' (command not found) interface_capprovider.regstration instantiation must precede interface_capprovider.provider"
}
set provider_pkg [string trim $providerpkg ""]
}
method register {{capabilityname_glob *}} {
#***
#[call [class interface_capprovider.provider] [method register] [opt capabilityname_glob]]
variable provider_pkg
set all_decls [$registrationobj get_declarations]
set register_decls [lsearch -all -inline -index 0 $all_decls $capabilityname_glob]
punk::cap::register_package $provider_pkg $register_decls
}
method capabilities {} {
#***
#[call [class interface_capprovider.provider] [method capabilities]]
variable provider_pkg
variable registrationobj
set capabilities [list]
set decls [$registrationobj get_declarations]
foreach decl $decls {
lassign $decl capname capdict
if {$capname ni $capabilities} {
lappend capabilities $capname
}
}
return $capname
}
} }
} }
} ;# end namespace class
namespace eval capsystem {
proc get_caphandler_registry {capname} {
set ns [::punk::cap::get_handler $capname]::capsystem
if {[namespace exists ${ns}]} {
if {[info command ${ns}::caphandler.registry] ne ""} {
if {[info object isa object ${ns}::caphandler.registry]} {
return ${ns}::caphandler.registry
}
}
}
return ""
}
} }
#Not all capabilities have to be registered. #Not all capabilities have to be registered.
#A package registering as a provider using register_package can include capabilitynames in it's capabilitylist which have no associated capnamespace (handler). #A package registering as a provider using register_package can include capabilitynames in it's capabilitylist which have no associated capnamespace (handler).
#such unregistered capabilitynames may be used just to flag something, or have datamembers significant to callers cooperatively interested in that capname. #such unregistered capabilitynames may be used just to flag something, or have datamembers significant to callers cooperatively interested in that capname.
@ -88,7 +171,7 @@ namespace eval punk::cap {
} }
if {[llength [set providers [dict get $caps $capname providers]]]} { if {[llength [set providers [dict get $caps $capname providers]]]} {
#some provider(s) were in place before the handler was registered #some provider(s) were in place before the handler was registered
if {[set capreg [get_caphandler_registry $capname]] ne ""} { if {[set capreg [punk::cap::capsystem::get_caphandler_registry $capname]] ne ""} {
foreach pkg $providers { foreach pkg $providers {
set fullcapabilitylist [dict get $pkgcapsdeclared $pkg] set fullcapabilitylist [dict get $pkgcapsdeclared $pkg]
foreach capspec $fullcapabilitylist { foreach capspec $fullcapabilitylist {
@ -131,10 +214,31 @@ namespace eval punk::cap {
} }
} }
proc exists {capname} { proc exists {capname} {
#*** !doctools
# [call [fun exists] [arg capname]]
# Return a boolean indicating if the named capability exists (0|1)
# mkdoc markdown
#'
#' ## **exists(capname)**
#'
#' > return a boolean indicating the existence of a capability
#'
#' > Arguments:
#'
#' > - *capname* - string indicating the name of the capability
#'
#' > Returns: 0|1
#'
variable caps variable caps
return [dict exists $caps $capname] return [dict exists $caps $capname]
} }
proc has_handler {capname} { proc has_handler {capname} {
#*** !doctools
# [call [fun has_handler] [arg capname]]
# Return a boolean indicating if the named capability has a handler package installed (0|1)
variable caps variable caps
return [expr {[dict exists $caps $capname handler] && [dict get $caps $capname handler] ne ""}] return [expr {[dict exists $caps $capname handler] && [dict get $caps $capname handler] ne ""}]
} }
@ -157,20 +261,9 @@ namespace eval punk::cap {
if {[set handler [get_handler $capname]] eq ""} { if {[set handler [get_handler $capname]] eq ""} {
error "punk::cap::call_handler $capname $args - no handler registered for capability $capname" error "punk::cap::call_handler $capname $args - no handler registered for capability $capname"
} }
set obj ${handler}::$capname set obj ${handler}::api_$capname
$obj [lindex $args 0] {*}[lrange $args 1 end] $obj [lindex $args 0] {*}[lrange $args 1 end]
} }
proc get_caphandler_registry {capname} {
set ns [get_handler $capname]::capsystem
if {[namespace exists ${ns}]} {
if {[info command ${ns}::caphandler.registry] ne ""} {
if {[info object isa object ${ns}::caphandler.registry]} {
return ${ns}::caphandler.registry
}
}
}
return ""
}
proc get_providers {capname} { proc get_providers {capname} {
variable caps variable caps
if {[dict exists $caps $capname]} { if {[dict exists $caps $capname]} {
@ -188,6 +281,11 @@ namespace eval punk::cap {
if {[string match ::* $pkg]} { if {[string match ::* $pkg]} {
set pkg [string range $pkg 2 end] set pkg [string range $pkg 2 end]
} }
if {[dict exists $pkgcapsaccepted $pkg]} {
set pkg_already_accepted [dict get $pkgcapsaccepted $pkg]
} else {
set pkg_already_accepted [list]
}
#for each capability #for each capability
# - ensure 1st element is a single word # - ensure 1st element is a single word
# - ensure that if 2nd element (capdict) is present - it is dict shaped # - ensure that if 2nd element (capdict) is present - it is dict shaped
@ -199,6 +297,11 @@ namespace eval punk::cap {
if {[expr {[llength $capdict] %2 != 0}]} { if {[expr {[llength $capdict] %2 != 0}]} {
error "register_package error. pkg:'$pkg' The second element for capname:'$capname' doesn't appear to be a valid dict. Problematic entry: '$capspec'" error "register_package error. pkg:'$pkg' The second element for capname:'$capname' doesn't appear to be a valid dict. Problematic entry: '$capspec'"
} }
if {$capspec in $pkg_already_accepted} {
#review - multiple handlers? if so - will need to record which handler(s) accepted the capspec
puts stderr "register_package pkg $pkg already has capspec marked as accepted: $capspec"
continue
}
if {[dict exists $caps $capname]} { if {[dict exists $caps $capname]} {
set cap_pkgs [dict get $caps $capname providers] set cap_pkgs [dict get $caps $capname providers]
} else { } else {
@ -207,7 +310,7 @@ namespace eval punk::cap {
} }
#todo - if there's a caphandler - call it's init/validation callback for the pkg #todo - if there's a caphandler - call it's init/validation callback for the pkg
set do_register 1 ;#default assumption unless vetoed by handler set do_register 1 ;#default assumption unless vetoed by handler
if {[set capreg [get_caphandler_registry $capname]] ne ""} { if {[set capreg [punk::cap::capsystem::get_caphandler_registry $capname]] ne ""} {
#Note that the interface_caphandler.registry instance must be able to handle multiple calls for same pkg #Note that the interface_caphandler.registry instance must be able to handle multiple calls for same pkg
set do_register [$capreg pkg_register $pkg $capname $capdict $capabilitylist] set do_register [$capreg pkg_register $pkg $capname $capdict $capabilitylist]
} }
@ -219,17 +322,23 @@ namespace eval punk::cap {
dict lappend pkgcapsaccepted $pkg $capspec ;#if pkg is being registered prior to handler-registration - the handler may undo this entry dict lappend pkgcapsaccepted $pkg $capspec ;#if pkg is being registered prior to handler-registration - the handler may undo this entry
} }
} }
#another call to register_pkg with same pkg may have been made (most likely with different capname) so we must append #another call to register_pkg with same pkg may have been made (most likely with different capname) so we must append - but check not already present
#dict lappend pkgcapsdeclared $pkg $capabilitylist #dict lappend pkgcapsdeclared $pkg $capabilitylist
if {[dict exists $pkgcapsdeclared $pkg]} { if {[dict exists $pkgcapsdeclared $pkg]} {
set caps [dict get $pkgcapsdeclared $pkg] set capspecs [dict get $pkgcapsdeclared $pkg]
lappend caps {*}$capabilitylist foreach spec $capspecs {
dict set pkgcapsdeclared $pkg $caps if {$spec ni $capspecs} {
lappend capspecs $spec
}
}
dict set pkgcapsdeclared $pkg $capspecs
} else { } else {
dict set pkgcapsdeclared $pkg $capabilitylist dict set pkgcapsdeclared $pkg $capabilitylist
} }
} }
proc unregister_package {pkg} {
#todo!
proc unregister_package {pkg {capname *}} {
variable pkgcapsdeclared variable pkgcapsdeclared
variable caps variable caps
if {[string match ::* $pkg]} { if {[string match ::* $pkg]} {
@ -245,13 +354,13 @@ namespace eval punk::cap {
set pkglist [dict get $cap_info providers] set pkglist [dict get $cap_info providers]
set posn [lsearch $pkglist $pkg] set posn [lsearch $pkglist $pkg]
if {$posn >= 0} { if {$posn >= 0} {
if {[set capreg [get_caphandler_registry $capname]] ne ""} { if {[set capreg [punk::cap::capsystem::get_caphandler_registry $capname]] ne ""} {
#review #review
# it seems not useful to allow the callback to block this unregister action # it seems not useful to allow the callback to block this unregister action
#the pkg may have multiple datasets for each capname so callback will only be called for first dataset we encounter #the pkg may have multiple datasets for each capname so callback will only be called for first dataset we encounter
#vetoing unregister would make this more complex for no particular advantage #vetoing unregister would make this more complex for no particular advantage
#if per capability deregistration required this should probably be a separate thing (e.g disable_capability?) #if per dataset deregistration required this should probably be a separate thing
$capreg pkg_unregister $pkg $capreg pkg_unregister $pkg $capname
} }
set pkglist [lreplace $pkglist $posn $posn] set pkglist [lreplace $pkglist $posn $posn]
dict set caps $capname providers $pkglist dict set caps $capname providers $pkglist
@ -398,21 +507,22 @@ namespace eval punk::cap {
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Ready ## Ready
package provide punk::cap [namespace eval punk::cap { package provide punk::cap [namespace eval punk::cap {
variable version variable version
variable pkg punk::cap
set version 0.1.0 set version 0.1.0
variable README.md [string map [list %pkg% $pkg %ver% $version] {
# punk capabilities system
## pkg: %pkg% version: %ver%
punk::cap base namespace
}]
return $version
}] }]
return return
#*** !doctools
#[list_end]
#[manpage_end]

74
src/bootsupport/modules/punk/cap/handlers/templates-0.1.0.tm

@ -35,10 +35,14 @@ namespace eval punk::cap::handlers::templates {
namespace eval capsystem { namespace eval capsystem {
#interfaces for punk::cap to call into #interfaces for punk::cap to call into
if {[info commands caphandler.registry] eq ""} { if {[info commands caphandler.registry] eq ""} {
punk::cap::interface_caphandler.registry create caphandler.registry punk::cap::class::interface_caphandler.registry create caphandler.registry
oo::objdefine caphandler.registry { oo::objdefine caphandler.registry {
method pkg_register {pkg capname capdict caplist} { method pkg_register {pkg capname capdict caplist} {
#caplist may not be complete set - which somewhat reduces its utility here regarding any decisions based on the context of this capname/capdict (review - remove this arg?) #caplist may not be complete set - which somewhat reduces its utility here regarding any decisions based on the context of this capname/capdict (review - remove this arg?)
# -- --- --- --- --- --- --- ---- ---
# validation of capdict
# -- --- --- --- --- --- --- ---- ---
if {![dict exists $capdict relpath]} { if {![dict exists $capdict relpath]} {
puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - package '$pkg' is attempting to register with punk::cap as a provider of '$capname' capability, but is missing 'relpath' key" puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - package '$pkg' is attempting to register with punk::cap as a provider of '$capname' capability, but is missing 'relpath' key"
return 0 return 0
@ -52,16 +56,28 @@ namespace eval punk::cap::handlers::templates {
set tpath [file normalize [file join $tmfile [dict get $capdict relpath]]] ;#relpath is relative to the tm *file* - not it's containing folder set tpath [file normalize [file join $tmfile [dict get $capdict relpath]]] ;#relpath is relative to the tm *file* - not it's containing folder
if {![file isdirectory $tpath]} { if {![file isdirectory $tpath]} {
puts stderr "punk::cap::handlers::templates::capsystem pkg_register WARNING - unable to validate relpath location [dict get $capdict relpath] ($tpath) for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability" puts stderr "punk::cap::handlers::templates::capsystem pkg_register WARNING - unable to validate relpath location [dict get $capdict relpath] ($tpath) for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability"
return 0
} }
# -- --- --- --- --- --- --- ---- ---
# update package internal data
# -- --- --- --- --- --- --- ---- ---
if {$capname ni $::punk::cap::handlers::templates::handled_caps} { if {$capname ni $::punk::cap::handlers::templates::handled_caps} {
lappend ::punk::cap::handlers::templates::handled_caps $capname lappend ::punk::cap::handlers::templates::handled_caps $capname
} }
if {[info commands punk::cap::handlers::templates::$capname] eq ""} {
punk::cap::handlers::templates::api create ::punk::cap::handlers::templates::$capname $capname
}
set cname [string map [list . _] $capname] set cname [string map [list . _] $capname]
upvar ::punk::cap::handlers::templates::pkg_folders_$cname pfolders upvar ::punk::cap::handlers::templates::pkg_folders_$cname pfolders
dict lappend pfolders $pkg $tpath dict lappend pfolders $pkg $tpath
# -- --- --- --- --- --- --- ---- ---
# instantiation of api at punk::cap::handlers::templates::api_$capname
# -- --- --- --- --- --- --- ---- ---
if {[info commands ::punk::cap::handlers::templates::$capname] eq ""} {
punk::cap::handlers::templates::class::api create ::punk::cap::handlers::templates::api_$capname $capname
}
return 1 return 1
} }
method pkg_unregister {pkg} { method pkg_unregister {pkg} {
@ -84,36 +100,38 @@ namespace eval punk::cap::handlers::templates {
#handler api for clients of this capability - called via punk::cap::call_handler <capname> <method> ?args? #handler api for clients of this capability - called via punk::cap::call_handler <capname> <method> ?args?
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
namespace export * namespace export *
namespace eval class {
oo::class create api { oo::class create api {
#return a dict keyed on folder with source pkg as value #return a dict keyed on folder with source pkg as value
constructor {capname} { constructor {capname} {
variable capabilityname variable capabilityname
variable cname variable cname
set cname [string map [list . _] $capname] set cname [string map [list . _] $capname]
set capabilityname $capname set capabilityname $capname
} }
method folders {} { method folders {} {
variable capabilityname variable capabilityname
variable cname variable cname
upvar punk::cap::handlers::templates::pkg_folders_$cname pkg_folders upvar punk::cap::handlers::templates::pkg_folders_$cname pkg_folders
package require punk::cap package require punk::cap
set capinfo [punk::cap::capability $capabilityname] set capinfo [punk::cap::capability $capabilityname]
# e.g {punk.templates {handler punk::mix::templates providers ::somepkg}} # e.g {punk.templates {handler punk::mix::templates providers ::somepkg}}
#use the order of pkgs as registered with punk::cap - may have been modified with punk::cap::promote_package/demote_package #use the order of pkgs as registered with punk::cap - may have been modified with punk::cap::promote_package/demote_package
set pkgs [dict get $capinfo providers] set pkgs [dict get $capinfo providers]
set folderdict [dict create] set folderdict [dict create]
foreach pkg $pkgs { foreach pkg $pkgs {
foreach pfolder [dict get $pkg_folders $pkg] { foreach pfolder [dict get $pkg_folders $pkg] {
dict set folderdict $pfolder [list source $pkg sourcetype package] dict set folderdict $pfolder [list source $pkg sourcetype package]
}
} }
return $folderdict
} }
return $folderdict
} }
} }
} }

2
src/bootsupport/modules/punk/mix-0.2.tm

@ -5,7 +5,7 @@ package require punk::cap::handlers::templates ;#handler for templates cap
punk::cap::register_capabilityname punk.templates ::punk::cap::handlers::templates punk::cap::register_capabilityname punk.templates ::punk::cap::handlers::templates
package require punk::mix::templates ;#registers as provider pkg for 'punk.templates' capability with punk::cap package require punk::mix::templates ;#registers as provider pkg for 'punk.templates' capability with punk::cap
#punk::mix::templates::provider register * punk::mix::templates::provider register *
package require punk::mix::base package require punk::mix::base
package require punk::mix::cli package require punk::mix::cli

3
src/bootsupport/modules/punk/mix/cli-0.3.tm

@ -170,7 +170,8 @@ namespace eval punk::mix::cli {
} }
cd $sourcefolder cd $sourcefolder
#use run so that stdout visible as it goes #use run so that stdout visible as it goes
if {![catch {run --timeout=5000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} { if {![catch {run --timeout=55000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} {
#todo - notify if exit because of timeout!
puts stderr "exitinfo: $exitinfo" puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode] set exitcode [dict get $exitinfo exitcode]
} else { } else {

74
src/bootsupport/modules/punk/mix/commandset/doc-0.1.0.tm

@ -18,7 +18,11 @@
## Requirements ## Requirements
##e.g package require frobz ##e.g package require frobz
package require punk ;# for treefilenames
package require punk::repo
package require punk::docgen ;#inline doctools - generate doctools .man files at src/docgen prior to using kettle to producing .html .md etc
package require punk::mix::cli ;#punk::mix::cli::lib used for kettle_call
package require punk::mix::util ;#for path_relative
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
@ -38,6 +42,30 @@ namespace eval punk::mix::commandset::doc {
puts stderr "No current project dir - unable to build docs" puts stderr "No current project dir - unable to build docs"
return return
} }
#user may delete the comment containing "--- punk::docgen::overwrites" and then manually edit, and we won't overwrite
#we still generate output in src/docgen so user can diff and manually update if thats what they prefer
set oldfiles [glob -nocomplain -dir $projectdir/src/doc -type f _module_*]
foreach maybedoomed $oldfiles {
set fd [open $maybedoomed r]
set data [read $fd]
close $fd
if {[string match "*--- punk::docgen overwrites *" $data]} {
file delete -force $maybedoomed
}
}
set generated [lib::do_docgen modules]
if {[dict get $generated count] > 0} {
#review
set doclist [dict get $generated docs]
foreach dinfo $doclist {
lassign $dinfo module fpath
set target $projectdir/src/doc/_module_[file tail $fpath]
if {![file exists $target]} {
file copy $fpath $target
}
}
}
if {[file exists $projectdir/src/doc]} { if {[file exists $projectdir/src/doc]} {
set original_wd [pwd] set original_wd [pwd]
cd $projectdir/src cd $projectdir/src
@ -125,6 +153,7 @@ namespace eval punk::mix::commandset::doc {
cd $original_wd cd $original_wd
} }
proc validate {} { proc validate {} {
#todo - run and validate punk::docgen output
set projectdir [punk::repo::find_project] set projectdir [punk::repo::find_project]
if {$projectdir eq ""} { if {$projectdir eq ""} {
puts stderr "No current project dir - unable to check doc status" puts stderr "No current project dir - unable to check doc status"
@ -154,6 +183,49 @@ namespace eval punk::mix::commandset::doc {
namespace eval lib { namespace eval lib {
variable pkg variable pkg
set pkg punk::mix::commandset::doc set pkg punk::mix::commandset::doc
proc do_docgen {{project_subpath modules}} {
set projectdir [punk::repo::find_project]
set outdir [file join $projectdir src docgen]
set subpath [file join $projectdir $project_subpath]
if {![file isdirectory $subpath]} {
puts stderr "WARNING punk::mix::commandset::doc unable to find subpath $subpath during do_docgen - skipping inline doctools generation"
return
}
if {[file isdirectory $outdir]} {
if {[catch {
file delete -force $outdir
}]} {
error "do_docgen failed to delete existing $outdir"
}
}
file mkdir $outdir
set matched_paths [punk::treefilenames $subpath *.tm]
set count 0
set newdocs [list]
set docgen_header_comments ""
append docgen_header_comments {[comment {--- punk::docgen generated from inline doctools comments ---}]} \n
append docgen_header_comments {[comment {--- punk::docgen DO NOT EDIT DOCS HERE UNLESS YOU REMOVE THESE COMMENT LINES ---}]} \n
append docgen_header_comments {[comment {--- punk::docgen overwrites this file ---}]} \n
foreach fullpath $matched_paths {
set relpath [punk::mix::util::path_relative $subpath $fullpath]
set tailsegs [file split $relpath]
set module_fullname [join $tailsegs ::]
set docname [string map [list :: _] $module_fullname].man ;#todo - something better - need to ensure unique
set doctools [punk::docgen::get_doctools_comments $fullpath]
if {$doctools ne ""} {
puts stdout "generating doctools output from file $relpath"
set outfile [file join $outdir $docname]
set fd [open $outfile w]
fconfigure $fd -translation binary
puts -nonewline $fd $docgen_header_comments$doctools
close $fd
incr count
lappend newdocs [list $module_fullname $outfile]
}
}
return [list count $count docs $newdocs]
}
} }
} }

16
src/bootsupport/modules/punk/mix/templates-0.1.0.tm

@ -26,17 +26,19 @@ namespace eval punk::mix::templates {
variable pkg punk::mix::templates variable pkg punk::mix::templates
variable cap_provider variable cap_provider
punk::cap::register_package punk::mix::templates [list\ #punk::cap::register_package punk::mix::templates [list\
{punk.templates {relpath ../templates}}\ # {punk.templates {relpath ../templates}}\
] #]
namespace eval capsystem { namespace eval capsystem {
if {[info commands capprovider.registration] eq ""} { if {[info commands capprovider.registration] eq ""} {
punk::cap::interface_capprovider.registration create capprovider.registration punk::cap::class::interface_capprovider.registration create capprovider.registration
oo::objdefine capprovider.registration { oo::objdefine capprovider.registration {
method get_declarations {} { method get_declarations {} {
set decls [list] set decls [list]
lappend decls punk.templates {relpath ../templates} lappend decls [list punk.templates {relpath ../templates}]
lappend decls punk.templates {relpath ../templates2} lappend decls [list punk.templates {relpath ../templates2}]
lappend decls [list punk.test {something blah}]
return $decls return $decls
} }
} }
@ -44,7 +46,7 @@ namespace eval punk::mix::templates {
} }
if {[info commands provider] eq ""} { if {[info commands provider] eq ""} {
punk::cap::interface_capprovider.provider create provider punk::cap::class::interface_capprovider.provider create provider punk::mix::templates
oo::objdefine provider { oo::objdefine provider {
method register {{capabilityname_glob *}} { method register {{capabilityname_glob *}} {
#puts registering punk::mix::templates $capabilityname #puts registering punk::mix::templates $capabilityname

32
src/bootsupport/modules/punkcheck-0.1.0.tm

@ -1078,7 +1078,7 @@ namespace eval punkcheck {
} }
proc install_non_tm_files {srcdir basedir args} { proc install_non_tm_files {srcdir basedir args} {
#set keys [dict keys $args] #set keys [dict keys $args]
#adjust the default anti_glob_dir_core entries so that .fossil-custom, .fossil-settings are copied #adjust the default antiglob_dir_core entries so that .fossil-custom, .fossil-settings are copied
set antiglob_dir_core [punkcheck::default_antiglob_dir_core] set antiglob_dir_core [punkcheck::default_antiglob_dir_core]
set posn [lsearch $antiglob_dir_core ".fossil*"] set posn [lsearch $antiglob_dir_core ".fossil*"]
if {$posn >=0} { if {$posn >=0} {
@ -1168,7 +1168,7 @@ namespace eval punkcheck {
-antiglob_file "" \ -antiglob_file "" \
-antiglob_dir_core "\uFFFF"\ -antiglob_dir_core "\uFFFF"\
-antiglob_dir {}\ -antiglob_dir {}\
-unpublish_paths {}\ -antiglob_paths {}\
-overwrite no-targets\ -overwrite no-targets\
-source_checksum comparestore\ -source_checksum comparestore\
-punkcheck_folder target\ -punkcheck_folder target\
@ -1225,8 +1225,8 @@ namespace eval punkcheck {
# -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
set opt_antiglob_dir [dict get $opts -antiglob_dir] set opt_antiglob_dir [dict get $opts -antiglob_dir]
# -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
set opt_unpublish_paths [dict get $opts -unpublish_paths] ;#todo - combine with config file in source tree .punkcheckpublish (?) set opt_antiglob_paths [dict get $opts -antiglob_paths] ;#todo - combine with config file in source tree .punkcheckpublish (?)
set unpublish_paths_matched [list] set antiglob_paths_matched [list]
# -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
set known_whats [list no-targets newer-targets older-targets all-targets installedsourcechanged-targets synced-targets] set known_whats [list no-targets newer-targets older-targets all-targets installedsourcechanged-targets synced-targets]
set overwrite_what [string tolower [dict get $opts -overwrite]]; #accept any case for value to allow emphasis by caller e.g -overwrite NEWER-TARGETS set overwrite_what [string tolower [dict get $opts -overwrite]]; #accept any case for value to allow emphasis by caller e.g -overwrite NEWER-TARGETS
@ -1347,11 +1347,11 @@ namespace eval punkcheck {
if {$target_relative_to_punkcheck_dir eq "."} { if {$target_relative_to_punkcheck_dir eq "."} {
set target_relative_to_punkcheck_dir "" set target_relative_to_punkcheck_dir ""
} }
foreach unpub $opt_unpublish_paths { foreach unpub $opt_antiglob_paths {
#puts "testing folder - globmatchpath $unpub $relative_source_dir" #puts "testing folder - globmatchpath $unpub $relative_source_dir"
if {[globmatchpath $unpub $relative_source_dir]} { if {[globmatchpath $unpub $relative_source_dir]} {
lappend unpublish_paths_matched $current_source_dir lappend antiglob_paths_matched $current_source_dir
return [list files_copied {} files_skipped {} sources_unchanged {} punkcheck_records $punkcheck_records unpublish_paths_matched $unpublish_paths_matched srcdir $srcdir tgtdir $tgtdir punkcheck_folder $punkcheck_folder] return [list files_copied {} files_skipped {} sources_unchanged {} punkcheck_records $punkcheck_records antiglob_paths_matched $antiglob_paths_matched srcdir $srcdir tgtdir $tgtdir punkcheck_folder $punkcheck_folder]
} }
} }
@ -1418,16 +1418,16 @@ namespace eval punkcheck {
set relative_target_path [file join $relative_target_dir $m] set relative_target_path [file join $relative_target_dir $m]
set relative_source_path [file join $relative_source_dir $m] set relative_source_path [file join $relative_source_dir $m]
set punkcheck_target_relpath [file join $target_relative_to_punkcheck_dir $m] set punkcheck_target_relpath [file join $target_relative_to_punkcheck_dir $m]
set is_unpublished 0 set is_antipath 0
foreach unpub $opt_unpublish_paths { foreach antipath $opt_antiglob_paths {
#puts "testing file - globmatchpath $unpub vs $relative_source_path" #puts "testing file - globmatchpath $antipath vs $relative_source_path"
if {[globmatchpath $unpub $relative_source_path]} { if {[globmatchpath $antipath $relative_source_path]} {
lappend unpublish_paths_matched $current_source_dir lappend antiglob_paths_matched $current_source_dir
set is_unpublished 1 set is_antipath 1
break break
} }
} }
if {$is_unpublished} { if {$is_antipath} {
continue continue
} }
#puts stdout " checking file : $current_source_dir/$m" #puts stdout " checking file : $current_source_dir/$m"
@ -1642,7 +1642,7 @@ namespace eval punkcheck {
lappend files_copied {*}[dict get $sub_result files_copied] lappend files_copied {*}[dict get $sub_result files_copied]
lappend files_skipped {*}[dict get $sub_result files_skipped] lappend files_skipped {*}[dict get $sub_result files_skipped]
lappend sources_unchanged {*}[dict get $sub_result sources_unchanged] lappend sources_unchanged {*}[dict get $sub_result sources_unchanged]
lappend unpublish_paths_matched {*}[dict get $sub_result unpublish_paths_matched] lappend antiglob_paths_matched {*}[dict get $sub_result antiglob_paths_matched]
set punkcheck_records [dict get $sub_result punkcheck_records] set punkcheck_records [dict get $sub_result punkcheck_records]
} }
@ -1664,7 +1664,7 @@ namespace eval punkcheck {
} }
} }
return [list files_copied $files_copied files_skipped $files_skipped sources_unchanged $sources_unchanged unpublish_paths_matched $unpublish_paths_matched punkcheck_records $punkcheck_records punkcheck_folder $punkcheck_folder srcdir $srcdir tgtdir $tgtdir] return [list files_copied $files_copied files_skipped $files_skipped sources_unchanged $sources_unchanged antiglob_paths_matched $antiglob_paths_matched punkcheck_records $punkcheck_records punkcheck_folder $punkcheck_folder srcdir $srcdir tgtdir $tgtdir]
} }
proc summarize_install_resultdict {resultdict} { proc summarize_install_resultdict {resultdict} {
set msg "" set msg ""

80
src/bootsupport/modules/textutil-0.9.tm

@ -0,0 +1,80 @@
# textutil.tcl --
#
# Utilities for manipulating strings, words, single lines,
# paragraphs, ...
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2002 by Joe English <jenglish@users.sourceforge.net>
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: textutil.tcl,v 1.17 2006/09/21 06:46:24 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil {}
# ### ### ### ######### ######### #########
## API implementation
## All through sub-packages imported here.
package require textutil::string
package require textutil::repeat
package require textutil::adjust
package require textutil::split
package require textutil::tabify
package require textutil::trim
package require textutil::wcswidth
namespace eval ::textutil {
# Import the miscellaneous string command for public export
namespace import -force string::chop string::tail
namespace import -force string::cap string::uncap string::capEachWord
namespace import -force string::longestCommonPrefix
namespace import -force string::longestCommonPrefixList
# Import the repeat commands for public export
namespace import -force repeat::strRepeat repeat::blank
# Import the adjust commands for public export
namespace import -force adjust::adjust adjust::indent adjust::undent
# Import the split commands for public export
namespace import -force split::splitx split::splitn
# Import the trim commands for public export
namespace import -force trim::trim trim::trimleft trim::trimright
namespace import -force trim::trimPrefix trim::trimEmptyHeading
# Import the tabify commands for public export
namespace import -force tabify::tabify tabify::untabify
namespace import -force tabify::tabify2 tabify::untabify2
# Re-export all the imported commands
namespace export chop tail cap uncap capEachWord
namespace export longestCommonPrefix longestCommonPrefixList
namespace export strRepeat blank
namespace export adjust indent undent
namespace export splitx splitn
namespace export trim trimleft trimright trimPrefix trimEmptyHeading
namespace export tabify untabify tabify2 untabify2
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil 0.9

761
src/bootsupport/modules/textutil/adjust-0.7.3.tm

@ -0,0 +1,761 @@
# trim.tcl --
#
# Various ways of trimming a string.
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2002-2004 by Johannes-Heinrich Vogeler <vogeler@users.sourceforge.net>
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: adjust.tcl,v 1.16 2011/12/13 18:12:56 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
package require textutil::repeat
package require textutil::string
namespace eval ::textutil::adjust {}
# ### ### ### ######### ######### #########
## API implementation
namespace eval ::textutil::adjust {
namespace import -force ::textutil::repeat::strRepeat
}
proc ::textutil::adjust::adjust {text args} {
if {[string length [string trim $text]] == 0} {
return ""
}
Configure $args
Adjust text newtext
return $newtext
}
proc ::textutil::adjust::Configure {args} {
variable Justify left
variable Length 72
variable FullLine 0
variable StrictLength 0
variable Hyphenate 0
variable HyphPatterns ; # hyphenation patterns (TeX)
set args [ lindex $args 0 ]
foreach { option value } $args {
switch -exact -- $option {
-full {
if { ![ string is boolean -strict $value ] } then {
error "expected boolean but got \"$value\""
}
set FullLine [ string is true $value ]
}
-hyphenate {
# the word exceeding the length of line is tried to be
# hyphenated; if a word cannot be hyphenated to fit into
# the line processing stops! The length of the line should
# be set to a reasonable value!
if { ![ string is boolean -strict $value ] } then {
error "expected boolean but got \"$value\""
}
set Hyphenate [string is true $value]
if { $Hyphenate && ![info exists HyphPatterns(_LOADED_)]} {
error "hyphenation patterns not loaded!"
}
}
-justify {
set lovalue [ string tolower $value ]
switch -exact -- $lovalue {
left -
right -
center -
plain {
set Justify $lovalue
}
default {
error "bad value \"$value\": should be center, left, plain or right"
}
}
}
-length {
if { ![ string is integer $value ] } then {
error "expected positive integer but got \"$value\""
}
if { $value < 1 } then {
error "expected positive integer but got \"$value\""
}
set Length $value
}
-strictlength {
# the word exceeding the length of line is moved to the
# next line without hyphenation; words longer than given
# line length are cut into smaller pieces
if { ![ string is boolean -strict $value ] } then {
error "expected boolean but got \"$value\""
}
set StrictLength [ string is true $value ]
}
default {
error "bad option \"$option\": must be -full, -hyphenate, \
-justify, -length, or -strictlength"
}
}
}
return ""
}
# ::textutil::adjust::Adjust
#
# History:
# rewritten on 2004-04-13 for bugfix tcllib-bugs-882402 (jhv)
proc ::textutil::adjust::Adjust { varOrigName varNewName } {
variable Length
variable FullLine
variable StrictLength
variable Hyphenate
upvar $varOrigName orig
upvar $varNewName text
set pos 0; # Cursor after writing
set line ""
set text ""
if {!$FullLine} {
regsub -all -- "(\n)|(\t)" $orig " " orig
regsub -all -- " +" $orig " " orig
regsub -all -- "(^ *)|( *\$)" $orig "" orig
}
set words [split $orig]
set numWords [llength $words]
set numline 0
for {set cnt 0} {$cnt < $numWords} {incr cnt} {
set w [lindex $words $cnt]
set wLen [string length $w]
# the word $w doesn't fit into the present line
# case #1: we try to hyphenate
if {$Hyphenate && ($pos+$wLen >= $Length)} {
# Hyphenation instructions
set w2 [textutil::adjust::Hyphenation $w]
set iMax [llength $w2]
if {$iMax == 1 && [string length $w] > $Length} {
# word cannot be hyphenated and exceeds linesize
error "Word \"$w2\" can\'t be hyphenated\
and exceeds linesize $Length!"
} else {
# hyphenating of $w was successfull, but we have to look
# that every sylable would fit into the line
foreach x $w2 {
if {[string length $x] >= $Length} {
error "Word \"$w\" can\'t be hyphenated\
to fit into linesize $Length!"
}
}
}
for {set i 0; set w3 ""} {$i < $iMax} {incr i} {
set syl [lindex $w2 $i]
if {($pos+[string length " $w3$syl-"]) > $Length} {break}
append w3 $syl
}
for {set w4 ""} {$i < $iMax} {incr i} {
set syl [lindex $w2 $i]
append w4 $syl
}
if {[string length $w3] && [string length $w4]} {
# hyphenation was successfull: redefine
# list of words w => {"$w3-" "$w4"}
set x [lreplace $words $cnt $cnt "$w4"]
set words [linsert $x $cnt "$w3-"]
set w [lindex $words $cnt]
set wLen [string length $w]
incr numWords
}
}
# the word $w doesn't fit into the present line
# case #2: we try to cut the word into pieces
if {$StrictLength && ([string length $w] > $Length)} {
# cut word into two pieces
set w2 $w
set over [expr {$pos+2+$wLen-$Length}]
incr Length -1
set w3 [string range $w2 0 $Length]
incr Length
set w4 [string range $w2 $Length end]
set x [lreplace $words $cnt $cnt $w4]
set words [linsert $x $cnt $w3 ]
set w [lindex $words $cnt]
set wLen [string length $w]
incr numWords
}
# continuing with the normal procedure
if {($pos+$wLen < $Length)} {
# append word to current line
if {$pos} {append line " "; incr pos}
append line $w
incr pos $wLen
} else {
# line full => write buffer and begin a new line
if {[string length $text]} {append text "\n"}
append text [Justification $line [incr numline]]
set line $w
set pos $wLen
}
}
# write buffer and return!
if {[string length $text]} {append text "\n"}
append text [Justification $line end]
return $text
}
# ::textutil::adjust::Justification
#
# justify a given line
#
# Parameters:
# line text for justification
# index index for line in text
#
# Returns:
# the justified line
#
# Remarks:
# Only lines with size not exceeding the max. linesize provided
# for text formatting are justified!!!
proc ::textutil::adjust::Justification { line index } {
variable Justify
variable Length
variable FullLine
set len [string length $line]; # length of current line
if { $Length <= $len } then {
# the length of current line ($len) is equal as or greater than
# the value provided for text formatting ($Length) => to avoid
# inifinite loops we leave $line unchanged and return!
return $line
}
# Special case:
# for the last line, and if the justification is set to 'plain'
# the real justification is 'left' if the length of the line
# is less than 90% (rounded) of the max length allowed. This is
# to avoid expansion of this line when it is too small: without
# it, the added spaces will 'unbeautify' the result.
#
set justify $Justify
if { ( "$index" == "end" ) && \
( "$Justify" == "plain" ) && \
( $len < round($Length * 0.90) ) } then {
set justify left
}
# For a left justification, nothing to do, but to
# add some spaces at the end of the line if requested
if { "$justify" == "left" } then {
set jus ""
if { $FullLine } then {
set jus [strRepeat " " [ expr { $Length - $len } ]]
}
return "${line}${jus}"
}
# For a right justification, just add enough spaces
# at the beginning of the line
if { "$justify" == "right" } then {
set jus [strRepeat " " [ expr { $Length - $len } ]]
return "${jus}${line}"
}
# For a center justification, add half of the needed spaces
# at the beginning of the line, and the rest at the end
# only if needed.
if { "$justify" == "center" } then {
set mr [ expr { ( $Length - $len ) / 2 } ]
set ml [ expr { $Length - $len - $mr } ]
set jusl [strRepeat " " $ml]
set jusr [strRepeat " " $mr]
if { $FullLine } then {
return "${jusl}${line}${jusr}"
} else {
return "${jusl}${line}"
}
}
# For a plain justification, it's a little bit complex:
#
# if some spaces are missing, then
#
# 1) sort the list of words in the current line by decreasing size
# 2) foreach word, add one space before it, except if it's the
# first word, until enough spaces are added
# 3) rebuild the line
if { "$justify" == "plain" } then {
set miss [ expr { $Length - [ string length $line ] } ]
# Bugfix tcllib-bugs-860753 (jhv)
set words [split $line]
set numWords [llength $words]
if {$numWords < 2} {
# current line consists of less than two words - we can't
# insert blanks to achieve a plain justification => leave
# $line unchanged and return!
return $line
}
for {set i 0; set totalLen 0} {$i < $numWords} {incr i} {
set w($i) [lindex $words $i]
if {$i > 0} {set w($i) " $w($i)"}
set wLen($i) [string length $w($i)]
set totalLen [expr {$totalLen+$wLen($i)}]
}
set miss [expr {$Length - $totalLen}]
# len walks through all lengths of words of the line under
# consideration
for {set len 1} {$miss > 0} {incr len} {
for {set i 1} {($i < $numWords) && ($miss > 0)} {incr i} {
if {$wLen($i) == $len} {
set w($i) " $w($i)"
incr wLen($i)
incr miss -1
}
}
}
set line ""
for {set i 0} {$i < $numWords} {incr i} {
set line "$line$w($i)"
}
# End of bugfix
return "${line}"
}
error "Illegal justification key \"$justify\""
}
proc ::textutil::adjust::SortList { list dir index } {
if { [ catch { lsort -integer -$dir -index $index $list } sl ] != 0 } then {
error "$sl"
}
return $sl
}
# Hyphenation utilities based on Knuth's algorithm
#
# Copyright (C) 2001-2003 by Dr.Johannes-Heinrich Vogeler (jhv)
# These procedures may be used as part of the tcllib
# textutil::adjust::Hyphenation
#
# Hyphenate a string using Knuth's algorithm
#
# Parameters:
# str string to be hyphenated
#
# Returns:
# the hyphenated string
proc ::textutil::adjust::Hyphenation { str } {
# if there are manual set hyphenation marks e.g. "Recht\-schrei\-bung"
# use these for hyphenation and return
if {[regexp {[^\\-]*[\\-][.]*} $str]} {
regsub -all {(\\)(-)} $str {-} tmp
return [split $tmp -]
}
# Don't hyphenate very short words! Minimum length for hyphenation
# is set to 3 characters!
if { [string length $str] < 4 } then { return $str }
# otherwise follow Knuth's algorithm
variable HyphPatterns; # hyphenation patterns (TeX)
set w ".[string tolower $str]."; # transform to lower case
set wLen [string length $w]; # and add delimiters
# Initialize hyphenation weights
set s {}
for {set i 0} {$i < $wLen} {incr i} {
lappend s 0
}
for {set i 0} {$i < $wLen} {incr i} {
set kmax [expr {$wLen-$i}]
for {set k 1} {$k < $kmax} {incr k} {
set sw [string range $w $i [expr {$i+$k}]]
if {[info exists HyphPatterns($sw)]} {
set hw $HyphPatterns($sw)
set hwLen [string length $hw]
for {set l1 0; set l2 0} {$l1 < $hwLen} {incr l1} {
set c [string index $hw $l1]
if {[string is digit $c]} {
set sPos [expr {$i+$l2}]
if {$c > [lindex $s $sPos]} {
set s [lreplace $s $sPos $sPos $c]
}
} else {
incr l2
}
}
}
}
}
# Replace all even hyphenation weigths by zero
for {set i 0} {$i < [llength $s]} {incr i} {
set c [lindex $s $i]
if {!($c%2)} { set s [lreplace $s $i $i 0] }
}
# Don't start with a hyphen! Take also care of words enclosed in quotes
# or that someone has forgotten to put a blank between a punctuation
# character and the following word etc.
for {set i 1} {$i < ($wLen-1)} {incr i} {
set c [string range $w $i end]
if {[regexp {^[:alpha:][.]*} $c]} {
for {set k 1} {$k < ($i+1)} {incr k} {
set s [lreplace $s $k $k 0]
}
break
}
}
# Don't separate the last character of a word with a hyphen
set max [expr {[llength $s]-2}]
if {$max} {set s [lreplace $s $max end 0]}
# return the syllabels of the hyphenated word as a list!
set ret ""
set w ".$str."
for {set i 1} {$i < ($wLen-1)} {incr i} {
if {[lindex $s $i]} { append ret - }
append ret [string index $w $i]
}
return [split $ret -]
}
# textutil::adjust::listPredefined
#
# Return the names of the hyphenation files coming with the package.
#
# Parameters:
# None.
#
# Result:
# List of filenames (without directory)
proc ::textutil::adjust::listPredefined {} {
variable here
return [glob -type f -directory $here -tails *.tex]
}
# textutil::adjust::getPredefined
#
# Retrieve the full path for a predefined hyphenation file
# coming with the package.
#
# Parameters:
# name Name of the predefined file.
#
# Results:
# Full path to the file, or an error if it doesn't
# exist or is matching the pattern *.tex.
proc ::textutil::adjust::getPredefined {name} {
variable here
if {![string match *.tex $name]} {
return -code error \
"Illegal hyphenation file \"$name\""
}
set path [file join $here $name]
if {![file exists $path]} {
return -code error \
"Unknown hyphenation file \"$path\""
}
return $path
}
# textutil::adjust::readPatterns
#
# Read hyphenation patterns from a file and store them in an array
#
# Parameters:
# filNam name of the file containing the patterns
proc ::textutil::adjust::readPatterns { filNam } {
variable HyphPatterns; # hyphenation patterns (TeX)
# HyphPatterns(_LOADED_) is used as flag for having loaded
# hyphenation patterns from the respective file (TeX format)
if {[info exists HyphPatterns(_LOADED_)]} {
unset HyphPatterns(_LOADED_)
}
# the array xlat provides translation from TeX encoded characters
# to those of the ISO-8859-1 character set
set xlat(\"s) \337; # 223 := sharp s "
set xlat(\`a) \340; # 224 := a, grave
set xlat(\'a) \341; # 225 := a, acute
set xlat(\^a) \342; # 226 := a, circumflex
set xlat(\"a) \344; # 228 := a, diaeresis "
set xlat(\`e) \350; # 232 := e, grave
set xlat(\'e) \351; # 233 := e, acute
set xlat(\^e) \352; # 234 := e, circumflex
set xlat(\`i) \354; # 236 := i, grave
set xlat(\'i) \355; # 237 := i, acute
set xlat(\^i) \356; # 238 := i, circumflex
set xlat(\~n) \361; # 241 := n, tilde
set xlat(\`o) \362; # 242 := o, grave
set xlat(\'o) \363; # 243 := o, acute
set xlat(\^o) \364; # 244 := o, circumflex
set xlat(\"o) \366; # 246 := o, diaeresis "
set xlat(\`u) \371; # 249 := u, grave
set xlat(\'u) \372; # 250 := u, acute
set xlat(\^u) \373; # 251 := u, circumflex
set xlat(\"u) \374; # 252 := u, diaeresis "
set fd [open $filNam RDONLY]
set status 0
while {[gets $fd line] >= 0} {
switch -exact $status {
PATTERNS {
if {[regexp {^\}[.]*} $line]} {
# End of patterns encountered: set status
# and ignore that line
set status 0
continue
} else {
# This seems to be pattern definition line; to process it
# we have first to do some editing
#
# 1) eat comments in a pattern definition line
# 2) eat braces and coded linefeeds
set z [string first "%" $line]
if {$z > 0} { set line [string range $line 0 [expr {$z-1}]] }
regsub -all {(\\n|\{|\})} $line {} tmp
set line $tmp
# Now $line should consist only of hyphenation patterns
# separated by white space
# Translate TeX encoded characters to ISO-8859-1 characters
# using the array xlat defined above
foreach x [array names xlat] {
regsub -all {$x} $line $xlat($x) tmp
set line $tmp
}
# split the line and create a lookup array for
# the repective hyphenation patterns
foreach item [split $line] {
if {[string length $item]} {
if {![string match {\\} $item]} {
# create index for hyphenation patterns
set var $item
regsub -all {[0-9]} $var {} idx
# store hyphenation patterns as elements of an array
set HyphPatterns($idx) $item
}
}
}
}
}
EXCEPTIONS {
if {[regexp {^\}[.]*} $line]} {
# End of patterns encountered: set status
# and ignore that line
set status 0
continue
} else {
# to be done in the future
}
}
default {
if {[regexp {^\\endinput[.]*} $line]} {
# end of data encountered, stop processing and
# ignore all the following text ..
break
} elseif {[regexp {^\\patterns[.]*} $line]} {
# begin of patterns encountered: set status
# and ignore that line
set status PATTERNS
continue
} elseif {[regexp {^\\hyphenation[.]*} $line]} {
# some particular cases to be treated separately
set status EXCEPTIONS
continue
} else {
set status 0
}
}
}
}
close $fd
set HyphPatterns(_LOADED_) 1
return
}
#######################################################
# @c The specified <a text>block is indented
# @c by <a prefix>ing each line. The first
# @c <a hang> lines ares skipped.
#
# @a text: The paragraph to indent.
# @a prefix: The string to use as prefix for each line
# @a prefix: of <a text> with.
# @a skip: The number of lines at the beginning to leave untouched.
#
# @r Basically <a text>, but indented a certain amount.
#
# @i indent
# @n This procedure is not checked by the testsuite.
proc ::textutil::adjust::indent {text prefix {skip 0}} {
set text [string trimright $text]
set res [list]
foreach line [split $text \n] {
if {[string compare "" [string trim $line]] == 0} {
lappend res {}
} else {
set line [string trimright $line]
if {$skip <= 0} {
lappend res $prefix$line
} else {
lappend res $line
}
}
if {$skip > 0} {incr skip -1}
}
return [join $res \n]
}
# Undent the block of text: Compute LCP (restricted to whitespace!)
# and remove that from each line. Note that this preverses the
# shaping of the paragraph (i.e. hanging indent are _not_ flattened)
# We ignore empty lines !!
proc ::textutil::adjust::undent {text} {
if {$text == {}} {return {}}
set lines [split $text \n]
set ne [list]
foreach l $lines {
if {[string length [string trim $l]] == 0} continue
lappend ne $l
}
set lcp [::textutil::string::longestCommonPrefixList $ne]
if {[string length $lcp] == 0} {return $text}
regexp "^(\[\t \]*)" $lcp -> lcp
if {[string length $lcp] == 0} {return $text}
set len [string length $lcp]
set res [list]
foreach l $lines {
if {[string length [string trim $l]] == 0} {
lappend res {}
} else {
lappend res [string range $l $len end]
}
}
return [join $res \n]
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::adjust {
variable here [file dirname [info script]]
variable Justify left
variable Length 72
variable FullLine 0
variable StrictLength 0
variable Hyphenate 0
variable HyphPatterns
namespace export adjust indent undent
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::adjust 0.7.3

902
src/bootsupport/modules/textutil/dehypht.tex

@ -0,0 +1,902 @@
% This is `dehypht.tex' as of 03 March 1999.
%
% Copyright (C) 1988,1991 Rechenzentrum der Ruhr-Universitaet Bochum
% [german hyphen patterns]
% Copyright (C) 1993,1994,1999 Bernd Raichle/DANTE e.V.
% [macros, adaption for TeX 2]
%
% -----------------------------------------------------------------
% IMPORTANT NOTICE:
%
% This program can be redistributed and/or modified under the terms
% of the LaTeX Project Public License Distributed from CTAN
% archives in directory macros/latex/base/lppl.txt; either
% version 1 of the License, or any later version.
% -----------------------------------------------------------------
%
%
% This file contains german hyphen patterns following traditional
% hyphenation rules and includes umlauts and sharp s, but without
% `c-k' and triple consonants. It is based on hyphen patterns
% containing 5719 german hyphen patterns with umlauts in the
% recommended version of September 27, 1990.
%
% For use with TeX generated by
%
% Norbert Schwarz
% Rechenzentrum Ruhr-Universitaet Bochum
% Universitaetsstrasse 150
% D-44721 Bochum, FRG
%
%
% Adaption of these patterns for TeX, Version 2.x and 3.x and
% all fonts in T1/`Cork'/EC/DC and/or OT1/CM encoding by
%
% Bernd Raichle
% Stettener Str. 73
% D-73732 Esslingen, FRG
% Email: raichle@Informatik.Uni-Stuttgart.DE
%
%
% Error reports in case of UNCHANGED versions to
%
% DANTE e.V., Koordinator `german.sty'
% Postfach 10 18 40
% D-69008 Heidelberg, FRG
% Email: german@Dante.DE
%
% or one of the addresses given above.
%
%
% Changes:
% 1990-09-27 First version of `ghyphen3.tex' (Norbert Schwarz)
% 1991-02-13 PC umlauts changed to ^^xx (Norbert Schwarz)
% 1993-08-27 Umlauts/\ss changed to "a/\3 macros, added macro
% definitions and additional logic to select correct
% patterns/encoding (Bernd Raichle)
% 1994-02-13 Release of `ghyph31.tex' V3.1a (Bernd Raichle)
% 1999-03-03 Renamed file to `dehypht.tex' according to the
% naming scheme using the ISO country code `de', the
% common part `hyph' for all hyphenation patterns files,
% and the additional postfix `t' for traditional,
% removed wrong catcode change of ^^e (the comment
% character %) and ^^f (the character &),
% do _not_ change \catcode, \lccode, \uccode to avoid
% problems with other hyphenation pattern files,
% changed code to distinguish TeX 2.x/3.x,
% changed license conditions to LPPL (Bernd Raichle)
%
%
% For more information see the additional documentation
% at the end of this file.
%
% -----------------------------------------------------------------
%
\message{German Traditional Hyphenation Patterns %
`dehypht' Version 3.2a <1999/03/03>}
\message{(Formerly known under the name `ghyph31' and `ghyphen'.)}
%
%
% Next we define some commands which are used inside the patterns.
% To keep them local, we enclose the rest of the file in a group
% (The \patterns command globally changes the hyphenation trie!).
%
\begingroup
%
%
% Make sure that doublequote is not active:
\catcode`\"=12
%
%
% Because ^^e4 is used in the following macros which is read by
% TeX 2.x as ^^e or %, the comment character of TeX, some trick
% has to be found to avoid this problem. The same is true for the
% character ^^f or & in the TeX 2.x code.
% Therefore in the code the exclamationmark ! is used instead of
% the circumflex ^ and its \catcode is set appropriately
% (normally \catcode`\!=12, in the code \catcode`\!=7).
%
% The following \catcode, \lccode assignments and macro definitions
% are defined in such a way that the following \pattern{...} list
% can be used for both, TeX 2.x and TeX 3.x.
%
% We first change the \lccode of ^^Y to make sure that we can
% include this character in the hyphenation patterns.
%
\catcode`\^^Y=11 \lccode`\^^Y=`\^^Y
%
% Then we have to define some macros depending on the TeX version.
% Therefore we have to distinguish TeX version 2.x and 3.x:
%
\ifnum`\@=`\^^40 % true => TeX 3.x
%
% For TeX 3:
% ----------
%
% Assign appropriate \catcode and \lccode values for all
% accented characters used in the patterns (\uccode changes are
% not used within \patterns{...} and thus not necessary):
%
\catcode"E4=11 \catcode"C4=11 % \"a \"A
\catcode"F6=11 \catcode"D6=11 % \"o \"O
\catcode"FC=11 \catcode"DC=11 % \"u \"U
\catcode"FF=11 \catcode"DF=11 % \ss SS
%
\lccode"C4="E4 \uccode"C4="C4 \lccode"E4="E4 \uccode"E4="C4
\lccode"D6="F6 \uccode"D6="D6 \lccode"F6="F6 \uccode"F6="D6
\lccode"DC="FC \uccode"DC="DC \lccode"FC="FC \uccode"FC="DC
\lccode"DF="FF \uccode"DF="DF \lccode"FF="FF \uccode"FF="DF
%
% In the following definitions we use ??xy instead of ^^xy
% to avoid errors when reading the following macro definitions
% with TeX 2.x (remember ^^e(4) is the comment character):
%
\catcode`\?=7
%
% Define the accent macro " in such a way that it
% expands to single letters in font encoding T1.
\catcode`\"=13
\def"#1{\ifx#1a??e4\else \ifx#1o??f6\else \ifx#1u??fc\else
\errmessage{Hyphenation pattern file corrupted!}%
\fi\fi\fi}
%
% - patterns with umlauts are ok
\def\n#1{#1}
%
% For \ss which exists in T1 _and_ OT1 encoded fonts but with
% different glyph codes, duplicated patterns for both encodings
% are included. Thus you can use these hyphenation patterns for
% T1 and OT1 encoded fonts:
% - define \3 to be code `\^^ff (\ss in font encoding T1)
% - define \9 to be code `\^^Y (\ss in font encoding OT1)
\def\3{??ff}
\def\9{??Y}
% - duplicated patterns to support font encoding OT1 are ok
\def\c#1{#1}
% >>>>>> UNCOMMENT the next line, if you do not want
% >>>>>> to use fonts in font encoding OT1
%\def\c#1{}
%
\catcode`\?=12
%
\else
%
% For TeX 2:
% ----------
%
% Define the accent macro " to throw an error message.
\catcode`\"=13
\def"#1{\errmessage{Hyphenation pattern file corrupted!}}
%
% - ignore all patterns with umlauts
\def\n#1{}
%
% With TeX 2 fonts in encoding T1 can be used, but all glyphs
% in positions > 127 can not be used in hyphenation patterns.
% Thus only patterns with glyphs in OT1 positions are included:
% - define \3 to be code ^^Y (\ss in CM font encoding)
% - define \9 to throw an error message
\def\3{^^Y}
\def\9{\errmessage{Hyphenation pattern file corrupted!}}
% - ignore all duplicated patterns with \ss in T1 encoding
\def\c#1{}
%
\fi
%
%
\patterns{%
.aa6l .ab3a4s .ab3ei .abi2 .ab3it .ab1l .ab1r .ab3u .ad3o4r .alti6
.ana3c .an5alg .an1e .ang8s .an1s .ap1p .ar6sc .ar6ta .ar6tei .as2z
.au2f1 .au2s3 .be5erb .be3na .ber6t5r .bie6r5 .bim6s5t .brot3 .bru6s
.ch6 .che6f5 .da8c .da2r .dar5in .dar5u .den6ka .de5r6en .des6pe
.de8spo .de3sz .dia3s4 .dien4 .dy2s1 .ehren5 .eine6 .ei6n5eh .ei8nen
.ein5sa .en6der .en6d5r .en3k4 .en8ta8 .en8tei .en4t3r .epo1 .er6ban
.er6b5ei .er6bla .er6d5um .er3ei .er5er .er3in .er3o4b .erwi5s .es1p
.es8t .ex1a2 .ex3em .fal6sc .fe6st5a .flu4g3 .furch8 .ga6ner .ge3n4a
\n{.ge5r"o} .ges6 .halb5 .halbe6 .hal6br .haup4 .hau4t .heima6 .he4r3e
.her6za .he5x .hin3 .hir8sc .ho4c .hu3sa .hy5o .ibe5 .ima6ge .in1
.ini6 .is5chi .jagd5 .kal6k5o .ka6ph .ki4e .kop6f3 .kraf6 \n{.k"u5ra}
.lab6br .liie6 .lo6s5k \n{.l"o4s3t} .ma5d .mi2t1 .no6th .no6top
.obe8ri .ob1l .obs2 .ob6st5e .or3c .ort6s5e .ost3a .oste8r .pe4re
.pe3ts .ph6 .po8str .rau4m3 .re5an .ro8q .ru5the \n{.r"u5be}
\n{.r"u8stet} .sch8 .se6e .se5n6h .se5ra .si2e .spi6ke .st4 .sy2n
.tages5 .tan6kl .ta8th .te6e .te8str .to6der .to8nin .to6we .um1
.umpf4 .un1 .une6 .unge5n .ur1c .ur5en .ve6rin .vora8 .wah6l5 .we8ges
.wo6r .wor3a .wun4s .zi4e .zuch8 \n{."ande8re} \n{."och8} aa1c aa2gr
aal5e aa6r5a a5arti aa2s1t aat2s 6aba ab3art 1abdr 6abel aben6dr
ab5erk ab5err ab5esse 1abf 1abg \n{1abh"a} ab1ir 1abko a1bl ab1la
5ablag a6bla\3 \c{a6bla\9} ab4ler ab1lu \n{a8bl"a} \n{5a6bl"o} abma5c
1abn ab1ra ab1re 5a6brec ab1ro ab1s ab8sk abs2z 3abtei ab1ur 1abw
5abze 5abzu \n{ab1"an} \n{ab"au8} a4ce. a5chal ach5art ach5au a1che
a8chent ach6er. a6ch5erf a1chi ach1l ach3m ach5n a1cho ach3re a1chu
ach1w a1chy \n{ach5"af} ack1o acks6t ack5sta a1d 8ad. a6d5ac ad3ant
ad8ar 5addi a8dein ade5o8 adi5en 1adj 1adle ad1op a2dre 3adres adt1
1adv \n{a6d"a} a1e2d ae1r a1er. 1aero 8afa a3fal af1an a5far a5fat
af1au a6fentl a2f1ex af1fr af5rau af1re 1afri af6tent af6tra aft5re
a6f5um \n{8af"a} ag5abe 5a4gent ag8er ages5e 1aggr ag5las ag1lo a1gn
ag2ne 1agog a6g5und a1ha a1he ah5ein a4h3erh a1hi ahl1a ah1le ah4m3ar
ahn1a a5ho ahra6 ahr5ab ah1re ah8rei ahren8s ahre4s3 ahr8ti ah1ru a1hu
\n{ah8"o} ai3d2s ai1e aif6 a3inse ai4re. a5isch. ais8e a3ismu ais6n
aiso6 a1j 1akad a4kade a1ke a1ki 1akko 5akro1 a5lal al5ans 3al8arm
al8beb al8berw alb5la 3album al1c a1le a6l5e6be a4l3ein a8lel a8lerb
a8lerh a6lert 5a6l5eth 1algi al4gli al3int al4lab al8lan al4l3ar
alle3g a1lo a4l5ob al6schm al4the altist5 al4t3re 8a1lu alu5i a6lur
alu3ta \n{a1l"a} a6mate 8ame. 5a6meise am6m5ei am6mum am2n ampf3a
am6schw am2ta a1mu \n{a1m"a} a3nac a1nad anadi5e an3ako an3alp 3analy
an3ame an3ara a1nas an5asti a1nat anat5s an8dent ande4s3 an1ec an5eis
an1e2k 4aner. a6n5erd a8nerf a6n5erke 1anfa 5anfert \n{1anf"a} 3angab
5angebo an3gli ang6lis an2gn 3angri ang5t6 \n{5anh"a} ani5g ani4ka
an5i8on an1kl an6kno an4kro 1anl anma5c anmar4 3annah anne4s3 a1no
5a6n1o2d 5a6n3oma 5a6nord 1anr an1sa 5anschl an4soz an1st 5anstal
an1s2z 5antenn an1th \n{5anw"a} a5ny an4z3ed 5anzeig 5anzieh 3anzug
\n{an1"a} \n{5an"as} \n{a1n"o} \n{an"o8d} a1os a1pa 3apfel a2ph1t
\n{aph5"a6} a1pi 8apl apo1c apo1s a6poste a6poth 1appa ap1pr a1pr
\n{a5p"a} \n{a3p"u} a1ra a4r3af ar3all 3arbei 2arbt ar1c 2a1re ar3ein
ar2gl 2a1ri ari5es ar8kers ar6les ar4nan ar5o6ch ar1o2d a1rol ar3ony
a8ror a3ros ar5ox ar6schl 8artei ar6t5ri a1ru a1ry 1arzt arz1w
\n{ar8z"a} \n{ar"a8m} \n{ar"o6} \n{ar5"om} \n{ar1"u2} a1sa a6schec
asch5l asch3m a6schn a3s4hi as1pa asp5l a8steb as5tev 1asth a6stoc
a1str ast3re 8a1ta ata5c ata3la a6tapf ata5pl a1te a6teli aten5a
ate5ran 6atf 6atg a1th at3hal 1athl 2a1ti 5atlant 3atlas 8atmus 6atn
a1to a6t5ops ato6ra a6t5ort. 4a1tr a6t5ru at2t1h \n{at5t6h"a} 6a1tu
atz1w \n{a1t"a} \n{a1t"u} au1a au6bre auch3a au1e aue4l 5aufent
\n{3auff"u} 3aufga 1aufn auf1t 3auftr 1aufw 3auge. au4kle aule8s 6aum
au8mar aum5p 1ausb 3ausd 1ausf 1ausg au8sin 3auss au4sta 1ausw 1ausz
aut5eng au1th 1auto au\3e8 \c{au\9e8} a1v ave5r6a aver6i a1w a6wes a1x
a2xia a6xio a1ya a1z azi5er. 8a\3 \c{8a\9} 1ba 8ba8del ba1la ba1na
ban6k5r ba5ot bardi6n ba1ro basten6 bau3sp 2b1b bb6le b2bli 2b1c 2b1d
1be be1a be8at. be1ch 8becht 8becke. be5el be1en bee8rei be5eta bef2
8beff be1g2 \n{beh"o8} bei1s 6b5eisen bei3tr b8el bel8o belu3t be3nac
bend6o be6ners be6nerw be4nor ben4se6 bens5el \n{be1n"a} \n{be1n"u}
be1o2 b8er. be1ra be8rac ber8gab. ber1r \n{be1r"u} bes8c bes5erh
bes2p be5tha bet5sc be1un be1ur 8bex be6zwec 2b1f8 bfe6st5e 2b1g2
bga2s5 bge1 2b1h bhole6 1bi bi1bl b6ie bi1el bi1la \n{bil"a5} bi1na
bi4nok bi5str bi6stu bi5tr bit4t5r b1j 2b1k2 \n{bk"u6} bl8 b6la.
6b1lad 6blag 8blam 1blat b8latt 3blau. b6lav 3ble. b1leb b1led
8b1leg 8b1leh 8bleid 8bleih 6b3lein blei3s ble4m3o 4blich b4lind
8bling b2lio 5blit b4litz b1loh 8b1los 1blu 5blum 2blun blut3a blut5sc
\n{3bl"a} \n{bl"as5c} \n{5bl"o} \n{3bl"u} \n{bl"u8sc} 2b1m 2b1n 1bo
bo1ch bo5d6s boe5 8boff 8bonk bo1ra b1ort 2b1p2 b1q 1br brail6 brast8
bre4a b5red 8bref 8b5riem b6riga bro1s b1rup b2ruz \n{8br"oh}
\n{br"os5c} 8bs b1sa b8sang b2s1ar b1sc bs3erl bs3erz b8sof b1s2p
bst1h b3stru \n{b5st"a} b6sun 2b1t b2t1h 1bu bu1ie bul6k b8ure bu6sin
6b1v 2b1w 1by1 by6te. 8b1z bzi1s \n{1b"a} \n{b5"a6s5} \n{1b"u}
\n{b6"u5bere} \n{b"uge6} \n{b"ugel5e} \n{b"ur6sc} 1ca cag6 ca5la ca6re
ca5y c1c 1ce celi4c celich5 ce1ro c8h 2ch. 1chae ch1ah ch3akt cha6mer
8chanz 5chara 3chari 5chato 6chb 1chef 6chei ch3eil ch3eis 6cherkl
6chf 4chh 5chiad 5chias 6chins 8chj chl6 5chlor 6ch2m 2chn6 ch8nie
5cho. 8chob choi8d 6chp ch3ren ch6res \n{ch3r"u} 2chs 2cht cht5ha
cht3hi 5chthon ch6tin 6chuh chu4la 6ch3unt chut6t 8chw 1ci ci5tr c2k
2ck. ck1ei 4ckh ck3l ck3n ck5o8f ck1r 2cks ck5stra ck6s5u c2l 1c8o
con6ne 8corb cos6t c3q 1c6r 8c1t 1cu 1cy \n{5c"a1} \n{c"o5} 1da.
8daas 2dabg 8dabr 6dabt 6dabw 1dac da2gr 6d5alk 8d5amt dan6ce.
dani5er dan8ker 2danl danla6 6dans 8danzi 6danzu d1ap da2r1a8 2d1arb
d3arc dar6men 4d3art 8darz 1dat 8datm 2d1auf 2d1aus 2d1b 2d1c 2d1d
d5de d3d2h \n{dd"amme8} 1de 2deal de5an de3cha de1e defe6 6deff 2d1ehr
5d4eic de5isc de8lar del6s5e del6spr de4mag de8mun de8nep dene6r
8denge. 8dengen de5o6d 2deol de5ram 8derdb der5ein de1ro der1r d8ers
der5um de4s3am de4s3an de4sau de6sil de4sin de8sor de4spr de2su 8deul
de5us. 2d1f df2l 2d1g 2d1h 1di dia5c di5ara dice5 di3chr di5ena di1gn
di1la dil8s di1na 8dind 6dinf 4d3inh 2d1ins di5o6d di3p4t di8sen dis1p
di5s8per di6s5to dis5tra di8tan di8tin d1j 6dje 2dju 2d1k 2d1l 2d1m
2d1n6 dni6 dnje6 1do 6d5obe do6berf 6d5ony do3ran 6dord 2d1org dor4t3h
do6ste 6doth dott8e 2d1p d5q dr4 1drah 8drak d5rand 6dre. 4drech
d6reck 4d3reg 8d3reic d5reife 8drem 8d1ren 2drer 8dres. 6d5rh 1dria
d1ric 8drind droi6 dro5x 1dru 8drut \n{dr"os5c} \n{1dr"u} \n{dr"u5b}
\n{dr"u8sc} 2ds d1sa d6san dsat6 d1sc 5d6scha. 5dschik dse8e d8serg
8dsl d1sp d4spak ds2po \n{d8sp"a} d1st \n{d1s"u} 2dt d1ta d1te d1ti
d1to dt1s6 d1tu \n{d5t"a} 1du du5als du1b6 du1e duf4t3r 4d3uh du5ie
8duml 8dumw 2d1und du8ni 6d5unt dur2c durch3 6durl 6dursa 8durt du1s
du8schr 2d1v 2d1w dwa8l 2d1z \n{1d"a} \n{6d"ah} \n{8d"and} \n{d"a6r}
\n{d"o8bl} \n{d5"ol} \n{d"or6fl} \n{d"o8sc} \n{d5"o4st} \n{d"os3te}
\n{1d"u} ea4ben e1ac e1ah e1akt e1al. e5alf e1alg e5a8lin e1alk e1all
e5alp e1alt e5alw e1am e1and ea6nim e1ar. e5arf e1ark e5arm e3art
e5at. e6ate e6a5t6l e8ats e5att e6au. e1aus e1b e6b5am ebens5e
eb4lie eb4ser eb4s3in e1che e8cherz e1chi ech3m 8ech3n ech1r ech8send
ech4su e1chu eck5an e5cl e1d ee5a ee3e ee5g e1ei ee5isc eei4s3t
ee6lend e1ell \n{ee5l"o} e1erd ee3r4e ee8reng eere6s5 \n{ee5r"a}
ee6tat e1ex e1f e6fau e8fe8b 3effek ef3rom ege6ra eglo6si 1egy e1ha
e6h5ach eh5ans e6hap eh5auf e1he e1hi ehl3a eh1le ehl5ein eh1mu ehn5ec
e1ho ehr1a eh1re ehre6n eh1ri eh1ru ehr5um e1hu eh1w e1hy \n{e1h"a}
\n{e1h"o} \n{e3h"ut} ei1a eia6s ei6bar eich3a eich5r ei4dar ei6d5ei
ei8derf ei3d4sc ei1e 8eifen 3eifri 1eign eil1d ei6mab ei8mag ein1a4
ei8nat ei8nerh ei8ness ei6nete ein1g e8ini ein1k ei6n5od ei8nok ei4nor
\n{e3ins"a} ei1o e1irr ei5ru ei8sab ei5schn ei6s5ent ei8sol ei4t3al
eit3ar eit1h ei6thi ei8tho eit8samt ei6t5um e1j 1ekd e1ke e1ki e1k2l
e1kn ekni4 e1la e2l1al 6elan e6lanf e8lanl e6l5ans el3arb el3arm
e6l3art 5e6lasti e6lauge elbst5a e1le 6elef ele6h e6l5ehe e8leif
e6l5einh 1elek e8lel 3eleme e6lemen e6lente el5epi e4l3err e6l5ersc
elf2l elg2 e6l5ins ell8er 4e1lo e4l3ofe el8soh el8tent 5eltern e1lu
elut2 \n{e1l"a} \n{e1l"u} em8dei em8meis 4emo emo5s 1emp1f 1empt 1emto
e1mu emurk4 emurks5 \n{e1m"a} en5a6ben en5achs en5ack e1nad en5af
en5all en3alt en1am en3an. en3ant en3anz en1a6p en1ar en1a6s 6e1nat
en3auf en3aus en2ce enda6l end5erf end5erg en8dess 4ene. en5eck
e8neff e6n5ehr e6n5eim en3eis 6enem. 6enen e4nent 4ener. e8nerd
e6n3erf e4nerg 5energi e6n5erla en5ers e6nerst en5erw 6enes e6n5ess
e2nex en3glo 2eni enni6s5 ennos4 enns8 e1no e6nober eno8f en5opf
e4n3ord en8sers ens8kl en1sp ens6por en5t6ag enta5go en8terbu en6tid
3entla ent5ric 5entwic 5entwu 1entz enu5i e3ny en8zan \n{en1"of}
\n{e1n"os} \n{e1n"ug} eo1c e5o6fe e5okk e1on. e3onf e5onk e5onl e5onr
e5opf e5ops e5or. e1ord e1org eo5r6h eo1t e1pa e8pee e6p5e6g ep5ent
e1p2f e1pi 5epid e6pidem e1pl 5epos e6pos. ep4p3a e1pr \n{e1p"a} e1q
e1ra. er5aal 8eraba e5rabel er5a6ben e5rabi er3abs er3ach era5e
era5k6l er3all er3amt e3rand e3rane er3ans e5ranz. e1rap er3arc
e3rari er3a6si e1rat erat3s er3auf e3raum 3erbse er1c e1re 4e5re.
er3eck er5egg er5e2h 2erei e3rei. e8reine er5einr 6eren. e4r3enm
4erer. e6r5erm er5ero er5erst e4r3erz er3ess \n{5erf"ul} er8gan.
5ergebn er2g5h \n{5erg"anz} \n{5erh"ohu} 2e1ri eri5ak e6r5iat e4r3ind
e6r5i6n5i6 er5ins e6r5int er5itio er1kl \n{3erkl"a} \n{5erl"os.}
ermen6s er6nab 3ernst 6e1ro. e1rod er1o2f e1rog 6e3roi ero8ide e3rol
e1rom e1ron e3rop8 e2r1or e1ros e1rot er5ox ersch4 5erstat er6t5ein
er2t1h er5t6her 2e1ru eruf4s3 e4r3uhr er3ums e5rus 5erwerb e1ry er5zwa
er3zwu \n{er"a8m} \n{er5"as} \n{er"o8} \n{e3r"os.} \n{e6r1"u2b} e1sa
esa8b e8sap e6s5a6v e1sc esch4l ese1a es5ebe eserve5 e8sh es5ill
es3int es4kop e2sl eso8b e1sp espei6s5 es2po es2pu 5essenz e6stabs
e6staf e6st5ak est3ar e8stob e1str est5res es3ur e2sz \n{e1s"u} e1ta
et8ag etari5e eta8ta e1te eten6te et5hal e5thel e1ti 1etn e1to e1tr
et3rec e8tscha et8se et6tei et2th et2t1r e1tu etu1s et8zent et8zw
\n{e1t"a} \n{e1t"o} \n{e1t"u} eu1a2 eu1e eue8rei eu5fe euin5 euk2
e1um. eu6nio e5unter eu1o6 eu5p 3europ eu1sp eu5str eu8zo e1v eval6s
eve5r6en ever4i e1w e2wig ex1or 1exp 1extr ey3er. e1z \n{e1"a2}
\n{e5"o8} \n{e1"u} e8\3es \c{e8\9es} fa6ch5i fade8 fa6del fa5el.
fal6lo falt8e fa1na fan4gr 6fanl 6fap far6ba far4bl far6r5a 2f1art
fa1sc fau8str fa3y 2f1b2 6f1c 2f1d 1fe 2f1eck fe6dr feh6lei f6eim
8feins f5eis fel5en 8feltern 8femp fe5rant 4ferd. ferri8 fe8stof
fe6str fe6stum fe8tag fet6ta fex1 2ff f1fa f6f5arm f5fe ffe5in ffe6la
ffe8ler ff1f f1fla ff3lei ff4lie ff8sa ff6s5ta 2f1g2 fgewen6 4f1h 1fi
fid4 fi3ds fieb4 fi1la fi8lei fil4m5a f8in. fi1na 8finf fi8scho fi6u
6f1j 2f1k2 f8lanz fl8e 4f3lein 8flib 4fling f2lix 6f3lon 5flop 1flor
\n{5f8l"ac} \n{3fl"ot} 2f1m 2f1n 1fo foh1 f2on fo6na 2f1op fo5ra
for8mei for8str for8th for6t5r fo5ru 6f5otte 2f1p8 f1q fr6 f5ram
1f8ran f8ra\3 \c{f8ra\9} f8re. frei1 5frei. f3reic f3rest f1rib
8f1ric 6frig 1fris fro8na \n{fr"as5t} 2fs f1sc f2s1er f5str
\n{fs3t"at} 2ft f1tak f1te ft5e6h ftere6 ft1h f1ti f5to f1tr ft5rad
ft1sc ft2so f1tu ftwi3d4 ft1z 1fu 6f5ums 6funf fun4ka fu8\3end
\c{fu8\9end} 6f1v 2f1w 2f1z \n{1f"a} \n{f"a1c} \n{8f"arm} \n{6f"aug}
\n{f"a8\3} \n{\c{f"a8\9}} \n{f"ode3} \n{8f"of} \n{3f"or} \n{1f"u}
\n{f"un4f3u} 1ga ga6bl 6gabw 8gabz g3a4der ga8ho ga5isc 4gak ga1la
6g5amt ga1na gan5erb gan6g5a ga5nj 6ganl 8gansc 6garb 2g1arc 2g1arm
ga5ro 6g3arti ga8sa ga8sc ga6stre 2g1atm 6g5auf gau5fr g5aus 2g1b g5c
6gd g1da 1ge ge1a2 ge6an ge8at. ge1e2 ge6es gef2 8geff ge1g2l ge1im
4g3eise geist5r gel8bra gelt8s \n{ge5l"o} ge8nin gen3k 6g5entf
\n{ge3n"a} ge1or ge1ra ge6rab ger8au \n{8gerh"o} ger8ins ge1ro 6g5erz.
\n{ge1r"a} \n{ge1r"u} ge1s ges2p ge5unt 4g3ex3 2g1f8 2g1g g1ha 6g1hei
5ghel. g5henn 6g1hi g1ho 1ghr \n{g1h"o} 1gi gi5la gi8me. gi1na
4g3ins gi3str g1j 2g1k 8gl. 1glad g5lag glan4z3 1glas 6glass 5glaub
g3lauf 1gle. g5leb 3gleic g3lein 5gleis 1glem 2gler 8g3leu gli8a
g2lie 3glied 1g2lik 1g2lim g6lio 1gloa 5glom 1glon 1glop g1los g4loss
g5luf 1g2ly \n{1gl"u} 2g1m gn8 6gn. 1gna 8gnach 2gnah g1nas g8neu
g2nie g3nis 1gno 8gnot 1go goe1 8gof 2gog 5gogr 6g5oh goni5e 6gonist
go1ra 8gord 2g1p2 g1q 1gr4 g5rahm gra8m gra4s3t 6g1rec gre6ge 4g3reic
g5reit 8grenn gri4e g5riem 5grif 2grig g5ring 6groh 2grot gro6\3
\c{gro6\9} 4grut 2gs gs1ab g5sah gs1ak gs1an gs8and gs1ar gs1au g1sc
gs1ef g5seil gs5ein g2s1er gs1in g2s1o gso2r gs1pr g2s1u 2g1t g3te
g2t1h 1gu gu5as gu2e 2gue. 6gued 4g3uh 8gums 6g5unt gu1s gut3h gu2tu
4g1v 2g1w gy1n g1z \n{1g"a} \n{8g"a8m} \n{6g"arm} \n{1g"o} \n{1g"u}
\n{6g"ub} 1haa hab8r ha8del hade4n 8hae ha5el. haf6tr 2hal. ha1la
hal4b5a 6hale 8han. ha1na han6dr han6ge. 2hani h5anth 6hanz 6harb
h3arbe h3arme ha5ro ha2t1h h1atm hau6san ha8\3 \c{ha8\9} h1b2 h1c h1d
he2bl he3cho h3echt he5d6s 5heft h5e6he. hei8ds h1eif 2hein he3ism
he5ist. heit8s3 hek6ta hel8lau 8helt he6mer 1hemm 6h1emp hen5end
hen5klo hen6tri he2nu 8heo he8q her3ab he5rak her3an 4herap her3au
h3erbi he1ro he8ro8b he4r3um her6z5er he4spe he1st heta6 het5am he5th
heu3sc he1xa hey5e h1f2 h1g hgol8 h1h h1iat hie6r5i hi5kt hil1a2
hil4fr hi5nak hin4ta hi2nu hi5ob hirn5e hir6ner hi1sp hi1th hi5tr
5hitz h1j h6jo h1k2 hlabb4 hla4ga hla6gr h5lai hl8am h1las h1la\3
\c{h1la\9} hl1c h1led h3lein h5ler. h2lif h2lim h8linf hl5int h2lip
h2lit h4lor h3lose \n{h1l"as} hme5e h2nee h2nei hn3eig h2nel hne8n
hne4p3f hn8erz h6netz h2nip h2nit h1nol hn5sp h2nuc h2nud h2nul hoch1
1hoh hoh8lei 2hoi ho4l3ar 1holz h2on ho1ra 6horg 5horn. ho3sl hos1p
ho4spi h1p hpi6 h1q 6hr h1rai h8rank h5raum hr1c hrcre8 h1red h3reg
h8rei. h4r3erb h8rert hrg2 h1ric hr5ins h2rom hr6t5erl hr2t1h hr6t5ra
hr8tri h6rum hr1z hs3ach h6s5amt h1sc h6s5ec h6s5erl hs8erle h4sob
h1sp h8spa\3 \c{h8spa\9} h8spel hs6po h4spun h1str h4s3tum hs3und
\n{h1s"u} h5ta. h5tab ht3ac ht1ak ht3ang h5tanz ht1ar ht1at h5taub
h1te h2t1ec ht3eff ht3ehe h4t3eif h8teim h4t3ein ht3eis h6temp h8tentf
hte8ren \n{h6terf"u} h8tergr h4t3erh h6t5ersc h8terst h8tese h8tess
h2t1eu h4t3ex ht1he ht5hu h1ti ht5rak hts3ah ht1sc ht6sex ht8sk ht8so
h1tu htz8 \n{h5t"um} hub5l hu6b5r huh1l h5uhr. huld5a6 hu8lent
\n{hu8l"a} h5up. h1v h5weib h3weis h1z \n{h"a8kl} \n{h"al8s}
\n{h"ama8tu8} \n{h"a8sche.} \n{h"at1s} \n{h"au4s3c} \n{2h"o.}
\n{2h"oe} \n{8h"oi} \n{h"o6s} \n{h"os5c} \n{h"uhne6} \n{h"ul4s3t}
\n{h"utte8re} i5adn i1af i5ak. i1al. i1al1a i1alb i1ald i5alei i1alf
i1alg i3alh i1alk i1all i1alp i1alr i1als i1alt i1alv i5alw i3alz
i1an. ia5na i3and ian8e ia8ne8b i1ang i3ank i5ann i1ant i1anz i6apo
i1ar. ia6rab i5arr i1as. i1asm i1ass i5ast. i1at. i5ats i1au i5azz
i6b5eig i6b5eis ib2le i4blis i6brig i6b5unt \n{i6b"ub} i1che ich5ei
i6cherb i1chi ich5ins ich1l ich3m ich1n i1cho icht5an icht3r i1chu
ich1w ick6s5te ic5l i1d id3arm 3ideal ide8na 3ideol \n{ide5r"o} i6diot
id5rec id1t ie1a ie6b5ar iebe4s3 ie2bl ieb1r ie8bra ie4bre \n{ie8b"a}
ie2dr ie1e8 ie6f5ad ief5f ie2f1l ie4fro ief1t i1ei ie4l3ec ie8lei
ie4lek i3ell i1en. i1end ien6e i3enf i5enn ien6ne. i1enp i1enr
i5ensa ien8stal i5env i1enz ie5o ier3a4b ie4rap i2ere ie4rec ie6r5ein
ie6r5eis ier8er i3ern. ie8rum ie8rund ie6s5che ie6tau ie8tert ie5the
ie6t5ri i1ett ie5un iex5 2if i1fa if5ang i6fau if1fr if5lac i5f6lie
i1fre ift5a if6t5r ig3art 2ige i8gess ig5he i5gla ig2ni i5go ig3rot
ig3s2p i1ha i8ham i8hans i1he i1hi ih1n ih1r i1hu i8hum ih1w 8i1i ii2s
ii2t i1j i1k i6kak i8kerz i6kes ik4ler i6k5unt 2il i5lac i1lag il3ans
i5las i1lau il6auf i1le ile8h i8lel il2fl il3ipp il6l5enn i1lo ilt8e
i1lu \n{i1l"a} i8mart imb2 i8mele i8mid imme6l5a i1mu \n{i1m"a}
\n{i5m"o} ina5he i1nat in1au inau8s 8ind. in4d3an 5index ind2r 3indus
i5nec i2n1ei i8nerw 3infek 1info 5ingeni ing5s6o 5inhab ini5er. 5inj
\n{in8k"at} in8nan i1no inoi8d in3o4ku in5sau in1sp 5inspe 5instit
5instru ins4ze 5intere 5interv in3the in5t2r i5ny \n{in"a2} \n{i1n"ar}
\n{in1"as} \n{in"o8} \n{in5"od} \n{i1n"os} 2io io1a8 io1c iode4 io2di
ioi8 i1ol. i1om. i1on. i5onb ion2s1 i1ont i5ops i5o8pt i1or.
i3oral io3rat i5orc i1os. i1ot. i1o8x 2ip i1pa i1pi i1p2l i1pr i1q
i1ra ir6bl i1re i1ri ir8me8d ir2m1o2 ir8nak i1ro ir5rho ir6schl
ir6sch5r i5rus i5ry \n{i5r"a} i1sa i8samt i6sar i2s1au i8scheh i8schei
isch5m isch3r \n{isch"a8} is8ele ise3ra i4s3erh is3err isi6de i8sind
is4kop ison5e is6por i8s5tum i5sty \n{i5s"o} i1ta it5ab. i2t1a2m
i8tax i1te i8tersc i1thi i1tho i5thr \n{it8h"a} i1ti i8ti8d iti6kl
itmen4 i1to i8tof it3ran it3rau i1tri itri5o it1sc it2se it5spa it8tru
i1tu it6z5erg it6z1w \n{i1t"a} \n{it"a6r5e} \n{it"at2} \n{it"ats5}
\n{i1t"u} i1u iu6r 2i1v i6vad iva8tin i8vei i6v5ene i8verh i2vob i8vur
i1w iwi2 i5xa i1xe i1z ize8n i8zir i6z5w \n{i"a8m} \n{i1"a6r}
\n{i5"at.} \n{i5"av} \n{i1"o8} \n{i"u8} i6\35ers \c{i6\95ers} ja5la
je2t3r 6jm 5jo jo5as jo1ra jou6l ju5cha jugen4 jugend5 jung5s6 ju1s
\n{3j"a} 1ka 8kachs 8kakz ka1la kal5d kam5t ka1na 2kanl 8kapf ka6pl
ka5r6a 6k3arbe ka1ro kar6p5f 4k3arti 8karz \n{ka1r"a} kasi5e ka6teb
kat8ta kauf6s kau3t2 2k1b 2k1c 4k1d kehr6s kehrs5a 8keic 2k1eig 6k5ein
6k5eis ke6lar ke8leis ke8lo 8kemp k5ente. k3entf 8k5ents 6kentz ke1ra
k5erlau 2k1f8 2k1g 2k1h ki5fl 8kik king6s5 6kinh ki5os ki5sp ki5th
\n{8ki8"o} 2k1k2 kl8 1kla 8klac k5lager kle4br k3leib 3kleid kle5isc
4k3leit k3lek 6k5ler. 5klet 2klic 8klig k2lim k2lin 5klip 5klop k3lor
\n{1kl"a} 2k1m kmani5e kn8 6kner k2ni \n{kn"a8} 1k2o ko1a2 ko6de.
ko1i koi8t ko6min ko1op ko1or ko6pht ko3ra kor6d5er ko5ru ko5t6sc k3ou
3kow 6k5ox 2k1p2 k1q 1kr8 4k3rad 2k1rec 4k3reic kre5ie 2krib 6krig
2krip 6kroba 2ks k1sa k6sab ksal8s k8samt k6san k1sc k2s1ex k5spat
k5spe k8spil ks6por k1spr kst8 k2s1uf 2k1t kta8l kt5a6re k8tein kte8re
k2t1h k8tinf kt3rec kt1s 1ku ku1ch kuck8 k3uhr ku5ie kum2s1 kunfts5
kun2s kunst3 ku8rau ku4ro kurz1 ku1st 4kusti ku1ta ku8\3 \c{ku8\9}
6k1v 2k1w ky5n 2k1z \n{1k"a} \n{k"a4m} \n{4k3"ami} \n{k"ase5} \n{1k"o}
\n{k"o1c} \n{k"o1s} \n{1k"u} \n{k"u1c} \n{k"ur6sc} \n{k"u1s} 1la.
8labf 8labh lab2r 2l1abs lach3r la8dr 5ladu 8ladv 6laff laf5t la2gn
5laken 8lamb la6mer 5lampe. 2l1amt la1na 1land lan4d3a lan4d3r lan4gr
8lanme 6lann 8lanw \n{6lan"a} 8lappa lap8pl lap6pr l8ar. la5ra lar4af
la8rag la8ran la6r5a6s l3arbe la8rei 6larm. la8sa la1sc la8sta lat8i
6l5atm 4lauss 4lauto 1law 2lb l8bab l8bauf l8bede l4b3ins l5blo
lbst5an lbst3e 8lc l1che l8chert l1chi lch3m l5cho lch5w 6ld l4d3ei
ld1re \n{l6d"ub} le2bl le8bre lecht6s5 led2r 6leff le4gas 1lehr lei6br
le8inf 8leinn 5leistu 4lektr le6l5ers lemo2 8lemp l8en. 8lends
6lendun le8nend len8erw 6l5ents 4l3entw 4lentz 8lenzy 8leoz 6lepi
le6pip 8lepo 1ler l6er. 8lerbs 6l5erde le8reis le8rend le4r3er 4l3erg
l8ergr 6lerkl 6l5erzie \n{8ler"o} 8lesel lesi5e le3sko le3tha let1s
5leuc 4leuro leu4s3t le5xe 6lexp l1f 2l1g lgend8 l8gh lglie3 lglied6
6l1h 1li li1ar li1as 2lick li8dr li1en lien6n li8ers li8ert 2lie\3
\c{2lie\9} 3lig li8ga8b li1g6n li1l8a 8limb li1na 4l3indu lings5
4l3inh 6linj link4s3 4linkt 2lint 8linv lion5s6t 4lipp 5lipt 4lisam
livi5e 6l1j 6l1k l8keim l8kj lk2l lko8f lkor8 lk2sa lk2se 6ll l1la
ll3a4be l8labt ll8anl ll1b ll1c ll1d6 l1le l4l3eim l6l5eise ller3a
l4leti l5lip l1lo ll3ort ll5ov ll6spr llte8 l1lu ll3urg \n{l1l"a}
\n{l5l"u} \n{l6l"ub} 2l1m l6m5o6d 6ln l1na l1no 8lobl lo6br 3loch.
l5o4fen 5loge. 5lohn 4l3ohr 1lok l2on 4l3o4per lo1ra 2l1ord 6lorg
4lort lo1ru 1los. lo8sei 3losig lo6ve lowi5 6l1p lp2f l8pho l8pn
lp4s3te l2pt l1q 8l1r 2ls l1sa l6sarm l1sc l8sec l6s5erg l4s3ers l8sh
l5s6la l1sp ls4por ls2pu l1str l8suni \n{l1s"u} 2l1t lt5amp l4t3ein
l5ten l6t5eng l6t5erp l4t3hei lt3her l2t1ho l6t5i6b lti1l \n{l8tr"o}
lt1sc lt6ser lt4s3o lt5ums lu8br lu2dr lu1en8 8lu8fe luft3a luf8tr
lu6g5r 2luh l1uhr lu5it 5luk 2l1umf 2l1umw 1lun 6l5u6nio 4l3unte lu5ol
4lurg 6lurs l3urt lu4sto lu3str lu6st5re lu8su lu6tal lu6t5e6g lu8terg
lu3the lu6t5or lu2t1r lu6\35 \c{lu6\95} l1v lve5r6u 2l1w 1ly lya6
6lymp ly1no l8zess l8zo8f l3zwei lz5wu \n{3l"and} \n{l"a5on}
\n{l"a6sc} \n{l"at1s} \n{5l"auf} \n{2l"aug} \n{l"au6s5c} \n{l"a5v}
\n{l1"ol} \n{1l"os} \n{l"o1\36t} \n{\c{l"o1\96t}} \n{6l1"ube} 1ma
8mabg ma5chan mad2 ma5el 4magg mag8n ma1la ma8lau mal5d 8malde mali5e
malu8 ma8lut 2m1amp 3man mand2 man3ds 8mangr mani5o 8m5anst 6mappa
4m3arbe mar8kr ma1r4o mar8schm 3mas ma1sc \n{ma1t"o} 4m5auf ma5yo 2m1b
mb6r 2m1c 2m1d \n{md6s"a} 1me me1ch me5isc 5meld mel8sa 8memp me5nal
men4dr men8schl men8schw 8mentsp me1ra mer4gl me1ro 3mes me6s5ei me1th
me8\3 \c{me8\9} 2m1f6 2m1g 2m1h 1mi mi1a mi6ale mi1la 2m1imm mi1na
\n{mi5n"u} mi4s3an mit1h mi5t6ra 3mitt mitta8 mi6\35 \c{mi6\95} 6mj
2m1k8 2m1l 2m1m m6mad m6m5ak m8menth m8mentw mme6ra m2mn mm5sp mm5ums
mmut5s \n{m8m"an} m1n8 m5ni 1mo mo5ar mo4dr 8mof mo8gal mo4kla mol5d
m2on mon8do mo4n3od mont8a 6m5ony mopa6 mo1ra mor8d5a mo1sc mo1sp 5mot
moy5 2mp m1pa mpfa6 mpf3l mphe6 m1pi mpin6 m1pl mp2li m2plu mpo8ste
m1pr \n{mpr"a5} mp8th mput6 mpu5ts \n{m1p"o} 8m1q 2m1r 2ms ms5au m1sc
msch4l ms6po m3spri m1str 2m1t mt1ar m8tein m2t1h mt6se \n{mt8s"a}
mu5e 6m5uh mumi1 1mun mun6dr muse5e mu1ta 2m1v mvol2 mvoll3 2m1w 1my
2m1z \n{m"a6kl} \n{1m"an} \n{m"a1s} \n{m"a5tr} \n{m"au4s3c} \n{3m"a\3}
\n{\c{3m"a\9}} \n{m"ob2} \n{6m"ol} \n{1m"u} \n{5m"un} \n{3m"ut} 1na.
n5ab. 8nabn n1abs n1abz \n{na6b"a} na2c nach3e 3nacht 1nae na5el
n1afr 1nag 1n2ah na8ha na8ho 1nai 6nair na4kol n1akt nal1a 8naly 1nama
na4mer na1mn n1amp 8n1amt 5nanc nan6ce n1and n6and. 2n1ang 1nani
1nann n1ans 8nanw 5napf. 1n2ar. na2ra 2n1arc n8ard 1nari n8ark
6n1arm 5n6ars 2n1art n8arv 6natm nat6s5e 1naue 4nauf n3aug 5naui n5auk
na5um 6nausb 6nauto 1nav 2nax 3naz 1na\3 \c{1na\9} n1b2 nbau5s n1c
nche5e nch5m 2n1d nda8d n2d1ak nd5ans n2d1ei nde8lac ndel6sa n8derhi
nde4se nde8stal n2dj ndnis5 n6d5or6t nd3rec nd3rot nd8samt nd6sau
ndt1h n8dumd 1ne ne5as ne2bl 6n5ebn 2nec 5neei ne5en ne1g4l 2negy
4n1ein 8neis 4n3e4lem 8nemb 2n1emp nen1a 6n5energ nen3k 8nentb
4n3en3th 8nentl 8n5entn 8n5ents ne1ra ne5r8al ne8ras 8nerbi 6n5erde.
nere5i6d nerfor6 \n{6n5erh"o} \n{8nerl"o} 2n1err n8ers. 6n5ertra
2n1erz nesi3e net1h neu4ra neu5sc 8neu\3 \c{8neu\9} n1f nf5f nf2l
nflei8 nf5lin nft8st n8g5ac ng5d ng8en nge8ram ngg2 ng1h n6glic ng3rip
ng8ru ng2se4 ng2si n2g1um n1gy \n{n8g"al} n1h nhe6r5e 1ni ni1bl
\n{ni5ch"a} ni8dee n6ie ni1en nie6s5te niet5h ni8etn 4n3i6gel n6ik
ni1la 2n1imp ni5na 2n1ind 8ninf 6n5inh ni8nit 6n5inn 2n1ins 4n1int
n6is ni3str ni1th ni1tr n1j n6ji n8kad nk5ans n1ke n8kerla n1ki nk5inh
\n{n5kl"o} n1k2n n8k5not nk3rot \n{n8kr"u} nk5spo nk6t5r n8kuh
\n{n6k"ub} n5l6 nli4mi n1m nmen4s n1na n8nerg nni5o n1no nn4t3ak nnt1h
nnu1e n1ny \n{n1n"a} \n{n1n"o} \n{n1n"u} no5a no4b3la 4n3obs 2nobt
noche8 no6die no4dis no8ia no5isc 6n5o6leu no4mal noni6er 2n1onk n1ony
4n3o4per 6nopf 6nopti no3ra no4ram nor6da 4n1org 2n1ort n6os no1st
8nost. no8tan no8ter noty6pe 6n5ox n1p2 n1q n1r \n{nr"os3} 6ns n1sac
ns3ang n1sc n8self n8s5erf n8serg n6serk ns5erw n8sint n1s2pe n1spr
n6s5tat. n5s6te. n6stob n1str n1ta n4t3a4go nt5anh nt3ark nt3art
n1te nt3eis nte5n6ar nte8nei nter3a nte6rei nt1ha nt6har n3ther nt5hie
n3thus n1ti nti1c n8tinh nti1t ntlo6b ntmen8 n1to nt3o4ti n1tr ntra5f
ntra5ut nt8rea nt3rec nt8rep n4t3rin nt8rop n4t3rot \n{n4tr"u} nt1s
nts6an nt2sk n1tu nt1z \n{n1t"a} \n{n1t"o} \n{n8t"ol} \n{n1t"u} 1nu
nu1a nu5el nu5en 4n1uhr nu5ie 8numl 6n5ums 6n5umw 2n1und 6nuni 6n5unr
2n1unt 2nup 2nu6r n5uri nu3skr nu5ta n1v 8n1w 1nys n1za n6zab n2z1ar
n6zaus nzi4ga n8zof n6z5unt n1zw n6zwir \n{1n"ac} \n{5n"ae} \n{5n"ai}
\n{n8"al} \n{n"a6m} \n{n"a6re} \n{n5"arz} \n{5n"aus} \n{n1"ol}
\n{1n"ot} \n{n5"oz} \n{5n"u.} \n{6n1"u2b} \n{5n"u\3} \n{\c{5n"u\9}}
o5ab. oa2l o8ala o1a2m o1an ob1ac obe4ra o6berh 5o4bers o4beru
obe6ser 1obj o1bl o2bli ob5sk 3obst. ob8sta obst5re ob5sz o1che
oche8b o8chec o3chi och1l och3m ocho8f o3chro och3to o3chu och1w o1d
o2d1ag od2dr ode5i ode6n5e od1tr o5e6b o5e6der. oe8du o1ef o1e2l
o1e2p o1er. o5e8x o1fa of8fan 1offi of8fin of6f5la o5fla o1fr 8o1g
og2n o1ha o1he o6h5eis o1hi ohl1a oh1le oh4l3er 5ohm. oh2ni o1ho
oh1re oh1ru o1hu oh1w o1hy \n{o1h"a} o5ia o1id. o8idi oi8dr o5ids
o5isch. oiset6 o1ism o3ist. o5i6tu o1j o1k ok2l ok3lau \n{o8kl"a}
1okta o1la old5am old5r o1le ole5in ole1r ole3u ol6gl ol2kl olk4s1
ol8lak ol8lauf. ol6lel ol8less o1lo ol1s ol6sk o1lu oly1e2 5olym
o2mab om6an o8mau ombe4 o8merz om5sp o1mu o8munt \n{o1m"a} \n{o1m"o}
o1na ona8m on1ax on8ent o6n5erb 8oni oni5er. on1k on6n5a6b o1no ono1c
o4nokt 1ons onts8 \n{o1n"a} oo8f 1oog oo2pe oo2sa o1pa 3o4pera o3pfli
opf3lo opf3r o1pi o1pl o2pli o5p6n op8pa op6pl o1pr o3p4ter 1opti
\n{o1p"a} \n{o5p"o} o1q o1ra. o3rad o8radd 1oram o6rang o5ras o8rauf
or5cha or4d3a4m or8dei or8deu 1ordn or4dos o1re o5re. ore2h o8r5ein
ore5isc or6enn or8fla or8fli 1orga 5orgel. or2gl o1ri 5o6rient or8nan
\n{or8n"a} o1ro or1r2h or6t5an or8tau or8tere o1rus o1ry \n{o1r"a}
\n{or1"u2} o1sa osa3i 6ose o8serk o1sk o6ske o6ski os2kl os2ko os2kr
osni5e o2s1o2d o3s4per o4stam o6stau o3stra ost3re osu6 o6s5ur o5s6ze
o1ta ot3auf o6taus o1te o6terw o1th othe5u o2th1r o1ti o1to oto1a
ot1re o1tri o1tro ot1sc o3tsu ot6t5erg ot2t3h ot2t5r \n{ot8t"o} o1tu
ou3e ouf1 ou5f6l o5u6gr ou5ie ou6rar ou1t6a o1v o1wa o1we o6wer. o1wi
owid6 o1wo o5wu o1xe oy5al. oy1e oy1i o5yo o1z oza2r 1o2zea ozo3is
\n{o"o8} o\35elt \c{o\95elt} o\31t \c{o\91t} 3paa pa6ce 5pad pag2 1pak
pa1la pa8na8t pani5el pa4nor pan1s2 1pap pap8s pa8rei par8kr paro8n
par5o6ti part8e 5partei 3partn pas6sep pa4tha 1pau 6paug pau3sc p1b
8p5c 4p1d 1pe 4peic pe5isc 2pek pen3k pen8to8 p8er pe1ra pere6 per5ea
per5eb pe4rem 2perr per8ran 3pers 4persi \n{pe3r"u} pe4sta pet2s
p2f1ec p4fei pf1f pf2l 5pflanz pf8leg pf3lei 2pft pf3ta p1g 1ph 2ph.
2p1haf 6phb 8phd 6p5heit ph5eme 6phg phi6e 8phk 6phn p5holl pht2
ph3tha 4ph3the phu6 6phz pi1en pi5err pi1la pi1na 5pinse pioni8e 1pis
pi1s2k pi1th p1k pl8 5pla p2lau 4plei p3lein 2pler 6p5les 2plig p6lik
6p5ling p2liz plo8min 6p1m p1n 1p2o 8poh 5pol po8lan poly1 po3ny po1ra
2porn por4t3h \n{po5r"o} 5poti p1pa p6p5ei ppe6la pp5f p2p1h p1pi pp1l
ppp6 pp5ren pp1s \n{p5p"o} pr6 3preis 1pres 2p3rig 5prinz 1prob 1prod
5prog pro8pt pro6t5a prote5i 8pro\3 \c{8pro\9} \n{pr"a3l} \n{1pr"as}
\n{pr"ate4} \n{1pr"uf} p5schl 2pst 1p2sy p1t p8to8d pt1s 5p6ty 1pu
pu1b2 2puc pu2dr puf8fr 6p5uh pun8s pu8rei pu5s6h pu1ta p1v p3w 5py
py5l p1z \n{p"a6der} \n{p5"a6m} \n{p"a8nu} \n{8p"ar} \n{p"at5h}
\n{p"at1s} qu6 1qui 8rabk ra6bla 3rable ra2br r1abt 6rabz ra4dan ra2dr
5rafal ra4f3er ra5gla ra2g3n 6raha ral5am 5rald 4ralg ra8lins 2rall
ral5t 8ramei r3anal r6and ran8der ran4dr 8ranf 6ranga 5rangi ran8gli
r3angr rans5pa 8ranw r8anz. ra5or 6rapf ra5pl rap6s5er 2r1arb 1rarh
r1arm ra5ro 2r1art 6r1arz ra8tei ra6t5he 6ratl ra4t3ro r5atta raue4n
6raus. r5austa rau8tel raut5s ray1 r1b rb5lass r6bler rb4lie rbon6n
r8brecht \n{rb6s5t"a} r8ces r1che rch1l rch3m rch3re rch3tr rch1w 8rd
r1da r8dachs r8dap rda5ro rde5ins rdio5 r8dir rd3ost r1dr r8drau 1re.
re1ak 3reakt re3als re6am. re1as 4reben re6bl rech5a r8edi re3er
8reff 3refl 2reh 5reha r4ei. reich6s5 8reier 6reign re5imp 4r3eina
6r3einb 6reing 6r5einn 6reinr 4r3eins r3eint reli3e 8r5elt 6rempf
2remt ren5a6b ren8gl r3enni 1reno 5rente 4r3enth 8rentl 4r3entw 8rentz
ren4zw re1on requi5 1rer rer4bl 6rerbs 4r3erd \n{8rerh"o} 8rerkl
4r3erla \n{8rerl"o} 4r3erns \n{6r5ern"a} rer5o 6r5erreg r5ertr r5erwec
\n{r5er"o} re2sa re8schm 2ress re5u8ni 6rewo 2r1ex r1f r8ferd rf4lie
8r1g r8gah rge4bl rge5na rgest4 rg6ne r2gni2 r8gob r4g3ret rg8sel r1h8
r2hy 5rhyt ri1ar ri5cha rid2g r2ie rieg4s5 ri8ei ri1el ri6ele ri1en
ri3er. ri5ers. ri6fan ri8fer ri8fr 1r2ig ri8kn ri5la \n{rim"a8}
ri1na r8inde rin4ga rin6gr 1rinn 6rinner rino1 r8insp 4rinst
\n{ri1n"a} ri5o6ch ri1o2d ri3o6st 2r1ir r2is ri3sko ri8spr \n{ri8st"u}
ri5sv r2it 6r5i6tal ri5tr ri6ve. 8r1j 6rk r1ke rkehrs5 r1ki r3klin
r1k2n rk3str rk4t3an rk6to r6kuh \n{rk"a4s3t} r1l r5li rline5a 6r1m
r6manl rma4p r4m3aph r8minf r8mob rm5sa 2rn r1na rna8be r5ne rn2ei
r6neif r6nex r6nh rn1k r1no r6n5oc rn1sp \n{r1n"a} \n{r1n"u} ro6bern
6robs ro1ch 3rock. ro5de ro1e 4rofe ro8hert 1rohr ro5id ro1in ro5isc
6rolym r2on 6roog ro6phan r3ort ro1s2p ro5s6w ro4tau ro1tr ro6ts 5rout
r1p rpe8re rp2f r2ps r2pt r1q 2rr r1ra r1re rrer6 rr6hos \n{r5rh"o}
r1ri r1ro rro8f rr8or rror5a r1ru r3ry \n{r1r"a} \n{r1r"o} \n{r1r"u}
2r1s r6sab r4sanf rse6e rse5na r2sh r6ska r6ski rs2kl r8sko r2sl rs2p
r6stauf r8sterw r8stran rswi3d4 r2sz 2r1t rt3art r8taut r5tei rt5eige
r8tepe r4t3erh r8terla r4t3hei r5t6hu r4t3int rt5reif rt1sc rt6ser
rt6s5o rt6s5u rt5und r8turt rube6 ru1en 1r4uf ruf4st ru1ie 2r1umg
2r1uml 2rums run8der run4d5r 6rundz 6runf 8runs 2r1unt 2r1ur r6us
ru6sta ru3str ru6tr 1ruts r1v rven1 rvi2c r1w r1x r1za rz5ac r6z5al
r8z1ar r8zerd r6z5erf rz8erh rz4t3h r8zum \n{r"a4ste} \n{r"au8sc}
\n{r1"of} \n{5r"ohr} \n{r"o5le} \n{3r"oll} \n{5r"omis} \n{r1"or}
\n{r"o2sc} \n{3r"ump} 1sa. 1saa s3a4ben sa2bl 2s1abs 6s1abt 6sabw
3sack. 6s3a4der 1saf sa1fa 4s1aff sa5fr 1sag 1sai sa1i2k1 4s1akt 1sal
sa1la 4s3alpi 6salter salz3a 1sam s5anb san2c 1sand s5angeh 6sanl
2s1ans 6s3antr 8s1anw s1ap s6aph 8sapo sap5p6 s8ar. 2s1arb 3sarg
s1arm sa5ro 2s1art 6s1arz 1sas 1sat sat8a 2s1atl sa8tom 3s8aue s5auff
sau5i s6aur 2s1aus 5s6ause 2s1b2 2sca s4ce 8sch. 3scha. 5schade
3schaf 3schal sch5ame 8schanc 8schb 1sche 6schef 8schex 2schf 2schg
2schh 1schi 2schk 5schlag 5schlu \n{6schm"a\3} \n{\c{6schm"a\9}}
6schna\3 \c{6schna\9} 1scho 6schord 6schp 3schri 8schric 8schrig
8schrou 6schs 2scht sch3ta sch3tr 1schu 8schunt 6schv 2schz \n{5sch"o}
\n{5sch"u} 2sco scre6 6scu 2s1d 1se se5an se1ap se6ben se5ec see5i6g
se3erl 8seff se6han se8hi \n{se8h"o} 6s5eid. 2s1eig s8eil 5sein.
sei5n6e 6s5einh 3s8eit 3sel. se4lar selb4 6s3e4lem se8lerl 2s1emp
sen3ac se5nec 6s5ents 4sentz s8er. se8reim ser5inn \n{8serm"a}
8s5erzi \n{6ser"of} se1um 8sexa 6sexp 2s1f2 sfal8ler 2s3g2 sge5b2 s1h
s8hew 5s6hip 5s4hop 1si 2siat si1b sicht6s 6s5i6dee siege6s5 si1en
si5err si1f2 si1g2n si6g5r si8kau sik1i si4kin si2kl \n{si8k"u} si1la
sil6br si1na 2s1inf sin5gh 2s1inh sinne6s5 2s1ins si5ru si5str 4s1j
s1k2 6sk. 2skau skel6c skelch5 s6kele 1s2ki. 3s4kin. s6kiz s8kj
6skn 2skow 3skrib 3skrip 2sku \n{8sk"u} s1l s8lal slei3t s4low 2s1m
s1n 6sna 6snot 1so so1ch 2s1odo so4dor 6s5o4fen solo3 s2on so5of 4sope
so1ra 2s1ord 4sorga sou5c so3un 4s3ox sp2 8spaa 5spal 1span 2spap
s2pec s4peis 1spek s6perg 4spers s6pes 2s1pf 8sphi \n{1s2ph"a} 1spi
spi4e 6s5pig 6spinse 2spis 2spla 2spol 5s6pom 6s5pos 6spoti 1spra
3s8prec 6spreis 5spring 6sprob 1spru s2pul 1s2pur 6spy \n{5sp"an}
\n{1sp"u} s1q 2s1r 2s1s2 sse8nu ssini6s ssoi6r 2st. 1sta 4stafe 2stag
sta3la 6stale 4stalg 8stalk 8stamt 6st5anf 4stans 6stanw 6starb sta4te
6staus 2stb 6stc 6std 1ste 4steil 3s2tel st3elb 8stemb 6steppi 8stese
8stesse 6stf 2stg 2sth st1ha st3hei s8t1hi st1ho st5hu 1sti sti4el
4stigm sti3na 6stind 4stinf sti8r 2stk 2stl 2stm 1sto 6stoll. 4st3ope
6stopf. 6stord 6stp 5stra. 4strai 3s4tral 6s5traum 3stra\3
\c{3stra\9} 3strec 6s3tref 8streib 5streif 6streno 6stres 6strev
5s6tria 6strig 5strik 8strisi 3s4troa s8troma st5rose 4struf 3strum
\n{6str"ag} 2st1s6 2stt 1stu stu5a 4stuc 2stue 8stun. 2stv 2stw s2tyl
6stz \n{1st"a} \n{8st"ag} \n{1st"o} \n{1st"u} \n{8st"uch} \n{4st"ur.}
1su su2b1 3suc su1e su2fe su8mar 6sumfa 8sumk 2s1unt sup1p2 6s5u6ran
6surte 2s1v 2s1w 1sy 8syl. sy5la syn1 sy2na syne4 s1z s4zend 5s6zene.
8szu \n{1s"a} \n{6s5"and} \n{6s"augi} \n{6s"au\3} \n{\c{6s"au\9}}
\n{5s"om} \n{2s1"u2b} \n{1s"uc} \n{s"u8di} \n{1s"un} \n{5s"u\3}
\n{\c{5s"u\9}} taats3 4tab. taba6k ta8ban tab2l ta6bre 4tabs t3absc
8tabz 6t3acht ta6der 6tadr tad6s tad2t 1tafe4 1tag ta6ga6 ta8gei
tage4s tag6s5t tah8 tahl3 tai6ne. ta5ir. tak8ta tal3au 1tale ta8leng
tal5ert 6t5a6mer 6tamp tampe6 2t1amt tan5d6a tan8dr tands5a tani5e
6tanl 2tanr t3ans 8t5antr tanu6 t5anw 8tanwa tan8zw ta8rau 6tarbe
1tari 2tark 2t1arm ta1ro 2tart t3arti 6tarz ta1sc ta6sien ta8stem
ta8sto t5aufb 4taufn 8taus. 5tause 8tausf 6tausg t5ausl 2t1b2 2t1c
t6chu 2t1d te2am tea4s te8ben 5techn 4teff te4g3re te6hau 2tehe te4hel
2t1ehr te5id. teig5l 6teign tei8gr 1teil 4teinh t5einhe 4teis t5eisen
8teiw te8lam te4lar 4telek 8telem te6man te6n5ag ten8erw ten5k tens4p
ten8tro 4t3entw 8tentz te6pli 5teppi ter5a6b te3ral ter5au 8terbar
t5erbe. 6terben 8terbs 4t3erbt t5erde. ter5ebe ter5ein te8rers terf4
\n{8terh"o} \n{6terkl"a} ter8nor ter6re. t8erscha t5e6sel te8stau
t3euro te1xa tex3e 8texp tex6ta 2t1f2 2t1g2 2th. th6a 5tha. 2thaa
6t1hab 6t5haf t5hah 8thak 3thal. 6thals 6t3hand 2t1hau 1the. 3t4hea
t1heb t5heil t3heit t3helf 1theo 5therap 5therf 6t5herz 1thes 1thet
5thi. 2t1hil t3him 8thir 3this t5hj 2th1l 2th1m th1n t5hob t5hof
4tholz 6thopti 1thr6 4ths t1hum 1thy \n{4t1h"a} \n{2t1h"o} \n{t1h"u}
ti1a2m ti1b tie6fer ti1en ti8gerz tig3l ti8kin ti5lat 1tilg t1ind
tin4k3l ti3spa ti5str 5tite ti5tr ti8vel ti8vr 2t1j 2t1k2 2t1l tl8a
2t1m8 2t1n 3tobe 8tobj to3cha 5tocht 8tock tode4 to8del to8du to1e
6t5o6fen to1in toi6r 5toll. to8mene t2ons 2t1ony to4per 5topf. 6topt
to1ra to1s to6ska tos2l 2toti to1tr t8ou 2t1p2 6t1q tr6 tra5cha
tra8far traf5t 1trag tra6gl tra6gr t3rahm 1trai t6rans tra3sc tra6st
3traue t4re. 2trec t3rech t8reck 6t1red t8ree 4t1reg 3treib 4treif
8t3reis 8trepo tre6t5r t3rev 4t3rez 1trib t6rick tri6er 2trig t8rink
tri6o5d trizi5 tro1a 3troc trocke6 troi8d tro8man. tro3ny 5tropf
6t5rosa t5ro\3 \c{t5ro\9} 5trub 5trup trut5 \n{1tr"ag} \n{6t1r"oh}
\n{5tr"ub} \n{tr"u3bu} \n{t1r"uc} \n{t1r"us} 2ts ts1ab t1sac tsa8d
ts1ak t6s5alt ts1an ts1ar ts3auf t3schr \n{t5sch"a} tse6e tsee5i
tsein6s ts3ent ts1er t8serf t4serk t8sh 5t6sik t4s3int ts5ort.
t5s6por t6sprei t1st t6s5tanz ts1th t6stit t4s3tor 1t2sua t2s1uf
t8sum. t2s1u8n t2s1ur 2t1t tt5eif tte6sa tt1ha tt8ret tt1sc tt8ser
tt5s6z 1tuc tuch5a 1tu1e 6tuh t5uhr tu1i tu6it 1tumh 6t5umr 1tums
8tumt 6tund 6tunf 2t1unt tu5ra tu6rau tu6re. tu4r3er 2t1v 2t1w 1ty1
ty6a ty8la 8tym 6ty6o 2tz tz5al tz1an tz1ar t8zec tzeh6 tzehn5 t6z5ei.
t6zor t4z3um \n{t6z"au} \n{5t"ag} \n{6t"ah} \n{t5"alt} \n{t8"an}
\n{t"are8} \n{8t"a8st} \n{6t"au\3} \n{\c{6t"au\9}} \n{t5"offen}
\n{8t"o8k} \n{1t"on} \n{4t"ub} \n{t6"u5ber.} \n{5t"uch} \n{1t"ur.}
u3al. u5alb u5alf u3alh u5alk u3alp u3an. ua5na u3and u5ans u5ar.
ua6th u1au ua1y u2bab ubi5er. u6b5rit ubs2k \n{u5b"o} \n{u8b"ub} 2uc
u1che u6ch5ec u1chi uch1l uch3m uch5n uch1r uch5to ucht5re u1chu uch1w
uck1a uck5in u1d ud4a u1ei u6ela uene8 u6ep u1er uer1a ue8rerl uer5o
u8esc u2est u8ev u1fa u2f1ei u4f3ent u8ferh uf1fr uf1l uf1ra uf1re
\n{uf1r"a} \n{uf1r"u} uf1s2p uf1st uft1s u8gabt u8gad u6gap ugeb8 u8gn
ugo3s4 u1ha u1he u1hi uh1le u1ho uh1re u1hu uh1w \n{u1h"a} \n{u1h"o}
6ui ui5en u1ig u3ins uin8tes u5isch. u1j 6uk u1ke u1ki u1kl u8klu
u1k6n u5ky u1la uld8se u1le ul8lac ul6lau ul6le6l ul6lo ulni8 u1lo
ulo6i ult6a ult8e u1lu ul2vr \n{u1l"a} \n{u1l"o} 3umfan 5umlau umo8f
um8pho u1mu umu8s \n{u5m"o} u1n1a un2al un6at unau2 6und. 5undein
un4d3um 3undzw \n{und"u8} \n{un8d"ub} une2b un1ec une2h un3eis 3unfal
\n{1unf"a} 5ungea \n{3ungl"u} ung2s1 \n{un8g"a} 1u2nif un4it un8kro
unk5s u1no unpa2 uns2p unvol4 unvoll5 u5os. u1pa u1pi u1p2l u1pr
up4s3t up2t1a u1q u1ra ur5abs ura8d ur5ah u6rak ur3alt u6rana u6r5ans
u8rap ur5a6ri u8ratt u1re ur3eig ur8gri u1ri ur5ins 3urlau urmen6
ur8nan u1ro 3ursac ur8sau ur8sei ur4sk 3urtei u1ru uru5i6 uru6r u1ry
ur2za \n{ur6z"a} \n{ur5"a6m} \n{u5r"o} \n{u1r"u} \n{ur"uck3} u1sa
usa4gi u2s1ar u2s1au u8schec usch5wi u2s1ei use8kel u8sl u4st3a4b
us3tau u3s4ter u2s1uf u8surn ut1ac u1tal uta8m u1tan ut1ar u1tas ut1au
u1te u8teic u4tent u8terf u6terin u4t3hei ut5ho ut1hu u1ti utine5
uti6q u1to uto5c u1tr ut1sa ut1s6p ut6stro u1tu utz5w u1u u1v uve5n
\n{uve3r4"a} u1w u1xe u5ya uy5e6 u1yi u2z1eh u8zerh \n{u5"o} u\3e6n
\c{u\9e6n} u\3en5e \c{u\9en5e} 8vanb 6vang 6varb var8d va6t5a va8tei
va2t1r 2v1b 6v5c 6vd 1ve 6ve5g6 ver1 ver5b verb8l ve2re2 verg8 ve2ru8
ve1s ve2s3p ve3xe 2v1f 2v1g 6v5h vi6el vie6w5 vi1g4 vi8leh vil6le.
8vint vi1ru vi1tr 2v1k 2v1l 2v1m 4v5n 8vo8f voi6le vol8lend vol8li
v2or1 vo2re vo8rin vo2ro 2v1p 8vra v6re 2v1s 2v1t 2v1v 4v3w 2v1z
waffe8 wa6g5n 1wah wah8n wa5la wal8din wal6ta wan4dr 5ware wa8ru
war4za 1was w5c w1d 5wech we6fl 1weg we8geng weg5h weg3l we2g1r
weh6r5er 5weise weit3r wel2t welt3r we6rat 8werc 5werdu wer4fl 5werk.
wer4ka wer8ku wer4ta wer8term we2sp we8stend we6steu we8str
\n{we8st"o} wet8ta wich6s5t 1wid wi2dr wiede4 wieder5 wik6 wim6ma
win4d3r 5wirt wisch5l 1wj 6wk 2w1l 8w1n wo1c woche6 wol6f wor6t5r 6ws2
w1sk 6w5t 5wunde. wun6gr wu1sc wu2t1 6w5w wy5a \n{w"arme5} \n{w"a1sc}
1xag x1ak x3a4men 8xamt x1an 8x1b x1c 1xe. x3e4g 1xen xe1ro x1erz
1xes 8xf x1g 8x1h 1xi 8xid xi8so 4xiste x1k 6x1l x1m 8xn 1xo 8x5o6d
8x3p2 x1r x1s6 8x1t x6tak x8terf x2t1h 1xu xu1e x5ul 6x3w x1z 5ya.
y5an. y5ank y1b y1c y6cha y4chia y1d yen6n y5ern y1g y5h y5in y1j
y1k2 y1lak yl1al yla8m y5lax y1le y1lo y5lu y8mn ym1p2 y3mu y1na yno2d
yn1t y1on. y1o4p y5ou ypo1 y1pr y8ps y1r yri3e yr1r2 y1s ys5iat ys8ty
y1t y3w y1z \n{y"a8m} z5a6b zab5l 8za6d 1zah za5is 4z3ak 6z1am 5zange.
8zanl 2z1ara 6z5as z5auf 3zaun 2z1b 6z1c 6z1d 1ze ze4dik 4z3eff 8zein
zei4ta zei8ters ze6la ze8lec zel8th 4zemp 6z5engel zen8zin \n{8zerg"a}
zer8i ze1ro zers8 zerta8 zer8tab zer8tag 8zerz ze8ste zeu6gr 2z1ex
2z1f8 z1g 4z1h 1zi zi1en zi5es. 4z3imp zi1na 6z5inf 6z5inni zin6s5er
8zinsuf zist5r zi5th zi1tr 6z1j 2z1k 2z1l 2z1m 6z1n 1zo zo6gl 4z3oh
zo1on zor6na8 4z1p z5q 6z1r 2z1s8 2z1t z4t3end z4t3hei z8thi 1zu zu3al
zu1b4 zu1f2 6z5uhr zun2a 8zunem zunf8 8zungl zu1o zup8fi zu1s8 zu1z
2z1v zw8 z1wal 5zweck zwei3s z1wel z1wer z6werg 8z5wes 1zwi zwi1s
6z1wo 1zy 2z1z zz8a zzi1s \n{1z"a} \n{1z"o} \n{6z"ol.} \n{z"o1le}
\n{1z"u} \n{2z1"u2b} \n{"a1a6} \n{"ab1l} \n{"a1che} \n{"a3chi}
\n{"ach8sc} \n{"ach8sp} \n{"a5chu} \n{"ack5a} \n{"ad1a} \n{"ad5era}
\n{"a6d5ia} \n{"a1e} \n{"a5fa} \n{"af1l} \n{"aft6s} \n{"ag1h}
\n{"ag3le} \n{"a6g5nan} \n{"ag5str} \n{"a1he} \n{"a1hi} \n{"ah1le}
\n{"ah5ne} \n{1"ahnl} \n{"ah1re} \n{"ah5ri} \n{"ah1ru} \n{"a1hu}
\n{"ah1w} \n{6"ai} \n{"a1isc} \n{"a6ische} \n{"a5ism} \n{"a5j}
\n{"a1k} \n{"al1c} \n{"a1le} \n{"a8lei} \n{"al6schl} \n{"ami1e}
\n{"am8n} \n{"am8s} \n{"a5na} \n{5"anderu} \n{"ane5i8} \n{"ang3l}
\n{"ank5l} \n{"a1no} \n{"an6s5c} \n{"a1pa} \n{"ap6s5c} \n{3"aq}
\n{"ar1c} \n{"a1re} \n{"are8m} \n{5"argern} \n{"ar6gl} \n{"a1ri}
\n{3"armel} \n{"a1ro} \n{"art6s5} \n{"a1ru} \n{3"arztl} \n{"a5r"o}
\n{"a6s5chen} \n{"asen8s} \n{"as1th} \n{"ata8b} \n{"a1te} \n{"ateri4}
\n{"ater5it} \n{"a6thy} \n{"a1ti} \n{3"atk} \n{"a1to} \n{"at8schl}
\n{"ats1p} \n{"a5tu} \n{"aub1l} \n{"au1e} \n{1"aug} \n{"au8ga}
\n{"au5i} \n{"a1um.} \n{"a1us.} \n{1"au\3} \n{\c{1"au\9}} \n{"a1z}
\n{"o1b} \n{"o1che} \n{"o5chi} \n{"och8stei} \n{"och8str} \n{"ocht6}
\n{5"o6dem} \n{5"offn} \n{"o1he} \n{"oh1l8} \n{"oh1re} \n{"o1hu}
\n{"o1is} \n{"o1ke} \n{1"o2ko} \n{1"ol.} \n{"ol6k5l} \n{"ol8pl}
\n{"o1mu} \n{"o5na} \n{"onig6s3} \n{"o1no} \n{"o5o6t} \n{"opf3l}
\n{"op6s5c} \n{"o1re} \n{"or8gli} \n{"o1ri} \n{"or8tr} \n{"o1ru}
\n{5"osterr} \n{"o1te} \n{"o5th} \n{"o1ti} \n{"o1tu} \n{"o1v} \n{"o1w}
\n{"owe8} \n{"o2z} \n{"ub6e2} \n{3"u4ber1} \n{"ub1l} \n{"ub1r}
\n{5"u2bu} \n{"u1che} \n{"u1chi} \n{"u8ch3l} \n{"uch6s5c} \n{"u8ck}
\n{"uck1a} \n{"uck5ers} \n{"ud1a2} \n{"u6deu} \n{"udi8t} \n{"u2d1o4}
\n{"ud5s6} \n{"uge4l5a} \n{"ug1l} \n{"uh5a} \n{"u1he} \n{"u8heh}
\n{"u6h5erk} \n{"uh1le} \n{"uh1re} \n{"uh1ru} \n{"u1hu} \n{"uh1w}
\n{"u3k} \n{"u1le} \n{"ul4l5a} \n{"ul8lo} \n{"ul4ps} \n{"ul6s5c}
\n{"u1lu} \n{"un8da} \n{"un8fei} \n{"unk5l} \n{"un8za} \n{"un6zw}
\n{"u5pi} \n{"u1re} \n{"u8rei} \n{"ur8fl} \n{"ur8fr} \n{"ur8geng}
\n{"u1ri} \n{"u1ro} \n{"ur8sta} \n{"ur8ster} \n{"u1ru} \n{"use8n}
\n{"u8sta} \n{"u8stes} \n{"u6s5tete} \n{"u3ta} \n{"u1te} \n{"u1ti}
\n{"ut8tr} \n{"u1tu} \n{"ut8zei} \n{"u1v} \31a8 \c{\91a8} 5\3a.
\c{5\9a.} \38as \c{\98as} \31b8 \c{\91b8} \31c \c{\91c} \31d \c{\91d}
1\3e \c{1\9e} \35ec \c{\95ec} 8\3e8g \c{8\9e8g} 8\3e8h \c{8\9e8h}
2\31ei \c{2\91ei} 8\3em \c{8\9em} \31f8 \c{\91f8} \31g \c{\91g} \31h
\c{\91h} 1\3i \c{1\9i} \31k \c{\91k} \31l \c{\91l} \31m \c{\91m}
\3mana8 \c{\9mana8} \31n \c{\91n} \31o \c{\91o} \31p8 \c{\91p8} \35q
\c{\95q} \31r \c{\91r} \31s2 \c{\91s2} \3st8 \c{\9st8} \31ta \c{\91ta}
\31te \c{\91te} \3t3hei \c{\9t3hei} \31ti \c{\91ti} \35to \c{\95to}
\31tr \c{\91tr} 1\3u8 \c{1\9u8} 6\35um \c{6\95um} \31v \c{\91v} \31w
\c{\91w} \31z \c{\91z}
}%
\endgroup
\relax\endinput
%
% -----------------------------------------------------------------
%
% =============== Additional Documentation ===============
%
%
% Older Versions of German Hyphenation Patterns:
% ----------------------------------------------
%
% All older versions of `ghyphen.tex' distributed as
%
% ghyphen.tex/germhyph.tex as of 1986/11/01
% ghyphen.min/ghyphen.max as of 1988/10/10
% ghyphen3.tex as of 1990/09/27 & 1991/02/13
% ghyph31.tex as of 1994/02/13
%
% are out of date and it is recommended to replace them
% with the new version `dehypht.tex' as of 1999/03/03.
%
% If you are using `ghyphen.min' (a minor version of `ghyphen')
% because of limited trie memory space, try this version and if
% the space is exceeded get a newer TeX implementation with
% larger or configurable trie memory sizes.
%
%
%
% Trie Memory Requirements/Space for Hyphenation Patterns:
% --------------------------------------------------------
%
% To load this set of german hyphenation patterns the parameters
% of TeX has to have at least these values:
%
% TeX 3.x:
% IniTeX: trie_size >= 9733 trie_op_size >= 207
% VirTeX: trie_size >= 8375 trie_op_size >= 207
%
% TeX 2.x:
% IniTeX: trie_size >= 8675 trie_op_size >= 198
% VirTeX: trie_size >= 7560 trie_op_size >= 198
%
% If you want to load more than one set of hyphenation patterns
% (in TeX 3.x), the parameters have to be set to a value larger
% than or equal to the sum of all required values for each set.
%
%
% Setting Trie Memory Parameters:
% -------------------------------
%
% Some implementations allow the user to change the default value
% of a set of the internal TeX parameters including the trie memory
% size parameter specifying the used memory for the hyphenation
% patterns.
%
% Web2c 7.x (Source), teTeX 0.9 (Unix, Amiga), fpTeX (Win32)
% and newer:
% The used memory size of the true is usually set high enough.
% If needed set the size of the trie using the keyword `trie_size'
% in the configuration file `texmf/web2c/texmf.cnf'. For details
% see the included documentation.
%
% emTeX (OS/2, MS-DOS, Windows 3.x/9x/NT):
% You can set the used memory size of the trie using the
% `-mt<number>' option on the command line or in the
% TEXOPTIONS environment variable.
%
% PasTeX (Amiga):
% The values for the parameters can be set using the keywords
% `triesize', `itriesize' and `trieopsize' in the configuration
% file.
%
% others (binaries only):
% See the documentation of the implementation if it is possible
% and how to change these values without recompilation.
%
% others (with sources)
% If the trie memory is too small, you have to recompile TeX
% using larger values for `trie_size' and `trie_op_size'.
% Modify the change file `tex.ch' and recompile TeX.
% For details see the documentation included in the sources.
%
%
%
% Necessary Settings in TeX macro files:
% --------------------------------------
%
% \lefthyphenmin, \righthyphenmin:
% You can set both parameters to 2.
%
% \lccode <char>:
% To get correct hyphenation points within words containing
% umlauts or \ss, it's necessary to assign values > 0 to the
% appropriate \lccode <char> positions.
%
% These changes are _not_ done when reading this file and have to
% be included in the language switching mechanism as is done in,
% for example, `german.sty' (\lccode change for ^^Y = \ss in OT1,
% \left-/\righthyphenmin settings).
%
%
%% \CharacterTable
%% {Upper-case \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
%% Lower-case \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
%% Digits \0\1\2\3\4\5\6\7\8\9
%% Exclamation \! Double quote \" Hash (number) \#
%% Dollar \$ Percent \% Ampersand \&
%% Acute accent \' Left paren \( Right paren \)
%% Asterisk \* Plus \+ Comma \,
%% Minus \- Point \. Solidus \/
%% Colon \: Semicolon \; Less than \<
%% Equals \= Greater than \> Question mark \?
%% Commercial at \@ Left bracket \[ Backslash \\
%% Right bracket \] Circumflex \^ Underscore \_
%% Grave accent \` Left brace \{ Vertical bar \|
%% Right brace \} Tilde \~}
%%
\endinput
%%
%% End of file `dehypht.tex'.

1104
src/bootsupport/modules/textutil/eshyph_vo.tex

File diff suppressed because it is too large Load Diff

1122
src/bootsupport/modules/textutil/expander-1.3.1.tm

File diff suppressed because it is too large Load Diff

223
src/bootsupport/modules/textutil/ithyph.tex

@ -0,0 +1,223 @@
%%%%%%%%%%%%%%%%%%%% file ithyph.tex
%%%%%%%%%%%%%%%%%%%%%%%%%%% file ithyph.tex %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Prepared by Claudio Beccari e-mail beccari@polito.it
%
% Dipartimento di Elettronica
% Politecnico di Torino
% Corso Duca degli Abruzzi, 24
% 10129 TORINO
%
% Copyright 1998, 2001 Claudio Beccari
%
% This program can be redistributed and/or modified under the terms
% of the LaTeX Project Public License Distributed from CTAN
% archives in directory macros/latex/base/lppl.txt; either
% version 1 of the License, or any later version.
%
% \versionnumber{4.8d} \versiondate{2001/11/21}
%
% These hyphenation patterns for the Italian language are supposed to comply
% with the Reccomendation UNI 6461 on hyphenation issued by the Italian
% Standards Institution (Ente Nazionale di Unificazione UNI). No guarantee
% or declaration of fitness to any particular purpose is given and any
% liability is disclaimed.
%
% See comments and loading instructions at the end of the file after the
% \endinput line
%
{\lccode`\'=`\' % Apostrophe has its own lccode so that it is treated
% as a letter
%>> 1998/04/14 inserted grouping
%
%\lccode23=23 % Compound word mark is a letter in encoding T1
%\def\W{^^W} % ^^W =\char23 = \char"17 =\char'27
%
\patterns{
.a3p2n % After the Garzanti dictionary: a-pnea, a-pnoi-co,...
.anti1 .anti3m2n
.bio1
.ca4p3s
.circu2m1
.di2s3cine
%.e2x
.fran2k3
.free3
.narco1
.opto1
.orto3p2
.para1
.poli3p2
.pre1
.p2s
%.ri1a2 .ri1e2 .re1i2 .ri1o2 .ri1u2
.sha2re3
.tran2s3c .tran2s3d .tran2s3f .tran2s3l .tran2s3n .tran2s3p .tran2s3r .tran2s3t
.su2b3lu .su2b3r
.wa2g3n
.wel2t1
a1ia a1ie a1io a1iu a1uo a1ya 2at.
e1iu e2w
o1ia o1ie o1io o1iu
%u1u
%
%1\W0a2 1\W0e2 1\W0i2 1\W0o2 1\W0u2
'2
1b 2bb 2bc 2bd 2bf 2bm 2bn 2bp 2bs 2bt 2bv
b2l b2r 2b. 2b'. 2b''
1c 2cb 2cc 2cd 2cf 2ck 2cm 2cn 2cq 2cs 2ct 2cz
2chh c2h 2chb ch2r 2chn c2l c2r 2c. 2c'. 2c'' .c2
1d 2db 2dd 2dg 2dl 2dm 2dn 2dp d2r 2ds 2dt 2dv 2dw
2d. 2d'. 2d'' .d2
1f 2fb 2fg 2ff 2fn f2l f2r 2fs 2ft 2f. 2f'. 2f''
1g 2gb 2gd 2gf 2gg g2h g2l 2gm g2n 2gp g2r 2gs 2gt
2gv 2gw 2gz 2gh2t 2g. 2g'. 2g''
1h 2hb 2hd 2hh hi3p2n h2l 2hm 2hn 2hr 2hv 2h. 2h'. 2h''
1j 2j. 2j'. 2j''
1k 2kg 2kf k2h 2kk k2l 2km k2r 2ks 2kt 2k. 2k'. 2k''
1l 2lb 2lc 2ld 2l3f2 2lg l2h 2lk 2ll 2lm 2ln 2lp
2lq 2lr 2ls 2lt 2lv 2lw 2lz 2l. 2l'. 2l''
1m 2mb 2mc 2mf 2ml 2mm 2mn 2mp 2mq 2mr 2ms 2mt 2mv 2mw
2m. 2m'. 2m''
1n 2nb 2nc 2nd 2nf 2ng 2nk 2nl 2nm 2nn 2np 2nq 2nr
2ns 2nt 2nv 2nz n2g3n 2nheit. 2n. 2n' 2n''
1p 2pd p2h p2l 2pn 3p2ne 2pp p2r 2ps 3p2sic 2pt 2pz 2p. 2p'. 2p''
1q 2qq 2q. 2q'. 2q''
1r 2rb 2rc 2rd 2rf r2h 2rg 2rk 2rl 2rm 2rn 2rp
2rq 2rr 2rs 2rt rt2s3 2rv 2rx 2rw 2rz 2r. 2r'. 2r''
1s2 2shm 2s3s s4s3m 2s3p2n 2stb 2stc 2std 2stf 2stg 2stm 2stn
2stp 2sts 2stt 2stv 2sz 4s. 4s'. 4s''
1t 2tb 2tc 2td 2tf 2tg t2h t2l 2tm 2tn 2tp t2r 2ts
3t2sch 2tt 2tv 2tw t2z 2tzk 2tzs 2t. 2t'. 2t''
1v 2vc v2l v2r 2vv 2v. 2v'. 2v''
1w w2h wa2r 2w1y 2w. 2w'. 2w''
1x 2xt 2xw 2x. 2x'. 2x''
y1ou y1i
1z 2zb 2zd 2zl 2zn 2zp 2zt 2zs 2zv 2zz 2z. 2z'. 2z'' .z2
}} % Pattern end
\endinput
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Information %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
LOADING THESE PATTERNS
These patterns, as well as those for any other language, do not become
effective until they are loaded in a special form into a format file; this
task is performed by the TeX initializer; any TeX system has its own
initializer with its special way of being activated. Before loading these
patterns, then, it is necessary to read very carefully the instructions that
come with your TeX system.
Here I describe how to load the patterns with the freeware TeX system named
MiKTeX version 2.x for Windows 9x, NT, 2000, XP; with minor changes the
whole procedure is applicable with other TeX systems, but the details must
be deduced from your TeX system documentation at the section/chapter "How to
build or to rebuild a format file".
With MikTeX:
a) copy this file and replace the existing file ithyph.tex in the directory
\texmf\tex\generic\hyphen if the existing one has an older version date
and number.
b) select Start|Programs|MiKTeX|MiKTeX options.
c) in the Language tab add a check mark to the line concerning the Italian
language.
d) in the Geneal tab click "Update format files".
e) That's all!
For the activation of these patterns with the specific Italian typesetting
features, use the babel package as this:
\documentclass{article} % Or whatever other class
\usepackage[italian]{babel}
...
\begin{document}
...
\end{document}
ON ITALIAN HYPHENATION
I have been working on patterns for the Italian language since 1987; in 1992
I published
C. Beccari, "Computer aided hyphenation for Italian and Modern
Latin", TUG vol. 13, n. 1, pp. 23-33 (1992)
which contained a set of patterns that allowed hyphenation for both Italian
and Latin; a slightly modified version of the patterns published in the
above paper is contained in LAHYPH.TEX available on the CTAN archives.
From the above patterns I extracted the minimum set necessary for
hyphenating Italian that was made available on the CTAN archives with the
name ITHYPH.tex the version number 3.5 on the 16th of August 1994.
The original pattern set required 37 ops; being interested in a local
version of TeX/LaTeX capable of dealing with half a dozen languages, I
wanted to reduce memory occupation and therefore the number of ops.
Th new version (4.0 released in 1996) of ITHYPH.TEX is much simpler than
version 3.5 and requires just 29 ops while it retains all the power of
version 3.5; it contains many more new patterns that allow to hyphenate
unusual words that generally have a root borrowed from a foreign language.
Updated versions 4.x contain minor additions and the number of ops is
increased to 30 (version 4.7 of 1998/06/01).
This new pattern set has been tested with the same set of difficult Italian
words that was used to test version 3.5 and it yields the same results (a
part a minor change that was deliberately introduced so as to reduce the
typographical hyphenation with hyathi, since hyphenated hyathi are not
appreciated by Italian readers). A new enlarged word set for testing
purposes gets correct hyphen points that were missed or wrongly placed with
version 3.5, although no error had been reported, because such words are of
very specialized nature and are seldom used.
As the previous version, this new set of patterns does not contain any
accented character so that the hyphenation algorithm behaves properly in
both cases, that is with cm and with dc/ec fonts. With LaTeXe terminology
the difference is between OT1 and T1 encodings; with the former encoding
fonts do not contain accented characters, while with the latter accented
characters are present and sequences such as \`a map directly to slot "E0
that contains "agrave".
Of course if you use dc/ec fonts (or any other real or virtual font with T1
encoding) you get the full power of the hyphenation algorithm, while if you
use cm fonts (or any other real or virtual font with OT1 encoding) you miss
some possible break points; this is not a big inconvenience in Italian
because:
1) The Regulation UNI 6015 on accents specifies that compulsory accents
appear only on the ending vowel of oxitone words; this means that it is
almost indifferent to have or to miss the dc/ec fonts because the only
difference consists in how TeX evaluates the end of the word; in practice
if you have these special facilities you get "qua-li-t\`a", while if you
miss them, you get "qua-lit\`a" (assuming that \righthyphenmin > 1).
2) Optional accents are so rare in Italian, that if you absolutely want to
use them in those rare instances, and you miss the T1 encoding
facilities, you should also provide explicit discretionary hyphens as in
"s\'e\-gui\-to".
There is no explicit hyphenation exception list because these patterns
proved to hyphenate correctly a very large set of words suitably chosen in
order to test them in the most heavy circumstances; these patterns were used
in the preparation of a number of books and no errors were discovered.
Nevertheless if you frequently use technical terms that you want hyphenated
differently from what is normally done (for example if you prefer
etymological hyphenation of prefixed and/or suffixed words) you should
insert a specific hyphenation list in the preamble of your document, for
example:
\hyphenation{su-per-in-dut-to-re su-per-in-dut-to-ri}
Should you find any word that gets hyphenated in a wrong way, please, AFTER
CHECKING ON A RELIABLE MODERN DICTIONARY, report to the author, preferably
by e-mail.
Happy multilingual typesetting !

180
src/bootsupport/modules/textutil/patch-0.1.tm

@ -0,0 +1,180 @@
# patch.tcl --
#
# Application of a diff -ruN patch to a directory tree.
#
# Copyright (c) 2019 Christian Gollwitzer <auriocus@gmx.de>
# with tweaks by Andreas Kupries
# - Factored patch parsing into a helper
# - Replaced `puts` with report callback.
package require Tcl 8.5
package provide textutil::patch 0.1
# # ## ### ##### ######## ############# #####################
namespace eval ::textutil::patch {
namespace export apply
namespace ensemble create
}
# # ## ### ##### ######## ############# #####################
proc ::textutil::patch::apply {dir striplevel patch reportcmd} {
set patchdict [Parse $dir $striplevel $patch]
# Apply, now that we have parsed the patch.
dict for {fn hunks} $patchdict {
Report apply $fn
if {[catch {open $fn} fd]} {
set orig {}
} else {
set orig [split [read $fd] \n]
}
close $fd
set patched $orig
set fail false
set already_applied false
set hunknr 1
foreach hunk $hunks {
dict with hunk {
set oldend [expr {$oldstart+[llength $oldcode]-1}]
set newend [expr {$newstart+[llength $newcode]-1}]
# check if the hunk matches
set origcode [lrange $orig $oldstart $oldend]
if {$origcode ne $oldcode} {
set fail true
# check if the patch is already applied
set origcode_applied [lrange $orig $newstart $newend]
if {$origcode_applied eq $newcode} {
set already_applied true
Report fail-already $fn $hunknr
} else {
Report fail $fn $hunknr $oldcode $origcode
}
break
}
# apply patch
set patched [list \
{*}[lrange $patched 0 $newstart-1] \
{*}$newcode \
{*}[lrange $orig $oldend+1 end]]
}
incr hunknr
}
if {!$fail} {
# success - write the result back
set fd [open $fn w]
puts -nonewline $fd [join $patched \n]
close $fd
}
}
return
}
# # ## ### ##### ######## ############# #####################
proc ::textutil::patch::Report args {
upvar 1 reportcmd reportcmd
uplevel #0 [list {*}$reportcmd {*}$args]
##
# apply $fname
# fail-already $fname $hunkno
# fail $fname $hunkno $expected $seen
##
}
proc ::textutil::patch::Parse {dir striplevel patch} {
set patchlines [split $patch \n]
set inhunk false
set oldcode {}
set newcode {}
set n [llength $patchlines]
set patchdict {}
for {set lineidx 0} {$lineidx < $n} {incr lineidx} {
set line [lindex $patchlines $lineidx]
if {[string match ---* $line]} {
# a diff block starts. Current line should be
# --- oldfile date time TZ
# Next line should be
# +++ newfile date time TZ
set in $line
incr lineidx
set out [lindex $patchlines $lineidx]
if {![string match ---* $in] || ![string match +++* $out]} {
#puts $in
#puts $out
return -code error "Patch not in unified diff format, line $lineidx $in $out"
}
# the quoting is compatible with list
lassign $in -> oldfile
lassign $out -> newfile
set fntopatch [file join $dir {*}[lrange [file split $oldfile] $striplevel end]]
set inhunk false
#puts "Found diffline for $fntopatch"
continue
}
# state machine for parsing the hunks
set typechar [string index $line 0]
set codeline [string range $line 1 end]
switch $typechar {
@ {
if {![regexp {@@\s+\-(\d+),(\d+)\s+\+(\d+),(\d+)\s+@@} $line \
-> oldstart oldlen newstart newlen]} {
return code -error "Erroneous hunk in line $lindeidx, $line"
}
# adjust line numbers for 0-based indexing
incr oldstart -1
incr newstart -1
#puts "New hunk"
set newcode {}
set oldcode {}
set inhunk true
}
- { # line only in old code
if {$inhunk} {
lappend oldcode $codeline
}
}
+ { # line only in new code
if {$inhunk} {
lappend newcode $codeline
}
}
" " { # common line
if {$inhunk} {
lappend oldcode $codeline
lappend newcode $codeline
}
}
default {
# puts "Junk: $codeline";
continue
}
}
# test if the hunk is complete
if {[llength $oldcode]==$oldlen && [llength $newcode]==$newlen} {
set hunk [dict create \
oldcode $oldcode \
newcode $newcode \
oldstart $oldstart \
newstart $newstart]
#puts "hunk complete: $hunk"
set inhunk false
dict lappend patchdict $fntopatch $hunk
}
}
return $patchdict
}
# # ## ### ##### ######## ############# #####################
return

91
src/bootsupport/modules/textutil/repeat-0.7.tm

@ -0,0 +1,91 @@
# repeat.tcl --
#
# Emulation of string repeat for older
# revisions of Tcl.
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: repeat.tcl,v 1.1 2006/04/21 04:42:28 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil::repeat {}
# ### ### ### ######### ######### #########
namespace eval ::textutil::repeat {
variable HaveBuiltin [expr {![catch {string repeat a 1}]}]
}
if {0} {
# Problems with the deactivated code:
# - Linear in 'num'.
# - Tests for 'string repeat' in every call!
# (Ok, just the variable, still a test every call)
# - Fails for 'num == 0' because of undefined 'str'.
proc textutil::repeat::StrRepeat { char num } {
variable HaveBuiltin
if { $HaveBuiltin == 0 } then {
for { set i 0 } { $i < $num } { incr i } {
append str $char
}
} else {
set str [ string repeat $char $num ]
}
return $str
}
}
if {$::textutil::repeat::HaveBuiltin} {
proc ::textutil::repeat::strRepeat {char num} {
return [string repeat $char $num]
}
proc ::textutil::repeat::blank {n} {
return [string repeat " " $n]
}
} else {
proc ::textutil::repeat::strRepeat {char num} {
if {$num <= 0} {
# No replication required
return ""
} elseif {$num == 1} {
# Quick exit for recursion
return $char
} elseif {$num == 2} {
# Another quick exit for recursion
return $char$char
} elseif {0 == ($num % 2)} {
# Halving the problem results in O (log n) complexity.
set result [strRepeat $char [expr {$num / 2}]]
return "$result$result"
} else {
# Uneven length, reduce problem by one
return "$char[strRepeat $char [incr num -1]]"
}
}
proc ::textutil::repeat::blank {n} {
return [strRepeat " " $n]
}
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::repeat {
namespace export strRepeat blank
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::repeat 0.7

176
src/bootsupport/modules/textutil/split-0.8.tm

@ -0,0 +1,176 @@
# split.tcl --
#
# Various ways of splitting a string.
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2001 by Reinhard Max <max@suse.de>
# Copyright (c) 2003 by Pat Thoyts <patthoyts@users.sourceforge.net>
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: split.tcl,v 1.7 2006/04/21 04:42:28 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil::split {}
########################################################################
# This one was written by Bob Techentin (RWT in Tcl'ers Wiki):
# http://www.techentin.net
# mailto:techentin.robert@mayo.edu
#
# Later, he send me an email stated that I can use it anywhere, because
# no copyright was added, so the code is defacto in the public domain.
#
# You can found it in the Tcl'ers Wiki here:
# http://mini.net/cgi-bin/wikit/460.html
#
# Bob wrote:
# If you need to split string into list using some more complicated rule
# than builtin split command allows, use following function. It mimics
# Perl split operator which allows regexp as element separator, but,
# like builtin split, it expects string to split as first arg and regexp
# as second (optional) By default, it splits by any amount of whitespace.
# Note that if you add parenthesis into regexp, parenthesed part of separator
# would be added into list as additional element. Just like in Perl. -- cary
#
# Speed improvement by Reinhard Max:
# Instead of repeatedly copying around the not yet matched part of the
# string, I use [regexp]'s -start option to restrict the match to that
# part. This reduces the complexity from something like O(n^1.5) to
# O(n). My test case for that was:
#
# foreach i {1 10 100 1000 10000} {
# set s [string repeat x $i]
# puts [time {splitx $s .}]
# }
#
if {[package vsatisfies [package provide Tcl] 8.3]} {
proc ::textutil::split::splitx {str {regexp {[\t \r\n]+}}} {
# Bugfix 476988
if {[string length $str] == 0} {
return {}
}
if {[string length $regexp] == 0} {
return [::split $str ""]
}
if {[regexp $regexp {}]} {
return -code error \
"splitting on regexp \"$regexp\" would cause infinite loop"
}
set list {}
set start 0
while {[regexp -start $start -indices -- $regexp $str match submatch]} {
foreach {subStart subEnd} $submatch break
foreach {matchStart matchEnd} $match break
incr matchStart -1
incr matchEnd
lappend list [string range $str $start $matchStart]
if {$subStart >= $start} {
lappend list [string range $str $subStart $subEnd]
}
set start $matchEnd
}
lappend list [string range $str $start end]
return $list
}
} else {
# For tcl <= 8.2 we do not have regexp -start...
proc ::textutil::split::splitx [list str [list regexp "\[\t \r\n\]+"]] {
if {[string length $str] == 0} {
return {}
}
if {[string length $regexp] == 0} {
return [::split $str {}]
}
if {[regexp $regexp {}]} {
return -code error \
"splitting on regexp \"$regexp\" would cause infinite loop"
}
set list {}
while {[regexp -indices -- $regexp $str match submatch]} {
lappend list [string range $str 0 [expr {[lindex $match 0] -1}]]
if {[lindex $submatch 0] >= 0} {
lappend list [string range $str [lindex $submatch 0] \
[lindex $submatch 1]]
}
set str [string range $str [expr {[lindex $match 1]+1}] end]
}
lappend list $str
return $list
}
}
#
# splitn --
#
# splitn splits the string $str into chunks of length $len. These
# chunks are returned as a list.
#
# If $str really contains a ByteArray object (as retrieved from binary
# encoded channels) splitn must honor this by splitting the string
# into chunks of $len bytes.
#
# It is an error to call splitn with a nonpositive $len.
#
# If splitn is called with an empty string, it returns the empty list.
#
# If the length of $str is not an entire multiple of the chunk length,
# the last chunk in the generated list will be shorter than $len.
#
# The implementation presented here was given by Bryan Oakley, as
# part of a ``contest'' I staged on c.l.t in July 2004. I selected
# this version, as it does not rely on runtime generated code, is
# very fast for chunk size one, not too bad in all the other cases,
# and uses [split] or [string range] which have been around for quite
# some time.
#
# -- Robert Suetterlin (robert@mpe.mpg.de)
#
proc ::textutil::split::splitn {str {len 1}} {
if {$len <= 0} {
return -code error "len must be > 0"
}
if {$len == 1} {
return [split $str {}]
}
set result [list]
set max [string length $str]
set i 0
set j [expr {$len -1}]
while {$i < $max} {
lappend result [string range $str $i $j]
incr i $len
incr j $len
}
return $result
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::split {
namespace export splitx splitn
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::split 0.8

144
src/bootsupport/modules/textutil/string-0.8.tm

@ -0,0 +1,144 @@
# string.tcl --
#
# Utilities for manipulating strings, words, single lines,
# paragraphs, ...
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2002 by Joe English <jenglish@users.sourceforge.net>
# Copyright (c) 2001-2014 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: string.tcl,v 1.2 2008/03/22 16:03:11 mic42 Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil::string {}
# ### ### ### ######### ######### #########
## API implementation
# @c Removes the last character from the given <a string>.
#
# @a string: The string to manipulate.
#
# @r The <a string> without its last character.
#
# @i chopping
proc ::textutil::string::chop {string} {
return [string range $string 0 [expr {[string length $string]-2}]]
}
# @c Removes the first character from the given <a string>.
# @c Convenience procedure.
#
# @a string: string to manipulate.
#
# @r The <a string> without its first character.
#
# @i tail
proc ::textutil::string::tail {string} {
return [string range $string 1 end]
}
# @c Capitalizes first character of the given <a string>.
# @c Complementary procedure to <p ::textutil::uncap>.
#
# @a string: string to manipulate.
#
# @r The <a string> with its first character capitalized.
#
# @i capitalize
proc ::textutil::string::cap {string} {
return [string toupper [string index $string 0]][string range $string 1 end]
}
# @c unCapitalizes first character of the given <a string>.
# @c Complementary procedure to <p ::textutil::cap>.
#
# @a string: string to manipulate.
#
# @r The <a string> with its first character uncapitalized.
#
# @i uncapitalize
proc ::textutil::string::uncap {string} {
return [string tolower [string index $string 0]][string range $string 1 end]
}
# @c Capitalizes first character of each word of the given <a sentence>.
#
# @a sentence: string to manipulate.
#
# @r The <a sentence> with the first character of each word capitalized.
#
# @i capitalize
proc ::textutil::string::capEachWord {sentence} {
regsub -all {\S+} [string map {\\ \\\\ \$ \\$} $sentence] {[string toupper [string index & 0]][string range & 1 end]} cmd
return [subst -nobackslashes -novariables $cmd]
}
# Compute the longest string which is common to all strings given to
# the command, and at the beginning of said strings, i.e. a prefix. If
# only one argument is specified it is treated as a list of the
# strings to look at. If more than one argument is specified these
# arguments are the strings to be looked at. If only one string is
# given, in either form, the string is returned, as it is its own
# longest common prefix.
proc ::textutil::string::longestCommonPrefix {args} {
return [longestCommonPrefixList $args]
}
proc ::textutil::string::longestCommonPrefixList {list} {
if {[llength $list] <= 1} {
return [lindex $list 0]
}
set list [lsort $list]
set min [lindex $list 0]
set max [lindex $list end]
# Min and max are the two strings which are most different. If
# they have a common prefix, it will also be the common prefix for
# all of them.
# Fast bailouts for common cases.
set n [string length $min]
if {$n == 0} {return ""}
if {0 == [string compare $min $max]} {return $min}
set prefix ""
set i 0
while {[string index $min $i] == [string index $max $i]} {
append prefix [string index $min $i]
if {[incr i] > $n} {break}
}
set prefix
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::string {
# Export the imported commands
namespace export chop tail cap uncap capEachWord
namespace export longestCommonPrefix
namespace export longestCommonPrefixList
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::string 0.8

289
src/bootsupport/modules/textutil/tabify-0.7.tm

@ -0,0 +1,289 @@
#
# As the author of the procs 'tabify2' and 'untabify2' I suggest that the
# comments explaining their behaviour be kept in this file.
# 1) Beginners in any programming language (I am new to Tcl so I know what I
# am talking about) can profit enormously from studying 'correct' code.
# Of course comments will help a lot in this regard.
# 2) Many problems newbies face can be solved by directing them towards
# available libraries - after all, libraries have been written to solve
# recurring problems. Then they can just use them, or have a closer look
# to see and to discover how things are done the 'Tcl way'.
# 3) And if ever a proc from a library should be less than perfect, having
# comments explaining the behaviour of the code will surely help.
#
# This said, I will welcome any error reports or suggestions for improvements
# (especially on the 'doing things the Tcl way' aspect).
#
# Use of these sources is licensed under the same conditions as is Tcl.
#
# June 2001, Helmut Giese (hgiese@ratiosoft.com)
#
# ----------------------------------------------------------------------------
#
# The original procs 'tabify' and 'untabify' each work with complete blocks
# of $num spaces ('num' holding the tab size). While this is certainly useful
# in some circumstances, it does not reflect the way an editor works:
# Counting columns from 1, assuming a tab size of 8 and entering '12345'
# followed by a tab, you expect to advance to column 9. Your editor might
# put a tab into the file or 3 spaces, depending on its configuration.
# Now, on 'tabifying' you will expect to see those 3 spaces converted to a
# tab (and on the other hand expect the tab *at this position* to be
# converted to 3 spaces).
#
# This behaviour is mimicked by the new procs 'tabify2' and 'untabify2'.
# Both have one feature in common: They accept multi-line strings (a whole
# file if you want to) but in order to make life simpler for the programmer,
# they split the incoming string into individual lines and hand each line to
# a proc that does the real work.
#
# One design decision worth mentioning here:
# A single space is never converted to a tab even if its position would
# allow to do so.
# Single spaces occur very often, say in arithmetic expressions like
# [expr (($a + $b) * $c) < $d]. If we didn't follow the above rule we might
# need to replace one or more of them to tabs. However if the tab size gets
# changed, this expression would be formatted quite differently - which is
# probably not a good idea.
#
# 'untabifying' on the other hand might need to replace a tab with a single
# space: If the current position requires it, what else to do?
# As a consequence those two procs are unsymmetric in this aspect, but I
# couldn't think of a better solution. Could you?
#
# ----------------------------------------------------------------------------
#
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
package require textutil::repeat
namespace eval ::textutil::tabify {}
# ### ### ### ######### ######### #########
## API implementation
namespace eval ::textutil::tabify {
namespace import -force ::textutil::repeat::strRepeat
}
proc ::textutil::tabify::tabify { string { num 8 } } {
return [string map [list [MakeTabStr $num] \t] $string]
}
proc ::textutil::tabify::untabify { string { num 8 } } {
return [string map [list \t [MakeTabStr $num]] $string]
}
proc ::textutil::tabify::MakeTabStr { num } {
variable TabStr
variable TabLen
if { $TabLen != $num } then {
set TabLen $num
set TabStr [strRepeat " " $num]
}
return $TabStr
}
# ----------------------------------------------------------------------------
#
# tabifyLine: Works on a single line of text, replacing 'spaces at correct
# positions' with tabs. $num is the requested tab size.
# Returns the (possibly modified) line.
#
# 'spaces at correct positions': Only spaces which 'fill the space' between
# an arbitrary position and the next tab stop can be replaced.
# Example: With tab size 8, spaces at positions 11 - 13 will *not* be replaced,
# because an expansion of a tab at position 11 will jump up to 16.
# See also the comment at the beginning of this file why single spaces are
# *never* replaced by a tab.
#
# The proc works backwards, from the end of the string up to the beginning:
# - Set the position to start the search from ('lastPos') to 'end'.
# - Find the last occurrence of ' ' in 'line' with respect to 'lastPos'
# ('currPos' below). This is a candidate for replacement.
# - Find to 'currPos' the following tab stop using the expression
# set nextTab [expr ($currPos + $num) - ($currPos % $num)]
# and get the previous tab stop as well (this will be the starting
# point for the next iteration).
# - The ' ' at 'currPos' is only a candidate for replacement if
# 1) it is just one position before a tab stop *and*
# 2) there is at least one space at its left (see comment above on not
# touching an isolated space).
# Continue, if any of these conditions is not met.
# - Determine where to put the tab (that is: how many spaces to replace?)
# by stepping up to the beginning until
# -- you hit a non-space or
# -- you are at the previous tab position
# - Do the replacement and continue.
#
# This algorithm only works, if $line does not contain tabs. Otherwise our
# interpretation of any position beyond the tab will be wrong. (Imagine you
# find a ' ' at position 4 in $line. If you got 3 leading tabs, your *real*
# position might be 25 (tab size of 8). Since in real life some strings might
# already contain tabs, we test for it (and eventually call untabifyLine).
#
proc ::textutil::tabify::tabifyLine { line num } {
if { [string first \t $line] != -1 } {
# assure array 'Spaces' is set up 'comme il faut'
checkArr $num
# remove existing tabs
set line [untabifyLine $line $num]
}
set lastPos end
while { $lastPos > 0 } {
set currPos [string last " " $line $lastPos]
if { $currPos == -1 } {
# no more spaces
break;
}
set nextTab [expr {($currPos + $num) - ($currPos % $num)}]
set prevTab [expr {$nextTab - $num}]
# prepare for next round: continue at 'previous tab stop - 1'
set lastPos [expr {$prevTab - 1}]
if { ($currPos + 1) != $nextTab } {
continue ;# crit. (1)
}
if { [string index $line [expr {$currPos - 1}]] != " " } {
continue ;# crit. (2)
}
# now step backwards while there are spaces
for {set pos [expr {$currPos - 2}]} {$pos >= $prevTab} {incr pos -1} {
if { [string index $line $pos] != " " } {
break;
}
}
# ... and replace them
set line [string replace $line [expr {$pos + 1}] $currPos \t]
}
return $line
}
#
# Helper proc for 'untabifyLine': Checks if all needed elements of array
# 'Spaces' exist and creates the missing ones if needed.
#
proc ::textutil::tabify::checkArr { num } {
variable TabLen2
variable Spaces
if { $num > $TabLen2 } {
for { set i [expr {$TabLen2 + 1}] } { $i <= $num } { incr i } {
set Spaces($i) [strRepeat " " $i]
}
set TabLen2 $num
}
}
# untabifyLine: Works on a single line of text, replacing tabs with enough
# spaces to get to the next tab position.
# Returns the (possibly modified) line.
#
# The procedure is straight forward:
# - Find the next tab.
# - Calculate the next tab position following it.
# - Delete the tab and insert as many spaces as needed to get there.
#
proc ::textutil::tabify::untabifyLine { line num } {
variable Spaces
set currPos 0
while { 1 } {
set currPos [string first \t $line $currPos]
if { $currPos == -1 } {
# no more tabs
break
}
# how far is the next tab position ?
set dist [expr {$num - ($currPos % $num)}]
# replace '\t' at $currPos with $dist spaces
set line [string replace $line $currPos $currPos $Spaces($dist)]
# set up for next round (not absolutely necessary but maybe a trifle
# more efficient)
incr currPos $dist
}
return $line
}
# tabify2: Replace all 'appropriate' spaces as discussed above with tabs.
# 'string' might hold any number of lines, 'num' is the requested tab size.
# Returns (possibly modified) 'string'.
#
proc ::textutil::tabify::tabify2 { string { num 8 } } {
# split string into individual lines
set inLst [split $string \n]
# now work on each line
set outLst [list]
foreach line $inLst {
lappend outLst [tabifyLine $line $num]
}
# return all as one string
return [join $outLst \n]
}
# untabify2: Replace all tabs with the appropriate number of spaces.
# 'string' might hold any number of lines, 'num' is the requested tab size.
# Returns (possibly modified) 'string'.
#
proc ::textutil::tabify::untabify2 { string { num 8 } } {
# assure array 'Spaces' is set up 'comme il faut'
checkArr $num
set inLst [split $string \n]
set outLst [list]
foreach line $inLst {
lappend outLst [untabifyLine $line $num]
}
return [join $outLst \n]
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::tabify {
variable TabLen 8
variable TabStr [strRepeat " " $TabLen]
namespace export tabify untabify tabify2 untabify2
# The proc 'untabify2' uses the following variables for efficiency.
# Since a tab can be replaced by one up to 'tab size' spaces, it is handy
# to have the appropriate 'space strings' available. This is the use of
# the array 'Spaces', where 'Spaces(n)' contains just 'n' spaces.
# The variable 'TabLen2' remembers the biggest tab size used.
variable TabLen2 0
variable Spaces
array set Spaces {0 ""}
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::tabify 0.7

112
src/bootsupport/modules/textutil/trim-0.7.tm

@ -0,0 +1,112 @@
# trim.tcl --
#
# Various ways of trimming a string.
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: trim.tcl,v 1.5 2006/04/21 04:42:28 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil::trim {}
# ### ### ### ######### ######### #########
## API implementation
proc ::textutil::trim::trimleft {text {trim "[ \t]+"}} {
regsub -line -all -- [MakeStr $trim left] $text {} text
return $text
}
proc ::textutil::trim::trimright {text {trim "[ \t]+"}} {
regsub -line -all -- [MakeStr $trim right] $text {} text
return $text
}
proc ::textutil::trim::trim {text {trim "[ \t]+"}} {
regsub -line -all -- [MakeStr $trim left] $text {} text
regsub -line -all -- [MakeStr $trim right] $text {} text
return $text
}
# @c Strips <a prefix> from <a text>, if found at its start.
#
# @a text: The string to check for <a prefix>.
# @a prefix: The string to remove from <a text>.
#
# @r The <a text>, but without <a prefix>.
#
# @i remove, prefix
proc ::textutil::trim::trimPrefix {text prefix} {
if {[string first $prefix $text] == 0} {
return [string range $text [string length $prefix] end]
} else {
return $text
}
}
# @c Removes the Heading Empty Lines of <a text>.
#
# @a text: The text block to manipulate.
#
# @r The <a text>, but without heading empty lines.
#
# @i remove, empty lines
proc ::textutil::trim::trimEmptyHeading {text} {
regsub -- "^(\[ \t\]*\n)*" $text {} text
return $text
}
# ### ### ### ######### ######### #########
## Helper commands. Internal
proc ::textutil::trim::MakeStr { string pos } {
variable StrU
variable StrR
variable StrL
if { "$string" != "$StrU" } {
set StrU $string
set StrR "(${StrU})\$"
set StrL "^(${StrU})"
}
if { "$pos" == "left" } {
return $StrL
}
if { "$pos" == "right" } {
return $StrR
}
return -code error "Panic, illegal position key \"$pos\""
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::trim {
variable StrU "\[ \t\]+"
variable StrR "(${StrU})\$"
variable StrL "^(${StrU})"
namespace export \
trim trimright trimleft \
trimPrefix trimEmptyHeading
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::trim 0.7

772
src/bootsupport/modules/textutil/wcswidth-35.1.tm

@ -0,0 +1,772 @@
###
# This file is automatically generated by the build/build.tcl file
# based on information in the following database:
# http://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt
#
# (This is the 35th edition, thus version 35 for our package)
#
# Author: Sean Woods <yoda@etoyoc.com>
###
package provide textutil::wcswidth 35.1
proc ::textutil::wcswidth_type char {
if {$char == 161} { return A }
if {$char == 164} { return A }
if {$char == 167} { return A }
if {$char == 168} { return A }
if {$char == 170} { return A }
if {$char == 173} { return A }
if {$char == 174} { return A }
if {$char == 176} { return A }
if {$char == 177} { return A }
if {$char >= 178 && $char <= 179 } { return A }
if {$char == 180} { return A }
if {$char >= 182 && $char <= 183 } { return A }
if {$char == 184} { return A }
if {$char == 185} { return A }
if {$char == 186} { return A }
if {$char >= 188 && $char <= 190 } { return A }
if {$char == 191} { return A }
if {$char == 198} { return A }
if {$char == 208} { return A }
if {$char == 215} { return A }
if {$char == 216} { return A }
if {$char >= 222 && $char <= 225 } { return A }
if {$char == 230} { return A }
if {$char >= 232 && $char <= 234 } { return A }
if {$char >= 236 && $char <= 237 } { return A }
if {$char == 240} { return A }
if {$char >= 242 && $char <= 243 } { return A }
if {$char == 247} { return A }
if {$char >= 248 && $char <= 250 } { return A }
if {$char == 252} { return A }
if {$char == 254} { return A }
if {$char == 257} { return A }
if {$char == 273} { return A }
if {$char == 275} { return A }
if {$char == 283} { return A }
if {$char >= 294 && $char <= 295 } { return A }
if {$char == 299} { return A }
if {$char >= 305 && $char <= 307 } { return A }
if {$char == 312} { return A }
if {$char >= 319 && $char <= 322 } { return A }
if {$char == 324} { return A }
if {$char >= 328 && $char <= 331 } { return A }
if {$char == 333} { return A }
if {$char >= 338 && $char <= 339 } { return A }
if {$char >= 358 && $char <= 359 } { return A }
if {$char == 363} { return A }
if {$char == 462} { return A }
if {$char == 464} { return A }
if {$char == 466} { return A }
if {$char == 468} { return A }
if {$char == 470} { return A }
if {$char == 472} { return A }
if {$char == 474} { return A }
if {$char == 476} { return A }
if {$char == 593} { return A }
if {$char == 609} { return A }
if {$char == 708} { return A }
if {$char == 711} { return A }
if {$char >= 713 && $char <= 715 } { return A }
if {$char == 717} { return A }
if {$char == 720} { return A }
if {$char >= 728 && $char <= 731 } { return A }
if {$char == 733} { return A }
if {$char == 735} { return A }
if {$char >= 768 && $char <= 879 } { return A }
if {$char >= 913 && $char <= 929 } { return A }
if {$char >= 931 && $char <= 937 } { return A }
if {$char >= 945 && $char <= 961 } { return A }
if {$char >= 963 && $char <= 969 } { return A }
if {$char == 1025} { return A }
if {$char >= 1040 && $char <= 1103 } { return A }
if {$char == 1105} { return A }
if {$char >= 4352 && $char <= 4447 } { return W }
if {$char == 8208} { return A }
if {$char >= 8211 && $char <= 8213 } { return A }
if {$char == 8214} { return A }
if {$char == 8216} { return A }
if {$char == 8217} { return A }
if {$char == 8220} { return A }
if {$char == 8221} { return A }
if {$char >= 8224 && $char <= 8226 } { return A }
if {$char >= 8228 && $char <= 8231 } { return A }
if {$char == 8240} { return A }
if {$char >= 8242 && $char <= 8243 } { return A }
if {$char == 8245} { return A }
if {$char == 8251} { return A }
if {$char == 8254} { return A }
if {$char == 8308} { return A }
if {$char == 8319} { return A }
if {$char >= 8321 && $char <= 8324 } { return A }
if {$char == 8361} { return H }
if {$char == 8364} { return A }
if {$char == 8451} { return A }
if {$char == 8453} { return A }
if {$char == 8457} { return A }
if {$char == 8467} { return A }
if {$char == 8470} { return A }
if {$char >= 8481 && $char <= 8482 } { return A }
if {$char == 8486} { return A }
if {$char == 8491} { return A }
if {$char >= 8531 && $char <= 8532 } { return A }
if {$char >= 8539 && $char <= 8542 } { return A }
if {$char >= 8544 && $char <= 8555 } { return A }
if {$char >= 8560 && $char <= 8569 } { return A }
if {$char == 8585} { return A }
if {$char >= 8592 && $char <= 8596 } { return A }
if {$char >= 8597 && $char <= 8601 } { return A }
if {$char >= 8632 && $char <= 8633 } { return A }
if {$char == 8658} { return A }
if {$char == 8660} { return A }
if {$char == 8679} { return A }
if {$char == 8704} { return A }
if {$char >= 8706 && $char <= 8707 } { return A }
if {$char >= 8711 && $char <= 8712 } { return A }
if {$char == 8715} { return A }
if {$char == 8719} { return A }
if {$char == 8721} { return A }
if {$char == 8725} { return A }
if {$char == 8730} { return A }
if {$char >= 8733 && $char <= 8736 } { return A }
if {$char == 8739} { return A }
if {$char == 8741} { return A }
if {$char >= 8743 && $char <= 8748 } { return A }
if {$char == 8750} { return A }
if {$char >= 8756 && $char <= 8759 } { return A }
if {$char >= 8764 && $char <= 8765 } { return A }
if {$char == 8776} { return A }
if {$char == 8780} { return A }
if {$char == 8786} { return A }
if {$char >= 8800 && $char <= 8801 } { return A }
if {$char >= 8804 && $char <= 8807 } { return A }
if {$char >= 8810 && $char <= 8811 } { return A }
if {$char >= 8814 && $char <= 8815 } { return A }
if {$char >= 8834 && $char <= 8835 } { return A }
if {$char >= 8838 && $char <= 8839 } { return A }
if {$char == 8853} { return A }
if {$char == 8857} { return A }
if {$char == 8869} { return A }
if {$char == 8895} { return A }
if {$char == 8978} { return A }
if {$char >= 8986 && $char <= 8987 } { return W }
if {$char == 9001} { return W }
if {$char == 9002} { return W }
if {$char >= 9193 && $char <= 9196 } { return W }
if {$char == 9200} { return W }
if {$char == 9203} { return W }
if {$char >= 9312 && $char <= 9371 } { return A }
if {$char >= 9372 && $char <= 9449 } { return A }
if {$char >= 9451 && $char <= 9471 } { return A }
if {$char >= 9472 && $char <= 9547 } { return A }
if {$char >= 9552 && $char <= 9587 } { return A }
if {$char >= 9600 && $char <= 9615 } { return A }
if {$char >= 9618 && $char <= 9621 } { return A }
if {$char >= 9632 && $char <= 9633 } { return A }
if {$char >= 9635 && $char <= 9641 } { return A }
if {$char >= 9650 && $char <= 9651 } { return A }
if {$char == 9654} { return A }
if {$char == 9655} { return A }
if {$char >= 9660 && $char <= 9661 } { return A }
if {$char == 9664} { return A }
if {$char == 9665} { return A }
if {$char >= 9670 && $char <= 9672 } { return A }
if {$char == 9675} { return A }
if {$char >= 9678 && $char <= 9681 } { return A }
if {$char >= 9698 && $char <= 9701 } { return A }
if {$char == 9711} { return A }
if {$char >= 9725 && $char <= 9726 } { return W }
if {$char >= 9733 && $char <= 9734 } { return A }
if {$char == 9737} { return A }
if {$char >= 9742 && $char <= 9743 } { return A }
if {$char >= 9748 && $char <= 9749 } { return W }
if {$char == 9756} { return A }
if {$char == 9758} { return A }
if {$char == 9792} { return A }
if {$char == 9794} { return A }
if {$char >= 9800 && $char <= 9811 } { return W }
if {$char >= 9824 && $char <= 9825 } { return A }
if {$char >= 9827 && $char <= 9829 } { return A }
if {$char >= 9831 && $char <= 9834 } { return A }
if {$char >= 9836 && $char <= 9837 } { return A }
if {$char == 9839} { return A }
if {$char == 9855} { return W }
if {$char == 9875} { return W }
if {$char >= 9886 && $char <= 9887 } { return A }
if {$char == 9889} { return W }
if {$char >= 9898 && $char <= 9899 } { return W }
if {$char >= 9917 && $char <= 9918 } { return W }
if {$char == 9919} { return A }
if {$char >= 9924 && $char <= 9925 } { return W }
if {$char >= 9926 && $char <= 9933 } { return A }
if {$char == 9934} { return W }
if {$char >= 9935 && $char <= 9939 } { return A }
if {$char == 9940} { return W }
if {$char >= 9941 && $char <= 9953 } { return A }
if {$char == 9955} { return A }
if {$char >= 9960 && $char <= 9961 } { return A }
if {$char == 9962} { return W }
if {$char >= 9963 && $char <= 9969 } { return A }
if {$char >= 9970 && $char <= 9971 } { return W }
if {$char == 9972} { return A }
if {$char == 9973} { return W }
if {$char >= 9974 && $char <= 9977 } { return A }
if {$char == 9978} { return W }
if {$char >= 9979 && $char <= 9980 } { return A }
if {$char == 9981} { return W }
if {$char >= 9982 && $char <= 9983 } { return A }
if {$char == 9989} { return W }
if {$char >= 9994 && $char <= 9995 } { return W }
if {$char == 10024} { return W }
if {$char == 10045} { return A }
if {$char == 10060} { return W }
if {$char == 10062} { return W }
if {$char >= 10067 && $char <= 10069 } { return W }
if {$char == 10071} { return W }
if {$char >= 10102 && $char <= 10111 } { return A }
if {$char >= 10133 && $char <= 10135 } { return W }
if {$char == 10160} { return W }
if {$char == 10175} { return W }
if {$char >= 11035 && $char <= 11036 } { return W }
if {$char == 11088} { return W }
if {$char == 11093} { return W }
if {$char >= 11094 && $char <= 11097 } { return A }
if {$char >= 11904 && $char <= 11929 } { return W }
if {$char >= 11931 && $char <= 12019 } { return W }
if {$char >= 12032 && $char <= 12245 } { return W }
if {$char >= 12272 && $char <= 12283 } { return W }
if {$char == 12288} { return F }
if {$char >= 12289 && $char <= 12291 } { return W }
if {$char == 12292} { return W }
if {$char == 12293} { return W }
if {$char == 12294} { return W }
if {$char == 12295} { return W }
if {$char == 12296} { return W }
if {$char == 12297} { return W }
if {$char == 12298} { return W }
if {$char == 12299} { return W }
if {$char == 12300} { return W }
if {$char == 12301} { return W }
if {$char == 12302} { return W }
if {$char == 12303} { return W }
if {$char == 12304} { return W }
if {$char == 12305} { return W }
if {$char >= 12306 && $char <= 12307 } { return W }
if {$char == 12308} { return W }
if {$char == 12309} { return W }
if {$char == 12310} { return W }
if {$char == 12311} { return W }
if {$char == 12312} { return W }
if {$char == 12313} { return W }
if {$char == 12314} { return W }
if {$char == 12315} { return W }
if {$char == 12316} { return W }
if {$char == 12317} { return W }
if {$char >= 12318 && $char <= 12319 } { return W }
if {$char == 12320} { return W }
if {$char >= 12321 && $char <= 12329 } { return W }
if {$char >= 12330 && $char <= 12333 } { return W }
if {$char >= 12334 && $char <= 12335 } { return W }
if {$char == 12336} { return W }
if {$char >= 12337 && $char <= 12341 } { return W }
if {$char >= 12342 && $char <= 12343 } { return W }
if {$char >= 12344 && $char <= 12346 } { return W }
if {$char == 12347} { return W }
if {$char == 12348} { return W }
if {$char == 12349} { return W }
if {$char == 12350} { return W }
if {$char >= 12353 && $char <= 12438 } { return W }
if {$char >= 12441 && $char <= 12442 } { return W }
if {$char >= 12443 && $char <= 12444 } { return W }
if {$char >= 12445 && $char <= 12446 } { return W }
if {$char == 12447} { return W }
if {$char == 12448} { return W }
if {$char >= 12449 && $char <= 12538 } { return W }
if {$char == 12539} { return W }
if {$char >= 12540 && $char <= 12542 } { return W }
if {$char == 12543} { return W }
if {$char >= 12549 && $char <= 12591 } { return W }
if {$char >= 12593 && $char <= 12686 } { return W }
if {$char >= 12688 && $char <= 12689 } { return W }
if {$char >= 12690 && $char <= 12693 } { return W }
if {$char >= 12694 && $char <= 12703 } { return W }
if {$char >= 12704 && $char <= 12730 } { return W }
if {$char >= 12736 && $char <= 12771 } { return W }
if {$char >= 12784 && $char <= 12799 } { return W }
if {$char >= 12800 && $char <= 12830 } { return W }
if {$char >= 12832 && $char <= 12841 } { return W }
if {$char >= 12842 && $char <= 12871 } { return W }
if {$char >= 12872 && $char <= 12879 } { return A }
if {$char == 12880} { return W }
if {$char >= 12881 && $char <= 12895 } { return W }
if {$char >= 12896 && $char <= 12927 } { return W }
if {$char >= 12928 && $char <= 12937 } { return W }
if {$char >= 12938 && $char <= 12976 } { return W }
if {$char >= 12977 && $char <= 12991 } { return W }
if {$char >= 12992 && $char <= 13054 } { return W }
if {$char >= 13056 && $char <= 13311 } { return W }
if {$char >= 13312 && $char <= 19893 } { return W }
if {$char >= 19894 && $char <= 19903 } { return W }
if {$char >= 19968 && $char <= 40943 } { return W }
if {$char >= 40944 && $char <= 40959 } { return W }
if {$char >= 40960 && $char <= 40980 } { return W }
if {$char == 40981} { return W }
if {$char >= 40982 && $char <= 42124 } { return W }
if {$char >= 42128 && $char <= 42182 } { return W }
if {$char >= 43360 && $char <= 43388 } { return W }
if {$char >= 44032 && $char <= 55203 } { return W }
if {$char >= 57344 && $char <= 63743 } { return A }
if {$char >= 63744 && $char <= 64109 } { return W }
if {$char >= 64110 && $char <= 64111 } { return W }
if {$char >= 64112 && $char <= 64217 } { return W }
if {$char >= 64218 && $char <= 64255 } { return W }
if {$char >= 65024 && $char <= 65039 } { return A }
if {$char >= 65040 && $char <= 65046 } { return W }
if {$char == 65047} { return W }
if {$char == 65048} { return W }
if {$char == 65049} { return W }
if {$char == 65072} { return W }
if {$char >= 65073 && $char <= 65074 } { return W }
if {$char >= 65075 && $char <= 65076 } { return W }
if {$char == 65077} { return W }
if {$char == 65078} { return W }
if {$char == 65079} { return W }
if {$char == 65080} { return W }
if {$char == 65081} { return W }
if {$char == 65082} { return W }
if {$char == 65083} { return W }
if {$char == 65084} { return W }
if {$char == 65085} { return W }
if {$char == 65086} { return W }
if {$char == 65087} { return W }
if {$char == 65088} { return W }
if {$char == 65089} { return W }
if {$char == 65090} { return W }
if {$char == 65091} { return W }
if {$char == 65092} { return W }
if {$char >= 65093 && $char <= 65094 } { return W }
if {$char == 65095} { return W }
if {$char == 65096} { return W }
if {$char >= 65097 && $char <= 65100 } { return W }
if {$char >= 65101 && $char <= 65103 } { return W }
if {$char >= 65104 && $char <= 65106 } { return W }
if {$char >= 65108 && $char <= 65111 } { return W }
if {$char == 65112} { return W }
if {$char == 65113} { return W }
if {$char == 65114} { return W }
if {$char == 65115} { return W }
if {$char == 65116} { return W }
if {$char == 65117} { return W }
if {$char == 65118} { return W }
if {$char >= 65119 && $char <= 65121 } { return W }
if {$char == 65122} { return W }
if {$char == 65123} { return W }
if {$char >= 65124 && $char <= 65126 } { return W }
if {$char == 65128} { return W }
if {$char == 65129} { return W }
if {$char >= 65130 && $char <= 65131 } { return W }
if {$char >= 65281 && $char <= 65283 } { return F }
if {$char == 65284} { return F }
if {$char >= 65285 && $char <= 65287 } { return F }
if {$char == 65288} { return F }
if {$char == 65289} { return F }
if {$char == 65290} { return F }
if {$char == 65291} { return F }
if {$char == 65292} { return F }
if {$char == 65293} { return F }
if {$char >= 65294 && $char <= 65295 } { return F }
if {$char >= 65296 && $char <= 65305 } { return F }
if {$char >= 65306 && $char <= 65307 } { return F }
if {$char >= 65308 && $char <= 65310 } { return F }
if {$char >= 65311 && $char <= 65312 } { return F }
if {$char >= 65313 && $char <= 65338 } { return F }
if {$char == 65339} { return F }
if {$char == 65340} { return F }
if {$char == 65341} { return F }
if {$char == 65342} { return F }
if {$char == 65343} { return F }
if {$char == 65344} { return F }
if {$char >= 65345 && $char <= 65370 } { return F }
if {$char == 65371} { return F }
if {$char == 65372} { return F }
if {$char == 65373} { return F }
if {$char == 65374} { return F }
if {$char == 65375} { return F }
if {$char == 65376} { return F }
if {$char == 65377} { return H }
if {$char == 65378} { return H }
if {$char == 65379} { return H }
if {$char >= 65380 && $char <= 65381 } { return H }
if {$char >= 65382 && $char <= 65391 } { return H }
if {$char == 65392} { return H }
if {$char >= 65393 && $char <= 65437 } { return H }
if {$char >= 65438 && $char <= 65439 } { return H }
if {$char >= 65440 && $char <= 65470 } { return H }
if {$char >= 65474 && $char <= 65479 } { return H }
if {$char >= 65482 && $char <= 65487 } { return H }
if {$char >= 65490 && $char <= 65495 } { return H }
if {$char >= 65498 && $char <= 65500 } { return H }
if {$char >= 65504 && $char <= 65505 } { return F }
if {$char == 65506} { return F }
if {$char == 65507} { return F }
if {$char == 65508} { return F }
if {$char >= 65509 && $char <= 65510 } { return F }
if {$char == 65512} { return H }
if {$char >= 65513 && $char <= 65516 } { return H }
if {$char >= 65517 && $char <= 65518 } { return H }
if {$char == 65533} { return A }
if {$char >= 94176 && $char <= 94177 } { return W }
if {$char >= 94208 && $char <= 100337 } { return W }
if {$char >= 100352 && $char <= 101106 } { return W }
if {$char >= 110592 && $char <= 110847 } { return W }
if {$char >= 110848 && $char <= 110878 } { return W }
if {$char >= 110960 && $char <= 111355 } { return W }
if {$char == 126980} { return W }
if {$char == 127183} { return W }
if {$char >= 127232 && $char <= 127242 } { return A }
if {$char >= 127248 && $char <= 127277 } { return A }
if {$char >= 127280 && $char <= 127337 } { return A }
if {$char >= 127344 && $char <= 127373 } { return A }
if {$char == 127374} { return W }
if {$char >= 127375 && $char <= 127376 } { return A }
if {$char >= 127377 && $char <= 127386 } { return W }
if {$char >= 127387 && $char <= 127404 } { return A }
if {$char >= 127488 && $char <= 127490 } { return W }
if {$char >= 127504 && $char <= 127547 } { return W }
if {$char >= 127552 && $char <= 127560 } { return W }
if {$char >= 127568 && $char <= 127569 } { return W }
if {$char >= 127584 && $char <= 127589 } { return W }
if {$char >= 127744 && $char <= 127776 } { return W }
if {$char >= 127789 && $char <= 127797 } { return W }
if {$char >= 127799 && $char <= 127868 } { return W }
if {$char >= 127870 && $char <= 127891 } { return W }
if {$char >= 127904 && $char <= 127946 } { return W }
if {$char >= 127951 && $char <= 127955 } { return W }
if {$char >= 127968 && $char <= 127984 } { return W }
if {$char == 127988} { return W }
if {$char >= 127992 && $char <= 127994 } { return W }
if {$char >= 127995 && $char <= 127999 } { return W }
if {$char >= 128000 && $char <= 128062 } { return W }
if {$char == 128064} { return W }
if {$char >= 128066 && $char <= 128252 } { return W }
if {$char >= 128255 && $char <= 128317 } { return W }
if {$char >= 128331 && $char <= 128334 } { return W }
if {$char >= 128336 && $char <= 128359 } { return W }
if {$char == 128378} { return W }
if {$char >= 128405 && $char <= 128406 } { return W }
if {$char == 128420} { return W }
if {$char >= 128507 && $char <= 128511 } { return W }
if {$char >= 128512 && $char <= 128591 } { return W }
if {$char >= 128640 && $char <= 128709 } { return W }
if {$char == 128716} { return W }
if {$char >= 128720 && $char <= 128722 } { return W }
if {$char >= 128747 && $char <= 128748 } { return W }
if {$char >= 128756 && $char <= 128761 } { return W }
if {$char >= 129296 && $char <= 129342 } { return W }
if {$char >= 129344 && $char <= 129392 } { return W }
if {$char >= 129395 && $char <= 129398 } { return W }
if {$char == 129402} { return W }
if {$char >= 129404 && $char <= 129442 } { return W }
if {$char >= 129456 && $char <= 129465 } { return W }
if {$char >= 129472 && $char <= 129474 } { return W }
if {$char >= 129488 && $char <= 129535 } { return W }
if {$char >= 131072 && $char <= 173782 } { return W }
if {$char >= 173783 && $char <= 173823 } { return W }
if {$char >= 173824 && $char <= 177972 } { return W }
if {$char >= 177973 && $char <= 177983 } { return W }
if {$char >= 177984 && $char <= 178205 } { return W }
if {$char >= 178206 && $char <= 178207 } { return W }
if {$char >= 178208 && $char <= 183969 } { return W }
if {$char >= 183970 && $char <= 183983 } { return W }
if {$char >= 183984 && $char <= 191456 } { return W }
if {$char >= 191457 && $char <= 194559 } { return W }
if {$char >= 194560 && $char <= 195101 } { return W }
if {$char >= 195102 && $char <= 195103 } { return W }
if {$char >= 195104 && $char <= 196605 } { return W }
if {$char >= 196608 && $char <= 262141 } { return W }
if {$char >= 917760 && $char <= 917999 } { return A }
if {$char >= 983040 && $char <= 1048573 } { return A }
if {$char >= 1048576 && $char <= 1114109 } { return A }
return N
}
proc ::textutil::wcswidth_char char {
if {$char >= 4352 && $char <= 4447 } { return 2 }
if {$char >= 8986 && $char <= 8987 } { return 2 }
if {$char == 9001} { return 2 }
if {$char == 9002} { return 2 }
if {$char >= 9193 && $char <= 9196 } { return 2 }
if {$char == 9200} { return 2 }
if {$char == 9203} { return 2 }
if {$char >= 9725 && $char <= 9726 } { return 2 }
if {$char >= 9748 && $char <= 9749 } { return 2 }
if {$char >= 9800 && $char <= 9811 } { return 2 }
if {$char == 9855} { return 2 }
if {$char == 9875} { return 2 }
if {$char == 9889} { return 2 }
if {$char >= 9898 && $char <= 9899 } { return 2 }
if {$char >= 9917 && $char <= 9918 } { return 2 }
if {$char >= 9924 && $char <= 9925 } { return 2 }
if {$char == 9934} { return 2 }
if {$char == 9940} { return 2 }
if {$char == 9962} { return 2 }
if {$char >= 9970 && $char <= 9971 } { return 2 }
if {$char == 9973} { return 2 }
if {$char == 9978} { return 2 }
if {$char == 9981} { return 2 }
if {$char == 9989} { return 2 }
if {$char >= 9994 && $char <= 9995 } { return 2 }
if {$char == 10024} { return 2 }
if {$char == 10060} { return 2 }
if {$char == 10062} { return 2 }
if {$char >= 10067 && $char <= 10069 } { return 2 }
if {$char == 10071} { return 2 }
if {$char >= 10133 && $char <= 10135 } { return 2 }
if {$char == 10160} { return 2 }
if {$char == 10175} { return 2 }
if {$char >= 11035 && $char <= 11036 } { return 2 }
if {$char == 11088} { return 2 }
if {$char == 11093} { return 2 }
if {$char >= 11904 && $char <= 11929 } { return 2 }
if {$char >= 11931 && $char <= 12019 } { return 2 }
if {$char >= 12032 && $char <= 12245 } { return 2 }
if {$char >= 12272 && $char <= 12283 } { return 2 }
if {$char == 12288} { return 2 }
if {$char >= 12289 && $char <= 12291 } { return 2 }
if {$char == 12292} { return 2 }
if {$char == 12293} { return 2 }
if {$char == 12294} { return 2 }
if {$char == 12295} { return 2 }
if {$char == 12296} { return 2 }
if {$char == 12297} { return 2 }
if {$char == 12298} { return 2 }
if {$char == 12299} { return 2 }
if {$char == 12300} { return 2 }
if {$char == 12301} { return 2 }
if {$char == 12302} { return 2 }
if {$char == 12303} { return 2 }
if {$char == 12304} { return 2 }
if {$char == 12305} { return 2 }
if {$char >= 12306 && $char <= 12307 } { return 2 }
if {$char == 12308} { return 2 }
if {$char == 12309} { return 2 }
if {$char == 12310} { return 2 }
if {$char == 12311} { return 2 }
if {$char == 12312} { return 2 }
if {$char == 12313} { return 2 }
if {$char == 12314} { return 2 }
if {$char == 12315} { return 2 }
if {$char == 12316} { return 2 }
if {$char == 12317} { return 2 }
if {$char >= 12318 && $char <= 12319 } { return 2 }
if {$char == 12320} { return 2 }
if {$char >= 12321 && $char <= 12329 } { return 2 }
if {$char >= 12330 && $char <= 12333 } { return 2 }
if {$char >= 12334 && $char <= 12335 } { return 2 }
if {$char == 12336} { return 2 }
if {$char >= 12337 && $char <= 12341 } { return 2 }
if {$char >= 12342 && $char <= 12343 } { return 2 }
if {$char >= 12344 && $char <= 12346 } { return 2 }
if {$char == 12347} { return 2 }
if {$char == 12348} { return 2 }
if {$char == 12349} { return 2 }
if {$char == 12350} { return 2 }
if {$char >= 12353 && $char <= 12438 } { return 2 }
if {$char >= 12441 && $char <= 12442 } { return 2 }
if {$char >= 12443 && $char <= 12444 } { return 2 }
if {$char >= 12445 && $char <= 12446 } { return 2 }
if {$char == 12447} { return 2 }
if {$char == 12448} { return 2 }
if {$char >= 12449 && $char <= 12538 } { return 2 }
if {$char == 12539} { return 2 }
if {$char >= 12540 && $char <= 12542 } { return 2 }
if {$char == 12543} { return 2 }
if {$char >= 12549 && $char <= 12591 } { return 2 }
if {$char >= 12593 && $char <= 12686 } { return 2 }
if {$char >= 12688 && $char <= 12689 } { return 2 }
if {$char >= 12690 && $char <= 12693 } { return 2 }
if {$char >= 12694 && $char <= 12703 } { return 2 }
if {$char >= 12704 && $char <= 12730 } { return 2 }
if {$char >= 12736 && $char <= 12771 } { return 2 }
if {$char >= 12784 && $char <= 12799 } { return 2 }
if {$char >= 12800 && $char <= 12830 } { return 2 }
if {$char >= 12832 && $char <= 12841 } { return 2 }
if {$char >= 12842 && $char <= 12871 } { return 2 }
if {$char == 12880} { return 2 }
if {$char >= 12881 && $char <= 12895 } { return 2 }
if {$char >= 12896 && $char <= 12927 } { return 2 }
if {$char >= 12928 && $char <= 12937 } { return 2 }
if {$char >= 12938 && $char <= 12976 } { return 2 }
if {$char >= 12977 && $char <= 12991 } { return 2 }
if {$char >= 12992 && $char <= 13054 } { return 2 }
if {$char >= 13056 && $char <= 13311 } { return 2 }
if {$char >= 13312 && $char <= 19893 } { return 2 }
if {$char >= 19894 && $char <= 19903 } { return 2 }
if {$char >= 19968 && $char <= 40943 } { return 2 }
if {$char >= 40944 && $char <= 40959 } { return 2 }
if {$char >= 40960 && $char <= 40980 } { return 2 }
if {$char == 40981} { return 2 }
if {$char >= 40982 && $char <= 42124 } { return 2 }
if {$char >= 42128 && $char <= 42182 } { return 2 }
if {$char >= 43360 && $char <= 43388 } { return 2 }
if {$char >= 44032 && $char <= 55203 } { return 2 }
if {$char >= 63744 && $char <= 64109 } { return 2 }
if {$char >= 64110 && $char <= 64111 } { return 2 }
if {$char >= 64112 && $char <= 64217 } { return 2 }
if {$char >= 64218 && $char <= 64255 } { return 2 }
if {$char >= 65040 && $char <= 65046 } { return 2 }
if {$char == 65047} { return 2 }
if {$char == 65048} { return 2 }
if {$char == 65049} { return 2 }
if {$char == 65072} { return 2 }
if {$char >= 65073 && $char <= 65074 } { return 2 }
if {$char >= 65075 && $char <= 65076 } { return 2 }
if {$char == 65077} { return 2 }
if {$char == 65078} { return 2 }
if {$char == 65079} { return 2 }
if {$char == 65080} { return 2 }
if {$char == 65081} { return 2 }
if {$char == 65082} { return 2 }
if {$char == 65083} { return 2 }
if {$char == 65084} { return 2 }
if {$char == 65085} { return 2 }
if {$char == 65086} { return 2 }
if {$char == 65087} { return 2 }
if {$char == 65088} { return 2 }
if {$char == 65089} { return 2 }
if {$char == 65090} { return 2 }
if {$char == 65091} { return 2 }
if {$char == 65092} { return 2 }
if {$char >= 65093 && $char <= 65094 } { return 2 }
if {$char == 65095} { return 2 }
if {$char == 65096} { return 2 }
if {$char >= 65097 && $char <= 65100 } { return 2 }
if {$char >= 65101 && $char <= 65103 } { return 2 }
if {$char >= 65104 && $char <= 65106 } { return 2 }
if {$char >= 65108 && $char <= 65111 } { return 2 }
if {$char == 65112} { return 2 }
if {$char == 65113} { return 2 }
if {$char == 65114} { return 2 }
if {$char == 65115} { return 2 }
if {$char == 65116} { return 2 }
if {$char == 65117} { return 2 }
if {$char == 65118} { return 2 }
if {$char >= 65119 && $char <= 65121 } { return 2 }
if {$char == 65122} { return 2 }
if {$char == 65123} { return 2 }
if {$char >= 65124 && $char <= 65126 } { return 2 }
if {$char == 65128} { return 2 }
if {$char == 65129} { return 2 }
if {$char >= 65130 && $char <= 65131 } { return 2 }
if {$char >= 65281 && $char <= 65283 } { return 2 }
if {$char == 65284} { return 2 }
if {$char >= 65285 && $char <= 65287 } { return 2 }
if {$char == 65288} { return 2 }
if {$char == 65289} { return 2 }
if {$char == 65290} { return 2 }
if {$char == 65291} { return 2 }
if {$char == 65292} { return 2 }
if {$char == 65293} { return 2 }
if {$char >= 65294 && $char <= 65295 } { return 2 }
if {$char >= 65296 && $char <= 65305 } { return 2 }
if {$char >= 65306 && $char <= 65307 } { return 2 }
if {$char >= 65308 && $char <= 65310 } { return 2 }
if {$char >= 65311 && $char <= 65312 } { return 2 }
if {$char >= 65313 && $char <= 65338 } { return 2 }
if {$char == 65339} { return 2 }
if {$char == 65340} { return 2 }
if {$char == 65341} { return 2 }
if {$char == 65342} { return 2 }
if {$char == 65343} { return 2 }
if {$char == 65344} { return 2 }
if {$char >= 65345 && $char <= 65370 } { return 2 }
if {$char == 65371} { return 2 }
if {$char == 65372} { return 2 }
if {$char == 65373} { return 2 }
if {$char == 65374} { return 2 }
if {$char == 65375} { return 2 }
if {$char == 65376} { return 2 }
if {$char >= 65504 && $char <= 65505 } { return 2 }
if {$char == 65506} { return 2 }
if {$char == 65507} { return 2 }
if {$char == 65508} { return 2 }
if {$char >= 65509 && $char <= 65510 } { return 2 }
if {$char >= 94176 && $char <= 94177 } { return 2 }
if {$char >= 94208 && $char <= 100337 } { return 2 }
if {$char >= 100352 && $char <= 101106 } { return 2 }
if {$char >= 110592 && $char <= 110847 } { return 2 }
if {$char >= 110848 && $char <= 110878 } { return 2 }
if {$char >= 110960 && $char <= 111355 } { return 2 }
if {$char == 126980} { return 2 }
if {$char == 127183} { return 2 }
if {$char == 127374} { return 2 }
if {$char >= 127377 && $char <= 127386 } { return 2 }
if {$char >= 127488 && $char <= 127490 } { return 2 }
if {$char >= 127504 && $char <= 127547 } { return 2 }
if {$char >= 127552 && $char <= 127560 } { return 2 }
if {$char >= 127568 && $char <= 127569 } { return 2 }
if {$char >= 127584 && $char <= 127589 } { return 2 }
if {$char >= 127744 && $char <= 127776 } { return 2 }
if {$char >= 127789 && $char <= 127797 } { return 2 }
if {$char >= 127799 && $char <= 127868 } { return 2 }
if {$char >= 127870 && $char <= 127891 } { return 2 }
if {$char >= 127904 && $char <= 127946 } { return 2 }
if {$char >= 127951 && $char <= 127955 } { return 2 }
if {$char >= 127968 && $char <= 127984 } { return 2 }
if {$char == 127988} { return 2 }
if {$char >= 127992 && $char <= 127994 } { return 2 }
if {$char >= 127995 && $char <= 127999 } { return 2 }
if {$char >= 128000 && $char <= 128062 } { return 2 }
if {$char == 128064} { return 2 }
if {$char >= 128066 && $char <= 128252 } { return 2 }
if {$char >= 128255 && $char <= 128317 } { return 2 }
if {$char >= 128331 && $char <= 128334 } { return 2 }
if {$char >= 128336 && $char <= 128359 } { return 2 }
if {$char == 128378} { return 2 }
if {$char >= 128405 && $char <= 128406 } { return 2 }
if {$char == 128420} { return 2 }
if {$char >= 128507 && $char <= 128511 } { return 2 }
if {$char >= 128512 && $char <= 128591 } { return 2 }
if {$char >= 128640 && $char <= 128709 } { return 2 }
if {$char == 128716} { return 2 }
if {$char >= 128720 && $char <= 128722 } { return 2 }
if {$char >= 128747 && $char <= 128748 } { return 2 }
if {$char >= 128756 && $char <= 128761 } { return 2 }
if {$char >= 129296 && $char <= 129342 } { return 2 }
if {$char >= 129344 && $char <= 129392 } { return 2 }
if {$char >= 129395 && $char <= 129398 } { return 2 }
if {$char == 129402} { return 2 }
if {$char >= 129404 && $char <= 129442 } { return 2 }
if {$char >= 129456 && $char <= 129465 } { return 2 }
if {$char >= 129472 && $char <= 129474 } { return 2 }
if {$char >= 129488 && $char <= 129535 } { return 2 }
if {$char >= 131072 && $char <= 173782 } { return 2 }
if {$char >= 173783 && $char <= 173823 } { return 2 }
if {$char >= 173824 && $char <= 177972 } { return 2 }
if {$char >= 177973 && $char <= 177983 } { return 2 }
if {$char >= 177984 && $char <= 178205 } { return 2 }
if {$char >= 178206 && $char <= 178207 } { return 2 }
if {$char >= 178208 && $char <= 183969 } { return 2 }
if {$char >= 183970 && $char <= 183983 } { return 2 }
if {$char >= 183984 && $char <= 191456 } { return 2 }
if {$char >= 191457 && $char <= 194559 } { return 2 }
if {$char >= 194560 && $char <= 195101 } { return 2 }
if {$char >= 195102 && $char <= 195103 } { return 2 }
if {$char >= 195104 && $char <= 196605 } { return 2 }
if {$char >= 196608 && $char <= 262141 } { return 2 }
return 1
}
proc ::textutil::wcswidth {string} {
set width 0
set len [string length $string]
foreach c [split $string {}] {
scan $c %c char
set n [::textutil::wcswidth_char $char]
if {$n < 0} {
return -1
}
incr width $n
}
return $width
}

140
src/doc/_module_punk_cap-0.1.0.tm.man

@ -0,0 +1,140 @@
[comment {--- punk::docgen generated from inline doctools comments ---}]
[comment {--- punk::docgen DO NOT EDIT DOCS HERE UNLESS YOU REMOVE THESE COMMENT LINES ---}]
[comment {--- punk::docgen overwrites this file ---}]
[manpage_begin punk::cap 0 0.1.0]
[copyright "2023 JMNoble - BSD licensed"]
[titledesc {capability provider and handler plugin system}]
[moddesc {punk capabilities plugin system}]
[require punk::cap]
[description]
[section Overview]
[para]punk::cap provides management of named capabilities and the provider packages and handler packages that implement a pluggable capability.
[subsection Concepts]
[para]A [term capability] may be something like providing a folder of files, or just a data dictionary, and/or an API
[para][term {capability handler}] - a package/namespace which may provide validation and standardised ways of looking up provider data
registered (or not) using register_capabilityname <capname> <capnamespace>
[para][term {capability provider}] - a package which registers as providing one or more capablities.
[para]registered using register_package <pkg> <capabilitylist>
the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability
A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets.
[section API]
[subsection {Namespace punk::cap::class}]
[para] class definitions
[list_begin itemized] [comment {- punk::cap::class groupings -}]
[item]
[para] [emph {handler_classes}]
[list_begin enumerated]
[enum] [emph {CLASS interface_caphandler.registry}]
[list_begin definitions]
[call class::[class interface_caphandler.registry] [method pkg_register] [arg pkg] [arg capname] [arg capdict] [arg fullcapabilitylist]]
handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid
overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes.
[call class::[class interface_caphandler.registry] [method pkg_unregister] [arg pkg]]
[list_end]
[enum] [emph {CLASS interface_caphandler.sysapi}]
[list_begin definitions]
[list_end]
[list_end] [comment {- end enumeration handler classes -}]
[item]
[para] [emph {provider_classes}]
[list_begin enumerated]
[enum] [emph {CLASS interface_cappprovider.registration}]
Your provider package will need to instantiate this object under a sub-namespace called [namespace capsystem] within your package namespace.
[para]If your package namespace is mypackages::providerpkg then the object command would be at mypackages::providerpkg::capsystem::capprovider.registration
[para]Example code for your provider package to evaluate within its namespace:
[example {
namespace eval capsystem {
if {[info commands capprovider.registration] eq ""} {
punk::cap::class::interface_capprovider.registration create capprovider.registration
oo::objdefine capprovider.registration {
method get_declarations {} {
set decls [list]
lappend decls [list punk.templates {relpath ../templates}]
lappend decls [list another_capability_name {somekey blah key2 etc}]
return $decls
}
}
}
}
}]
[para] The above example declares that your package can be registered as a provider for the capabilities named 'punk.templates' and 'another_capability_name'
[list_begin definitions]
[call class::[class interface_capprovider.registration] [method get_declarations]]
[para] This method must be overridden by your provider using oo::objdefine cappprovider.registration as in the example above.
There must be at least one 2-element list in the result for the provider to be registerable.
[para]The first element of the list is the capabilityname - which can be custom to your provider/handler packages - or a well-known name that other authors may use/implement.
[para]The second element is a dictionary of keys specific to the capability being implemented. It may be empty if the any potential capability handlers for the named capability don't require registration data.
[list_end]
[enum] [emph {CLASS interface_capprovider.provider}]
[para] Your provider package will need to instantiate this directly under it's own namespace with the command name of [emph {provider}]
[example {
namespace eval mypackages::providerpkg {
punk::cap::class::interface_capprovider.provider create provider mypackages::providerpkg
}
}]
[list_begin definitions]
[call class::[class interface_capprovider.provider] [method constructor] [arg providerpkg]]
[comment {- -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---}]
[call class::[class interface_capprovider.provider] [method register] [opt capabilityname_glob]]
[para]This is the mechanism by which a user of your provider package will register your package as a provider of the capability named.
[para]A user of your provider may elect to register all your declared capabilities:
[example {
package require mypackages::providerpkg
mypackages::providerpkg::provider register *
}]
[para] Or a specific capability may be registered:
[example {
package require mypackages::providerpkg
mypackages::providerpkg::provider register another_capability_name
}]
[comment {- -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---}]
[call class::[class interface_capprovider.provider] [method capabilities]]
[para] return a list of capabilities supported by this provider package
[list_end] [comment {- end class definitions -}]
[list_end] [comment {- end enumeration provider_classes }]
[list_end] [comment {- end itemized list punk::cap::class groupings -}]
[subsection {Namespace punk::cap}]
[para] Main punk::cap API for client programs interested in using capability handler packages and associated (registered) provider packages
[list_begin definitions]
[call [fun capability_exists] [arg capname]]
Return a boolean indicating if the named capability exists (0|1)
[call [fun capability_has_handler] [arg capname]]
Return a boolean indicating if the named capability has a handler package installed (0|1)
[call [fun capability_get_handler] [arg capname]]
Return the base namespace of the active handler package for the named capability.
[para] The base namespace for a handler will always be the package name, but prefixed with ::
[list_end] [comment {- end definitions for namespace punk::cap -}]
[subsection {Namespace punk::cap::advanced}]
[para] punk::cap::advanced API. Functions here are generally not the preferred way to interact with punk::cap.
[para] In some cases they may allow interaction in less safe ways or may allow use of features that are unavailable in the base namespace.
[para] Some functions are here because they are only marginally or rarely useful, and they are here to keep the base API simple.
[list_begin definitions]
[call advanced::[fun promote_provider] [arg pkg]]
[para]Move the named provider package to the preferred end of the list (tail).
[para]The active handler may or may not utilise this for preferencing. See documentation for the specific handler package to confirm.
[para]
[para] promote/demote doesn't always make a lot of sense .. should preferably be configurable per capapbility for multicap provider pkgs
[para]The idea is to provide a crude way to preference/depreference packages independently of order the packages were loaded
e.g a caller or cap-handler can ascribe some meaning to the order of the 'providers' key returned from punk::cap::capabilities <capname>
[para]The order of providers will be the order the packages were loaded & registered
[para]the naming: "promote vs demote" operates on a latest-package-in-list has higher preference assumption (matching last pkg loaded)
[para]Each capability handler could and should implement specific preferencing methods within its own API if finer control needed.
In some cases the preference/loading order may be inapplicable/irrelevant to a particular capability anyway.
[para]As this is just a basic mechanism, which can't support independent per-cap preferencing for multi-cap packages -
it only allows putting the pkgs to the head or tail of the lists.
[para]Whether particular caps or users of caps do anything with this ordering is dependent on the cap-handler and/or calling code.
[call advanced::[fun demote_provider] [arg pkg]]
[para]Move the named provider package to the preferred end of the list (tail).
[para]The active handler may or may not utilise this for preferencing. See documentation for the specific handler package to confirm.
[list_end]
[section Internal]
[subsection {Namespace punk::cap::capsystem}]
[para] Internal functions used to communicate between punk::cap and capability handlers
[list_begin definitions]
[list_end]
[manpage_end]

23
src/doc/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.man

@ -0,0 +1,23 @@
[comment {--- punk::docgen generated from inline doctools comments ---}]
[comment {--- punk::docgen DO NOT EDIT DOCS HERE UNLESS YOU REMOVE THESE COMMENT LINES ---}]
[comment {--- punk::docgen overwrites this file ---}]
[manpage_begin punk::cap 0 0.1.0]
[copyright "2023 JMNoble - BSD licensed"]
[titledesc {Module API}]
[moddesc {punk capabilities plugin system}]
[require punk::cap]
[description]
[list_begin definitions]
[call [class interface_caphandler.registry] [method pkg_register] [arg pkg] [arg capname] [arg capdict] [arg fullcapabilitylist]]
handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid
overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes.
[call [class interface_caphandler.registry] [method pkg_unregister] [arg pkg]]
[call [class interface_capprovider.registration] [method pkg_unregister] [arg pkg]]
[call [class interface_capprovider.provider] [method register] [opt capabilityname_glob]]
[call [class interface_capprovider.provider] [method capabilities]]
[call [fun exists] [arg capname]]
Return a boolean indicating if the named capability exists (0|1)
[call [fun has_handler] [arg capname]]
Return a boolean indicating if the named capability has a handler package installed (0|1)
[list_end]
[manpage_end]

11
src/doc/_module_punk_mix_templates_modules_template_module-0.0.1.tm.man

@ -0,0 +1,11 @@
[comment {--- punk::docgen generated from inline doctools comments ---}]
[comment {--- punk::docgen DO NOT EDIT DOCS HERE UNLESS YOU REMOVE THESE COMMENT LINES ---}]
[manpage_begin %pkg% 0 999999.0a1.0]
[copyright "%year%"]
[titledesc {Module API}]
[moddesc {-}]
[require %pkg%]
[description]
[list_begin definitions]
[list_end]
[manpage_end]

140
src/docgen/punk_cap-0.1.0.tm.man

@ -0,0 +1,140 @@
[comment {--- punk::docgen generated from inline doctools comments ---}]
[comment {--- punk::docgen DO NOT EDIT DOCS HERE UNLESS YOU REMOVE THESE COMMENT LINES ---}]
[comment {--- punk::docgen overwrites this file ---}]
[manpage_begin punk::cap 0 0.1.0]
[copyright "2023 JMNoble - BSD licensed"]
[titledesc {capability provider and handler plugin system}]
[moddesc {punk capabilities plugin system}]
[require punk::cap]
[description]
[section Overview]
[para]punk::cap provides management of named capabilities and the provider packages and handler packages that implement a pluggable capability.
[subsection Concepts]
[para]A [term capability] may be something like providing a folder of files, or just a data dictionary, and/or an API
[para][term {capability handler}] - a package/namespace which may provide validation and standardised ways of looking up provider data
registered (or not) using register_capabilityname <capname> <capnamespace>
[para][term {capability provider}] - a package which registers as providing one or more capablities.
[para]registered using register_package <pkg> <capabilitylist>
the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability
A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets.
[section API]
[subsection {Namespace punk::cap::class}]
[para] class definitions
[list_begin itemized] [comment {- punk::cap::class groupings -}]
[item]
[para] [emph {handler_classes}]
[list_begin enumerated]
[enum] [emph {CLASS interface_caphandler.registry}]
[list_begin definitions]
[call class::[class interface_caphandler.registry] [method pkg_register] [arg pkg] [arg capname] [arg capdict] [arg fullcapabilitylist]]
handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid
overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes.
[call class::[class interface_caphandler.registry] [method pkg_unregister] [arg pkg]]
[list_end]
[enum] [emph {CLASS interface_caphandler.sysapi}]
[list_begin definitions]
[list_end]
[list_end] [comment {- end enumeration handler classes -}]
[item]
[para] [emph {provider_classes}]
[list_begin enumerated]
[enum] [emph {CLASS interface_cappprovider.registration}]
Your provider package will need to instantiate this object under a sub-namespace called [namespace capsystem] within your package namespace.
[para]If your package namespace is mypackages::providerpkg then the object command would be at mypackages::providerpkg::capsystem::capprovider.registration
[para]Example code for your provider package to evaluate within its namespace:
[example {
namespace eval capsystem {
if {[info commands capprovider.registration] eq ""} {
punk::cap::class::interface_capprovider.registration create capprovider.registration
oo::objdefine capprovider.registration {
method get_declarations {} {
set decls [list]
lappend decls [list punk.templates {relpath ../templates}]
lappend decls [list another_capability_name {somekey blah key2 etc}]
return $decls
}
}
}
}
}]
[para] The above example declares that your package can be registered as a provider for the capabilities named 'punk.templates' and 'another_capability_name'
[list_begin definitions]
[call class::[class interface_capprovider.registration] [method get_declarations]]
[para] This method must be overridden by your provider using oo::objdefine cappprovider.registration as in the example above.
There must be at least one 2-element list in the result for the provider to be registerable.
[para]The first element of the list is the capabilityname - which can be custom to your provider/handler packages - or a well-known name that other authors may use/implement.
[para]The second element is a dictionary of keys specific to the capability being implemented. It may be empty if the any potential capability handlers for the named capability don't require registration data.
[list_end]
[enum] [emph {CLASS interface_capprovider.provider}]
[para] Your provider package will need to instantiate this directly under it's own namespace with the command name of [emph {provider}]
[example {
namespace eval mypackages::providerpkg {
punk::cap::class::interface_capprovider.provider create provider mypackages::providerpkg
}
}]
[list_begin definitions]
[call class::[class interface_capprovider.provider] [method constructor] [arg providerpkg]]
[comment {- -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---}]
[call class::[class interface_capprovider.provider] [method register] [opt capabilityname_glob]]
[para]This is the mechanism by which a user of your provider package will register your package as a provider of the capability named.
[para]A user of your provider may elect to register all your declared capabilities:
[example {
package require mypackages::providerpkg
mypackages::providerpkg::provider register *
}]
[para] Or a specific capability may be registered:
[example {
package require mypackages::providerpkg
mypackages::providerpkg::provider register another_capability_name
}]
[comment {- -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---}]
[call class::[class interface_capprovider.provider] [method capabilities]]
[para] return a list of capabilities supported by this provider package
[list_end] [comment {- end class definitions -}]
[list_end] [comment {- end enumeration provider_classes }]
[list_end] [comment {- end itemized list punk::cap::class groupings -}]
[subsection {Namespace punk::cap}]
[para] Main punk::cap API for client programs interested in using capability handler packages and associated (registered) provider packages
[list_begin definitions]
[call [fun capability_exists] [arg capname]]
Return a boolean indicating if the named capability exists (0|1)
[call [fun capability_has_handler] [arg capname]]
Return a boolean indicating if the named capability has a handler package installed (0|1)
[call [fun capability_get_handler] [arg capname]]
Return the base namespace of the active handler package for the named capability.
[para] The base namespace for a handler will always be the package name, but prefixed with ::
[list_end] [comment {- end definitions for namespace punk::cap -}]
[subsection {Namespace punk::cap::advanced}]
[para] punk::cap::advanced API. Functions here are generally not the preferred way to interact with punk::cap.
[para] In some cases they may allow interaction in less safe ways or may allow use of features that are unavailable in the base namespace.
[para] Some functions are here because they are only marginally or rarely useful, and they are here to keep the base API simple.
[list_begin definitions]
[call advanced::[fun promote_provider] [arg pkg]]
[para]Move the named provider package to the preferred end of the list (tail).
[para]The active handler may or may not utilise this for preferencing. See documentation for the specific handler package to confirm.
[para]
[para] promote/demote doesn't always make a lot of sense .. should preferably be configurable per capapbility for multicap provider pkgs
[para]The idea is to provide a crude way to preference/depreference packages independently of order the packages were loaded
e.g a caller or cap-handler can ascribe some meaning to the order of the 'providers' key returned from punk::cap::capabilities <capname>
[para]The order of providers will be the order the packages were loaded & registered
[para]the naming: "promote vs demote" operates on a latest-package-in-list has higher preference assumption (matching last pkg loaded)
[para]Each capability handler could and should implement specific preferencing methods within its own API if finer control needed.
In some cases the preference/loading order may be inapplicable/irrelevant to a particular capability anyway.
[para]As this is just a basic mechanism, which can't support independent per-cap preferencing for multi-cap packages -
it only allows putting the pkgs to the head or tail of the lists.
[para]Whether particular caps or users of caps do anything with this ordering is dependent on the cap-handler and/or calling code.
[call advanced::[fun demote_provider] [arg pkg]]
[para]Move the named provider package to the preferred end of the list (tail).
[para]The active handler may or may not utilise this for preferencing. See documentation for the specific handler package to confirm.
[list_end]
[section Internal]
[subsection {Namespace punk::cap::capsystem}]
[para] Internal functions used to communicate between punk::cap and capability handlers
[list_begin definitions]
[list_end]
[manpage_end]

23
src/docgen/punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.man

@ -0,0 +1,23 @@
[comment {--- punk::docgen generated from inline doctools comments ---}]
[comment {--- punk::docgen DO NOT EDIT DOCS HERE UNLESS YOU REMOVE THESE COMMENT LINES ---}]
[comment {--- punk::docgen overwrites this file ---}]
[manpage_begin punk::cap 0 0.1.0]
[copyright "2023 JMNoble - BSD licensed"]
[titledesc {Module API}]
[moddesc {punk capabilities plugin system}]
[require punk::cap]
[description]
[list_begin definitions]
[call [class interface_caphandler.registry] [method pkg_register] [arg pkg] [arg capname] [arg capdict] [arg fullcapabilitylist]]
handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid
overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes.
[call [class interface_caphandler.registry] [method pkg_unregister] [arg pkg]]
[call [class interface_capprovider.registration] [method pkg_unregister] [arg pkg]]
[call [class interface_capprovider.provider] [method register] [opt capabilityname_glob]]
[call [class interface_capprovider.provider] [method capabilities]]
[call [fun exists] [arg capname]]
Return a boolean indicating if the named capability exists (0|1)
[call [fun has_handler] [arg capname]]
Return a boolean indicating if the named capability has a handler package installed (0|1)
[list_end]
[manpage_end]

40
src/docgen/punk_mix_templates_modules_template_module-0.0.1.tm.man

@ -0,0 +1,40 @@
[comment {--- punk::docgen generated from inline doctools comments ---}]
[comment {--- punk::docgen DO NOT EDIT DOCS HERE UNLESS YOU REMOVE THESE COMMENT LINES ---}]
[comment {--- punk::docgen overwrites this file ---}]
[manpage_begin %pkg% 0 999999.0a1.0]
[copyright "%year%"]
[titledesc {Module API}]
[moddesc {-}]
[require %pkg%]
[description]
++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
[section Overview]
[para] overview of %pkg%
[subsection Concepts]
[para] -
[subsection dependencies]
[para] packages used by %pkg%
[list_begin itemized]
[item] [package Tcl 8.6]
[list_end]
[section API]
[subsection {Namespace %pkg%::class}]
[para] class definitions
[list_begin enumerated]
[enum] [emph {CLASS interface_sample1}]
[list_begin definitions]
[call class::[class interface_sample1] [method test] [arg arg1]]
[para] test method
[list_end] [comment {-- end definitions interface_sample1}]
[list_end] [comment {--- end class enumeration ---}]
[subsection {Namespace %pkg%}]
[para] Core API functions for %pkg%
[list_begin definitions]
[subsection {Namespace %pkg%::lib}]
[para] Secondary functions that are part of the API
[list_begin definitions]
[list_end] [comment {--- end definitions namespace %pkg%::lib ---}]
[section Internal]
[subsection {Namespace %pkg%::system}]
[para] Internal functions that are not part of the API
[manpage_end]

489
src/embedded/man/files/_module_punk_cap-0.1.0.tm.n

@ -0,0 +1,489 @@
'\"
'\" Generated from file '_module_punk_cap-0\&.1\&.0\&.tm\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2023 JMNoble - BSD licensed
'\"
.TH "punk::cap" 0 0\&.1\&.0 doc "punk capabilities plugin system"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\" Start paragraph describing an argument to a library procedure.
.\" type is type of argument (int, etc.), in/out is either "in", "out",
.\" or "in/out" to describe whether procedure reads or modifies arg,
.\" and indent is equivalent to second arg of .IP (shouldn't ever be
.\" needed; use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\" Give maximum sizes of arguments for setting tab stops. Type and
.\" name are examples of largest possible arguments that will be passed
.\" to .AP later. If args are omitted, default tab stops are used.
.\"
.\" .BS
.\" Start box enclosure. From here until next .BE, everything will be
.\" enclosed in one large box.
.\"
.\" .BE
.\" End of box enclosure.
.\"
.\" .CS
.\" Begin code excerpt.
.\"
.\" .CE
.\" End code excerpt.
.\"
.\" .VS ?version? ?br?
.\" Begin vertical sidebar, for use in marking newly-changed parts
.\" of man pages. The first argument is ignored and used for recording
.\" the version when the .VS was added, so that the sidebars can be
.\" found and removed when they reach a certain age. If another argument
.\" is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\" End of vertical sidebar.
.\"
.\" .DS
.\" Begin an indented unfilled display.
.\"
.\" .DE
.\" End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\" Start of list of standard options for a Tk widget. The manpage
.\" argument defines where to look up the standard options; if
.\" omitted, defaults to "options". The options follow on successive
.\" lines, in three columns separated by tabs.
.\"
.\" .SE
.\" End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\" Start of description of a specific option. cmdName gives the
.\" option's name as specified in the class command, dbName gives
.\" the option's name in the option database, and dbClass gives
.\" the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\" Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\" Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\" Print an open parenthesis, arg1 in quotes, then arg2 normally
.\" (for trailing punctuation) and then a closing parenthesis.
.\"
.\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\" # Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
. ie !"\\$2"" .TP \\n()Cu
. el .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1 \\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\" # define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\" # BS - start boxed text
.\" # ^y = starting y location
.\" # ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\" # BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\" Draw four-sided box normally, but don't draw top of
.\" box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\" # VS - start vertical sidebar
.\" # ^Y = starting y location
.\" # ^v = 1 (for troff; for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\" # VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\" # Special macro to handle page bottom: finish off current
.\" # box/sidebar if in box/sidebar mode, then invoked standard
.\" # page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\" Draw three-sided box if this is the box's first page,
.\" draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\" # DS - begin display
.de DS
.RS
.nf
.sp
..
.\" # DE - end display
.de DE
.fi
.RE
.sp
..
.\" # SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\" # SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\" # OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name: \\fB\\$1\\fR
Database Name: \\fB\\$2\\fR
Database Class: \\fB\\$3\\fR
.fi
.IP
..
.\" # CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\" # CE - end code excerpt
.de CE
.fi
.RE
..
.\" # UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\" # QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\" # PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\" # QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\" # MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
punk::cap \- capability provider and handler plugin system
.SH SYNOPSIS
package require \fBpunk::cap \fR
.sp
class::\fBinterface_caphandler\&.registry\fR \fBpkg_register\fR \fIpkg\fR \fIcapname\fR \fIcapdict\fR \fIfullcapabilitylist\fR
.sp
class::\fBinterface_caphandler\&.registry\fR \fBpkg_unregister\fR \fIpkg\fR
.sp
class::\fBinterface_capprovider\&.registration\fR \fBget_declarations\fR
.sp
class::\fBinterface_capprovider\&.provider\fR \fBconstructor\fR \fIproviderpkg\fR
.sp
class::\fBinterface_capprovider\&.provider\fR \fBregister\fR ?capabilityname_glob?
.sp
class::\fBinterface_capprovider\&.provider\fR \fBcapabilities\fR
.sp
\fBcapability_exists\fR \fIcapname\fR
.sp
\fBcapability_has_handler\fR \fIcapname\fR
.sp
\fBcapability_get_handler\fR \fIcapname\fR
.sp
advanced::\fBpromote_provider\fR \fIpkg\fR
.sp
advanced::\fBdemote_provider\fR \fIpkg\fR
.sp
.BE
.SH DESCRIPTION
.SH OVERVIEW
.PP
punk::cap provides management of named capabilities and the provider packages and handler packages that implement a pluggable capability\&.
.SS CONCEPTS
.PP
A \fIcapability\fR may be something like providing a folder of files, or just a data dictionary, and/or an API
.PP
\fIcapability handler\fR - a package/namespace which may provide validation and standardised ways of looking up provider data
registered (or not) using register_capabilityname <capname> <capnamespace>
.PP
\fIcapability provider\fR - a package which registers as providing one or more capablities\&.
.PP
registered using register_package <pkg> <capabilitylist>
the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability
A capabilityname may appear multiple times\&. ie a package may register that it provides the capability with multiple datasets\&.
.SH API
.SS "NAMESPACE PUNK::CAP::CLASS"
.PP
class definitions
.IP \(bu
.sp
\fIhandler_classes\fR
.RS
.IP [1]
\fICLASS interface_caphandler\&.registry\fR
.RS
.TP
class::\fBinterface_caphandler\&.registry\fR \fBpkg_register\fR \fIpkg\fR \fIcapname\fR \fIcapdict\fR \fIfullcapabilitylist\fR
handler may override and return 0 (indicating don't register)e\&.g if pkg capdict data wasn't valid
overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes\&.
.TP
class::\fBinterface_caphandler\&.registry\fR \fBpkg_unregister\fR \fIpkg\fR
.RE
.IP [2]
\fICLASS interface_caphandler\&.sysapi\fR
.RS
.RE
.RE
.IP \(bu
.sp
\fIprovider_classes\fR
.RS
.IP [1]
\fICLASS interface_cappprovider\&.registration\fR
Your provider package will need to instantiate this object under a sub-namespace called \fBcapsystem\fR within your package namespace\&.
.sp
If your package namespace is mypackages::providerpkg then the object command would be at mypackages::providerpkg::capsystem::capprovider\&.registration
.sp
Example code for your provider package to evaluate within its namespace:
.CS
namespace eval capsystem {
if {[info commands capprovider\&.registration] eq ""} {
punk::cap::class::interface_capprovider\&.registration create capprovider\&.registration
oo::objdefine capprovider\&.registration {
method get_declarations {} {
set decls [list]
lappend decls [list punk\&.templates {relpath \&.\&./templates}]
lappend decls [list another_capability_name {somekey blah key2 etc}]
return $decls
}
}
}
}
.CE
.sp
The above example declares that your package can be registered as a provider for the capabilities named 'punk\&.templates' and 'another_capability_name'
.RS
.TP
class::\fBinterface_capprovider\&.registration\fR \fBget_declarations\fR
.sp
This method must be overridden by your provider using oo::objdefine cappprovider\&.registration as in the example above\&.
There must be at least one 2-element list in the result for the provider to be registerable\&.
.sp
The first element of the list is the capabilityname - which can be custom to your provider/handler packages - or a well-known name that other authors may use/implement\&.
.sp
The second element is a dictionary of keys specific to the capability being implemented\&. It may be empty if the any potential capability handlers for the named capability don't require registration data\&.
.RE
.IP [2]
\fICLASS interface_capprovider\&.provider\fR
.sp
Your provider package will need to instantiate this directly under it's own namespace with the command name of \fIprovider\fR
.CS
namespace eval mypackages::providerpkg {
punk::cap::class::interface_capprovider\&.provider create provider mypackages::providerpkg
}
.CE
.RS
.TP
class::\fBinterface_capprovider\&.provider\fR \fBconstructor\fR \fIproviderpkg\fR
.TP
class::\fBinterface_capprovider\&.provider\fR \fBregister\fR ?capabilityname_glob?
.sp
This is the mechanism by which a user of your provider package will register your package as a provider of the capability named\&.
.sp
A user of your provider may elect to register all your declared capabilities:
.CS
package require mypackages::providerpkg
mypackages::providerpkg::provider register *
.CE
.sp
Or a specific capability may be registered:
.CS
package require mypackages::providerpkg
mypackages::providerpkg::provider register another_capability_name
.CE
.TP
class::\fBinterface_capprovider\&.provider\fR \fBcapabilities\fR
.sp
return a list of capabilities supported by this provider package
.RE
.RE
.PP
.SS "NAMESPACE PUNK::CAP"
.PP
Main punk::cap API for client programs interested in using capability handler packages and associated (registered) provider packages
.TP
\fBcapability_exists\fR \fIcapname\fR
Return a boolean indicating if the named capability exists (0|1)
.TP
\fBcapability_has_handler\fR \fIcapname\fR
Return a boolean indicating if the named capability has a handler package installed (0|1)
.TP
\fBcapability_get_handler\fR \fIcapname\fR
Return the base namespace of the active handler package for the named capability\&.
.sp
The base namespace for a handler will always be the package name, but prefixed with ::
.PP
.SS "NAMESPACE PUNK::CAP::ADVANCED"
.PP
punk::cap::advanced API\&. Functions here are generally not the preferred way to interact with punk::cap\&.
.PP
In some cases they may allow interaction in less safe ways or may allow use of features that are unavailable in the base namespace\&.
.PP
Some functions are here because they are only marginally or rarely useful, and they are here to keep the base API simple\&.
.TP
advanced::\fBpromote_provider\fR \fIpkg\fR
.sp
Move the named provider package to the preferred end of the list (tail)\&.
.sp
The active handler may or may not utilise this for preferencing\&. See documentation for the specific handler package to confirm\&.
.sp
.sp
promote/demote doesn't always make a lot of sense \&.\&. should preferably be configurable per capapbility for multicap provider pkgs
.sp
The idea is to provide a crude way to preference/depreference packages independently of order the packages were loaded
e\&.g a caller or cap-handler can ascribe some meaning to the order of the 'providers' key returned from punk::cap::capabilities <capname>
.sp
The order of providers will be the order the packages were loaded & registered
.sp
the naming: "promote vs demote" operates on a latest-package-in-list has higher preference assumption (matching last pkg loaded)
.sp
Each capability handler could and should implement specific preferencing methods within its own API if finer control needed\&.
In some cases the preference/loading order may be inapplicable/irrelevant to a particular capability anyway\&.
.sp
As this is just a basic mechanism, which can't support independent per-cap preferencing for multi-cap packages -
it only allows putting the pkgs to the head or tail of the lists\&.
.sp
Whether particular caps or users of caps do anything with this ordering is dependent on the cap-handler and/or calling code\&.
.TP
advanced::\fBdemote_provider\fR \fIpkg\fR
.sp
Move the named provider package to the preferred end of the list (tail)\&.
.sp
The active handler may or may not utilise this for preferencing\&. See documentation for the specific handler package to confirm\&.
.PP
.SH INTERNAL
.SS "NAMESPACE PUNK::CAP::CAPSYSTEM"
.PP
Internal functions used to communicate between punk::cap and capability handlers
.PP
.SH COPYRIGHT
.nf
Copyright (c) 2023 JMNoble - BSD licensed
.fi

318
src/embedded/man/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.n

@ -0,0 +1,318 @@
'\"
'\" Generated from file '_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0\&.1\&.0\&.tm\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2023 JMNoble - BSD licensed
'\"
.TH "punk::cap" 0 0\&.1\&.0 doc "punk capabilities plugin system"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\" Start paragraph describing an argument to a library procedure.
.\" type is type of argument (int, etc.), in/out is either "in", "out",
.\" or "in/out" to describe whether procedure reads or modifies arg,
.\" and indent is equivalent to second arg of .IP (shouldn't ever be
.\" needed; use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\" Give maximum sizes of arguments for setting tab stops. Type and
.\" name are examples of largest possible arguments that will be passed
.\" to .AP later. If args are omitted, default tab stops are used.
.\"
.\" .BS
.\" Start box enclosure. From here until next .BE, everything will be
.\" enclosed in one large box.
.\"
.\" .BE
.\" End of box enclosure.
.\"
.\" .CS
.\" Begin code excerpt.
.\"
.\" .CE
.\" End code excerpt.
.\"
.\" .VS ?version? ?br?
.\" Begin vertical sidebar, for use in marking newly-changed parts
.\" of man pages. The first argument is ignored and used for recording
.\" the version when the .VS was added, so that the sidebars can be
.\" found and removed when they reach a certain age. If another argument
.\" is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\" End of vertical sidebar.
.\"
.\" .DS
.\" Begin an indented unfilled display.
.\"
.\" .DE
.\" End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\" Start of list of standard options for a Tk widget. The manpage
.\" argument defines where to look up the standard options; if
.\" omitted, defaults to "options". The options follow on successive
.\" lines, in three columns separated by tabs.
.\"
.\" .SE
.\" End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\" Start of description of a specific option. cmdName gives the
.\" option's name as specified in the class command, dbName gives
.\" the option's name in the option database, and dbClass gives
.\" the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\" Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\" Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\" Print an open parenthesis, arg1 in quotes, then arg2 normally
.\" (for trailing punctuation) and then a closing parenthesis.
.\"
.\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\" # Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
. ie !"\\$2"" .TP \\n()Cu
. el .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1 \\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\" # define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\" # BS - start boxed text
.\" # ^y = starting y location
.\" # ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\" # BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\" Draw four-sided box normally, but don't draw top of
.\" box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\" # VS - start vertical sidebar
.\" # ^Y = starting y location
.\" # ^v = 1 (for troff; for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\" # VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\" # Special macro to handle page bottom: finish off current
.\" # box/sidebar if in box/sidebar mode, then invoked standard
.\" # page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\" Draw three-sided box if this is the box's first page,
.\" draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\" # DS - begin display
.de DS
.RS
.nf
.sp
..
.\" # DE - end display
.de DE
.fi
.RE
.sp
..
.\" # SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\" # SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\" # OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name: \\fB\\$1\\fR
Database Name: \\fB\\$2\\fR
Database Class: \\fB\\$3\\fR
.fi
.IP
..
.\" # CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\" # CE - end code excerpt
.de CE
.fi
.RE
..
.\" # UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\" # QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\" # PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\" # QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\" # MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
punk::cap \- Module API
.SH SYNOPSIS
package require \fBpunk::cap \fR
.sp
\fBinterface_caphandler\&.registry\fR \fBpkg_register\fR \fIpkg\fR \fIcapname\fR \fIcapdict\fR \fIfullcapabilitylist\fR
.sp
\fBinterface_caphandler\&.registry\fR \fBpkg_unregister\fR \fIpkg\fR
.sp
\fBinterface_capprovider\&.registration\fR \fBpkg_unregister\fR \fIpkg\fR
.sp
\fBinterface_capprovider\&.provider\fR \fBregister\fR ?capabilityname_glob?
.sp
\fBinterface_capprovider\&.provider\fR \fBcapabilities\fR
.sp
\fBexists\fR \fIcapname\fR
.sp
\fBhas_handler\fR \fIcapname\fR
.sp
.BE
.SH DESCRIPTION
.TP
\fBinterface_caphandler\&.registry\fR \fBpkg_register\fR \fIpkg\fR \fIcapname\fR \fIcapdict\fR \fIfullcapabilitylist\fR
handler may override and return 0 (indicating don't register)e\&.g if pkg capdict data wasn't valid
overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes\&.
.TP
\fBinterface_caphandler\&.registry\fR \fBpkg_unregister\fR \fIpkg\fR
.TP
\fBinterface_capprovider\&.registration\fR \fBpkg_unregister\fR \fIpkg\fR
.TP
\fBinterface_capprovider\&.provider\fR \fBregister\fR ?capabilityname_glob?
.TP
\fBinterface_capprovider\&.provider\fR \fBcapabilities\fR
.TP
\fBexists\fR \fIcapname\fR
Return a boolean indicating if the named capability exists (0|1)
.TP
\fBhas_handler\fR \fIcapname\fR
Return a boolean indicating if the named capability has a handler package installed (0|1)
.PP
.SH COPYRIGHT
.nf
Copyright (c) 2023 JMNoble - BSD licensed
.fi

286
src/embedded/man/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.n

@ -0,0 +1,286 @@
'\"
'\" Generated from file '_module_punk_mix_templates_modules_template_module-0\&.0\&.1\&.tm\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) %year%
'\"
.TH "%pkg%" 0 999999\&.0a1\&.0 doc "-"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\" Start paragraph describing an argument to a library procedure.
.\" type is type of argument (int, etc.), in/out is either "in", "out",
.\" or "in/out" to describe whether procedure reads or modifies arg,
.\" and indent is equivalent to second arg of .IP (shouldn't ever be
.\" needed; use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\" Give maximum sizes of arguments for setting tab stops. Type and
.\" name are examples of largest possible arguments that will be passed
.\" to .AP later. If args are omitted, default tab stops are used.
.\"
.\" .BS
.\" Start box enclosure. From here until next .BE, everything will be
.\" enclosed in one large box.
.\"
.\" .BE
.\" End of box enclosure.
.\"
.\" .CS
.\" Begin code excerpt.
.\"
.\" .CE
.\" End code excerpt.
.\"
.\" .VS ?version? ?br?
.\" Begin vertical sidebar, for use in marking newly-changed parts
.\" of man pages. The first argument is ignored and used for recording
.\" the version when the .VS was added, so that the sidebars can be
.\" found and removed when they reach a certain age. If another argument
.\" is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\" End of vertical sidebar.
.\"
.\" .DS
.\" Begin an indented unfilled display.
.\"
.\" .DE
.\" End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\" Start of list of standard options for a Tk widget. The manpage
.\" argument defines where to look up the standard options; if
.\" omitted, defaults to "options". The options follow on successive
.\" lines, in three columns separated by tabs.
.\"
.\" .SE
.\" End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\" Start of description of a specific option. cmdName gives the
.\" option's name as specified in the class command, dbName gives
.\" the option's name in the option database, and dbClass gives
.\" the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\" Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\" Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\" Print an open parenthesis, arg1 in quotes, then arg2 normally
.\" (for trailing punctuation) and then a closing parenthesis.
.\"
.\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\" # Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
. ie !"\\$2"" .TP \\n()Cu
. el .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1 \\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\" # define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\" # BS - start boxed text
.\" # ^y = starting y location
.\" # ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\" # BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\" Draw four-sided box normally, but don't draw top of
.\" box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\" # VS - start vertical sidebar
.\" # ^Y = starting y location
.\" # ^v = 1 (for troff; for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\" # VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\" # Special macro to handle page bottom: finish off current
.\" # box/sidebar if in box/sidebar mode, then invoked standard
.\" # page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\" Draw three-sided box if this is the box's first page,
.\" draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\" # DS - begin display
.de DS
.RS
.nf
.sp
..
.\" # DE - end display
.de DE
.fi
.RE
.sp
..
.\" # SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\" # SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\" # OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name: \\fB\\$1\\fR
Database Name: \\fB\\$2\\fR
Database Class: \\fB\\$3\\fR
.fi
.IP
..
.\" # CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\" # CE - end code excerpt
.de CE
.fi
.RE
..
.\" # UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\" # QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\" # PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\" # QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\" # MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
%pkg% \- Module API
.SH SYNOPSIS
package require \fB%pkg% \fR
.sp
.BE
.SH DESCRIPTION
.PP
.SH COPYRIGHT
.nf
Copyright (c) %year%
.fi

9
src/embedded/man/toc.n

@ -273,5 +273,14 @@ Database Class: \\fB\\$3\\fR
doc doc
.RS .RS
.TP .TP
\fB%pkg%\fR
\fIfiles/_module_punk_mix_templates_modules_template_module-0\&.0\&.1\&.tm\&.n\fR: Module API
.TP
\fBpunk::cap\fR
\fIfiles/_module_punk_cap-0\&.1\&.0\&.tm\&.n\fR: capability provider and handler plugin system
.TP
\fBpunk::cap\fR
\fIfiles/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0\&.1\&.0\&.tm\&.n\fR: Module API
.TP
\fBpunkshell\fR \fBpunkshell\fR
\fIfiles/main\&.n\fR: punkshell - Core \fIfiles/main\&.n\fR: punkshell - Core

5
src/embedded/md/.doc/tocdoc

@ -1,3 +1,6 @@
[toc_begin {Table Of Contents} doc] [toc_begin {Table Of Contents} doc]
[item doc/files/main.md punkshell {punkshell - Core}] [item doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.md %pkg% {Module API}]
[item doc/files/_module_punk_cap-0.1.0.tm.md punk::cap {capability provider and handler plugin system}]
[item doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.md punk::cap {Module API}]
[item doc/files/main.md punkshell {punkshell - Core}]
[toc_end] [toc_end]

2
src/embedded/md/.toc

@ -1 +1 @@
doc {doc/toc {{doc/files/main.md punkshell {punkshell - Core}}}} doc {doc/toc {{doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.md %pkg% {Module API}} {doc/files/_module_punk_cap-0.1.0.tm.md punk::cap {capability provider and handler plugin system}} {doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.md punk::cap {Module API}} {doc/files/main.md punkshell {punkshell - Core}}}}

2
src/embedded/md/.xrf

@ -1 +1 @@
{punkshell - Core} doc/files/main.md shell {index.md shell} kw,punk {index.md punk} sa,punkshell(n) doc/files/main.md punkshell(n) doc/files/main.md kw,repl {index.md repl} sa,punkshell doc/files/main.md punkshell doc/files/main.md kw,shell {index.md shell} punk {index.md punk} repl {index.md repl} {capability provider and handler plugin system} doc/files/_module_punk_cap-0.1.0.tm.md repl {index.md repl} %pkg% doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.md kw,punk {index.md punk} %pkg%(0) doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.md punkshell(n) doc/files/main.md sa,punk::cap doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.md punkshell doc/files/main.md sa,punk::cap(0) doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.md {Module API} doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.md shell {index.md shell} kw,repl {index.md repl} sa,%pkg% doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.md {punkshell - Core} doc/files/main.md sa,%pkg%(0) doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.md sa,punkshell(n) doc/files/main.md punk::cap doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.md sa,punkshell doc/files/main.md kw,shell {index.md shell} punk {index.md punk} punk::cap(0) doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.md

262
src/embedded/md/doc/files/_module_punk_cap-0.1.0.tm.md

@ -0,0 +1,262 @@
[//000000001]: # (punk::cap \- punk capabilities plugin system)
[//000000002]: # (Generated from file '\_module\_punk\_cap\-0\.1\.0\.tm\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2023 JMNoble \- BSD licensed)
[//000000004]: # (punk::cap\(0\) 0\.1\.0 doc "punk capabilities plugin system")
<hr> [ <a href="../../toc.md">Main Table Of Contents</a> &#124; <a
href="../toc.md">Table Of Contents</a> &#124; <a
href="../../index.md">Keyword Index</a> ] <hr>
# NAME
punk::cap \- capability provider and handler plugin system
# <a name='toc'></a>Table Of Contents
- [Table Of Contents](#toc)
- [Synopsis](#synopsis)
- [Description](#section1)
- [Overview](#section2)
- [Concepts](#subsection1)
- [API](#section3)
- [Namespace punk::cap::class](#subsection2)
- [Namespace punk::cap](#subsection3)
- [Namespace punk::cap::advanced](#subsection4)
- [Internal](#section4)
- [Namespace punk::cap::capsystem](#subsection5)
- [Copyright](#copyright)
# <a name='synopsis'></a>SYNOPSIS
package require punk::cap
[class::__interface\_caphandler\.registry__ __pkg\_register__ *pkg* *capname* *capdict* *fullcapabilitylist*](#1)
[class::__interface\_caphandler\.registry__ __pkg\_unregister__ *pkg*](#2)
[class::__interface\_capprovider\.registration__ __get\_declarations__](#3)
[class::__interface\_capprovider\.provider__ __constructor__ *providerpkg*](#4)
[class::__interface\_capprovider\.provider__ __register__ ?capabilityname\_glob?](#5)
[class::__interface\_capprovider\.provider__ __capabilities__](#6)
[__capability\_exists__ *capname*](#7)
[__capability\_has\_handler__ *capname*](#8)
[__capability\_get\_handler__ *capname*](#9)
[advanced::__promote\_provider__ *pkg*](#10)
[advanced::__demote\_provider__ *pkg*](#11)
# <a name='description'></a>DESCRIPTION
# <a name='section2'></a>Overview
punk::cap provides management of named capabilities and the provider packages
and handler packages that implement a pluggable capability\.
## <a name='subsection1'></a>Concepts
A *capability* may be something like providing a folder of files, or just a
data dictionary, and/or an API
*capability handler* \- a package/namespace which may provide validation and
standardised ways of looking up provider data registered \(or not\) using
register\_capabilityname <capname> <capnamespace>
*capability provider* \- a package which registers as providing one or more
capablities\.
registered using register\_package <pkg> <capabilitylist> the capabilitylist is a
list of 2\-element lists where the first element is the capabilityname and the
second element is a \(possibly empty\) dict of data relevant to that capability A
capabilityname may appear multiple times\. ie a package may register that it
provides the capability with multiple datasets\.
# <a name='section3'></a>API
## <a name='subsection2'></a>Namespace punk::cap::class
class definitions
- *handler\_classes*
1. *CLASS interface\_caphandler\.registry*
* <a name='1'></a>class::__interface\_caphandler\.registry__ __pkg\_register__ *pkg* *capname* *capdict* *fullcapabilitylist*
handler may override and return 0 \(indicating don't register\)e\.g if
pkg capdict data wasn't valid overridden handler must be able to
handle multiple calls for same pkg \- but it may return 1 or 0 as it
wishes\.
* <a name='2'></a>class::__interface\_caphandler\.registry__ __pkg\_unregister__ *pkg*
1. *CLASS interface\_caphandler\.sysapi*
- *provider\_classes*
1. *CLASS interface\_cappprovider\.registration* Your provider package
will need to instantiate this object under a sub\-namespace called
__capsystem__ within your package namespace\.
If your package namespace is mypackages::providerpkg then the object
command would be at
mypackages::providerpkg::capsystem::capprovider\.registration
Example code for your provider package to evaluate within its
namespace:
namespace eval capsystem {
if {[info commands capprovider.registration] eq ""} {
punk::cap::class::interface_capprovider.registration create capprovider.registration
oo::objdefine capprovider.registration {
method get_declarations {} {
set decls [list]
lappend decls [list punk.templates {relpath ../templates}]
lappend decls [list another_capability_name {somekey blah key2 etc}]
return $decls
}
}
}
}
The above example declares that your package can be registered as a
provider for the capabilities named 'punk\.templates' and
'another\_capability\_name'
* <a name='3'></a>class::__interface\_capprovider\.registration__ __get\_declarations__
This method must be overridden by your provider using oo::objdefine
cappprovider\.registration as in the example above\. There must be at
least one 2\-element list in the result for the provider to be
registerable\.
The first element of the list is the capabilityname \- which can be
custom to your provider/handler packages \- or a well\-known name
that other authors may use/implement\.
The second element is a dictionary of keys specific to the
capability being implemented\. It may be empty if the any potential
capability handlers for the named capability don't require
registration data\.
1. *CLASS interface\_capprovider\.provider*
Your provider package will need to instantiate this directly under it's
own namespace with the command name of *provider*
namespace eval mypackages::providerpkg {
punk::cap::class::interface_capprovider.provider create provider mypackages::providerpkg
}
* <a name='4'></a>class::__interface\_capprovider\.provider__ __constructor__ *providerpkg*
* <a name='5'></a>class::__interface\_capprovider\.provider__ __register__ ?capabilityname\_glob?
This is the mechanism by which a user of your provider package will
register your package as a provider of the capability named\.
A user of your provider may elect to register all your declared
capabilities:
package require mypackages::providerpkg
mypackages::providerpkg::provider register *
Or a specific capability may be registered:
package require mypackages::providerpkg
mypackages::providerpkg::provider register another_capability_name
* <a name='6'></a>class::__interface\_capprovider\.provider__ __capabilities__
return a list of capabilities supported by this provider package
## <a name='subsection3'></a>Namespace punk::cap
Main punk::cap API for client programs interested in using capability handler
packages and associated \(registered\) provider packages
- <a name='7'></a>__capability\_exists__ *capname*
Return a boolean indicating if the named capability exists \(0&#124;1\)
- <a name='8'></a>__capability\_has\_handler__ *capname*
Return a boolean indicating if the named capability has a handler package
installed \(0&#124;1\)
- <a name='9'></a>__capability\_get\_handler__ *capname*
Return the base namespace of the active handler package for the named
capability\.
The base namespace for a handler will always be the package name, but
prefixed with ::
## <a name='subsection4'></a>Namespace punk::cap::advanced
punk::cap::advanced API\. Functions here are generally not the preferred way to
interact with punk::cap\.
In some cases they may allow interaction in less safe ways or may allow use of
features that are unavailable in the base namespace\.
Some functions are here because they are only marginally or rarely useful, and
they are here to keep the base API simple\.
- <a name='10'></a>advanced::__promote\_provider__ *pkg*
Move the named provider package to the preferred end of the list \(tail\)\.
The active handler may or may not utilise this for preferencing\. See
documentation for the specific handler package to confirm\.
promote/demote doesn't always make a lot of sense \.\. should preferably be
configurable per capapbility for multicap provider pkgs
The idea is to provide a crude way to preference/depreference packages
independently of order the packages were loaded e\.g a caller or cap\-handler
can ascribe some meaning to the order of the 'providers' key returned from
punk::cap::capabilities <capname>
The order of providers will be the order the packages were loaded &
registered
the naming: "promote vs demote" operates on a latest\-package\-in\-list has
higher preference assumption \(matching last pkg loaded\)
Each capability handler could and should implement specific preferencing
methods within its own API if finer control needed\. In some cases the
preference/loading order may be inapplicable/irrelevant to a particular
capability anyway\.
As this is just a basic mechanism, which can't support independent per\-cap
preferencing for multi\-cap packages \- it only allows putting the pkgs to the
head or tail of the lists\.
Whether particular caps or users of caps do anything with this ordering is
dependent on the cap\-handler and/or calling code\.
- <a name='11'></a>advanced::__demote\_provider__ *pkg*
Move the named provider package to the preferred end of the list \(tail\)\.
The active handler may or may not utilise this for preferencing\. See
documentation for the specific handler package to confirm\.
# <a name='section4'></a>Internal
## <a name='subsection5'></a>Namespace punk::cap::capsystem
Internal functions used to communicate between punk::cap and capability handlers
# <a name='copyright'></a>COPYRIGHT
Copyright &copy; 2023 JMNoble \- BSD licensed

64
src/embedded/md/doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.md

@ -0,0 +1,64 @@
[//000000001]: # (punk::cap \- punk capabilities plugin system)
[//000000002]: # (Generated from file '\_module\_punk\_mix\_templates\_layouts\_project\_src\_bootsupport\_modules\_punk\_cap\-0\.1\.0\.tm\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2023 JMNoble \- BSD licensed)
[//000000004]: # (punk::cap\(0\) 0\.1\.0 doc "punk capabilities plugin system")
<hr> [ <a href="../../toc.md">Main Table Of Contents</a> &#124; <a
href="../toc.md">Table Of Contents</a> &#124; <a
href="../../index.md">Keyword Index</a> ] <hr>
# NAME
punk::cap \- Module API
# <a name='toc'></a>Table Of Contents
- [Table Of Contents](#toc)
- [Synopsis](#synopsis)
- [Description](#section1)
- [Copyright](#copyright)
# <a name='synopsis'></a>SYNOPSIS
package require punk::cap
[__interface\_caphandler\.registry__ __pkg\_register__ *pkg* *capname* *capdict* *fullcapabilitylist*](#1)
[__interface\_caphandler\.registry__ __pkg\_unregister__ *pkg*](#2)
[__interface\_capprovider\.registration__ __pkg\_unregister__ *pkg*](#3)
[__interface\_capprovider\.provider__ __register__ ?capabilityname\_glob?](#4)
[__interface\_capprovider\.provider__ __capabilities__](#5)
[__exists__ *capname*](#6)
[__has\_handler__ *capname*](#7)
# <a name='description'></a>DESCRIPTION
- <a name='1'></a>__interface\_caphandler\.registry__ __pkg\_register__ *pkg* *capname* *capdict* *fullcapabilitylist*
handler may override and return 0 \(indicating don't register\)e\.g if pkg
capdict data wasn't valid overridden handler must be able to handle multiple
calls for same pkg \- but it may return 1 or 0 as it wishes\.
- <a name='2'></a>__interface\_caphandler\.registry__ __pkg\_unregister__ *pkg*
- <a name='3'></a>__interface\_capprovider\.registration__ __pkg\_unregister__ *pkg*
- <a name='4'></a>__interface\_capprovider\.provider__ __register__ ?capabilityname\_glob?
- <a name='5'></a>__interface\_capprovider\.provider__ __capabilities__
- <a name='6'></a>__exists__ *capname*
Return a boolean indicating if the named capability exists \(0&#124;1\)
- <a name='7'></a>__has\_handler__ *capname*
Return a boolean indicating if the named capability has a handler package
installed \(0&#124;1\)
# <a name='copyright'></a>COPYRIGHT
Copyright &copy; 2023 JMNoble \- BSD licensed

33
src/embedded/md/doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.md

@ -0,0 +1,33 @@
[//000000001]: # (%pkg% \- \-)
[//000000002]: # (Generated from file '\_module\_punk\_mix\_templates\_modules\_template\_module\-0\.0\.1\.tm\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; %year%)
[//000000004]: # (%pkg%\(0\) 999999\.0a1\.0 doc "\-")
<hr> [ <a href="../../toc.md">Main Table Of Contents</a> &#124; <a
href="../toc.md">Table Of Contents</a> &#124; <a
href="../../index.md">Keyword Index</a> ] <hr>
# NAME
%pkg% \- Module API
# <a name='toc'></a>Table Of Contents
- [Table Of Contents](#toc)
- [Synopsis](#synopsis)
- [Description](#section1)
- [Copyright](#copyright)
# <a name='synopsis'></a>SYNOPSIS
package require %pkg%
# <a name='description'></a>DESCRIPTION
# <a name='copyright'></a>COPYRIGHT
Copyright &copy; %year%

6
src/embedded/md/doc/toc.md

@ -3,4 +3,10 @@
# Table Of Contents \-\- doc # Table Of Contents \-\- doc
- [%pkg%](doc/files/\_module\_punk\_mix\_templates\_modules\_template\_module\-0\.0\.1\.tm\.md) Module API
- [punk::cap](doc/files/\_module\_punk\_cap\-0\.1\.0\.tm\.md) capability provider and handler plugin system
- [punk::cap](doc/files/\_module\_punk\_mix\_templates\_layouts\_project\_src\_bootsupport\_modules\_punk\_cap\-0\.1\.0\.tm\.md) Module API
- [punkshell](doc/files/main\.md) punkshell \- Core - [punkshell](doc/files/main\.md) punkshell \- Core

6
src/embedded/md/toc.md

@ -3,4 +3,10 @@
# Table Of Contents \-\- doc # Table Of Contents \-\- doc
- [%pkg%](doc/files/\_module\_punk\_mix\_templates\_modules\_template\_module\-0\.0\.1\.tm\.md) Module API
- [punk::cap](doc/files/\_module\_punk\_cap\-0\.1\.0\.tm\.md) capability provider and handler plugin system
- [punk::cap](doc/files/\_module\_punk\_mix\_templates\_layouts\_project\_src\_bootsupport\_modules\_punk\_cap\-0\.1\.0\.tm\.md) Module API
- [punkshell](doc/files/main\.md) punkshell \- Core - [punkshell](doc/files/main\.md) punkshell \- Core

5
src/embedded/www/.doc/tocdoc

@ -1,3 +1,6 @@
[toc_begin {Table Of Contents} doc] [toc_begin {Table Of Contents} doc]
[item doc/files/main.html punkshell {punkshell - Core}] [item doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.html %pkg% {Module API}]
[item doc/files/_module_punk_cap-0.1.0.tm.html punk::cap {capability provider and handler plugin system}]
[item doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.html punk::cap {Module API}]
[item doc/files/main.html punkshell {punkshell - Core}]
[toc_end] [toc_end]

2
src/embedded/www/.toc

@ -1 +1 @@
doc {doc/toc {{doc/files/main.html punkshell {punkshell - Core}}}} doc {doc/toc {{doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.html %pkg% {Module API}} {doc/files/_module_punk_cap-0.1.0.tm.html punk::cap {capability provider and handler plugin system}} {doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.html punk::cap {Module API}} {doc/files/main.html punkshell {punkshell - Core}}}}

2
src/embedded/www/.xrf

@ -1 +1 @@
{punkshell - Core} doc/files/main.html shell {index.html shell} kw,punk {index.html punk} sa,punkshell(n) doc/files/main.html punkshell(n) doc/files/main.html kw,repl {index.html repl} sa,punkshell doc/files/main.html punkshell doc/files/main.html kw,shell {index.html shell} punk {index.html punk} repl {index.html repl} {capability provider and handler plugin system} doc/files/_module_punk_cap-0.1.0.tm.html repl {index.html repl} %pkg% doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.html kw,punk {index.html punk} %pkg%(0) doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.html punkshell(n) doc/files/main.html sa,punk::cap doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.html punkshell doc/files/main.html sa,punk::cap(0) doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.html {Module API} doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.html shell {index.html shell} kw,repl {index.html repl} sa,%pkg% doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.html {punkshell - Core} doc/files/main.html sa,%pkg%(0) doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.html sa,punkshell(n) doc/files/main.html punk::cap doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.html sa,punkshell doc/files/main.html kw,shell {index.html shell} punk {index.html punk} punk::cap(0) doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.html

301
src/embedded/www/doc/files/_module_punk_cap-0.1.0.tm.html

@ -0,0 +1,301 @@
<!DOCTYPE html><html><head>
<title>punk::cap - punk capabilities plugin system</title>
<style type="text/css"><!--
HTML {
background: #FFFFFF;
color: black;
}
BODY {
background: #FFFFFF;
color: black;
}
DIV.doctools {
margin-left: 10%;
margin-right: 10%;
}
DIV.doctools H1,DIV.doctools H2 {
margin-left: -5%;
}
H1, H2, H3, H4 {
margin-top: 1em;
font-family: sans-serif;
font-size: large;
color: #005A9C;
background: transparent;
text-align: left;
}
H1.doctools_title {
text-align: center;
}
UL,OL {
margin-right: 0em;
margin-top: 3pt;
margin-bottom: 3pt;
}
UL LI {
list-style: disc;
}
OL LI {
list-style: decimal;
}
DT {
padding-top: 1ex;
}
UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
font: normal 12pt/14pt sans-serif;
list-style: none;
}
LI.doctools_section, LI.doctools_subsection {
list-style: none;
margin-left: 0em;
text-indent: 0em;
padding: 0em;
}
PRE {
display: block;
font-family: monospace;
white-space: pre;
margin: 0%;
padding-top: 0.5ex;
padding-bottom: 0.5ex;
padding-left: 1ex;
padding-right: 1ex;
width: 100%;
}
PRE.doctools_example {
color: black;
background: #f5dcb3;
border: 1px solid black;
}
UL.doctools_requirements LI, UL.doctools_syntax LI {
list-style: none;
margin-left: 0em;
text-indent: 0em;
padding: 0em;
}
DIV.doctools_synopsis {
color: black;
background: #80ffff;
border: 1px solid black;
font-family: serif;
margin-top: 1em;
margin-bottom: 1em;
}
UL.doctools_syntax {
margin-top: 1em;
border-top: 1px solid black;
}
UL.doctools_requirements {
margin-bottom: 1em;
border-bottom: 1px solid black;
}
--></style>
</head>
<!-- Generated from file '_module_punk_cap-0.1.0.tm.man' by tcllib/doctools with format 'html'
-->
<!-- Copyright &amp;copy; 2023 JMNoble - BSD licensed
-->
<!-- punk::cap.0
-->
<body><hr> [
<a href="../../toc.html">Main Table Of Contents</a>
&#124; <a href="../toc.html">Table Of Contents</a>
&#124; <a href="../../index.html">Keyword Index</a>
] <hr>
<div class="doctools">
<h1 class="doctools_title">punk::cap(0) 0.1.0 doc &quot;punk capabilities plugin system&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>punk::cap - capability provider and handler plugin system</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Overview</a>
<ul>
<li class="doctools_subsection"><a href="#subsection1">Concepts</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section3">API</a>
<ul>
<li class="doctools_subsection"><a href="#subsection2">Namespace punk::cap::class</a></li>
<li class="doctools_subsection"><a href="#subsection3">Namespace punk::cap</a></li>
<li class="doctools_subsection"><a href="#subsection4">Namespace punk::cap::advanced</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section4">Internal</a>
<ul>
<li class="doctools_subsection"><a href="#subsection5">Namespace punk::cap::capsystem</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">punk::cap</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1">class::<b class="class">interface_caphandler.registry</b> <b class="method">pkg_register</b> <i class="arg">pkg</i> <i class="arg">capname</i> <i class="arg">capdict</i> <i class="arg">fullcapabilitylist</i></a></li>
<li><a href="#2">class::<b class="class">interface_caphandler.registry</b> <b class="method">pkg_unregister</b> <i class="arg">pkg</i></a></li>
<li><a href="#3">class::<b class="class">interface_capprovider.registration</b> <b class="method">get_declarations</b></a></li>
<li><a href="#4">class::<b class="class">interface_capprovider.provider</b> <b class="method">constructor</b> <i class="arg">providerpkg</i></a></li>
<li><a href="#5">class::<b class="class">interface_capprovider.provider</b> <b class="method">register</b> <span class="opt">?capabilityname_glob?</span></a></li>
<li><a href="#6">class::<b class="class">interface_capprovider.provider</b> <b class="method">capabilities</b></a></li>
<li><a href="#7"><b class="function">capability_exists</b> <i class="arg">capname</i></a></li>
<li><a href="#8"><b class="function">capability_has_handler</b> <i class="arg">capname</i></a></li>
<li><a href="#9"><b class="function">capability_get_handler</b> <i class="arg">capname</i></a></li>
<li><a href="#10">advanced::<b class="function">promote_provider</b> <i class="arg">pkg</i></a></li>
<li><a href="#11">advanced::<b class="function">demote_provider</b> <i class="arg">pkg</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Overview</a></h2>
<p>punk::cap provides management of named capabilities and the provider packages and handler packages that implement a pluggable capability.</p>
<div id="subsection1" class="doctools_subsection"><h3><a name="subsection1">Concepts</a></h3>
<p>A <i class="term">capability</i> may be something like providing a folder of files, or just a data dictionary, and/or an API</p>
<p><i class="term">capability handler</i> - a package/namespace which may provide validation and standardised ways of looking up provider data
registered (or not) using register_capabilityname &lt;capname&gt; &lt;capnamespace&gt;</p>
<p><i class="term">capability provider</i> - a package which registers as providing one or more capablities.</p>
<p>registered using register_package &lt;pkg&gt; &lt;capabilitylist&gt;
the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability
A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets.</p>
</div>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">API</a></h2>
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">Namespace punk::cap::class</a></h3>
<p>class definitions</p>
<ul class="doctools_itemized">
<li><p><em>handler_classes</em></p>
<ol class="doctools_enumerated">
<li><p><em>CLASS interface_caphandler.registry</em></p>
<dl class="doctools_definitions">
<dt><a name="1">class::<b class="class">interface_caphandler.registry</b> <b class="method">pkg_register</b> <i class="arg">pkg</i> <i class="arg">capname</i> <i class="arg">capdict</i> <i class="arg">fullcapabilitylist</i></a></dt>
<dd><p>handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid
overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes.</p></dd>
<dt><a name="2">class::<b class="class">interface_caphandler.registry</b> <b class="method">pkg_unregister</b> <i class="arg">pkg</i></a></dt>
<dd></dd>
</dl>
</li>
<li><p><em>CLASS interface_caphandler.sysapi</em></p>
<dl class="doctools_definitions">
</dl>
</li>
</ol>
</li>
<li><p><em>provider_classes</em></p>
<ol class="doctools_enumerated">
<li><p><em>CLASS interface_cappprovider.registration</em>
Your provider package will need to instantiate this object under a sub-namespace called <b class="namespace">capsystem</b> within your package namespace.</p>
<p>If your package namespace is mypackages::providerpkg then the object command would be at mypackages::providerpkg::capsystem::capprovider.registration</p>
<p>Example code for your provider package to evaluate within its namespace:</p>
<pre class="doctools_example">
namespace eval capsystem {
if {[info commands capprovider.registration] eq &quot;&quot;} {
punk::cap::class::interface_capprovider.registration create capprovider.registration
oo::objdefine capprovider.registration {
method get_declarations {} {
set decls [list]
lappend decls [list punk.templates {relpath ../templates}]
lappend decls [list another_capability_name {somekey blah key2 etc}]
return $decls
}
}
}
}
</pre>
<p>The above example declares that your package can be registered as a provider for the capabilities named 'punk.templates' and 'another_capability_name'</p>
<dl class="doctools_definitions">
<dt><a name="3">class::<b class="class">interface_capprovider.registration</b> <b class="method">get_declarations</b></a></dt>
<dd><p>This method must be overridden by your provider using oo::objdefine cappprovider.registration as in the example above.
There must be at least one 2-element list in the result for the provider to be registerable.</p>
<p>The first element of the list is the capabilityname - which can be custom to your provider/handler packages - or a well-known name that other authors may use/implement.</p>
<p>The second element is a dictionary of keys specific to the capability being implemented. It may be empty if the any potential capability handlers for the named capability don't require registration data.</p></dd>
</dl>
</li>
<li><p><em>CLASS interface_capprovider.provider</em></p>
<p>Your provider package will need to instantiate this directly under it's own namespace with the command name of <em>provider</em></p>
<pre class="doctools_example">
namespace eval mypackages::providerpkg {
punk::cap::class::interface_capprovider.provider create provider mypackages::providerpkg
}
</pre>
<dl class="doctools_definitions">
<dt><a name="4">class::<b class="class">interface_capprovider.provider</b> <b class="method">constructor</b> <i class="arg">providerpkg</i></a></dt>
<dd></dd>
<dt><a name="5">class::<b class="class">interface_capprovider.provider</b> <b class="method">register</b> <span class="opt">?capabilityname_glob?</span></a></dt>
<dd><p>This is the mechanism by which a user of your provider package will register your package as a provider of the capability named.</p>
<p>A user of your provider may elect to register all your declared capabilities:</p>
<pre class="doctools_example">
package require mypackages::providerpkg
mypackages::providerpkg::provider register *
</pre>
<p>Or a specific capability may be registered:</p>
<pre class="doctools_example">
package require mypackages::providerpkg
mypackages::providerpkg::provider register another_capability_name
</pre>
</dd>
<dt><a name="6">class::<b class="class">interface_capprovider.provider</b> <b class="method">capabilities</b></a></dt>
<dd><p>return a list of capabilities supported by this provider package</p></dd>
</dl>
</li>
</ol>
</li>
</ul>
</div>
<div id="subsection3" class="doctools_subsection"><h3><a name="subsection3">Namespace punk::cap</a></h3>
<p>Main punk::cap API for client programs interested in using capability handler packages and associated (registered) provider packages</p>
<dl class="doctools_definitions">
<dt><a name="7"><b class="function">capability_exists</b> <i class="arg">capname</i></a></dt>
<dd><p>Return a boolean indicating if the named capability exists (0|1)</p></dd>
<dt><a name="8"><b class="function">capability_has_handler</b> <i class="arg">capname</i></a></dt>
<dd><p>Return a boolean indicating if the named capability has a handler package installed (0|1)</p></dd>
<dt><a name="9"><b class="function">capability_get_handler</b> <i class="arg">capname</i></a></dt>
<dd><p>Return the base namespace of the active handler package for the named capability.</p>
<p>The base namespace for a handler will always be the package name, but prefixed with ::</p></dd>
</dl>
</div>
<div id="subsection4" class="doctools_subsection"><h3><a name="subsection4">Namespace punk::cap::advanced</a></h3>
<p>punk::cap::advanced API. Functions here are generally not the preferred way to interact with punk::cap.</p>
<p>In some cases they may allow interaction in less safe ways or may allow use of features that are unavailable in the base namespace.</p>
<p>Some functions are here because they are only marginally or rarely useful, and they are here to keep the base API simple.</p>
<dl class="doctools_definitions">
<dt><a name="10">advanced::<b class="function">promote_provider</b> <i class="arg">pkg</i></a></dt>
<dd><p>Move the named provider package to the preferred end of the list (tail).</p>
<p>The active handler may or may not utilise this for preferencing. See documentation for the specific handler package to confirm.</p>
<p>promote/demote doesn't always make a lot of sense .. should preferably be configurable per capapbility for multicap provider pkgs</p>
<p>The idea is to provide a crude way to preference/depreference packages independently of order the packages were loaded
e.g a caller or cap-handler can ascribe some meaning to the order of the 'providers' key returned from punk::cap::capabilities &lt;capname&gt;</p>
<p>The order of providers will be the order the packages were loaded &amp; registered</p>
<p>the naming: &quot;promote vs demote&quot; operates on a latest-package-in-list has higher preference assumption (matching last pkg loaded)</p>
<p>Each capability handler could and should implement specific preferencing methods within its own API if finer control needed.
In some cases the preference/loading order may be inapplicable/irrelevant to a particular capability anyway.</p>
<p>As this is just a basic mechanism, which can't support independent per-cap preferencing for multi-cap packages -
it only allows putting the pkgs to the head or tail of the lists.</p>
<p>Whether particular caps or users of caps do anything with this ordering is dependent on the cap-handler and/or calling code.</p></dd>
<dt><a name="11">advanced::<b class="function">demote_provider</b> <i class="arg">pkg</i></a></dt>
<dd><p>Move the named provider package to the preferred end of the list (tail).</p>
<p>The active handler may or may not utilise this for preferencing. See documentation for the specific handler package to confirm.</p></dd>
</dl>
</div>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">Internal</a></h2>
<div id="subsection5" class="doctools_subsection"><h3><a name="subsection5">Namespace punk::cap::capsystem</a></h3>
<p>Internal functions used to communicate between punk::cap and capability handlers</p>
<dl class="doctools_definitions">
</dl>
</div>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2023 JMNoble - BSD licensed</p>
</div>
</div></body></html>

156
src/embedded/www/doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.html

@ -0,0 +1,156 @@
<!DOCTYPE html><html><head>
<title>punk::cap - punk capabilities plugin system</title>
<style type="text/css"><!--
HTML {
background: #FFFFFF;
color: black;
}
BODY {
background: #FFFFFF;
color: black;
}
DIV.doctools {
margin-left: 10%;
margin-right: 10%;
}
DIV.doctools H1,DIV.doctools H2 {
margin-left: -5%;
}
H1, H2, H3, H4 {
margin-top: 1em;
font-family: sans-serif;
font-size: large;
color: #005A9C;
background: transparent;
text-align: left;
}
H1.doctools_title {
text-align: center;
}
UL,OL {
margin-right: 0em;
margin-top: 3pt;
margin-bottom: 3pt;
}
UL LI {
list-style: disc;
}
OL LI {
list-style: decimal;
}
DT {
padding-top: 1ex;
}
UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
font: normal 12pt/14pt sans-serif;
list-style: none;
}
LI.doctools_section, LI.doctools_subsection {
list-style: none;
margin-left: 0em;
text-indent: 0em;
padding: 0em;
}
PRE {
display: block;
font-family: monospace;
white-space: pre;
margin: 0%;
padding-top: 0.5ex;
padding-bottom: 0.5ex;
padding-left: 1ex;
padding-right: 1ex;
width: 100%;
}
PRE.doctools_example {
color: black;
background: #f5dcb3;
border: 1px solid black;
}
UL.doctools_requirements LI, UL.doctools_syntax LI {
list-style: none;
margin-left: 0em;
text-indent: 0em;
padding: 0em;
}
DIV.doctools_synopsis {
color: black;
background: #80ffff;
border: 1px solid black;
font-family: serif;
margin-top: 1em;
margin-bottom: 1em;
}
UL.doctools_syntax {
margin-top: 1em;
border-top: 1px solid black;
}
UL.doctools_requirements {
margin-bottom: 1em;
border-bottom: 1px solid black;
}
--></style>
</head>
<!-- Generated from file '_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.man' by tcllib/doctools with format 'html'
-->
<!-- Copyright &amp;copy; 2023 JMNoble - BSD licensed
-->
<!-- punk::cap.0
-->
<body><hr> [
<a href="../../toc.html">Main Table Of Contents</a>
&#124; <a href="../toc.html">Table Of Contents</a>
&#124; <a href="../../index.html">Keyword Index</a>
] <hr>
<div class="doctools">
<h1 class="doctools_title">punk::cap(0) 0.1.0 doc &quot;punk capabilities plugin system&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>punk::cap - Module API</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">punk::cap</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="class">interface_caphandler.registry</b> <b class="method">pkg_register</b> <i class="arg">pkg</i> <i class="arg">capname</i> <i class="arg">capdict</i> <i class="arg">fullcapabilitylist</i></a></li>
<li><a href="#2"><b class="class">interface_caphandler.registry</b> <b class="method">pkg_unregister</b> <i class="arg">pkg</i></a></li>
<li><a href="#3"><b class="class">interface_capprovider.registration</b> <b class="method">pkg_unregister</b> <i class="arg">pkg</i></a></li>
<li><a href="#4"><b class="class">interface_capprovider.provider</b> <b class="method">register</b> <span class="opt">?capabilityname_glob?</span></a></li>
<li><a href="#5"><b class="class">interface_capprovider.provider</b> <b class="method">capabilities</b></a></li>
<li><a href="#6"><b class="function">exists</b> <i class="arg">capname</i></a></li>
<li><a href="#7"><b class="function">has_handler</b> <i class="arg">capname</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<dl class="doctools_definitions">
<dt><a name="1"><b class="class">interface_caphandler.registry</b> <b class="method">pkg_register</b> <i class="arg">pkg</i> <i class="arg">capname</i> <i class="arg">capdict</i> <i class="arg">fullcapabilitylist</i></a></dt>
<dd><p>handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid
overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes.</p></dd>
<dt><a name="2"><b class="class">interface_caphandler.registry</b> <b class="method">pkg_unregister</b> <i class="arg">pkg</i></a></dt>
<dd></dd>
<dt><a name="3"><b class="class">interface_capprovider.registration</b> <b class="method">pkg_unregister</b> <i class="arg">pkg</i></a></dt>
<dd></dd>
<dt><a name="4"><b class="class">interface_capprovider.provider</b> <b class="method">register</b> <span class="opt">?capabilityname_glob?</span></a></dt>
<dd></dd>
<dt><a name="5"><b class="class">interface_capprovider.provider</b> <b class="method">capabilities</b></a></dt>
<dd></dd>
<dt><a name="6"><b class="function">exists</b> <i class="arg">capname</i></a></dt>
<dd><p>Return a boolean indicating if the named capability exists (0|1)</p></dd>
<dt><a name="7"><b class="function">has_handler</b> <i class="arg">capname</i></a></dt>
<dd><p>Return a boolean indicating if the named capability has a handler package installed (0|1)</p></dd>
</dl>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2023 JMNoble - BSD licensed</p>
</div>
</div></body></html>

132
src/embedded/www/doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.html

@ -0,0 +1,132 @@
<!DOCTYPE html><html><head>
<title>%pkg% - -</title>
<style type="text/css"><!--
HTML {
background: #FFFFFF;
color: black;
}
BODY {
background: #FFFFFF;
color: black;
}
DIV.doctools {
margin-left: 10%;
margin-right: 10%;
}
DIV.doctools H1,DIV.doctools H2 {
margin-left: -5%;
}
H1, H2, H3, H4 {
margin-top: 1em;
font-family: sans-serif;
font-size: large;
color: #005A9C;
background: transparent;
text-align: left;
}
H1.doctools_title {
text-align: center;
}
UL,OL {
margin-right: 0em;
margin-top: 3pt;
margin-bottom: 3pt;
}
UL LI {
list-style: disc;
}
OL LI {
list-style: decimal;
}
DT {
padding-top: 1ex;
}
UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
font: normal 12pt/14pt sans-serif;
list-style: none;
}
LI.doctools_section, LI.doctools_subsection {
list-style: none;
margin-left: 0em;
text-indent: 0em;
padding: 0em;
}
PRE {
display: block;
font-family: monospace;
white-space: pre;
margin: 0%;
padding-top: 0.5ex;
padding-bottom: 0.5ex;
padding-left: 1ex;
padding-right: 1ex;
width: 100%;
}
PRE.doctools_example {
color: black;
background: #f5dcb3;
border: 1px solid black;
}
UL.doctools_requirements LI, UL.doctools_syntax LI {
list-style: none;
margin-left: 0em;
text-indent: 0em;
padding: 0em;
}
DIV.doctools_synopsis {
color: black;
background: #80ffff;
border: 1px solid black;
font-family: serif;
margin-top: 1em;
margin-bottom: 1em;
}
UL.doctools_syntax {
margin-top: 1em;
border-top: 1px solid black;
}
UL.doctools_requirements {
margin-bottom: 1em;
border-bottom: 1px solid black;
}
--></style>
</head>
<!-- Generated from file '_module_punk_mix_templates_modules_template_module-0.0.1.tm.man' by tcllib/doctools with format 'html'
-->
<!-- Copyright &amp;copy; %year%
-->
<!-- %pkg%.0
-->
<body><hr> [
<a href="../../toc.html">Main Table Of Contents</a>
&#124; <a href="../toc.html">Table Of Contents</a>
&#124; <a href="../../index.html">Keyword Index</a>
] <hr>
<div class="doctools">
<h1 class="doctools_title">%pkg%(0) 999999.0a1.0 doc &quot;-&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>%pkg% - Module API</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">%pkg%</b></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<dl class="doctools_definitions">
</dl>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; %year%</p>
</div>
</div></body></html>

12
src/embedded/www/doc/toc.html

@ -13,6 +13,18 @@
<hr><dl><dt><h2>doc</h2></dt><dd> <hr><dl><dt><h2>doc</h2></dt><dd>
<table class="#doctools_toc"> <table class="#doctools_toc">
<tr class="#doctools_toceven" > <tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='_pkg_'><a href="files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.html">%pkg%</a></td>
<td class="#doctools_tocright">Module API</td>
</tr>
<tr class="#doctools_tocodd" >
<td class="#doctools_tocleft" ><a name='punk_cap'><a href="files/_module_punk_cap-0.1.0.tm.html">punk::cap</a></td>
<td class="#doctools_tocright">capability provider and handler plugin system</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='punk_cap'><a href="files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.html">punk::cap</a></td>
<td class="#doctools_tocright">Module API</td>
</tr>
<tr class="#doctools_tocodd" >
<td class="#doctools_tocleft" ><a name='punkshell'><a href="files/main.html">punkshell</a></td> <td class="#doctools_tocleft" ><a name='punkshell'><a href="files/main.html">punkshell</a></td>
<td class="#doctools_tocright">punkshell - Core</td> <td class="#doctools_tocright">punkshell - Core</td>
</tr> </tr>

12
src/embedded/www/toc.html

@ -13,6 +13,18 @@
<hr><dl><dt><h2>doc</h2></dt><dd> <hr><dl><dt><h2>doc</h2></dt><dd>
<table class="#doctools_toc"> <table class="#doctools_toc">
<tr class="#doctools_toceven" > <tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='_pkg_'><a href="doc/files/_module_punk_mix_templates_modules_template_module-0.0.1.tm.html">%pkg%</a></td>
<td class="#doctools_tocright">Module API</td>
</tr>
<tr class="#doctools_tocodd" >
<td class="#doctools_tocleft" ><a name='punk_cap'><a href="doc/files/_module_punk_cap-0.1.0.tm.html">punk::cap</a></td>
<td class="#doctools_tocright">capability provider and handler plugin system</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='punk_cap'><a href="doc/files/_module_punk_mix_templates_layouts_project_src_bootsupport_modules_punk_cap-0.1.0.tm.html">punk::cap</a></td>
<td class="#doctools_tocright">Module API</td>
</tr>
<tr class="#doctools_tocodd" >
<td class="#doctools_tocleft" ><a name='punkshell'><a href="doc/files/main.html">punkshell</a></td> <td class="#doctools_tocleft" ><a name='punkshell'><a href="doc/files/main.html">punkshell</a></td>
<td class="#doctools_tocright">punkshell - Core</td> <td class="#doctools_tocright">punkshell - Core</td>
</tr> </tr>

16
src/make.tcl

@ -378,7 +378,7 @@ if {$::punkmake::command eq "bootsupport"} {
set project_layouts [glob -nocomplain -dir $project_layout_base -type d -tail *] set project_layouts [glob -nocomplain -dir $project_layout_base -type d -tail *]
foreach layoutname $project_layouts { foreach layoutname $project_layouts {
if {[file exists [file join $project_layout_base $layoutname/src/bootsupport]]} { if {[file exists [file join $project_layout_base $layoutname/src/bootsupport]]} {
set unpublish [list\ set antipaths [list\
README.md\ README.md\
] ]
set sourcemodules $projectroot/src/bootsupport/modules set sourcemodules $projectroot/src/bootsupport/modules
@ -386,7 +386,7 @@ if {$::punkmake::command eq "bootsupport"} {
file mkdir $targetroot file mkdir $targetroot
puts stdout "BOOTSUPPORT layouts/$layoutname: copying from $sourcemodules to $targetroot (if source file changed)" puts stdout "BOOTSUPPORT layouts/$layoutname: copying from $sourcemodules to $targetroot (if source file changed)"
set resultdict [punkcheck::install $sourcemodules $targetroot -overwrite installedsourcechanged-targets -unpublish_paths $unpublish] set resultdict [punkcheck::install $sourcemodules $targetroot -overwrite installedsourcechanged-targets -antiglob_paths $antipaths]
puts stdout [punkcheck::summarize_install_resultdict $resultdict] puts stdout [punkcheck::summarize_install_resultdict $resultdict]
flush stdout flush stdout
} }
@ -420,17 +420,17 @@ file mkdir $target_modules_base
#external libs and modules first - and any supporting files - no 'building' required #external libs and modules first - and any supporting files - no 'building' required
if {[file exists $sourcefolder/vendorlib]} { if {[file exists $sourcefolder/vendorlib]} {
#unpublish README.md from source folder - but only the root one #exclude README.md from source folder - but only the root one
#-unpublish_paths takes relative patterns e.g #-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep. # */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep. # */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root) # **/test.txt will match at any level below the root (but not in the root)
set unpublish [list\ set antipaths [list\
README.md\ README.md\
] ]
puts stdout "VENDORLIB: copying from $sourcefolder/vendorlib to $projectroot/lib (if source file changed)" puts stdout "VENDORLIB: copying from $sourcefolder/vendorlib to $projectroot/lib (if source file changed)"
set resultdict [punkcheck::install $sourcefolder/vendorlib $projectroot/lib -overwrite installedsourcechanged-targets -unpublish_paths $unpublish] set resultdict [punkcheck::install $sourcefolder/vendorlib $projectroot/lib -overwrite installedsourcechanged-targets -antiglob_paths $antipaths]
puts stdout [punkcheck::summarize_install_resultdict $resultdict] puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else { } else {
@ -440,7 +440,7 @@ if {[file exists $sourcefolder/vendorlib]} {
if {[file exists $sourcefolder/vendormodules]} { if {[file exists $sourcefolder/vendormodules]} {
#install .tm *and other files* #install .tm *and other files*
puts stdout "VENDORMODULES: copying from $sourcefolder/vendormodules to $target_modules_base (if source file changed)" puts stdout "VENDORMODULES: copying from $sourcefolder/vendormodules to $target_modules_base (if source file changed)"
set resultdict [punkcheck::install $sourcefolder/vendormodules $target_modules_base -installer make.tcl -overwrite installedsourcechanged-targets -unpublish_paths {README.md}] set resultdict [punkcheck::install $sourcefolder/vendormodules $target_modules_base -installer make.tcl -overwrite installedsourcechanged-targets -antiglob_paths {README.md}]
puts stdout [punkcheck::summarize_install_resultdict $resultdict] puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else { } else {
puts stderr "VENDORMODULES: No src/vendormodules folder found." puts stderr "VENDORMODULES: No src/vendormodules folder found."
@ -526,7 +526,7 @@ foreach src_module_dir $source_module_folderlist {
set overwrite "installedsourcechanged-targets" set overwrite "installedsourcechanged-targets"
#set overwrite "ALL-TARGETS" #set overwrite "ALL-TARGETS"
puts stdout "MODULEFOLDER non_tm_files $src_module_dir - copying to $target_modules_base (if source file changed)" puts stdout "MODULEFOLDER non_tm_files $src_module_dir - copying to $target_modules_base (if source file changed)"
set resultdict [punkcheck::install_non_tm_files $src_module_dir $target_modules_base -installer make.tcl -overwrite $overwrite -unpublish_paths {README.md}] set resultdict [punkcheck::install_non_tm_files $src_module_dir $target_modules_base -installer make.tcl -overwrite $overwrite -antiglob_paths {README.md}]
puts stdout [punkcheck::summarize_install_resultdict $resultdict] puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} }

3942
src/mixtemplates/layouts/basic/src/bootsupport/modules/mime-1.7.0.tm

File diff suppressed because it is too large Load Diff

228
src/mixtemplates/layouts/basic/src/bootsupport/modules/punk/cap-0.1.0.tm

@ -14,20 +14,36 @@
# @@ Meta End # @@ Meta End
#*** !doctools
#[manpage_begin punk::cap 0 0.1.0]
#[copyright "2023 JMNoble - BSD licensed"]
#[titledesc {Module API}]
#[moddesc {punk capabilities plugin system}]
#[require punk::cap]
#[description]
#[list_begin definitions]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Requirements ## Requirements
##e.g package require frobz ##e.g package require frobz
package require oolib
#concepts:
# A capability may be something like providing a folder of files, or just a data dictionary, and/or an API # mkdoc markdown
# #' ---
# capability handler - a package/namespace which may provide validation and standardised ways of looking up provider data #' author: JMNoble
# registered (or not) using register_capabilityname <capname> <capnamespace> #' ---
# capability provider - a package which registers as providing one or more capablities. #' ## Concepts:
# registered using register_package <pkg> <capabilitylist> #' > A **capability** may be something like providing a folder of files, or just a data dictionary, and/or an API
# the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability #'
# A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets. #' > **capability handler** - a package/namespace which may provide validation and standardised ways of looking up provider data
#' registered (or not) using register_capabilityname <capname> <capnamespace>
#'
#' > **capability provider** - a package which registers as providing one or more capablities.
#' registered using register_package <pkg> <capabilitylist>
#' the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability
#' A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets.
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
@ -35,32 +51,99 @@ namespace eval punk::cap {
variable pkgcapsdeclared [dict create] variable pkgcapsdeclared [dict create]
variable pkgcapsaccepted [dict create] variable pkgcapsaccepted [dict create]
variable caps [dict create] variable caps [dict create]
if {[info commands [namespace current]::interface_caphandler.registry] eq ""} {
oo::class create [namespace current]::interface_caphandler.registry { namespace eval class {
method pkg_register {pkg capname capdict fullcapabilitylist} { if {[info commands [namespace current]::interface_caphandler.registry] eq ""} {
#handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid #Handler classes
#overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes. oo::class create [namespace current]::interface_caphandler.registry {
return 1 ;#default to permit method pkg_register {pkg capname capdict fullcapabilitylist} {
} #***
method pkg_unregister {pkg} { #[call [class interface_caphandler.registry] [method pkg_register] [arg pkg] [arg capname] [arg capdict] [arg fullcapabilitylist]]
return ;#unregistration return is ignored - review #handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid
#overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes.
return 1 ;#default to permit
}
method pkg_unregister {pkg} {
#***
#[call [class interface_caphandler.registry] [method pkg_unregister] [arg pkg]]
return ;#unregistration return is ignored - review
}
} }
} oo::class create [namespace current]::interface_caphandler.sysapi {
oo::class create [namespace current]::interface_capprovider.registration {
method get_declarations {} {
error "interface_capprovider.registration not implemented by provider"
} }
}
oo::class create [namespace current]::interface_capprovider.provider {
method register {{capabilityname_glob *}} {
#Provider classes
oo::class create [namespace current]::interface_capprovider.registration {
method get_declarations {} {
#***
#[call [class interface_capprovider.registration] [method pkg_unregister] [arg pkg]]
error "interface_capprovider.registration not implemented by provider"
}
} }
method capabilities {} { oo::class create [namespace current]::interface_capprovider.provider {
variable provider_pkg
variable registrationobj
constructor {providerpkg} {
variable provider_pkg
if {$providerpkg in [list "" "::"]} {
error "interface_capprovider.provider constructor error. Invalid provider '$providerpkg'"
}
if {![namespace exists ::$providerpkg]} {
error "interface_capprovider.provider constructor error. Invalid provider '$providerpkg' - matching namespace not found"
}
set registrationobj ::${providerpkg}::capsystem::capprovider.registration
if {[info commands $registrationobj] eq ""} {
error "capprovider.provider constructor error. Missing capprovider.registration interface at '$obj' (command not found) interface_capprovider.regstration instantiation must precede interface_capprovider.provider"
}
set provider_pkg [string trim $providerpkg ""]
}
method register {{capabilityname_glob *}} {
#***
#[call [class interface_capprovider.provider] [method register] [opt capabilityname_glob]]
variable provider_pkg
set all_decls [$registrationobj get_declarations]
set register_decls [lsearch -all -inline -index 0 $all_decls $capabilityname_glob]
punk::cap::register_package $provider_pkg $register_decls
}
method capabilities {} {
#***
#[call [class interface_capprovider.provider] [method capabilities]]
variable provider_pkg
variable registrationobj
set capabilities [list]
set decls [$registrationobj get_declarations]
foreach decl $decls {
lassign $decl capname capdict
if {$capname ni $capabilities} {
lappend capabilities $capname
}
}
return $capname
}
} }
} }
} ;# end namespace class
namespace eval capsystem {
proc get_caphandler_registry {capname} {
set ns [::punk::cap::get_handler $capname]::capsystem
if {[namespace exists ${ns}]} {
if {[info command ${ns}::caphandler.registry] ne ""} {
if {[info object isa object ${ns}::caphandler.registry]} {
return ${ns}::caphandler.registry
}
}
}
return ""
}
} }
#Not all capabilities have to be registered. #Not all capabilities have to be registered.
#A package registering as a provider using register_package can include capabilitynames in it's capabilitylist which have no associated capnamespace (handler). #A package registering as a provider using register_package can include capabilitynames in it's capabilitylist which have no associated capnamespace (handler).
#such unregistered capabilitynames may be used just to flag something, or have datamembers significant to callers cooperatively interested in that capname. #such unregistered capabilitynames may be used just to flag something, or have datamembers significant to callers cooperatively interested in that capname.
@ -88,7 +171,7 @@ namespace eval punk::cap {
} }
if {[llength [set providers [dict get $caps $capname providers]]]} { if {[llength [set providers [dict get $caps $capname providers]]]} {
#some provider(s) were in place before the handler was registered #some provider(s) were in place before the handler was registered
if {[set capreg [get_caphandler_registry $capname]] ne ""} { if {[set capreg [punk::cap::capsystem::get_caphandler_registry $capname]] ne ""} {
foreach pkg $providers { foreach pkg $providers {
set fullcapabilitylist [dict get $pkgcapsdeclared $pkg] set fullcapabilitylist [dict get $pkgcapsdeclared $pkg]
foreach capspec $fullcapabilitylist { foreach capspec $fullcapabilitylist {
@ -131,10 +214,31 @@ namespace eval punk::cap {
} }
} }
proc exists {capname} { proc exists {capname} {
#*** !doctools
# [call [fun exists] [arg capname]]
# Return a boolean indicating if the named capability exists (0|1)
# mkdoc markdown
#'
#' ## **exists(capname)**
#'
#' > return a boolean indicating the existence of a capability
#'
#' > Arguments:
#'
#' > - *capname* - string indicating the name of the capability
#'
#' > Returns: 0|1
#'
variable caps variable caps
return [dict exists $caps $capname] return [dict exists $caps $capname]
} }
proc has_handler {capname} { proc has_handler {capname} {
#*** !doctools
# [call [fun has_handler] [arg capname]]
# Return a boolean indicating if the named capability has a handler package installed (0|1)
variable caps variable caps
return [expr {[dict exists $caps $capname handler] && [dict get $caps $capname handler] ne ""}] return [expr {[dict exists $caps $capname handler] && [dict get $caps $capname handler] ne ""}]
} }
@ -157,20 +261,9 @@ namespace eval punk::cap {
if {[set handler [get_handler $capname]] eq ""} { if {[set handler [get_handler $capname]] eq ""} {
error "punk::cap::call_handler $capname $args - no handler registered for capability $capname" error "punk::cap::call_handler $capname $args - no handler registered for capability $capname"
} }
set obj ${handler}::$capname set obj ${handler}::api_$capname
$obj [lindex $args 0] {*}[lrange $args 1 end] $obj [lindex $args 0] {*}[lrange $args 1 end]
} }
proc get_caphandler_registry {capname} {
set ns [get_handler $capname]::capsystem
if {[namespace exists ${ns}]} {
if {[info command ${ns}::caphandler.registry] ne ""} {
if {[info object isa object ${ns}::caphandler.registry]} {
return ${ns}::caphandler.registry
}
}
}
return ""
}
proc get_providers {capname} { proc get_providers {capname} {
variable caps variable caps
if {[dict exists $caps $capname]} { if {[dict exists $caps $capname]} {
@ -188,6 +281,11 @@ namespace eval punk::cap {
if {[string match ::* $pkg]} { if {[string match ::* $pkg]} {
set pkg [string range $pkg 2 end] set pkg [string range $pkg 2 end]
} }
if {[dict exists $pkgcapsaccepted $pkg]} {
set pkg_already_accepted [dict get $pkgcapsaccepted $pkg]
} else {
set pkg_already_accepted [list]
}
#for each capability #for each capability
# - ensure 1st element is a single word # - ensure 1st element is a single word
# - ensure that if 2nd element (capdict) is present - it is dict shaped # - ensure that if 2nd element (capdict) is present - it is dict shaped
@ -199,6 +297,11 @@ namespace eval punk::cap {
if {[expr {[llength $capdict] %2 != 0}]} { if {[expr {[llength $capdict] %2 != 0}]} {
error "register_package error. pkg:'$pkg' The second element for capname:'$capname' doesn't appear to be a valid dict. Problematic entry: '$capspec'" error "register_package error. pkg:'$pkg' The second element for capname:'$capname' doesn't appear to be a valid dict. Problematic entry: '$capspec'"
} }
if {$capspec in $pkg_already_accepted} {
#review - multiple handlers? if so - will need to record which handler(s) accepted the capspec
puts stderr "register_package pkg $pkg already has capspec marked as accepted: $capspec"
continue
}
if {[dict exists $caps $capname]} { if {[dict exists $caps $capname]} {
set cap_pkgs [dict get $caps $capname providers] set cap_pkgs [dict get $caps $capname providers]
} else { } else {
@ -207,7 +310,7 @@ namespace eval punk::cap {
} }
#todo - if there's a caphandler - call it's init/validation callback for the pkg #todo - if there's a caphandler - call it's init/validation callback for the pkg
set do_register 1 ;#default assumption unless vetoed by handler set do_register 1 ;#default assumption unless vetoed by handler
if {[set capreg [get_caphandler_registry $capname]] ne ""} { if {[set capreg [punk::cap::capsystem::get_caphandler_registry $capname]] ne ""} {
#Note that the interface_caphandler.registry instance must be able to handle multiple calls for same pkg #Note that the interface_caphandler.registry instance must be able to handle multiple calls for same pkg
set do_register [$capreg pkg_register $pkg $capname $capdict $capabilitylist] set do_register [$capreg pkg_register $pkg $capname $capdict $capabilitylist]
} }
@ -219,17 +322,23 @@ namespace eval punk::cap {
dict lappend pkgcapsaccepted $pkg $capspec ;#if pkg is being registered prior to handler-registration - the handler may undo this entry dict lappend pkgcapsaccepted $pkg $capspec ;#if pkg is being registered prior to handler-registration - the handler may undo this entry
} }
} }
#another call to register_pkg with same pkg may have been made (most likely with different capname) so we must append #another call to register_pkg with same pkg may have been made (most likely with different capname) so we must append - but check not already present
#dict lappend pkgcapsdeclared $pkg $capabilitylist #dict lappend pkgcapsdeclared $pkg $capabilitylist
if {[dict exists $pkgcapsdeclared $pkg]} { if {[dict exists $pkgcapsdeclared $pkg]} {
set caps [dict get $pkgcapsdeclared $pkg] set capspecs [dict get $pkgcapsdeclared $pkg]
lappend caps {*}$capabilitylist foreach spec $capspecs {
dict set pkgcapsdeclared $pkg $caps if {$spec ni $capspecs} {
lappend capspecs $spec
}
}
dict set pkgcapsdeclared $pkg $capspecs
} else { } else {
dict set pkgcapsdeclared $pkg $capabilitylist dict set pkgcapsdeclared $pkg $capabilitylist
} }
} }
proc unregister_package {pkg} {
#todo!
proc unregister_package {pkg {capname *}} {
variable pkgcapsdeclared variable pkgcapsdeclared
variable caps variable caps
if {[string match ::* $pkg]} { if {[string match ::* $pkg]} {
@ -245,13 +354,13 @@ namespace eval punk::cap {
set pkglist [dict get $cap_info providers] set pkglist [dict get $cap_info providers]
set posn [lsearch $pkglist $pkg] set posn [lsearch $pkglist $pkg]
if {$posn >= 0} { if {$posn >= 0} {
if {[set capreg [get_caphandler_registry $capname]] ne ""} { if {[set capreg [punk::cap::capsystem::get_caphandler_registry $capname]] ne ""} {
#review #review
# it seems not useful to allow the callback to block this unregister action # it seems not useful to allow the callback to block this unregister action
#the pkg may have multiple datasets for each capname so callback will only be called for first dataset we encounter #the pkg may have multiple datasets for each capname so callback will only be called for first dataset we encounter
#vetoing unregister would make this more complex for no particular advantage #vetoing unregister would make this more complex for no particular advantage
#if per capability deregistration required this should probably be a separate thing (e.g disable_capability?) #if per dataset deregistration required this should probably be a separate thing
$capreg pkg_unregister $pkg $capreg pkg_unregister $pkg $capname
} }
set pkglist [lreplace $pkglist $posn $posn] set pkglist [lreplace $pkglist $posn $posn]
dict set caps $capname providers $pkglist dict set caps $capname providers $pkglist
@ -398,21 +507,22 @@ namespace eval punk::cap {
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Ready ## Ready
package provide punk::cap [namespace eval punk::cap { package provide punk::cap [namespace eval punk::cap {
variable version variable version
variable pkg punk::cap
set version 0.1.0 set version 0.1.0
variable README.md [string map [list %pkg% $pkg %ver% $version] {
# punk capabilities system
## pkg: %pkg% version: %ver%
punk::cap base namespace
}]
return $version
}] }]
return return
#*** !doctools
#[list_end]
#[manpage_end]

74
src/mixtemplates/layouts/basic/src/bootsupport/modules/punk/cap/handlers/templates-0.1.0.tm

@ -35,10 +35,14 @@ namespace eval punk::cap::handlers::templates {
namespace eval capsystem { namespace eval capsystem {
#interfaces for punk::cap to call into #interfaces for punk::cap to call into
if {[info commands caphandler.registry] eq ""} { if {[info commands caphandler.registry] eq ""} {
punk::cap::interface_caphandler.registry create caphandler.registry punk::cap::class::interface_caphandler.registry create caphandler.registry
oo::objdefine caphandler.registry { oo::objdefine caphandler.registry {
method pkg_register {pkg capname capdict caplist} { method pkg_register {pkg capname capdict caplist} {
#caplist may not be complete set - which somewhat reduces its utility here regarding any decisions based on the context of this capname/capdict (review - remove this arg?) #caplist may not be complete set - which somewhat reduces its utility here regarding any decisions based on the context of this capname/capdict (review - remove this arg?)
# -- --- --- --- --- --- --- ---- ---
# validation of capdict
# -- --- --- --- --- --- --- ---- ---
if {![dict exists $capdict relpath]} { if {![dict exists $capdict relpath]} {
puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - package '$pkg' is attempting to register with punk::cap as a provider of '$capname' capability, but is missing 'relpath' key" puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - package '$pkg' is attempting to register with punk::cap as a provider of '$capname' capability, but is missing 'relpath' key"
return 0 return 0
@ -52,16 +56,28 @@ namespace eval punk::cap::handlers::templates {
set tpath [file normalize [file join $tmfile [dict get $capdict relpath]]] ;#relpath is relative to the tm *file* - not it's containing folder set tpath [file normalize [file join $tmfile [dict get $capdict relpath]]] ;#relpath is relative to the tm *file* - not it's containing folder
if {![file isdirectory $tpath]} { if {![file isdirectory $tpath]} {
puts stderr "punk::cap::handlers::templates::capsystem pkg_register WARNING - unable to validate relpath location [dict get $capdict relpath] ($tpath) for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability" puts stderr "punk::cap::handlers::templates::capsystem pkg_register WARNING - unable to validate relpath location [dict get $capdict relpath] ($tpath) for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability"
return 0
} }
# -- --- --- --- --- --- --- ---- ---
# update package internal data
# -- --- --- --- --- --- --- ---- ---
if {$capname ni $::punk::cap::handlers::templates::handled_caps} { if {$capname ni $::punk::cap::handlers::templates::handled_caps} {
lappend ::punk::cap::handlers::templates::handled_caps $capname lappend ::punk::cap::handlers::templates::handled_caps $capname
} }
if {[info commands punk::cap::handlers::templates::$capname] eq ""} {
punk::cap::handlers::templates::api create ::punk::cap::handlers::templates::$capname $capname
}
set cname [string map [list . _] $capname] set cname [string map [list . _] $capname]
upvar ::punk::cap::handlers::templates::pkg_folders_$cname pfolders upvar ::punk::cap::handlers::templates::pkg_folders_$cname pfolders
dict lappend pfolders $pkg $tpath dict lappend pfolders $pkg $tpath
# -- --- --- --- --- --- --- ---- ---
# instantiation of api at punk::cap::handlers::templates::api_$capname
# -- --- --- --- --- --- --- ---- ---
if {[info commands ::punk::cap::handlers::templates::$capname] eq ""} {
punk::cap::handlers::templates::class::api create ::punk::cap::handlers::templates::api_$capname $capname
}
return 1 return 1
} }
method pkg_unregister {pkg} { method pkg_unregister {pkg} {
@ -84,36 +100,38 @@ namespace eval punk::cap::handlers::templates {
#handler api for clients of this capability - called via punk::cap::call_handler <capname> <method> ?args? #handler api for clients of this capability - called via punk::cap::call_handler <capname> <method> ?args?
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
namespace export * namespace export *
namespace eval class {
oo::class create api { oo::class create api {
#return a dict keyed on folder with source pkg as value #return a dict keyed on folder with source pkg as value
constructor {capname} { constructor {capname} {
variable capabilityname variable capabilityname
variable cname variable cname
set cname [string map [list . _] $capname] set cname [string map [list . _] $capname]
set capabilityname $capname set capabilityname $capname
} }
method folders {} { method folders {} {
variable capabilityname variable capabilityname
variable cname variable cname
upvar punk::cap::handlers::templates::pkg_folders_$cname pkg_folders upvar punk::cap::handlers::templates::pkg_folders_$cname pkg_folders
package require punk::cap package require punk::cap
set capinfo [punk::cap::capability $capabilityname] set capinfo [punk::cap::capability $capabilityname]
# e.g {punk.templates {handler punk::mix::templates providers ::somepkg}} # e.g {punk.templates {handler punk::mix::templates providers ::somepkg}}
#use the order of pkgs as registered with punk::cap - may have been modified with punk::cap::promote_package/demote_package #use the order of pkgs as registered with punk::cap - may have been modified with punk::cap::promote_package/demote_package
set pkgs [dict get $capinfo providers] set pkgs [dict get $capinfo providers]
set folderdict [dict create] set folderdict [dict create]
foreach pkg $pkgs { foreach pkg $pkgs {
foreach pfolder [dict get $pkg_folders $pkg] { foreach pfolder [dict get $pkg_folders $pkg] {
dict set folderdict $pfolder [list source $pkg sourcetype package] dict set folderdict $pfolder [list source $pkg sourcetype package]
}
} }
return $folderdict
} }
return $folderdict
} }
} }
} }

2
src/mixtemplates/layouts/basic/src/bootsupport/modules/punk/mix-0.2.tm

@ -5,7 +5,7 @@ package require punk::cap::handlers::templates ;#handler for templates cap
punk::cap::register_capabilityname punk.templates ::punk::cap::handlers::templates punk::cap::register_capabilityname punk.templates ::punk::cap::handlers::templates
package require punk::mix::templates ;#registers as provider pkg for 'punk.templates' capability with punk::cap package require punk::mix::templates ;#registers as provider pkg for 'punk.templates' capability with punk::cap
#punk::mix::templates::provider register * punk::mix::templates::provider register *
package require punk::mix::base package require punk::mix::base
package require punk::mix::cli package require punk::mix::cli

3
src/mixtemplates/layouts/basic/src/bootsupport/modules/punk/mix/cli-0.3.tm

@ -170,7 +170,8 @@ namespace eval punk::mix::cli {
} }
cd $sourcefolder cd $sourcefolder
#use run so that stdout visible as it goes #use run so that stdout visible as it goes
if {![catch {run --timeout=5000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} { if {![catch {run --timeout=55000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} {
#todo - notify if exit because of timeout!
puts stderr "exitinfo: $exitinfo" puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode] set exitcode [dict get $exitinfo exitcode]
} else { } else {

74
src/mixtemplates/layouts/basic/src/bootsupport/modules/punk/mix/commandset/doc-0.1.0.tm

@ -18,7 +18,11 @@
## Requirements ## Requirements
##e.g package require frobz ##e.g package require frobz
package require punk ;# for treefilenames
package require punk::repo
package require punk::docgen ;#inline doctools - generate doctools .man files at src/docgen prior to using kettle to producing .html .md etc
package require punk::mix::cli ;#punk::mix::cli::lib used for kettle_call
package require punk::mix::util ;#for path_relative
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
@ -38,6 +42,30 @@ namespace eval punk::mix::commandset::doc {
puts stderr "No current project dir - unable to build docs" puts stderr "No current project dir - unable to build docs"
return return
} }
#user may delete the comment containing "--- punk::docgen::overwrites" and then manually edit, and we won't overwrite
#we still generate output in src/docgen so user can diff and manually update if thats what they prefer
set oldfiles [glob -nocomplain -dir $projectdir/src/doc -type f _module_*]
foreach maybedoomed $oldfiles {
set fd [open $maybedoomed r]
set data [read $fd]
close $fd
if {[string match "*--- punk::docgen overwrites *" $data]} {
file delete -force $maybedoomed
}
}
set generated [lib::do_docgen modules]
if {[dict get $generated count] > 0} {
#review
set doclist [dict get $generated docs]
foreach dinfo $doclist {
lassign $dinfo module fpath
set target $projectdir/src/doc/_module_[file tail $fpath]
if {![file exists $target]} {
file copy $fpath $target
}
}
}
if {[file exists $projectdir/src/doc]} { if {[file exists $projectdir/src/doc]} {
set original_wd [pwd] set original_wd [pwd]
cd $projectdir/src cd $projectdir/src
@ -125,6 +153,7 @@ namespace eval punk::mix::commandset::doc {
cd $original_wd cd $original_wd
} }
proc validate {} { proc validate {} {
#todo - run and validate punk::docgen output
set projectdir [punk::repo::find_project] set projectdir [punk::repo::find_project]
if {$projectdir eq ""} { if {$projectdir eq ""} {
puts stderr "No current project dir - unable to check doc status" puts stderr "No current project dir - unable to check doc status"
@ -154,6 +183,49 @@ namespace eval punk::mix::commandset::doc {
namespace eval lib { namespace eval lib {
variable pkg variable pkg
set pkg punk::mix::commandset::doc set pkg punk::mix::commandset::doc
proc do_docgen {{project_subpath modules}} {
set projectdir [punk::repo::find_project]
set outdir [file join $projectdir src docgen]
set subpath [file join $projectdir $project_subpath]
if {![file isdirectory $subpath]} {
puts stderr "WARNING punk::mix::commandset::doc unable to find subpath $subpath during do_docgen - skipping inline doctools generation"
return
}
if {[file isdirectory $outdir]} {
if {[catch {
file delete -force $outdir
}]} {
error "do_docgen failed to delete existing $outdir"
}
}
file mkdir $outdir
set matched_paths [punk::treefilenames $subpath *.tm]
set count 0
set newdocs [list]
set docgen_header_comments ""
append docgen_header_comments {[comment {--- punk::docgen generated from inline doctools comments ---}]} \n
append docgen_header_comments {[comment {--- punk::docgen DO NOT EDIT DOCS HERE UNLESS YOU REMOVE THESE COMMENT LINES ---}]} \n
append docgen_header_comments {[comment {--- punk::docgen overwrites this file ---}]} \n
foreach fullpath $matched_paths {
set relpath [punk::mix::util::path_relative $subpath $fullpath]
set tailsegs [file split $relpath]
set module_fullname [join $tailsegs ::]
set docname [string map [list :: _] $module_fullname].man ;#todo - something better - need to ensure unique
set doctools [punk::docgen::get_doctools_comments $fullpath]
if {$doctools ne ""} {
puts stdout "generating doctools output from file $relpath"
set outfile [file join $outdir $docname]
set fd [open $outfile w]
fconfigure $fd -translation binary
puts -nonewline $fd $docgen_header_comments$doctools
close $fd
incr count
lappend newdocs [list $module_fullname $outfile]
}
}
return [list count $count docs $newdocs]
}
} }
} }

16
src/mixtemplates/layouts/basic/src/bootsupport/modules/punk/mix/templates-0.1.0.tm

@ -26,17 +26,19 @@ namespace eval punk::mix::templates {
variable pkg punk::mix::templates variable pkg punk::mix::templates
variable cap_provider variable cap_provider
punk::cap::register_package punk::mix::templates [list\ #punk::cap::register_package punk::mix::templates [list\
{punk.templates {relpath ../templates}}\ # {punk.templates {relpath ../templates}}\
] #]
namespace eval capsystem { namespace eval capsystem {
if {[info commands capprovider.registration] eq ""} { if {[info commands capprovider.registration] eq ""} {
punk::cap::interface_capprovider.registration create capprovider.registration punk::cap::class::interface_capprovider.registration create capprovider.registration
oo::objdefine capprovider.registration { oo::objdefine capprovider.registration {
method get_declarations {} { method get_declarations {} {
set decls [list] set decls [list]
lappend decls punk.templates {relpath ../templates} lappend decls [list punk.templates {relpath ../templates}]
lappend decls punk.templates {relpath ../templates2} lappend decls [list punk.templates {relpath ../templates2}]
lappend decls [list punk.test {something blah}]
return $decls return $decls
} }
} }
@ -44,7 +46,7 @@ namespace eval punk::mix::templates {
} }
if {[info commands provider] eq ""} { if {[info commands provider] eq ""} {
punk::cap::interface_capprovider.provider create provider punk::cap::class::interface_capprovider.provider create provider punk::mix::templates
oo::objdefine provider { oo::objdefine provider {
method register {{capabilityname_glob *}} { method register {{capabilityname_glob *}} {
#puts registering punk::mix::templates $capabilityname #puts registering punk::mix::templates $capabilityname

32
src/mixtemplates/layouts/basic/src/bootsupport/modules/punkcheck-0.1.0.tm

@ -1078,7 +1078,7 @@ namespace eval punkcheck {
} }
proc install_non_tm_files {srcdir basedir args} { proc install_non_tm_files {srcdir basedir args} {
#set keys [dict keys $args] #set keys [dict keys $args]
#adjust the default anti_glob_dir_core entries so that .fossil-custom, .fossil-settings are copied #adjust the default antiglob_dir_core entries so that .fossil-custom, .fossil-settings are copied
set antiglob_dir_core [punkcheck::default_antiglob_dir_core] set antiglob_dir_core [punkcheck::default_antiglob_dir_core]
set posn [lsearch $antiglob_dir_core ".fossil*"] set posn [lsearch $antiglob_dir_core ".fossil*"]
if {$posn >=0} { if {$posn >=0} {
@ -1168,7 +1168,7 @@ namespace eval punkcheck {
-antiglob_file "" \ -antiglob_file "" \
-antiglob_dir_core "\uFFFF"\ -antiglob_dir_core "\uFFFF"\
-antiglob_dir {}\ -antiglob_dir {}\
-unpublish_paths {}\ -antiglob_paths {}\
-overwrite no-targets\ -overwrite no-targets\
-source_checksum comparestore\ -source_checksum comparestore\
-punkcheck_folder target\ -punkcheck_folder target\
@ -1225,8 +1225,8 @@ namespace eval punkcheck {
# -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
set opt_antiglob_dir [dict get $opts -antiglob_dir] set opt_antiglob_dir [dict get $opts -antiglob_dir]
# -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
set opt_unpublish_paths [dict get $opts -unpublish_paths] ;#todo - combine with config file in source tree .punkcheckpublish (?) set opt_antiglob_paths [dict get $opts -antiglob_paths] ;#todo - combine with config file in source tree .punkcheckpublish (?)
set unpublish_paths_matched [list] set antiglob_paths_matched [list]
# -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
set known_whats [list no-targets newer-targets older-targets all-targets installedsourcechanged-targets synced-targets] set known_whats [list no-targets newer-targets older-targets all-targets installedsourcechanged-targets synced-targets]
set overwrite_what [string tolower [dict get $opts -overwrite]]; #accept any case for value to allow emphasis by caller e.g -overwrite NEWER-TARGETS set overwrite_what [string tolower [dict get $opts -overwrite]]; #accept any case for value to allow emphasis by caller e.g -overwrite NEWER-TARGETS
@ -1347,11 +1347,11 @@ namespace eval punkcheck {
if {$target_relative_to_punkcheck_dir eq "."} { if {$target_relative_to_punkcheck_dir eq "."} {
set target_relative_to_punkcheck_dir "" set target_relative_to_punkcheck_dir ""
} }
foreach unpub $opt_unpublish_paths { foreach unpub $opt_antiglob_paths {
#puts "testing folder - globmatchpath $unpub $relative_source_dir" #puts "testing folder - globmatchpath $unpub $relative_source_dir"
if {[globmatchpath $unpub $relative_source_dir]} { if {[globmatchpath $unpub $relative_source_dir]} {
lappend unpublish_paths_matched $current_source_dir lappend antiglob_paths_matched $current_source_dir
return [list files_copied {} files_skipped {} sources_unchanged {} punkcheck_records $punkcheck_records unpublish_paths_matched $unpublish_paths_matched srcdir $srcdir tgtdir $tgtdir punkcheck_folder $punkcheck_folder] return [list files_copied {} files_skipped {} sources_unchanged {} punkcheck_records $punkcheck_records antiglob_paths_matched $antiglob_paths_matched srcdir $srcdir tgtdir $tgtdir punkcheck_folder $punkcheck_folder]
} }
} }
@ -1418,16 +1418,16 @@ namespace eval punkcheck {
set relative_target_path [file join $relative_target_dir $m] set relative_target_path [file join $relative_target_dir $m]
set relative_source_path [file join $relative_source_dir $m] set relative_source_path [file join $relative_source_dir $m]
set punkcheck_target_relpath [file join $target_relative_to_punkcheck_dir $m] set punkcheck_target_relpath [file join $target_relative_to_punkcheck_dir $m]
set is_unpublished 0 set is_antipath 0
foreach unpub $opt_unpublish_paths { foreach antipath $opt_antiglob_paths {
#puts "testing file - globmatchpath $unpub vs $relative_source_path" #puts "testing file - globmatchpath $antipath vs $relative_source_path"
if {[globmatchpath $unpub $relative_source_path]} { if {[globmatchpath $antipath $relative_source_path]} {
lappend unpublish_paths_matched $current_source_dir lappend antiglob_paths_matched $current_source_dir
set is_unpublished 1 set is_antipath 1
break break
} }
} }
if {$is_unpublished} { if {$is_antipath} {
continue continue
} }
#puts stdout " checking file : $current_source_dir/$m" #puts stdout " checking file : $current_source_dir/$m"
@ -1642,7 +1642,7 @@ namespace eval punkcheck {
lappend files_copied {*}[dict get $sub_result files_copied] lappend files_copied {*}[dict get $sub_result files_copied]
lappend files_skipped {*}[dict get $sub_result files_skipped] lappend files_skipped {*}[dict get $sub_result files_skipped]
lappend sources_unchanged {*}[dict get $sub_result sources_unchanged] lappend sources_unchanged {*}[dict get $sub_result sources_unchanged]
lappend unpublish_paths_matched {*}[dict get $sub_result unpublish_paths_matched] lappend antiglob_paths_matched {*}[dict get $sub_result antiglob_paths_matched]
set punkcheck_records [dict get $sub_result punkcheck_records] set punkcheck_records [dict get $sub_result punkcheck_records]
} }
@ -1664,7 +1664,7 @@ namespace eval punkcheck {
} }
} }
return [list files_copied $files_copied files_skipped $files_skipped sources_unchanged $sources_unchanged unpublish_paths_matched $unpublish_paths_matched punkcheck_records $punkcheck_records punkcheck_folder $punkcheck_folder srcdir $srcdir tgtdir $tgtdir] return [list files_copied $files_copied files_skipped $files_skipped sources_unchanged $sources_unchanged antiglob_paths_matched $antiglob_paths_matched punkcheck_records $punkcheck_records punkcheck_folder $punkcheck_folder srcdir $srcdir tgtdir $tgtdir]
} }
proc summarize_install_resultdict {resultdict} { proc summarize_install_resultdict {resultdict} {
set msg "" set msg ""

80
src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil-0.9.tm

@ -0,0 +1,80 @@
# textutil.tcl --
#
# Utilities for manipulating strings, words, single lines,
# paragraphs, ...
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2002 by Joe English <jenglish@users.sourceforge.net>
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: textutil.tcl,v 1.17 2006/09/21 06:46:24 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil {}
# ### ### ### ######### ######### #########
## API implementation
## All through sub-packages imported here.
package require textutil::string
package require textutil::repeat
package require textutil::adjust
package require textutil::split
package require textutil::tabify
package require textutil::trim
package require textutil::wcswidth
namespace eval ::textutil {
# Import the miscellaneous string command for public export
namespace import -force string::chop string::tail
namespace import -force string::cap string::uncap string::capEachWord
namespace import -force string::longestCommonPrefix
namespace import -force string::longestCommonPrefixList
# Import the repeat commands for public export
namespace import -force repeat::strRepeat repeat::blank
# Import the adjust commands for public export
namespace import -force adjust::adjust adjust::indent adjust::undent
# Import the split commands for public export
namespace import -force split::splitx split::splitn
# Import the trim commands for public export
namespace import -force trim::trim trim::trimleft trim::trimright
namespace import -force trim::trimPrefix trim::trimEmptyHeading
# Import the tabify commands for public export
namespace import -force tabify::tabify tabify::untabify
namespace import -force tabify::tabify2 tabify::untabify2
# Re-export all the imported commands
namespace export chop tail cap uncap capEachWord
namespace export longestCommonPrefix longestCommonPrefixList
namespace export strRepeat blank
namespace export adjust indent undent
namespace export splitx splitn
namespace export trim trimleft trimright trimPrefix trimEmptyHeading
namespace export tabify untabify tabify2 untabify2
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil 0.9

761
src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/adjust-0.7.3.tm

@ -0,0 +1,761 @@
# trim.tcl --
#
# Various ways of trimming a string.
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2002-2004 by Johannes-Heinrich Vogeler <vogeler@users.sourceforge.net>
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: adjust.tcl,v 1.16 2011/12/13 18:12:56 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
package require textutil::repeat
package require textutil::string
namespace eval ::textutil::adjust {}
# ### ### ### ######### ######### #########
## API implementation
namespace eval ::textutil::adjust {
namespace import -force ::textutil::repeat::strRepeat
}
proc ::textutil::adjust::adjust {text args} {
if {[string length [string trim $text]] == 0} {
return ""
}
Configure $args
Adjust text newtext
return $newtext
}
proc ::textutil::adjust::Configure {args} {
variable Justify left
variable Length 72
variable FullLine 0
variable StrictLength 0
variable Hyphenate 0
variable HyphPatterns ; # hyphenation patterns (TeX)
set args [ lindex $args 0 ]
foreach { option value } $args {
switch -exact -- $option {
-full {
if { ![ string is boolean -strict $value ] } then {
error "expected boolean but got \"$value\""
}
set FullLine [ string is true $value ]
}
-hyphenate {
# the word exceeding the length of line is tried to be
# hyphenated; if a word cannot be hyphenated to fit into
# the line processing stops! The length of the line should
# be set to a reasonable value!
if { ![ string is boolean -strict $value ] } then {
error "expected boolean but got \"$value\""
}
set Hyphenate [string is true $value]
if { $Hyphenate && ![info exists HyphPatterns(_LOADED_)]} {
error "hyphenation patterns not loaded!"
}
}
-justify {
set lovalue [ string tolower $value ]
switch -exact -- $lovalue {
left -
right -
center -
plain {
set Justify $lovalue
}
default {
error "bad value \"$value\": should be center, left, plain or right"
}
}
}
-length {
if { ![ string is integer $value ] } then {
error "expected positive integer but got \"$value\""
}
if { $value < 1 } then {
error "expected positive integer but got \"$value\""
}
set Length $value
}
-strictlength {
# the word exceeding the length of line is moved to the
# next line without hyphenation; words longer than given
# line length are cut into smaller pieces
if { ![ string is boolean -strict $value ] } then {
error "expected boolean but got \"$value\""
}
set StrictLength [ string is true $value ]
}
default {
error "bad option \"$option\": must be -full, -hyphenate, \
-justify, -length, or -strictlength"
}
}
}
return ""
}
# ::textutil::adjust::Adjust
#
# History:
# rewritten on 2004-04-13 for bugfix tcllib-bugs-882402 (jhv)
proc ::textutil::adjust::Adjust { varOrigName varNewName } {
variable Length
variable FullLine
variable StrictLength
variable Hyphenate
upvar $varOrigName orig
upvar $varNewName text
set pos 0; # Cursor after writing
set line ""
set text ""
if {!$FullLine} {
regsub -all -- "(\n)|(\t)" $orig " " orig
regsub -all -- " +" $orig " " orig
regsub -all -- "(^ *)|( *\$)" $orig "" orig
}
set words [split $orig]
set numWords [llength $words]
set numline 0
for {set cnt 0} {$cnt < $numWords} {incr cnt} {
set w [lindex $words $cnt]
set wLen [string length $w]
# the word $w doesn't fit into the present line
# case #1: we try to hyphenate
if {$Hyphenate && ($pos+$wLen >= $Length)} {
# Hyphenation instructions
set w2 [textutil::adjust::Hyphenation $w]
set iMax [llength $w2]
if {$iMax == 1 && [string length $w] > $Length} {
# word cannot be hyphenated and exceeds linesize
error "Word \"$w2\" can\'t be hyphenated\
and exceeds linesize $Length!"
} else {
# hyphenating of $w was successfull, but we have to look
# that every sylable would fit into the line
foreach x $w2 {
if {[string length $x] >= $Length} {
error "Word \"$w\" can\'t be hyphenated\
to fit into linesize $Length!"
}
}
}
for {set i 0; set w3 ""} {$i < $iMax} {incr i} {
set syl [lindex $w2 $i]
if {($pos+[string length " $w3$syl-"]) > $Length} {break}
append w3 $syl
}
for {set w4 ""} {$i < $iMax} {incr i} {
set syl [lindex $w2 $i]
append w4 $syl
}
if {[string length $w3] && [string length $w4]} {
# hyphenation was successfull: redefine
# list of words w => {"$w3-" "$w4"}
set x [lreplace $words $cnt $cnt "$w4"]
set words [linsert $x $cnt "$w3-"]
set w [lindex $words $cnt]
set wLen [string length $w]
incr numWords
}
}
# the word $w doesn't fit into the present line
# case #2: we try to cut the word into pieces
if {$StrictLength && ([string length $w] > $Length)} {
# cut word into two pieces
set w2 $w
set over [expr {$pos+2+$wLen-$Length}]
incr Length -1
set w3 [string range $w2 0 $Length]
incr Length
set w4 [string range $w2 $Length end]
set x [lreplace $words $cnt $cnt $w4]
set words [linsert $x $cnt $w3 ]
set w [lindex $words $cnt]
set wLen [string length $w]
incr numWords
}
# continuing with the normal procedure
if {($pos+$wLen < $Length)} {
# append word to current line
if {$pos} {append line " "; incr pos}
append line $w
incr pos $wLen
} else {
# line full => write buffer and begin a new line
if {[string length $text]} {append text "\n"}
append text [Justification $line [incr numline]]
set line $w
set pos $wLen
}
}
# write buffer and return!
if {[string length $text]} {append text "\n"}
append text [Justification $line end]
return $text
}
# ::textutil::adjust::Justification
#
# justify a given line
#
# Parameters:
# line text for justification
# index index for line in text
#
# Returns:
# the justified line
#
# Remarks:
# Only lines with size not exceeding the max. linesize provided
# for text formatting are justified!!!
proc ::textutil::adjust::Justification { line index } {
variable Justify
variable Length
variable FullLine
set len [string length $line]; # length of current line
if { $Length <= $len } then {
# the length of current line ($len) is equal as or greater than
# the value provided for text formatting ($Length) => to avoid
# inifinite loops we leave $line unchanged and return!
return $line
}
# Special case:
# for the last line, and if the justification is set to 'plain'
# the real justification is 'left' if the length of the line
# is less than 90% (rounded) of the max length allowed. This is
# to avoid expansion of this line when it is too small: without
# it, the added spaces will 'unbeautify' the result.
#
set justify $Justify
if { ( "$index" == "end" ) && \
( "$Justify" == "plain" ) && \
( $len < round($Length * 0.90) ) } then {
set justify left
}
# For a left justification, nothing to do, but to
# add some spaces at the end of the line if requested
if { "$justify" == "left" } then {
set jus ""
if { $FullLine } then {
set jus [strRepeat " " [ expr { $Length - $len } ]]
}
return "${line}${jus}"
}
# For a right justification, just add enough spaces
# at the beginning of the line
if { "$justify" == "right" } then {
set jus [strRepeat " " [ expr { $Length - $len } ]]
return "${jus}${line}"
}
# For a center justification, add half of the needed spaces
# at the beginning of the line, and the rest at the end
# only if needed.
if { "$justify" == "center" } then {
set mr [ expr { ( $Length - $len ) / 2 } ]
set ml [ expr { $Length - $len - $mr } ]
set jusl [strRepeat " " $ml]
set jusr [strRepeat " " $mr]
if { $FullLine } then {
return "${jusl}${line}${jusr}"
} else {
return "${jusl}${line}"
}
}
# For a plain justification, it's a little bit complex:
#
# if some spaces are missing, then
#
# 1) sort the list of words in the current line by decreasing size
# 2) foreach word, add one space before it, except if it's the
# first word, until enough spaces are added
# 3) rebuild the line
if { "$justify" == "plain" } then {
set miss [ expr { $Length - [ string length $line ] } ]
# Bugfix tcllib-bugs-860753 (jhv)
set words [split $line]
set numWords [llength $words]
if {$numWords < 2} {
# current line consists of less than two words - we can't
# insert blanks to achieve a plain justification => leave
# $line unchanged and return!
return $line
}
for {set i 0; set totalLen 0} {$i < $numWords} {incr i} {
set w($i) [lindex $words $i]
if {$i > 0} {set w($i) " $w($i)"}
set wLen($i) [string length $w($i)]
set totalLen [expr {$totalLen+$wLen($i)}]
}
set miss [expr {$Length - $totalLen}]
# len walks through all lengths of words of the line under
# consideration
for {set len 1} {$miss > 0} {incr len} {
for {set i 1} {($i < $numWords) && ($miss > 0)} {incr i} {
if {$wLen($i) == $len} {
set w($i) " $w($i)"
incr wLen($i)
incr miss -1
}
}
}
set line ""
for {set i 0} {$i < $numWords} {incr i} {
set line "$line$w($i)"
}
# End of bugfix
return "${line}"
}
error "Illegal justification key \"$justify\""
}
proc ::textutil::adjust::SortList { list dir index } {
if { [ catch { lsort -integer -$dir -index $index $list } sl ] != 0 } then {
error "$sl"
}
return $sl
}
# Hyphenation utilities based on Knuth's algorithm
#
# Copyright (C) 2001-2003 by Dr.Johannes-Heinrich Vogeler (jhv)
# These procedures may be used as part of the tcllib
# textutil::adjust::Hyphenation
#
# Hyphenate a string using Knuth's algorithm
#
# Parameters:
# str string to be hyphenated
#
# Returns:
# the hyphenated string
proc ::textutil::adjust::Hyphenation { str } {
# if there are manual set hyphenation marks e.g. "Recht\-schrei\-bung"
# use these for hyphenation and return
if {[regexp {[^\\-]*[\\-][.]*} $str]} {
regsub -all {(\\)(-)} $str {-} tmp
return [split $tmp -]
}
# Don't hyphenate very short words! Minimum length for hyphenation
# is set to 3 characters!
if { [string length $str] < 4 } then { return $str }
# otherwise follow Knuth's algorithm
variable HyphPatterns; # hyphenation patterns (TeX)
set w ".[string tolower $str]."; # transform to lower case
set wLen [string length $w]; # and add delimiters
# Initialize hyphenation weights
set s {}
for {set i 0} {$i < $wLen} {incr i} {
lappend s 0
}
for {set i 0} {$i < $wLen} {incr i} {
set kmax [expr {$wLen-$i}]
for {set k 1} {$k < $kmax} {incr k} {
set sw [string range $w $i [expr {$i+$k}]]
if {[info exists HyphPatterns($sw)]} {
set hw $HyphPatterns($sw)
set hwLen [string length $hw]
for {set l1 0; set l2 0} {$l1 < $hwLen} {incr l1} {
set c [string index $hw $l1]
if {[string is digit $c]} {
set sPos [expr {$i+$l2}]
if {$c > [lindex $s $sPos]} {
set s [lreplace $s $sPos $sPos $c]
}
} else {
incr l2
}
}
}
}
}
# Replace all even hyphenation weigths by zero
for {set i 0} {$i < [llength $s]} {incr i} {
set c [lindex $s $i]
if {!($c%2)} { set s [lreplace $s $i $i 0] }
}
# Don't start with a hyphen! Take also care of words enclosed in quotes
# or that someone has forgotten to put a blank between a punctuation
# character and the following word etc.
for {set i 1} {$i < ($wLen-1)} {incr i} {
set c [string range $w $i end]
if {[regexp {^[:alpha:][.]*} $c]} {
for {set k 1} {$k < ($i+1)} {incr k} {
set s [lreplace $s $k $k 0]
}
break
}
}
# Don't separate the last character of a word with a hyphen
set max [expr {[llength $s]-2}]
if {$max} {set s [lreplace $s $max end 0]}
# return the syllabels of the hyphenated word as a list!
set ret ""
set w ".$str."
for {set i 1} {$i < ($wLen-1)} {incr i} {
if {[lindex $s $i]} { append ret - }
append ret [string index $w $i]
}
return [split $ret -]
}
# textutil::adjust::listPredefined
#
# Return the names of the hyphenation files coming with the package.
#
# Parameters:
# None.
#
# Result:
# List of filenames (without directory)
proc ::textutil::adjust::listPredefined {} {
variable here
return [glob -type f -directory $here -tails *.tex]
}
# textutil::adjust::getPredefined
#
# Retrieve the full path for a predefined hyphenation file
# coming with the package.
#
# Parameters:
# name Name of the predefined file.
#
# Results:
# Full path to the file, or an error if it doesn't
# exist or is matching the pattern *.tex.
proc ::textutil::adjust::getPredefined {name} {
variable here
if {![string match *.tex $name]} {
return -code error \
"Illegal hyphenation file \"$name\""
}
set path [file join $here $name]
if {![file exists $path]} {
return -code error \
"Unknown hyphenation file \"$path\""
}
return $path
}
# textutil::adjust::readPatterns
#
# Read hyphenation patterns from a file and store them in an array
#
# Parameters:
# filNam name of the file containing the patterns
proc ::textutil::adjust::readPatterns { filNam } {
variable HyphPatterns; # hyphenation patterns (TeX)
# HyphPatterns(_LOADED_) is used as flag for having loaded
# hyphenation patterns from the respective file (TeX format)
if {[info exists HyphPatterns(_LOADED_)]} {
unset HyphPatterns(_LOADED_)
}
# the array xlat provides translation from TeX encoded characters
# to those of the ISO-8859-1 character set
set xlat(\"s) \337; # 223 := sharp s "
set xlat(\`a) \340; # 224 := a, grave
set xlat(\'a) \341; # 225 := a, acute
set xlat(\^a) \342; # 226 := a, circumflex
set xlat(\"a) \344; # 228 := a, diaeresis "
set xlat(\`e) \350; # 232 := e, grave
set xlat(\'e) \351; # 233 := e, acute
set xlat(\^e) \352; # 234 := e, circumflex
set xlat(\`i) \354; # 236 := i, grave
set xlat(\'i) \355; # 237 := i, acute
set xlat(\^i) \356; # 238 := i, circumflex
set xlat(\~n) \361; # 241 := n, tilde
set xlat(\`o) \362; # 242 := o, grave
set xlat(\'o) \363; # 243 := o, acute
set xlat(\^o) \364; # 244 := o, circumflex
set xlat(\"o) \366; # 246 := o, diaeresis "
set xlat(\`u) \371; # 249 := u, grave
set xlat(\'u) \372; # 250 := u, acute
set xlat(\^u) \373; # 251 := u, circumflex
set xlat(\"u) \374; # 252 := u, diaeresis "
set fd [open $filNam RDONLY]
set status 0
while {[gets $fd line] >= 0} {
switch -exact $status {
PATTERNS {
if {[regexp {^\}[.]*} $line]} {
# End of patterns encountered: set status
# and ignore that line
set status 0
continue
} else {
# This seems to be pattern definition line; to process it
# we have first to do some editing
#
# 1) eat comments in a pattern definition line
# 2) eat braces and coded linefeeds
set z [string first "%" $line]
if {$z > 0} { set line [string range $line 0 [expr {$z-1}]] }
regsub -all {(\\n|\{|\})} $line {} tmp
set line $tmp
# Now $line should consist only of hyphenation patterns
# separated by white space
# Translate TeX encoded characters to ISO-8859-1 characters
# using the array xlat defined above
foreach x [array names xlat] {
regsub -all {$x} $line $xlat($x) tmp
set line $tmp
}
# split the line and create a lookup array for
# the repective hyphenation patterns
foreach item [split $line] {
if {[string length $item]} {
if {![string match {\\} $item]} {
# create index for hyphenation patterns
set var $item
regsub -all {[0-9]} $var {} idx
# store hyphenation patterns as elements of an array
set HyphPatterns($idx) $item
}
}
}
}
}
EXCEPTIONS {
if {[regexp {^\}[.]*} $line]} {
# End of patterns encountered: set status
# and ignore that line
set status 0
continue
} else {
# to be done in the future
}
}
default {
if {[regexp {^\\endinput[.]*} $line]} {
# end of data encountered, stop processing and
# ignore all the following text ..
break
} elseif {[regexp {^\\patterns[.]*} $line]} {
# begin of patterns encountered: set status
# and ignore that line
set status PATTERNS
continue
} elseif {[regexp {^\\hyphenation[.]*} $line]} {
# some particular cases to be treated separately
set status EXCEPTIONS
continue
} else {
set status 0
}
}
}
}
close $fd
set HyphPatterns(_LOADED_) 1
return
}
#######################################################
# @c The specified <a text>block is indented
# @c by <a prefix>ing each line. The first
# @c <a hang> lines ares skipped.
#
# @a text: The paragraph to indent.
# @a prefix: The string to use as prefix for each line
# @a prefix: of <a text> with.
# @a skip: The number of lines at the beginning to leave untouched.
#
# @r Basically <a text>, but indented a certain amount.
#
# @i indent
# @n This procedure is not checked by the testsuite.
proc ::textutil::adjust::indent {text prefix {skip 0}} {
set text [string trimright $text]
set res [list]
foreach line [split $text \n] {
if {[string compare "" [string trim $line]] == 0} {
lappend res {}
} else {
set line [string trimright $line]
if {$skip <= 0} {
lappend res $prefix$line
} else {
lappend res $line
}
}
if {$skip > 0} {incr skip -1}
}
return [join $res \n]
}
# Undent the block of text: Compute LCP (restricted to whitespace!)
# and remove that from each line. Note that this preverses the
# shaping of the paragraph (i.e. hanging indent are _not_ flattened)
# We ignore empty lines !!
proc ::textutil::adjust::undent {text} {
if {$text == {}} {return {}}
set lines [split $text \n]
set ne [list]
foreach l $lines {
if {[string length [string trim $l]] == 0} continue
lappend ne $l
}
set lcp [::textutil::string::longestCommonPrefixList $ne]
if {[string length $lcp] == 0} {return $text}
regexp "^(\[\t \]*)" $lcp -> lcp
if {[string length $lcp] == 0} {return $text}
set len [string length $lcp]
set res [list]
foreach l $lines {
if {[string length [string trim $l]] == 0} {
lappend res {}
} else {
lappend res [string range $l $len end]
}
}
return [join $res \n]
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::adjust {
variable here [file dirname [info script]]
variable Justify left
variable Length 72
variable FullLine 0
variable StrictLength 0
variable Hyphenate 0
variable HyphPatterns
namespace export adjust indent undent
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::adjust 0.7.3

902
src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/dehypht.tex

@ -0,0 +1,902 @@
% This is `dehypht.tex' as of 03 March 1999.
%
% Copyright (C) 1988,1991 Rechenzentrum der Ruhr-Universitaet Bochum
% [german hyphen patterns]
% Copyright (C) 1993,1994,1999 Bernd Raichle/DANTE e.V.
% [macros, adaption for TeX 2]
%
% -----------------------------------------------------------------
% IMPORTANT NOTICE:
%
% This program can be redistributed and/or modified under the terms
% of the LaTeX Project Public License Distributed from CTAN
% archives in directory macros/latex/base/lppl.txt; either
% version 1 of the License, or any later version.
% -----------------------------------------------------------------
%
%
% This file contains german hyphen patterns following traditional
% hyphenation rules and includes umlauts and sharp s, but without
% `c-k' and triple consonants. It is based on hyphen patterns
% containing 5719 german hyphen patterns with umlauts in the
% recommended version of September 27, 1990.
%
% For use with TeX generated by
%
% Norbert Schwarz
% Rechenzentrum Ruhr-Universitaet Bochum
% Universitaetsstrasse 150
% D-44721 Bochum, FRG
%
%
% Adaption of these patterns for TeX, Version 2.x and 3.x and
% all fonts in T1/`Cork'/EC/DC and/or OT1/CM encoding by
%
% Bernd Raichle
% Stettener Str. 73
% D-73732 Esslingen, FRG
% Email: raichle@Informatik.Uni-Stuttgart.DE
%
%
% Error reports in case of UNCHANGED versions to
%
% DANTE e.V., Koordinator `german.sty'
% Postfach 10 18 40
% D-69008 Heidelberg, FRG
% Email: german@Dante.DE
%
% or one of the addresses given above.
%
%
% Changes:
% 1990-09-27 First version of `ghyphen3.tex' (Norbert Schwarz)
% 1991-02-13 PC umlauts changed to ^^xx (Norbert Schwarz)
% 1993-08-27 Umlauts/\ss changed to "a/\3 macros, added macro
% definitions and additional logic to select correct
% patterns/encoding (Bernd Raichle)
% 1994-02-13 Release of `ghyph31.tex' V3.1a (Bernd Raichle)
% 1999-03-03 Renamed file to `dehypht.tex' according to the
% naming scheme using the ISO country code `de', the
% common part `hyph' for all hyphenation patterns files,
% and the additional postfix `t' for traditional,
% removed wrong catcode change of ^^e (the comment
% character %) and ^^f (the character &),
% do _not_ change \catcode, \lccode, \uccode to avoid
% problems with other hyphenation pattern files,
% changed code to distinguish TeX 2.x/3.x,
% changed license conditions to LPPL (Bernd Raichle)
%
%
% For more information see the additional documentation
% at the end of this file.
%
% -----------------------------------------------------------------
%
\message{German Traditional Hyphenation Patterns %
`dehypht' Version 3.2a <1999/03/03>}
\message{(Formerly known under the name `ghyph31' and `ghyphen'.)}
%
%
% Next we define some commands which are used inside the patterns.
% To keep them local, we enclose the rest of the file in a group
% (The \patterns command globally changes the hyphenation trie!).
%
\begingroup
%
%
% Make sure that doublequote is not active:
\catcode`\"=12
%
%
% Because ^^e4 is used in the following macros which is read by
% TeX 2.x as ^^e or %, the comment character of TeX, some trick
% has to be found to avoid this problem. The same is true for the
% character ^^f or & in the TeX 2.x code.
% Therefore in the code the exclamationmark ! is used instead of
% the circumflex ^ and its \catcode is set appropriately
% (normally \catcode`\!=12, in the code \catcode`\!=7).
%
% The following \catcode, \lccode assignments and macro definitions
% are defined in such a way that the following \pattern{...} list
% can be used for both, TeX 2.x and TeX 3.x.
%
% We first change the \lccode of ^^Y to make sure that we can
% include this character in the hyphenation patterns.
%
\catcode`\^^Y=11 \lccode`\^^Y=`\^^Y
%
% Then we have to define some macros depending on the TeX version.
% Therefore we have to distinguish TeX version 2.x and 3.x:
%
\ifnum`\@=`\^^40 % true => TeX 3.x
%
% For TeX 3:
% ----------
%
% Assign appropriate \catcode and \lccode values for all
% accented characters used in the patterns (\uccode changes are
% not used within \patterns{...} and thus not necessary):
%
\catcode"E4=11 \catcode"C4=11 % \"a \"A
\catcode"F6=11 \catcode"D6=11 % \"o \"O
\catcode"FC=11 \catcode"DC=11 % \"u \"U
\catcode"FF=11 \catcode"DF=11 % \ss SS
%
\lccode"C4="E4 \uccode"C4="C4 \lccode"E4="E4 \uccode"E4="C4
\lccode"D6="F6 \uccode"D6="D6 \lccode"F6="F6 \uccode"F6="D6
\lccode"DC="FC \uccode"DC="DC \lccode"FC="FC \uccode"FC="DC
\lccode"DF="FF \uccode"DF="DF \lccode"FF="FF \uccode"FF="DF
%
% In the following definitions we use ??xy instead of ^^xy
% to avoid errors when reading the following macro definitions
% with TeX 2.x (remember ^^e(4) is the comment character):
%
\catcode`\?=7
%
% Define the accent macro " in such a way that it
% expands to single letters in font encoding T1.
\catcode`\"=13
\def"#1{\ifx#1a??e4\else \ifx#1o??f6\else \ifx#1u??fc\else
\errmessage{Hyphenation pattern file corrupted!}%
\fi\fi\fi}
%
% - patterns with umlauts are ok
\def\n#1{#1}
%
% For \ss which exists in T1 _and_ OT1 encoded fonts but with
% different glyph codes, duplicated patterns for both encodings
% are included. Thus you can use these hyphenation patterns for
% T1 and OT1 encoded fonts:
% - define \3 to be code `\^^ff (\ss in font encoding T1)
% - define \9 to be code `\^^Y (\ss in font encoding OT1)
\def\3{??ff}
\def\9{??Y}
% - duplicated patterns to support font encoding OT1 are ok
\def\c#1{#1}
% >>>>>> UNCOMMENT the next line, if you do not want
% >>>>>> to use fonts in font encoding OT1
%\def\c#1{}
%
\catcode`\?=12
%
\else
%
% For TeX 2:
% ----------
%
% Define the accent macro " to throw an error message.
\catcode`\"=13
\def"#1{\errmessage{Hyphenation pattern file corrupted!}}
%
% - ignore all patterns with umlauts
\def\n#1{}
%
% With TeX 2 fonts in encoding T1 can be used, but all glyphs
% in positions > 127 can not be used in hyphenation patterns.
% Thus only patterns with glyphs in OT1 positions are included:
% - define \3 to be code ^^Y (\ss in CM font encoding)
% - define \9 to throw an error message
\def\3{^^Y}
\def\9{\errmessage{Hyphenation pattern file corrupted!}}
% - ignore all duplicated patterns with \ss in T1 encoding
\def\c#1{}
%
\fi
%
%
\patterns{%
.aa6l .ab3a4s .ab3ei .abi2 .ab3it .ab1l .ab1r .ab3u .ad3o4r .alti6
.ana3c .an5alg .an1e .ang8s .an1s .ap1p .ar6sc .ar6ta .ar6tei .as2z
.au2f1 .au2s3 .be5erb .be3na .ber6t5r .bie6r5 .bim6s5t .brot3 .bru6s
.ch6 .che6f5 .da8c .da2r .dar5in .dar5u .den6ka .de5r6en .des6pe
.de8spo .de3sz .dia3s4 .dien4 .dy2s1 .ehren5 .eine6 .ei6n5eh .ei8nen
.ein5sa .en6der .en6d5r .en3k4 .en8ta8 .en8tei .en4t3r .epo1 .er6ban
.er6b5ei .er6bla .er6d5um .er3ei .er5er .er3in .er3o4b .erwi5s .es1p
.es8t .ex1a2 .ex3em .fal6sc .fe6st5a .flu4g3 .furch8 .ga6ner .ge3n4a
\n{.ge5r"o} .ges6 .halb5 .halbe6 .hal6br .haup4 .hau4t .heima6 .he4r3e
.her6za .he5x .hin3 .hir8sc .ho4c .hu3sa .hy5o .ibe5 .ima6ge .in1
.ini6 .is5chi .jagd5 .kal6k5o .ka6ph .ki4e .kop6f3 .kraf6 \n{.k"u5ra}
.lab6br .liie6 .lo6s5k \n{.l"o4s3t} .ma5d .mi2t1 .no6th .no6top
.obe8ri .ob1l .obs2 .ob6st5e .or3c .ort6s5e .ost3a .oste8r .pe4re
.pe3ts .ph6 .po8str .rau4m3 .re5an .ro8q .ru5the \n{.r"u5be}
\n{.r"u8stet} .sch8 .se6e .se5n6h .se5ra .si2e .spi6ke .st4 .sy2n
.tages5 .tan6kl .ta8th .te6e .te8str .to6der .to8nin .to6we .um1
.umpf4 .un1 .une6 .unge5n .ur1c .ur5en .ve6rin .vora8 .wah6l5 .we8ges
.wo6r .wor3a .wun4s .zi4e .zuch8 \n{."ande8re} \n{."och8} aa1c aa2gr
aal5e aa6r5a a5arti aa2s1t aat2s 6aba ab3art 1abdr 6abel aben6dr
ab5erk ab5err ab5esse 1abf 1abg \n{1abh"a} ab1ir 1abko a1bl ab1la
5ablag a6bla\3 \c{a6bla\9} ab4ler ab1lu \n{a8bl"a} \n{5a6bl"o} abma5c
1abn ab1ra ab1re 5a6brec ab1ro ab1s ab8sk abs2z 3abtei ab1ur 1abw
5abze 5abzu \n{ab1"an} \n{ab"au8} a4ce. a5chal ach5art ach5au a1che
a8chent ach6er. a6ch5erf a1chi ach1l ach3m ach5n a1cho ach3re a1chu
ach1w a1chy \n{ach5"af} ack1o acks6t ack5sta a1d 8ad. a6d5ac ad3ant
ad8ar 5addi a8dein ade5o8 adi5en 1adj 1adle ad1op a2dre 3adres adt1
1adv \n{a6d"a} a1e2d ae1r a1er. 1aero 8afa a3fal af1an a5far a5fat
af1au a6fentl a2f1ex af1fr af5rau af1re 1afri af6tent af6tra aft5re
a6f5um \n{8af"a} ag5abe 5a4gent ag8er ages5e 1aggr ag5las ag1lo a1gn
ag2ne 1agog a6g5und a1ha a1he ah5ein a4h3erh a1hi ahl1a ah1le ah4m3ar
ahn1a a5ho ahra6 ahr5ab ah1re ah8rei ahren8s ahre4s3 ahr8ti ah1ru a1hu
\n{ah8"o} ai3d2s ai1e aif6 a3inse ai4re. a5isch. ais8e a3ismu ais6n
aiso6 a1j 1akad a4kade a1ke a1ki 1akko 5akro1 a5lal al5ans 3al8arm
al8beb al8berw alb5la 3album al1c a1le a6l5e6be a4l3ein a8lel a8lerb
a8lerh a6lert 5a6l5eth 1algi al4gli al3int al4lab al8lan al4l3ar
alle3g a1lo a4l5ob al6schm al4the altist5 al4t3re 8a1lu alu5i a6lur
alu3ta \n{a1l"a} a6mate 8ame. 5a6meise am6m5ei am6mum am2n ampf3a
am6schw am2ta a1mu \n{a1m"a} a3nac a1nad anadi5e an3ako an3alp 3analy
an3ame an3ara a1nas an5asti a1nat anat5s an8dent ande4s3 an1ec an5eis
an1e2k 4aner. a6n5erd a8nerf a6n5erke 1anfa 5anfert \n{1anf"a} 3angab
5angebo an3gli ang6lis an2gn 3angri ang5t6 \n{5anh"a} ani5g ani4ka
an5i8on an1kl an6kno an4kro 1anl anma5c anmar4 3annah anne4s3 a1no
5a6n1o2d 5a6n3oma 5a6nord 1anr an1sa 5anschl an4soz an1st 5anstal
an1s2z 5antenn an1th \n{5anw"a} a5ny an4z3ed 5anzeig 5anzieh 3anzug
\n{an1"a} \n{5an"as} \n{a1n"o} \n{an"o8d} a1os a1pa 3apfel a2ph1t
\n{aph5"a6} a1pi 8apl apo1c apo1s a6poste a6poth 1appa ap1pr a1pr
\n{a5p"a} \n{a3p"u} a1ra a4r3af ar3all 3arbei 2arbt ar1c 2a1re ar3ein
ar2gl 2a1ri ari5es ar8kers ar6les ar4nan ar5o6ch ar1o2d a1rol ar3ony
a8ror a3ros ar5ox ar6schl 8artei ar6t5ri a1ru a1ry 1arzt arz1w
\n{ar8z"a} \n{ar"a8m} \n{ar"o6} \n{ar5"om} \n{ar1"u2} a1sa a6schec
asch5l asch3m a6schn a3s4hi as1pa asp5l a8steb as5tev 1asth a6stoc
a1str ast3re 8a1ta ata5c ata3la a6tapf ata5pl a1te a6teli aten5a
ate5ran 6atf 6atg a1th at3hal 1athl 2a1ti 5atlant 3atlas 8atmus 6atn
a1to a6t5ops ato6ra a6t5ort. 4a1tr a6t5ru at2t1h \n{at5t6h"a} 6a1tu
atz1w \n{a1t"a} \n{a1t"u} au1a au6bre auch3a au1e aue4l 5aufent
\n{3auff"u} 3aufga 1aufn auf1t 3auftr 1aufw 3auge. au4kle aule8s 6aum
au8mar aum5p 1ausb 3ausd 1ausf 1ausg au8sin 3auss au4sta 1ausw 1ausz
aut5eng au1th 1auto au\3e8 \c{au\9e8} a1v ave5r6a aver6i a1w a6wes a1x
a2xia a6xio a1ya a1z azi5er. 8a\3 \c{8a\9} 1ba 8ba8del ba1la ba1na
ban6k5r ba5ot bardi6n ba1ro basten6 bau3sp 2b1b bb6le b2bli 2b1c 2b1d
1be be1a be8at. be1ch 8becht 8becke. be5el be1en bee8rei be5eta bef2
8beff be1g2 \n{beh"o8} bei1s 6b5eisen bei3tr b8el bel8o belu3t be3nac
bend6o be6ners be6nerw be4nor ben4se6 bens5el \n{be1n"a} \n{be1n"u}
be1o2 b8er. be1ra be8rac ber8gab. ber1r \n{be1r"u} bes8c bes5erh
bes2p be5tha bet5sc be1un be1ur 8bex be6zwec 2b1f8 bfe6st5e 2b1g2
bga2s5 bge1 2b1h bhole6 1bi bi1bl b6ie bi1el bi1la \n{bil"a5} bi1na
bi4nok bi5str bi6stu bi5tr bit4t5r b1j 2b1k2 \n{bk"u6} bl8 b6la.
6b1lad 6blag 8blam 1blat b8latt 3blau. b6lav 3ble. b1leb b1led
8b1leg 8b1leh 8bleid 8bleih 6b3lein blei3s ble4m3o 4blich b4lind
8bling b2lio 5blit b4litz b1loh 8b1los 1blu 5blum 2blun blut3a blut5sc
\n{3bl"a} \n{bl"as5c} \n{5bl"o} \n{3bl"u} \n{bl"u8sc} 2b1m 2b1n 1bo
bo1ch bo5d6s boe5 8boff 8bonk bo1ra b1ort 2b1p2 b1q 1br brail6 brast8
bre4a b5red 8bref 8b5riem b6riga bro1s b1rup b2ruz \n{8br"oh}
\n{br"os5c} 8bs b1sa b8sang b2s1ar b1sc bs3erl bs3erz b8sof b1s2p
bst1h b3stru \n{b5st"a} b6sun 2b1t b2t1h 1bu bu1ie bul6k b8ure bu6sin
6b1v 2b1w 1by1 by6te. 8b1z bzi1s \n{1b"a} \n{b5"a6s5} \n{1b"u}
\n{b6"u5bere} \n{b"uge6} \n{b"ugel5e} \n{b"ur6sc} 1ca cag6 ca5la ca6re
ca5y c1c 1ce celi4c celich5 ce1ro c8h 2ch. 1chae ch1ah ch3akt cha6mer
8chanz 5chara 3chari 5chato 6chb 1chef 6chei ch3eil ch3eis 6cherkl
6chf 4chh 5chiad 5chias 6chins 8chj chl6 5chlor 6ch2m 2chn6 ch8nie
5cho. 8chob choi8d 6chp ch3ren ch6res \n{ch3r"u} 2chs 2cht cht5ha
cht3hi 5chthon ch6tin 6chuh chu4la 6ch3unt chut6t 8chw 1ci ci5tr c2k
2ck. ck1ei 4ckh ck3l ck3n ck5o8f ck1r 2cks ck5stra ck6s5u c2l 1c8o
con6ne 8corb cos6t c3q 1c6r 8c1t 1cu 1cy \n{5c"a1} \n{c"o5} 1da.
8daas 2dabg 8dabr 6dabt 6dabw 1dac da2gr 6d5alk 8d5amt dan6ce.
dani5er dan8ker 2danl danla6 6dans 8danzi 6danzu d1ap da2r1a8 2d1arb
d3arc dar6men 4d3art 8darz 1dat 8datm 2d1auf 2d1aus 2d1b 2d1c 2d1d
d5de d3d2h \n{dd"amme8} 1de 2deal de5an de3cha de1e defe6 6deff 2d1ehr
5d4eic de5isc de8lar del6s5e del6spr de4mag de8mun de8nep dene6r
8denge. 8dengen de5o6d 2deol de5ram 8derdb der5ein de1ro der1r d8ers
der5um de4s3am de4s3an de4sau de6sil de4sin de8sor de4spr de2su 8deul
de5us. 2d1f df2l 2d1g 2d1h 1di dia5c di5ara dice5 di3chr di5ena di1gn
di1la dil8s di1na 8dind 6dinf 4d3inh 2d1ins di5o6d di3p4t di8sen dis1p
di5s8per di6s5to dis5tra di8tan di8tin d1j 6dje 2dju 2d1k 2d1l 2d1m
2d1n6 dni6 dnje6 1do 6d5obe do6berf 6d5ony do3ran 6dord 2d1org dor4t3h
do6ste 6doth dott8e 2d1p d5q dr4 1drah 8drak d5rand 6dre. 4drech
d6reck 4d3reg 8d3reic d5reife 8drem 8d1ren 2drer 8dres. 6d5rh 1dria
d1ric 8drind droi6 dro5x 1dru 8drut \n{dr"os5c} \n{1dr"u} \n{dr"u5b}
\n{dr"u8sc} 2ds d1sa d6san dsat6 d1sc 5d6scha. 5dschik dse8e d8serg
8dsl d1sp d4spak ds2po \n{d8sp"a} d1st \n{d1s"u} 2dt d1ta d1te d1ti
d1to dt1s6 d1tu \n{d5t"a} 1du du5als du1b6 du1e duf4t3r 4d3uh du5ie
8duml 8dumw 2d1und du8ni 6d5unt dur2c durch3 6durl 6dursa 8durt du1s
du8schr 2d1v 2d1w dwa8l 2d1z \n{1d"a} \n{6d"ah} \n{8d"and} \n{d"a6r}
\n{d"o8bl} \n{d5"ol} \n{d"or6fl} \n{d"o8sc} \n{d5"o4st} \n{d"os3te}
\n{1d"u} ea4ben e1ac e1ah e1akt e1al. e5alf e1alg e5a8lin e1alk e1all
e5alp e1alt e5alw e1am e1and ea6nim e1ar. e5arf e1ark e5arm e3art
e5at. e6ate e6a5t6l e8ats e5att e6au. e1aus e1b e6b5am ebens5e
eb4lie eb4ser eb4s3in e1che e8cherz e1chi ech3m 8ech3n ech1r ech8send
ech4su e1chu eck5an e5cl e1d ee5a ee3e ee5g e1ei ee5isc eei4s3t
ee6lend e1ell \n{ee5l"o} e1erd ee3r4e ee8reng eere6s5 \n{ee5r"a}
ee6tat e1ex e1f e6fau e8fe8b 3effek ef3rom ege6ra eglo6si 1egy e1ha
e6h5ach eh5ans e6hap eh5auf e1he e1hi ehl3a eh1le ehl5ein eh1mu ehn5ec
e1ho ehr1a eh1re ehre6n eh1ri eh1ru ehr5um e1hu eh1w e1hy \n{e1h"a}
\n{e1h"o} \n{e3h"ut} ei1a eia6s ei6bar eich3a eich5r ei4dar ei6d5ei
ei8derf ei3d4sc ei1e 8eifen 3eifri 1eign eil1d ei6mab ei8mag ein1a4
ei8nat ei8nerh ei8ness ei6nete ein1g e8ini ein1k ei6n5od ei8nok ei4nor
\n{e3ins"a} ei1o e1irr ei5ru ei8sab ei5schn ei6s5ent ei8sol ei4t3al
eit3ar eit1h ei6thi ei8tho eit8samt ei6t5um e1j 1ekd e1ke e1ki e1k2l
e1kn ekni4 e1la e2l1al 6elan e6lanf e8lanl e6l5ans el3arb el3arm
e6l3art 5e6lasti e6lauge elbst5a e1le 6elef ele6h e6l5ehe e8leif
e6l5einh 1elek e8lel 3eleme e6lemen e6lente el5epi e4l3err e6l5ersc
elf2l elg2 e6l5ins ell8er 4e1lo e4l3ofe el8soh el8tent 5eltern e1lu
elut2 \n{e1l"a} \n{e1l"u} em8dei em8meis 4emo emo5s 1emp1f 1empt 1emto
e1mu emurk4 emurks5 \n{e1m"a} en5a6ben en5achs en5ack e1nad en5af
en5all en3alt en1am en3an. en3ant en3anz en1a6p en1ar en1a6s 6e1nat
en3auf en3aus en2ce enda6l end5erf end5erg en8dess 4ene. en5eck
e8neff e6n5ehr e6n5eim en3eis 6enem. 6enen e4nent 4ener. e8nerd
e6n3erf e4nerg 5energi e6n5erla en5ers e6nerst en5erw 6enes e6n5ess
e2nex en3glo 2eni enni6s5 ennos4 enns8 e1no e6nober eno8f en5opf
e4n3ord en8sers ens8kl en1sp ens6por en5t6ag enta5go en8terbu en6tid
3entla ent5ric 5entwic 5entwu 1entz enu5i e3ny en8zan \n{en1"of}
\n{e1n"os} \n{e1n"ug} eo1c e5o6fe e5okk e1on. e3onf e5onk e5onl e5onr
e5opf e5ops e5or. e1ord e1org eo5r6h eo1t e1pa e8pee e6p5e6g ep5ent
e1p2f e1pi 5epid e6pidem e1pl 5epos e6pos. ep4p3a e1pr \n{e1p"a} e1q
e1ra. er5aal 8eraba e5rabel er5a6ben e5rabi er3abs er3ach era5e
era5k6l er3all er3amt e3rand e3rane er3ans e5ranz. e1rap er3arc
e3rari er3a6si e1rat erat3s er3auf e3raum 3erbse er1c e1re 4e5re.
er3eck er5egg er5e2h 2erei e3rei. e8reine er5einr 6eren. e4r3enm
4erer. e6r5erm er5ero er5erst e4r3erz er3ess \n{5erf"ul} er8gan.
5ergebn er2g5h \n{5erg"anz} \n{5erh"ohu} 2e1ri eri5ak e6r5iat e4r3ind
e6r5i6n5i6 er5ins e6r5int er5itio er1kl \n{3erkl"a} \n{5erl"os.}
ermen6s er6nab 3ernst 6e1ro. e1rod er1o2f e1rog 6e3roi ero8ide e3rol
e1rom e1ron e3rop8 e2r1or e1ros e1rot er5ox ersch4 5erstat er6t5ein
er2t1h er5t6her 2e1ru eruf4s3 e4r3uhr er3ums e5rus 5erwerb e1ry er5zwa
er3zwu \n{er"a8m} \n{er5"as} \n{er"o8} \n{e3r"os.} \n{e6r1"u2b} e1sa
esa8b e8sap e6s5a6v e1sc esch4l ese1a es5ebe eserve5 e8sh es5ill
es3int es4kop e2sl eso8b e1sp espei6s5 es2po es2pu 5essenz e6stabs
e6staf e6st5ak est3ar e8stob e1str est5res es3ur e2sz \n{e1s"u} e1ta
et8ag etari5e eta8ta e1te eten6te et5hal e5thel e1ti 1etn e1to e1tr
et3rec e8tscha et8se et6tei et2th et2t1r e1tu etu1s et8zent et8zw
\n{e1t"a} \n{e1t"o} \n{e1t"u} eu1a2 eu1e eue8rei eu5fe euin5 euk2
e1um. eu6nio e5unter eu1o6 eu5p 3europ eu1sp eu5str eu8zo e1v eval6s
eve5r6en ever4i e1w e2wig ex1or 1exp 1extr ey3er. e1z \n{e1"a2}
\n{e5"o8} \n{e1"u} e8\3es \c{e8\9es} fa6ch5i fade8 fa6del fa5el.
fal6lo falt8e fa1na fan4gr 6fanl 6fap far6ba far4bl far6r5a 2f1art
fa1sc fau8str fa3y 2f1b2 6f1c 2f1d 1fe 2f1eck fe6dr feh6lei f6eim
8feins f5eis fel5en 8feltern 8femp fe5rant 4ferd. ferri8 fe8stof
fe6str fe6stum fe8tag fet6ta fex1 2ff f1fa f6f5arm f5fe ffe5in ffe6la
ffe8ler ff1f f1fla ff3lei ff4lie ff8sa ff6s5ta 2f1g2 fgewen6 4f1h 1fi
fid4 fi3ds fieb4 fi1la fi8lei fil4m5a f8in. fi1na 8finf fi8scho fi6u
6f1j 2f1k2 f8lanz fl8e 4f3lein 8flib 4fling f2lix 6f3lon 5flop 1flor
\n{5f8l"ac} \n{3fl"ot} 2f1m 2f1n 1fo foh1 f2on fo6na 2f1op fo5ra
for8mei for8str for8th for6t5r fo5ru 6f5otte 2f1p8 f1q fr6 f5ram
1f8ran f8ra\3 \c{f8ra\9} f8re. frei1 5frei. f3reic f3rest f1rib
8f1ric 6frig 1fris fro8na \n{fr"as5t} 2fs f1sc f2s1er f5str
\n{fs3t"at} 2ft f1tak f1te ft5e6h ftere6 ft1h f1ti f5to f1tr ft5rad
ft1sc ft2so f1tu ftwi3d4 ft1z 1fu 6f5ums 6funf fun4ka fu8\3end
\c{fu8\9end} 6f1v 2f1w 2f1z \n{1f"a} \n{f"a1c} \n{8f"arm} \n{6f"aug}
\n{f"a8\3} \n{\c{f"a8\9}} \n{f"ode3} \n{8f"of} \n{3f"or} \n{1f"u}
\n{f"un4f3u} 1ga ga6bl 6gabw 8gabz g3a4der ga8ho ga5isc 4gak ga1la
6g5amt ga1na gan5erb gan6g5a ga5nj 6ganl 8gansc 6garb 2g1arc 2g1arm
ga5ro 6g3arti ga8sa ga8sc ga6stre 2g1atm 6g5auf gau5fr g5aus 2g1b g5c
6gd g1da 1ge ge1a2 ge6an ge8at. ge1e2 ge6es gef2 8geff ge1g2l ge1im
4g3eise geist5r gel8bra gelt8s \n{ge5l"o} ge8nin gen3k 6g5entf
\n{ge3n"a} ge1or ge1ra ge6rab ger8au \n{8gerh"o} ger8ins ge1ro 6g5erz.
\n{ge1r"a} \n{ge1r"u} ge1s ges2p ge5unt 4g3ex3 2g1f8 2g1g g1ha 6g1hei
5ghel. g5henn 6g1hi g1ho 1ghr \n{g1h"o} 1gi gi5la gi8me. gi1na
4g3ins gi3str g1j 2g1k 8gl. 1glad g5lag glan4z3 1glas 6glass 5glaub
g3lauf 1gle. g5leb 3gleic g3lein 5gleis 1glem 2gler 8g3leu gli8a
g2lie 3glied 1g2lik 1g2lim g6lio 1gloa 5glom 1glon 1glop g1los g4loss
g5luf 1g2ly \n{1gl"u} 2g1m gn8 6gn. 1gna 8gnach 2gnah g1nas g8neu
g2nie g3nis 1gno 8gnot 1go goe1 8gof 2gog 5gogr 6g5oh goni5e 6gonist
go1ra 8gord 2g1p2 g1q 1gr4 g5rahm gra8m gra4s3t 6g1rec gre6ge 4g3reic
g5reit 8grenn gri4e g5riem 5grif 2grig g5ring 6groh 2grot gro6\3
\c{gro6\9} 4grut 2gs gs1ab g5sah gs1ak gs1an gs8and gs1ar gs1au g1sc
gs1ef g5seil gs5ein g2s1er gs1in g2s1o gso2r gs1pr g2s1u 2g1t g3te
g2t1h 1gu gu5as gu2e 2gue. 6gued 4g3uh 8gums 6g5unt gu1s gut3h gu2tu
4g1v 2g1w gy1n g1z \n{1g"a} \n{8g"a8m} \n{6g"arm} \n{1g"o} \n{1g"u}
\n{6g"ub} 1haa hab8r ha8del hade4n 8hae ha5el. haf6tr 2hal. ha1la
hal4b5a 6hale 8han. ha1na han6dr han6ge. 2hani h5anth 6hanz 6harb
h3arbe h3arme ha5ro ha2t1h h1atm hau6san ha8\3 \c{ha8\9} h1b2 h1c h1d
he2bl he3cho h3echt he5d6s 5heft h5e6he. hei8ds h1eif 2hein he3ism
he5ist. heit8s3 hek6ta hel8lau 8helt he6mer 1hemm 6h1emp hen5end
hen5klo hen6tri he2nu 8heo he8q her3ab he5rak her3an 4herap her3au
h3erbi he1ro he8ro8b he4r3um her6z5er he4spe he1st heta6 het5am he5th
heu3sc he1xa hey5e h1f2 h1g hgol8 h1h h1iat hie6r5i hi5kt hil1a2
hil4fr hi5nak hin4ta hi2nu hi5ob hirn5e hir6ner hi1sp hi1th hi5tr
5hitz h1j h6jo h1k2 hlabb4 hla4ga hla6gr h5lai hl8am h1las h1la\3
\c{h1la\9} hl1c h1led h3lein h5ler. h2lif h2lim h8linf hl5int h2lip
h2lit h4lor h3lose \n{h1l"as} hme5e h2nee h2nei hn3eig h2nel hne8n
hne4p3f hn8erz h6netz h2nip h2nit h1nol hn5sp h2nuc h2nud h2nul hoch1
1hoh hoh8lei 2hoi ho4l3ar 1holz h2on ho1ra 6horg 5horn. ho3sl hos1p
ho4spi h1p hpi6 h1q 6hr h1rai h8rank h5raum hr1c hrcre8 h1red h3reg
h8rei. h4r3erb h8rert hrg2 h1ric hr5ins h2rom hr6t5erl hr2t1h hr6t5ra
hr8tri h6rum hr1z hs3ach h6s5amt h1sc h6s5ec h6s5erl hs8erle h4sob
h1sp h8spa\3 \c{h8spa\9} h8spel hs6po h4spun h1str h4s3tum hs3und
\n{h1s"u} h5ta. h5tab ht3ac ht1ak ht3ang h5tanz ht1ar ht1at h5taub
h1te h2t1ec ht3eff ht3ehe h4t3eif h8teim h4t3ein ht3eis h6temp h8tentf
hte8ren \n{h6terf"u} h8tergr h4t3erh h6t5ersc h8terst h8tese h8tess
h2t1eu h4t3ex ht1he ht5hu h1ti ht5rak hts3ah ht1sc ht6sex ht8sk ht8so
h1tu htz8 \n{h5t"um} hub5l hu6b5r huh1l h5uhr. huld5a6 hu8lent
\n{hu8l"a} h5up. h1v h5weib h3weis h1z \n{h"a8kl} \n{h"al8s}
\n{h"ama8tu8} \n{h"a8sche.} \n{h"at1s} \n{h"au4s3c} \n{2h"o.}
\n{2h"oe} \n{8h"oi} \n{h"o6s} \n{h"os5c} \n{h"uhne6} \n{h"ul4s3t}
\n{h"utte8re} i5adn i1af i5ak. i1al. i1al1a i1alb i1ald i5alei i1alf
i1alg i3alh i1alk i1all i1alp i1alr i1als i1alt i1alv i5alw i3alz
i1an. ia5na i3and ian8e ia8ne8b i1ang i3ank i5ann i1ant i1anz i6apo
i1ar. ia6rab i5arr i1as. i1asm i1ass i5ast. i1at. i5ats i1au i5azz
i6b5eig i6b5eis ib2le i4blis i6brig i6b5unt \n{i6b"ub} i1che ich5ei
i6cherb i1chi ich5ins ich1l ich3m ich1n i1cho icht5an icht3r i1chu
ich1w ick6s5te ic5l i1d id3arm 3ideal ide8na 3ideol \n{ide5r"o} i6diot
id5rec id1t ie1a ie6b5ar iebe4s3 ie2bl ieb1r ie8bra ie4bre \n{ie8b"a}
ie2dr ie1e8 ie6f5ad ief5f ie2f1l ie4fro ief1t i1ei ie4l3ec ie8lei
ie4lek i3ell i1en. i1end ien6e i3enf i5enn ien6ne. i1enp i1enr
i5ensa ien8stal i5env i1enz ie5o ier3a4b ie4rap i2ere ie4rec ie6r5ein
ie6r5eis ier8er i3ern. ie8rum ie8rund ie6s5che ie6tau ie8tert ie5the
ie6t5ri i1ett ie5un iex5 2if i1fa if5ang i6fau if1fr if5lac i5f6lie
i1fre ift5a if6t5r ig3art 2ige i8gess ig5he i5gla ig2ni i5go ig3rot
ig3s2p i1ha i8ham i8hans i1he i1hi ih1n ih1r i1hu i8hum ih1w 8i1i ii2s
ii2t i1j i1k i6kak i8kerz i6kes ik4ler i6k5unt 2il i5lac i1lag il3ans
i5las i1lau il6auf i1le ile8h i8lel il2fl il3ipp il6l5enn i1lo ilt8e
i1lu \n{i1l"a} i8mart imb2 i8mele i8mid imme6l5a i1mu \n{i1m"a}
\n{i5m"o} ina5he i1nat in1au inau8s 8ind. in4d3an 5index ind2r 3indus
i5nec i2n1ei i8nerw 3infek 1info 5ingeni ing5s6o 5inhab ini5er. 5inj
\n{in8k"at} in8nan i1no inoi8d in3o4ku in5sau in1sp 5inspe 5instit
5instru ins4ze 5intere 5interv in3the in5t2r i5ny \n{in"a2} \n{i1n"ar}
\n{in1"as} \n{in"o8} \n{in5"od} \n{i1n"os} 2io io1a8 io1c iode4 io2di
ioi8 i1ol. i1om. i1on. i5onb ion2s1 i1ont i5ops i5o8pt i1or.
i3oral io3rat i5orc i1os. i1ot. i1o8x 2ip i1pa i1pi i1p2l i1pr i1q
i1ra ir6bl i1re i1ri ir8me8d ir2m1o2 ir8nak i1ro ir5rho ir6schl
ir6sch5r i5rus i5ry \n{i5r"a} i1sa i8samt i6sar i2s1au i8scheh i8schei
isch5m isch3r \n{isch"a8} is8ele ise3ra i4s3erh is3err isi6de i8sind
is4kop ison5e is6por i8s5tum i5sty \n{i5s"o} i1ta it5ab. i2t1a2m
i8tax i1te i8tersc i1thi i1tho i5thr \n{it8h"a} i1ti i8ti8d iti6kl
itmen4 i1to i8tof it3ran it3rau i1tri itri5o it1sc it2se it5spa it8tru
i1tu it6z5erg it6z1w \n{i1t"a} \n{it"a6r5e} \n{it"at2} \n{it"ats5}
\n{i1t"u} i1u iu6r 2i1v i6vad iva8tin i8vei i6v5ene i8verh i2vob i8vur
i1w iwi2 i5xa i1xe i1z ize8n i8zir i6z5w \n{i"a8m} \n{i1"a6r}
\n{i5"at.} \n{i5"av} \n{i1"o8} \n{i"u8} i6\35ers \c{i6\95ers} ja5la
je2t3r 6jm 5jo jo5as jo1ra jou6l ju5cha jugen4 jugend5 jung5s6 ju1s
\n{3j"a} 1ka 8kachs 8kakz ka1la kal5d kam5t ka1na 2kanl 8kapf ka6pl
ka5r6a 6k3arbe ka1ro kar6p5f 4k3arti 8karz \n{ka1r"a} kasi5e ka6teb
kat8ta kauf6s kau3t2 2k1b 2k1c 4k1d kehr6s kehrs5a 8keic 2k1eig 6k5ein
6k5eis ke6lar ke8leis ke8lo 8kemp k5ente. k3entf 8k5ents 6kentz ke1ra
k5erlau 2k1f8 2k1g 2k1h ki5fl 8kik king6s5 6kinh ki5os ki5sp ki5th
\n{8ki8"o} 2k1k2 kl8 1kla 8klac k5lager kle4br k3leib 3kleid kle5isc
4k3leit k3lek 6k5ler. 5klet 2klic 8klig k2lim k2lin 5klip 5klop k3lor
\n{1kl"a} 2k1m kmani5e kn8 6kner k2ni \n{kn"a8} 1k2o ko1a2 ko6de.
ko1i koi8t ko6min ko1op ko1or ko6pht ko3ra kor6d5er ko5ru ko5t6sc k3ou
3kow 6k5ox 2k1p2 k1q 1kr8 4k3rad 2k1rec 4k3reic kre5ie 2krib 6krig
2krip 6kroba 2ks k1sa k6sab ksal8s k8samt k6san k1sc k2s1ex k5spat
k5spe k8spil ks6por k1spr kst8 k2s1uf 2k1t kta8l kt5a6re k8tein kte8re
k2t1h k8tinf kt3rec kt1s 1ku ku1ch kuck8 k3uhr ku5ie kum2s1 kunfts5
kun2s kunst3 ku8rau ku4ro kurz1 ku1st 4kusti ku1ta ku8\3 \c{ku8\9}
6k1v 2k1w ky5n 2k1z \n{1k"a} \n{k"a4m} \n{4k3"ami} \n{k"ase5} \n{1k"o}
\n{k"o1c} \n{k"o1s} \n{1k"u} \n{k"u1c} \n{k"ur6sc} \n{k"u1s} 1la.
8labf 8labh lab2r 2l1abs lach3r la8dr 5ladu 8ladv 6laff laf5t la2gn
5laken 8lamb la6mer 5lampe. 2l1amt la1na 1land lan4d3a lan4d3r lan4gr
8lanme 6lann 8lanw \n{6lan"a} 8lappa lap8pl lap6pr l8ar. la5ra lar4af
la8rag la8ran la6r5a6s l3arbe la8rei 6larm. la8sa la1sc la8sta lat8i
6l5atm 4lauss 4lauto 1law 2lb l8bab l8bauf l8bede l4b3ins l5blo
lbst5an lbst3e 8lc l1che l8chert l1chi lch3m l5cho lch5w 6ld l4d3ei
ld1re \n{l6d"ub} le2bl le8bre lecht6s5 led2r 6leff le4gas 1lehr lei6br
le8inf 8leinn 5leistu 4lektr le6l5ers lemo2 8lemp l8en. 8lends
6lendun le8nend len8erw 6l5ents 4l3entw 4lentz 8lenzy 8leoz 6lepi
le6pip 8lepo 1ler l6er. 8lerbs 6l5erde le8reis le8rend le4r3er 4l3erg
l8ergr 6lerkl 6l5erzie \n{8ler"o} 8lesel lesi5e le3sko le3tha let1s
5leuc 4leuro leu4s3t le5xe 6lexp l1f 2l1g lgend8 l8gh lglie3 lglied6
6l1h 1li li1ar li1as 2lick li8dr li1en lien6n li8ers li8ert 2lie\3
\c{2lie\9} 3lig li8ga8b li1g6n li1l8a 8limb li1na 4l3indu lings5
4l3inh 6linj link4s3 4linkt 2lint 8linv lion5s6t 4lipp 5lipt 4lisam
livi5e 6l1j 6l1k l8keim l8kj lk2l lko8f lkor8 lk2sa lk2se 6ll l1la
ll3a4be l8labt ll8anl ll1b ll1c ll1d6 l1le l4l3eim l6l5eise ller3a
l4leti l5lip l1lo ll3ort ll5ov ll6spr llte8 l1lu ll3urg \n{l1l"a}
\n{l5l"u} \n{l6l"ub} 2l1m l6m5o6d 6ln l1na l1no 8lobl lo6br 3loch.
l5o4fen 5loge. 5lohn 4l3ohr 1lok l2on 4l3o4per lo1ra 2l1ord 6lorg
4lort lo1ru 1los. lo8sei 3losig lo6ve lowi5 6l1p lp2f l8pho l8pn
lp4s3te l2pt l1q 8l1r 2ls l1sa l6sarm l1sc l8sec l6s5erg l4s3ers l8sh
l5s6la l1sp ls4por ls2pu l1str l8suni \n{l1s"u} 2l1t lt5amp l4t3ein
l5ten l6t5eng l6t5erp l4t3hei lt3her l2t1ho l6t5i6b lti1l \n{l8tr"o}
lt1sc lt6ser lt4s3o lt5ums lu8br lu2dr lu1en8 8lu8fe luft3a luf8tr
lu6g5r 2luh l1uhr lu5it 5luk 2l1umf 2l1umw 1lun 6l5u6nio 4l3unte lu5ol
4lurg 6lurs l3urt lu4sto lu3str lu6st5re lu8su lu6tal lu6t5e6g lu8terg
lu3the lu6t5or lu2t1r lu6\35 \c{lu6\95} l1v lve5r6u 2l1w 1ly lya6
6lymp ly1no l8zess l8zo8f l3zwei lz5wu \n{3l"and} \n{l"a5on}
\n{l"a6sc} \n{l"at1s} \n{5l"auf} \n{2l"aug} \n{l"au6s5c} \n{l"a5v}
\n{l1"ol} \n{1l"os} \n{l"o1\36t} \n{\c{l"o1\96t}} \n{6l1"ube} 1ma
8mabg ma5chan mad2 ma5el 4magg mag8n ma1la ma8lau mal5d 8malde mali5e
malu8 ma8lut 2m1amp 3man mand2 man3ds 8mangr mani5o 8m5anst 6mappa
4m3arbe mar8kr ma1r4o mar8schm 3mas ma1sc \n{ma1t"o} 4m5auf ma5yo 2m1b
mb6r 2m1c 2m1d \n{md6s"a} 1me me1ch me5isc 5meld mel8sa 8memp me5nal
men4dr men8schl men8schw 8mentsp me1ra mer4gl me1ro 3mes me6s5ei me1th
me8\3 \c{me8\9} 2m1f6 2m1g 2m1h 1mi mi1a mi6ale mi1la 2m1imm mi1na
\n{mi5n"u} mi4s3an mit1h mi5t6ra 3mitt mitta8 mi6\35 \c{mi6\95} 6mj
2m1k8 2m1l 2m1m m6mad m6m5ak m8menth m8mentw mme6ra m2mn mm5sp mm5ums
mmut5s \n{m8m"an} m1n8 m5ni 1mo mo5ar mo4dr 8mof mo8gal mo4kla mol5d
m2on mon8do mo4n3od mont8a 6m5ony mopa6 mo1ra mor8d5a mo1sc mo1sp 5mot
moy5 2mp m1pa mpfa6 mpf3l mphe6 m1pi mpin6 m1pl mp2li m2plu mpo8ste
m1pr \n{mpr"a5} mp8th mput6 mpu5ts \n{m1p"o} 8m1q 2m1r 2ms ms5au m1sc
msch4l ms6po m3spri m1str 2m1t mt1ar m8tein m2t1h mt6se \n{mt8s"a}
mu5e 6m5uh mumi1 1mun mun6dr muse5e mu1ta 2m1v mvol2 mvoll3 2m1w 1my
2m1z \n{m"a6kl} \n{1m"an} \n{m"a1s} \n{m"a5tr} \n{m"au4s3c} \n{3m"a\3}
\n{\c{3m"a\9}} \n{m"ob2} \n{6m"ol} \n{1m"u} \n{5m"un} \n{3m"ut} 1na.
n5ab. 8nabn n1abs n1abz \n{na6b"a} na2c nach3e 3nacht 1nae na5el
n1afr 1nag 1n2ah na8ha na8ho 1nai 6nair na4kol n1akt nal1a 8naly 1nama
na4mer na1mn n1amp 8n1amt 5nanc nan6ce n1and n6and. 2n1ang 1nani
1nann n1ans 8nanw 5napf. 1n2ar. na2ra 2n1arc n8ard 1nari n8ark
6n1arm 5n6ars 2n1art n8arv 6natm nat6s5e 1naue 4nauf n3aug 5naui n5auk
na5um 6nausb 6nauto 1nav 2nax 3naz 1na\3 \c{1na\9} n1b2 nbau5s n1c
nche5e nch5m 2n1d nda8d n2d1ak nd5ans n2d1ei nde8lac ndel6sa n8derhi
nde4se nde8stal n2dj ndnis5 n6d5or6t nd3rec nd3rot nd8samt nd6sau
ndt1h n8dumd 1ne ne5as ne2bl 6n5ebn 2nec 5neei ne5en ne1g4l 2negy
4n1ein 8neis 4n3e4lem 8nemb 2n1emp nen1a 6n5energ nen3k 8nentb
4n3en3th 8nentl 8n5entn 8n5ents ne1ra ne5r8al ne8ras 8nerbi 6n5erde.
nere5i6d nerfor6 \n{6n5erh"o} \n{8nerl"o} 2n1err n8ers. 6n5ertra
2n1erz nesi3e net1h neu4ra neu5sc 8neu\3 \c{8neu\9} n1f nf5f nf2l
nflei8 nf5lin nft8st n8g5ac ng5d ng8en nge8ram ngg2 ng1h n6glic ng3rip
ng8ru ng2se4 ng2si n2g1um n1gy \n{n8g"al} n1h nhe6r5e 1ni ni1bl
\n{ni5ch"a} ni8dee n6ie ni1en nie6s5te niet5h ni8etn 4n3i6gel n6ik
ni1la 2n1imp ni5na 2n1ind 8ninf 6n5inh ni8nit 6n5inn 2n1ins 4n1int
n6is ni3str ni1th ni1tr n1j n6ji n8kad nk5ans n1ke n8kerla n1ki nk5inh
\n{n5kl"o} n1k2n n8k5not nk3rot \n{n8kr"u} nk5spo nk6t5r n8kuh
\n{n6k"ub} n5l6 nli4mi n1m nmen4s n1na n8nerg nni5o n1no nn4t3ak nnt1h
nnu1e n1ny \n{n1n"a} \n{n1n"o} \n{n1n"u} no5a no4b3la 4n3obs 2nobt
noche8 no6die no4dis no8ia no5isc 6n5o6leu no4mal noni6er 2n1onk n1ony
4n3o4per 6nopf 6nopti no3ra no4ram nor6da 4n1org 2n1ort n6os no1st
8nost. no8tan no8ter noty6pe 6n5ox n1p2 n1q n1r \n{nr"os3} 6ns n1sac
ns3ang n1sc n8self n8s5erf n8serg n6serk ns5erw n8sint n1s2pe n1spr
n6s5tat. n5s6te. n6stob n1str n1ta n4t3a4go nt5anh nt3ark nt3art
n1te nt3eis nte5n6ar nte8nei nter3a nte6rei nt1ha nt6har n3ther nt5hie
n3thus n1ti nti1c n8tinh nti1t ntlo6b ntmen8 n1to nt3o4ti n1tr ntra5f
ntra5ut nt8rea nt3rec nt8rep n4t3rin nt8rop n4t3rot \n{n4tr"u} nt1s
nts6an nt2sk n1tu nt1z \n{n1t"a} \n{n1t"o} \n{n8t"ol} \n{n1t"u} 1nu
nu1a nu5el nu5en 4n1uhr nu5ie 8numl 6n5ums 6n5umw 2n1und 6nuni 6n5unr
2n1unt 2nup 2nu6r n5uri nu3skr nu5ta n1v 8n1w 1nys n1za n6zab n2z1ar
n6zaus nzi4ga n8zof n6z5unt n1zw n6zwir \n{1n"ac} \n{5n"ae} \n{5n"ai}
\n{n8"al} \n{n"a6m} \n{n"a6re} \n{n5"arz} \n{5n"aus} \n{n1"ol}
\n{1n"ot} \n{n5"oz} \n{5n"u.} \n{6n1"u2b} \n{5n"u\3} \n{\c{5n"u\9}}
o5ab. oa2l o8ala o1a2m o1an ob1ac obe4ra o6berh 5o4bers o4beru
obe6ser 1obj o1bl o2bli ob5sk 3obst. ob8sta obst5re ob5sz o1che
oche8b o8chec o3chi och1l och3m ocho8f o3chro och3to o3chu och1w o1d
o2d1ag od2dr ode5i ode6n5e od1tr o5e6b o5e6der. oe8du o1ef o1e2l
o1e2p o1er. o5e8x o1fa of8fan 1offi of8fin of6f5la o5fla o1fr 8o1g
og2n o1ha o1he o6h5eis o1hi ohl1a oh1le oh4l3er 5ohm. oh2ni o1ho
oh1re oh1ru o1hu oh1w o1hy \n{o1h"a} o5ia o1id. o8idi oi8dr o5ids
o5isch. oiset6 o1ism o3ist. o5i6tu o1j o1k ok2l ok3lau \n{o8kl"a}
1okta o1la old5am old5r o1le ole5in ole1r ole3u ol6gl ol2kl olk4s1
ol8lak ol8lauf. ol6lel ol8less o1lo ol1s ol6sk o1lu oly1e2 5olym
o2mab om6an o8mau ombe4 o8merz om5sp o1mu o8munt \n{o1m"a} \n{o1m"o}
o1na ona8m on1ax on8ent o6n5erb 8oni oni5er. on1k on6n5a6b o1no ono1c
o4nokt 1ons onts8 \n{o1n"a} oo8f 1oog oo2pe oo2sa o1pa 3o4pera o3pfli
opf3lo opf3r o1pi o1pl o2pli o5p6n op8pa op6pl o1pr o3p4ter 1opti
\n{o1p"a} \n{o5p"o} o1q o1ra. o3rad o8radd 1oram o6rang o5ras o8rauf
or5cha or4d3a4m or8dei or8deu 1ordn or4dos o1re o5re. ore2h o8r5ein
ore5isc or6enn or8fla or8fli 1orga 5orgel. or2gl o1ri 5o6rient or8nan
\n{or8n"a} o1ro or1r2h or6t5an or8tau or8tere o1rus o1ry \n{o1r"a}
\n{or1"u2} o1sa osa3i 6ose o8serk o1sk o6ske o6ski os2kl os2ko os2kr
osni5e o2s1o2d o3s4per o4stam o6stau o3stra ost3re osu6 o6s5ur o5s6ze
o1ta ot3auf o6taus o1te o6terw o1th othe5u o2th1r o1ti o1to oto1a
ot1re o1tri o1tro ot1sc o3tsu ot6t5erg ot2t3h ot2t5r \n{ot8t"o} o1tu
ou3e ouf1 ou5f6l o5u6gr ou5ie ou6rar ou1t6a o1v o1wa o1we o6wer. o1wi
owid6 o1wo o5wu o1xe oy5al. oy1e oy1i o5yo o1z oza2r 1o2zea ozo3is
\n{o"o8} o\35elt \c{o\95elt} o\31t \c{o\91t} 3paa pa6ce 5pad pag2 1pak
pa1la pa8na8t pani5el pa4nor pan1s2 1pap pap8s pa8rei par8kr paro8n
par5o6ti part8e 5partei 3partn pas6sep pa4tha 1pau 6paug pau3sc p1b
8p5c 4p1d 1pe 4peic pe5isc 2pek pen3k pen8to8 p8er pe1ra pere6 per5ea
per5eb pe4rem 2perr per8ran 3pers 4persi \n{pe3r"u} pe4sta pet2s
p2f1ec p4fei pf1f pf2l 5pflanz pf8leg pf3lei 2pft pf3ta p1g 1ph 2ph.
2p1haf 6phb 8phd 6p5heit ph5eme 6phg phi6e 8phk 6phn p5holl pht2
ph3tha 4ph3the phu6 6phz pi1en pi5err pi1la pi1na 5pinse pioni8e 1pis
pi1s2k pi1th p1k pl8 5pla p2lau 4plei p3lein 2pler 6p5les 2plig p6lik
6p5ling p2liz plo8min 6p1m p1n 1p2o 8poh 5pol po8lan poly1 po3ny po1ra
2porn por4t3h \n{po5r"o} 5poti p1pa p6p5ei ppe6la pp5f p2p1h p1pi pp1l
ppp6 pp5ren pp1s \n{p5p"o} pr6 3preis 1pres 2p3rig 5prinz 1prob 1prod
5prog pro8pt pro6t5a prote5i 8pro\3 \c{8pro\9} \n{pr"a3l} \n{1pr"as}
\n{pr"ate4} \n{1pr"uf} p5schl 2pst 1p2sy p1t p8to8d pt1s 5p6ty 1pu
pu1b2 2puc pu2dr puf8fr 6p5uh pun8s pu8rei pu5s6h pu1ta p1v p3w 5py
py5l p1z \n{p"a6der} \n{p5"a6m} \n{p"a8nu} \n{8p"ar} \n{p"at5h}
\n{p"at1s} qu6 1qui 8rabk ra6bla 3rable ra2br r1abt 6rabz ra4dan ra2dr
5rafal ra4f3er ra5gla ra2g3n 6raha ral5am 5rald 4ralg ra8lins 2rall
ral5t 8ramei r3anal r6and ran8der ran4dr 8ranf 6ranga 5rangi ran8gli
r3angr rans5pa 8ranw r8anz. ra5or 6rapf ra5pl rap6s5er 2r1arb 1rarh
r1arm ra5ro 2r1art 6r1arz ra8tei ra6t5he 6ratl ra4t3ro r5atta raue4n
6raus. r5austa rau8tel raut5s ray1 r1b rb5lass r6bler rb4lie rbon6n
r8brecht \n{rb6s5t"a} r8ces r1che rch1l rch3m rch3re rch3tr rch1w 8rd
r1da r8dachs r8dap rda5ro rde5ins rdio5 r8dir rd3ost r1dr r8drau 1re.
re1ak 3reakt re3als re6am. re1as 4reben re6bl rech5a r8edi re3er
8reff 3refl 2reh 5reha r4ei. reich6s5 8reier 6reign re5imp 4r3eina
6r3einb 6reing 6r5einn 6reinr 4r3eins r3eint reli3e 8r5elt 6rempf
2remt ren5a6b ren8gl r3enni 1reno 5rente 4r3enth 8rentl 4r3entw 8rentz
ren4zw re1on requi5 1rer rer4bl 6rerbs 4r3erd \n{8rerh"o} 8rerkl
4r3erla \n{8rerl"o} 4r3erns \n{6r5ern"a} rer5o 6r5erreg r5ertr r5erwec
\n{r5er"o} re2sa re8schm 2ress re5u8ni 6rewo 2r1ex r1f r8ferd rf4lie
8r1g r8gah rge4bl rge5na rgest4 rg6ne r2gni2 r8gob r4g3ret rg8sel r1h8
r2hy 5rhyt ri1ar ri5cha rid2g r2ie rieg4s5 ri8ei ri1el ri6ele ri1en
ri3er. ri5ers. ri6fan ri8fer ri8fr 1r2ig ri8kn ri5la \n{rim"a8}
ri1na r8inde rin4ga rin6gr 1rinn 6rinner rino1 r8insp 4rinst
\n{ri1n"a} ri5o6ch ri1o2d ri3o6st 2r1ir r2is ri3sko ri8spr \n{ri8st"u}
ri5sv r2it 6r5i6tal ri5tr ri6ve. 8r1j 6rk r1ke rkehrs5 r1ki r3klin
r1k2n rk3str rk4t3an rk6to r6kuh \n{rk"a4s3t} r1l r5li rline5a 6r1m
r6manl rma4p r4m3aph r8minf r8mob rm5sa 2rn r1na rna8be r5ne rn2ei
r6neif r6nex r6nh rn1k r1no r6n5oc rn1sp \n{r1n"a} \n{r1n"u} ro6bern
6robs ro1ch 3rock. ro5de ro1e 4rofe ro8hert 1rohr ro5id ro1in ro5isc
6rolym r2on 6roog ro6phan r3ort ro1s2p ro5s6w ro4tau ro1tr ro6ts 5rout
r1p rpe8re rp2f r2ps r2pt r1q 2rr r1ra r1re rrer6 rr6hos \n{r5rh"o}
r1ri r1ro rro8f rr8or rror5a r1ru r3ry \n{r1r"a} \n{r1r"o} \n{r1r"u}
2r1s r6sab r4sanf rse6e rse5na r2sh r6ska r6ski rs2kl r8sko r2sl rs2p
r6stauf r8sterw r8stran rswi3d4 r2sz 2r1t rt3art r8taut r5tei rt5eige
r8tepe r4t3erh r8terla r4t3hei r5t6hu r4t3int rt5reif rt1sc rt6ser
rt6s5o rt6s5u rt5und r8turt rube6 ru1en 1r4uf ruf4st ru1ie 2r1umg
2r1uml 2rums run8der run4d5r 6rundz 6runf 8runs 2r1unt 2r1ur r6us
ru6sta ru3str ru6tr 1ruts r1v rven1 rvi2c r1w r1x r1za rz5ac r6z5al
r8z1ar r8zerd r6z5erf rz8erh rz4t3h r8zum \n{r"a4ste} \n{r"au8sc}
\n{r1"of} \n{5r"ohr} \n{r"o5le} \n{3r"oll} \n{5r"omis} \n{r1"or}
\n{r"o2sc} \n{3r"ump} 1sa. 1saa s3a4ben sa2bl 2s1abs 6s1abt 6sabw
3sack. 6s3a4der 1saf sa1fa 4s1aff sa5fr 1sag 1sai sa1i2k1 4s1akt 1sal
sa1la 4s3alpi 6salter salz3a 1sam s5anb san2c 1sand s5angeh 6sanl
2s1ans 6s3antr 8s1anw s1ap s6aph 8sapo sap5p6 s8ar. 2s1arb 3sarg
s1arm sa5ro 2s1art 6s1arz 1sas 1sat sat8a 2s1atl sa8tom 3s8aue s5auff
sau5i s6aur 2s1aus 5s6ause 2s1b2 2sca s4ce 8sch. 3scha. 5schade
3schaf 3schal sch5ame 8schanc 8schb 1sche 6schef 8schex 2schf 2schg
2schh 1schi 2schk 5schlag 5schlu \n{6schm"a\3} \n{\c{6schm"a\9}}
6schna\3 \c{6schna\9} 1scho 6schord 6schp 3schri 8schric 8schrig
8schrou 6schs 2scht sch3ta sch3tr 1schu 8schunt 6schv 2schz \n{5sch"o}
\n{5sch"u} 2sco scre6 6scu 2s1d 1se se5an se1ap se6ben se5ec see5i6g
se3erl 8seff se6han se8hi \n{se8h"o} 6s5eid. 2s1eig s8eil 5sein.
sei5n6e 6s5einh 3s8eit 3sel. se4lar selb4 6s3e4lem se8lerl 2s1emp
sen3ac se5nec 6s5ents 4sentz s8er. se8reim ser5inn \n{8serm"a}
8s5erzi \n{6ser"of} se1um 8sexa 6sexp 2s1f2 sfal8ler 2s3g2 sge5b2 s1h
s8hew 5s6hip 5s4hop 1si 2siat si1b sicht6s 6s5i6dee siege6s5 si1en
si5err si1f2 si1g2n si6g5r si8kau sik1i si4kin si2kl \n{si8k"u} si1la
sil6br si1na 2s1inf sin5gh 2s1inh sinne6s5 2s1ins si5ru si5str 4s1j
s1k2 6sk. 2skau skel6c skelch5 s6kele 1s2ki. 3s4kin. s6kiz s8kj
6skn 2skow 3skrib 3skrip 2sku \n{8sk"u} s1l s8lal slei3t s4low 2s1m
s1n 6sna 6snot 1so so1ch 2s1odo so4dor 6s5o4fen solo3 s2on so5of 4sope
so1ra 2s1ord 4sorga sou5c so3un 4s3ox sp2 8spaa 5spal 1span 2spap
s2pec s4peis 1spek s6perg 4spers s6pes 2s1pf 8sphi \n{1s2ph"a} 1spi
spi4e 6s5pig 6spinse 2spis 2spla 2spol 5s6pom 6s5pos 6spoti 1spra
3s8prec 6spreis 5spring 6sprob 1spru s2pul 1s2pur 6spy \n{5sp"an}
\n{1sp"u} s1q 2s1r 2s1s2 sse8nu ssini6s ssoi6r 2st. 1sta 4stafe 2stag
sta3la 6stale 4stalg 8stalk 8stamt 6st5anf 4stans 6stanw 6starb sta4te
6staus 2stb 6stc 6std 1ste 4steil 3s2tel st3elb 8stemb 6steppi 8stese
8stesse 6stf 2stg 2sth st1ha st3hei s8t1hi st1ho st5hu 1sti sti4el
4stigm sti3na 6stind 4stinf sti8r 2stk 2stl 2stm 1sto 6stoll. 4st3ope
6stopf. 6stord 6stp 5stra. 4strai 3s4tral 6s5traum 3stra\3
\c{3stra\9} 3strec 6s3tref 8streib 5streif 6streno 6stres 6strev
5s6tria 6strig 5strik 8strisi 3s4troa s8troma st5rose 4struf 3strum
\n{6str"ag} 2st1s6 2stt 1stu stu5a 4stuc 2stue 8stun. 2stv 2stw s2tyl
6stz \n{1st"a} \n{8st"ag} \n{1st"o} \n{1st"u} \n{8st"uch} \n{4st"ur.}
1su su2b1 3suc su1e su2fe su8mar 6sumfa 8sumk 2s1unt sup1p2 6s5u6ran
6surte 2s1v 2s1w 1sy 8syl. sy5la syn1 sy2na syne4 s1z s4zend 5s6zene.
8szu \n{1s"a} \n{6s5"and} \n{6s"augi} \n{6s"au\3} \n{\c{6s"au\9}}
\n{5s"om} \n{2s1"u2b} \n{1s"uc} \n{s"u8di} \n{1s"un} \n{5s"u\3}
\n{\c{5s"u\9}} taats3 4tab. taba6k ta8ban tab2l ta6bre 4tabs t3absc
8tabz 6t3acht ta6der 6tadr tad6s tad2t 1tafe4 1tag ta6ga6 ta8gei
tage4s tag6s5t tah8 tahl3 tai6ne. ta5ir. tak8ta tal3au 1tale ta8leng
tal5ert 6t5a6mer 6tamp tampe6 2t1amt tan5d6a tan8dr tands5a tani5e
6tanl 2tanr t3ans 8t5antr tanu6 t5anw 8tanwa tan8zw ta8rau 6tarbe
1tari 2tark 2t1arm ta1ro 2tart t3arti 6tarz ta1sc ta6sien ta8stem
ta8sto t5aufb 4taufn 8taus. 5tause 8tausf 6tausg t5ausl 2t1b2 2t1c
t6chu 2t1d te2am tea4s te8ben 5techn 4teff te4g3re te6hau 2tehe te4hel
2t1ehr te5id. teig5l 6teign tei8gr 1teil 4teinh t5einhe 4teis t5eisen
8teiw te8lam te4lar 4telek 8telem te6man te6n5ag ten8erw ten5k tens4p
ten8tro 4t3entw 8tentz te6pli 5teppi ter5a6b te3ral ter5au 8terbar
t5erbe. 6terben 8terbs 4t3erbt t5erde. ter5ebe ter5ein te8rers terf4
\n{8terh"o} \n{6terkl"a} ter8nor ter6re. t8erscha t5e6sel te8stau
t3euro te1xa tex3e 8texp tex6ta 2t1f2 2t1g2 2th. th6a 5tha. 2thaa
6t1hab 6t5haf t5hah 8thak 3thal. 6thals 6t3hand 2t1hau 1the. 3t4hea
t1heb t5heil t3heit t3helf 1theo 5therap 5therf 6t5herz 1thes 1thet
5thi. 2t1hil t3him 8thir 3this t5hj 2th1l 2th1m th1n t5hob t5hof
4tholz 6thopti 1thr6 4ths t1hum 1thy \n{4t1h"a} \n{2t1h"o} \n{t1h"u}
ti1a2m ti1b tie6fer ti1en ti8gerz tig3l ti8kin ti5lat 1tilg t1ind
tin4k3l ti3spa ti5str 5tite ti5tr ti8vel ti8vr 2t1j 2t1k2 2t1l tl8a
2t1m8 2t1n 3tobe 8tobj to3cha 5tocht 8tock tode4 to8del to8du to1e
6t5o6fen to1in toi6r 5toll. to8mene t2ons 2t1ony to4per 5topf. 6topt
to1ra to1s to6ska tos2l 2toti to1tr t8ou 2t1p2 6t1q tr6 tra5cha
tra8far traf5t 1trag tra6gl tra6gr t3rahm 1trai t6rans tra3sc tra6st
3traue t4re. 2trec t3rech t8reck 6t1red t8ree 4t1reg 3treib 4treif
8t3reis 8trepo tre6t5r t3rev 4t3rez 1trib t6rick tri6er 2trig t8rink
tri6o5d trizi5 tro1a 3troc trocke6 troi8d tro8man. tro3ny 5tropf
6t5rosa t5ro\3 \c{t5ro\9} 5trub 5trup trut5 \n{1tr"ag} \n{6t1r"oh}
\n{5tr"ub} \n{tr"u3bu} \n{t1r"uc} \n{t1r"us} 2ts ts1ab t1sac tsa8d
ts1ak t6s5alt ts1an ts1ar ts3auf t3schr \n{t5sch"a} tse6e tsee5i
tsein6s ts3ent ts1er t8serf t4serk t8sh 5t6sik t4s3int ts5ort.
t5s6por t6sprei t1st t6s5tanz ts1th t6stit t4s3tor 1t2sua t2s1uf
t8sum. t2s1u8n t2s1ur 2t1t tt5eif tte6sa tt1ha tt8ret tt1sc tt8ser
tt5s6z 1tuc tuch5a 1tu1e 6tuh t5uhr tu1i tu6it 1tumh 6t5umr 1tums
8tumt 6tund 6tunf 2t1unt tu5ra tu6rau tu6re. tu4r3er 2t1v 2t1w 1ty1
ty6a ty8la 8tym 6ty6o 2tz tz5al tz1an tz1ar t8zec tzeh6 tzehn5 t6z5ei.
t6zor t4z3um \n{t6z"au} \n{5t"ag} \n{6t"ah} \n{t5"alt} \n{t8"an}
\n{t"are8} \n{8t"a8st} \n{6t"au\3} \n{\c{6t"au\9}} \n{t5"offen}
\n{8t"o8k} \n{1t"on} \n{4t"ub} \n{t6"u5ber.} \n{5t"uch} \n{1t"ur.}
u3al. u5alb u5alf u3alh u5alk u3alp u3an. ua5na u3and u5ans u5ar.
ua6th u1au ua1y u2bab ubi5er. u6b5rit ubs2k \n{u5b"o} \n{u8b"ub} 2uc
u1che u6ch5ec u1chi uch1l uch3m uch5n uch1r uch5to ucht5re u1chu uch1w
uck1a uck5in u1d ud4a u1ei u6ela uene8 u6ep u1er uer1a ue8rerl uer5o
u8esc u2est u8ev u1fa u2f1ei u4f3ent u8ferh uf1fr uf1l uf1ra uf1re
\n{uf1r"a} \n{uf1r"u} uf1s2p uf1st uft1s u8gabt u8gad u6gap ugeb8 u8gn
ugo3s4 u1ha u1he u1hi uh1le u1ho uh1re u1hu uh1w \n{u1h"a} \n{u1h"o}
6ui ui5en u1ig u3ins uin8tes u5isch. u1j 6uk u1ke u1ki u1kl u8klu
u1k6n u5ky u1la uld8se u1le ul8lac ul6lau ul6le6l ul6lo ulni8 u1lo
ulo6i ult6a ult8e u1lu ul2vr \n{u1l"a} \n{u1l"o} 3umfan 5umlau umo8f
um8pho u1mu umu8s \n{u5m"o} u1n1a un2al un6at unau2 6und. 5undein
un4d3um 3undzw \n{und"u8} \n{un8d"ub} une2b un1ec une2h un3eis 3unfal
\n{1unf"a} 5ungea \n{3ungl"u} ung2s1 \n{un8g"a} 1u2nif un4it un8kro
unk5s u1no unpa2 uns2p unvol4 unvoll5 u5os. u1pa u1pi u1p2l u1pr
up4s3t up2t1a u1q u1ra ur5abs ura8d ur5ah u6rak ur3alt u6rana u6r5ans
u8rap ur5a6ri u8ratt u1re ur3eig ur8gri u1ri ur5ins 3urlau urmen6
ur8nan u1ro 3ursac ur8sau ur8sei ur4sk 3urtei u1ru uru5i6 uru6r u1ry
ur2za \n{ur6z"a} \n{ur5"a6m} \n{u5r"o} \n{u1r"u} \n{ur"uck3} u1sa
usa4gi u2s1ar u2s1au u8schec usch5wi u2s1ei use8kel u8sl u4st3a4b
us3tau u3s4ter u2s1uf u8surn ut1ac u1tal uta8m u1tan ut1ar u1tas ut1au
u1te u8teic u4tent u8terf u6terin u4t3hei ut5ho ut1hu u1ti utine5
uti6q u1to uto5c u1tr ut1sa ut1s6p ut6stro u1tu utz5w u1u u1v uve5n
\n{uve3r4"a} u1w u1xe u5ya uy5e6 u1yi u2z1eh u8zerh \n{u5"o} u\3e6n
\c{u\9e6n} u\3en5e \c{u\9en5e} 8vanb 6vang 6varb var8d va6t5a va8tei
va2t1r 2v1b 6v5c 6vd 1ve 6ve5g6 ver1 ver5b verb8l ve2re2 verg8 ve2ru8
ve1s ve2s3p ve3xe 2v1f 2v1g 6v5h vi6el vie6w5 vi1g4 vi8leh vil6le.
8vint vi1ru vi1tr 2v1k 2v1l 2v1m 4v5n 8vo8f voi6le vol8lend vol8li
v2or1 vo2re vo8rin vo2ro 2v1p 8vra v6re 2v1s 2v1t 2v1v 4v3w 2v1z
waffe8 wa6g5n 1wah wah8n wa5la wal8din wal6ta wan4dr 5ware wa8ru
war4za 1was w5c w1d 5wech we6fl 1weg we8geng weg5h weg3l we2g1r
weh6r5er 5weise weit3r wel2t welt3r we6rat 8werc 5werdu wer4fl 5werk.
wer4ka wer8ku wer4ta wer8term we2sp we8stend we6steu we8str
\n{we8st"o} wet8ta wich6s5t 1wid wi2dr wiede4 wieder5 wik6 wim6ma
win4d3r 5wirt wisch5l 1wj 6wk 2w1l 8w1n wo1c woche6 wol6f wor6t5r 6ws2
w1sk 6w5t 5wunde. wun6gr wu1sc wu2t1 6w5w wy5a \n{w"arme5} \n{w"a1sc}
1xag x1ak x3a4men 8xamt x1an 8x1b x1c 1xe. x3e4g 1xen xe1ro x1erz
1xes 8xf x1g 8x1h 1xi 8xid xi8so 4xiste x1k 6x1l x1m 8xn 1xo 8x5o6d
8x3p2 x1r x1s6 8x1t x6tak x8terf x2t1h 1xu xu1e x5ul 6x3w x1z 5ya.
y5an. y5ank y1b y1c y6cha y4chia y1d yen6n y5ern y1g y5h y5in y1j
y1k2 y1lak yl1al yla8m y5lax y1le y1lo y5lu y8mn ym1p2 y3mu y1na yno2d
yn1t y1on. y1o4p y5ou ypo1 y1pr y8ps y1r yri3e yr1r2 y1s ys5iat ys8ty
y1t y3w y1z \n{y"a8m} z5a6b zab5l 8za6d 1zah za5is 4z3ak 6z1am 5zange.
8zanl 2z1ara 6z5as z5auf 3zaun 2z1b 6z1c 6z1d 1ze ze4dik 4z3eff 8zein
zei4ta zei8ters ze6la ze8lec zel8th 4zemp 6z5engel zen8zin \n{8zerg"a}
zer8i ze1ro zers8 zerta8 zer8tab zer8tag 8zerz ze8ste zeu6gr 2z1ex
2z1f8 z1g 4z1h 1zi zi1en zi5es. 4z3imp zi1na 6z5inf 6z5inni zin6s5er
8zinsuf zist5r zi5th zi1tr 6z1j 2z1k 2z1l 2z1m 6z1n 1zo zo6gl 4z3oh
zo1on zor6na8 4z1p z5q 6z1r 2z1s8 2z1t z4t3end z4t3hei z8thi 1zu zu3al
zu1b4 zu1f2 6z5uhr zun2a 8zunem zunf8 8zungl zu1o zup8fi zu1s8 zu1z
2z1v zw8 z1wal 5zweck zwei3s z1wel z1wer z6werg 8z5wes 1zwi zwi1s
6z1wo 1zy 2z1z zz8a zzi1s \n{1z"a} \n{1z"o} \n{6z"ol.} \n{z"o1le}
\n{1z"u} \n{2z1"u2b} \n{"a1a6} \n{"ab1l} \n{"a1che} \n{"a3chi}
\n{"ach8sc} \n{"ach8sp} \n{"a5chu} \n{"ack5a} \n{"ad1a} \n{"ad5era}
\n{"a6d5ia} \n{"a1e} \n{"a5fa} \n{"af1l} \n{"aft6s} \n{"ag1h}
\n{"ag3le} \n{"a6g5nan} \n{"ag5str} \n{"a1he} \n{"a1hi} \n{"ah1le}
\n{"ah5ne} \n{1"ahnl} \n{"ah1re} \n{"ah5ri} \n{"ah1ru} \n{"a1hu}
\n{"ah1w} \n{6"ai} \n{"a1isc} \n{"a6ische} \n{"a5ism} \n{"a5j}
\n{"a1k} \n{"al1c} \n{"a1le} \n{"a8lei} \n{"al6schl} \n{"ami1e}
\n{"am8n} \n{"am8s} \n{"a5na} \n{5"anderu} \n{"ane5i8} \n{"ang3l}
\n{"ank5l} \n{"a1no} \n{"an6s5c} \n{"a1pa} \n{"ap6s5c} \n{3"aq}
\n{"ar1c} \n{"a1re} \n{"are8m} \n{5"argern} \n{"ar6gl} \n{"a1ri}
\n{3"armel} \n{"a1ro} \n{"art6s5} \n{"a1ru} \n{3"arztl} \n{"a5r"o}
\n{"a6s5chen} \n{"asen8s} \n{"as1th} \n{"ata8b} \n{"a1te} \n{"ateri4}
\n{"ater5it} \n{"a6thy} \n{"a1ti} \n{3"atk} \n{"a1to} \n{"at8schl}
\n{"ats1p} \n{"a5tu} \n{"aub1l} \n{"au1e} \n{1"aug} \n{"au8ga}
\n{"au5i} \n{"a1um.} \n{"a1us.} \n{1"au\3} \n{\c{1"au\9}} \n{"a1z}
\n{"o1b} \n{"o1che} \n{"o5chi} \n{"och8stei} \n{"och8str} \n{"ocht6}
\n{5"o6dem} \n{5"offn} \n{"o1he} \n{"oh1l8} \n{"oh1re} \n{"o1hu}
\n{"o1is} \n{"o1ke} \n{1"o2ko} \n{1"ol.} \n{"ol6k5l} \n{"ol8pl}
\n{"o1mu} \n{"o5na} \n{"onig6s3} \n{"o1no} \n{"o5o6t} \n{"opf3l}
\n{"op6s5c} \n{"o1re} \n{"or8gli} \n{"o1ri} \n{"or8tr} \n{"o1ru}
\n{5"osterr} \n{"o1te} \n{"o5th} \n{"o1ti} \n{"o1tu} \n{"o1v} \n{"o1w}
\n{"owe8} \n{"o2z} \n{"ub6e2} \n{3"u4ber1} \n{"ub1l} \n{"ub1r}
\n{5"u2bu} \n{"u1che} \n{"u1chi} \n{"u8ch3l} \n{"uch6s5c} \n{"u8ck}
\n{"uck1a} \n{"uck5ers} \n{"ud1a2} \n{"u6deu} \n{"udi8t} \n{"u2d1o4}
\n{"ud5s6} \n{"uge4l5a} \n{"ug1l} \n{"uh5a} \n{"u1he} \n{"u8heh}
\n{"u6h5erk} \n{"uh1le} \n{"uh1re} \n{"uh1ru} \n{"u1hu} \n{"uh1w}
\n{"u3k} \n{"u1le} \n{"ul4l5a} \n{"ul8lo} \n{"ul4ps} \n{"ul6s5c}
\n{"u1lu} \n{"un8da} \n{"un8fei} \n{"unk5l} \n{"un8za} \n{"un6zw}
\n{"u5pi} \n{"u1re} \n{"u8rei} \n{"ur8fl} \n{"ur8fr} \n{"ur8geng}
\n{"u1ri} \n{"u1ro} \n{"ur8sta} \n{"ur8ster} \n{"u1ru} \n{"use8n}
\n{"u8sta} \n{"u8stes} \n{"u6s5tete} \n{"u3ta} \n{"u1te} \n{"u1ti}
\n{"ut8tr} \n{"u1tu} \n{"ut8zei} \n{"u1v} \31a8 \c{\91a8} 5\3a.
\c{5\9a.} \38as \c{\98as} \31b8 \c{\91b8} \31c \c{\91c} \31d \c{\91d}
1\3e \c{1\9e} \35ec \c{\95ec} 8\3e8g \c{8\9e8g} 8\3e8h \c{8\9e8h}
2\31ei \c{2\91ei} 8\3em \c{8\9em} \31f8 \c{\91f8} \31g \c{\91g} \31h
\c{\91h} 1\3i \c{1\9i} \31k \c{\91k} \31l \c{\91l} \31m \c{\91m}
\3mana8 \c{\9mana8} \31n \c{\91n} \31o \c{\91o} \31p8 \c{\91p8} \35q
\c{\95q} \31r \c{\91r} \31s2 \c{\91s2} \3st8 \c{\9st8} \31ta \c{\91ta}
\31te \c{\91te} \3t3hei \c{\9t3hei} \31ti \c{\91ti} \35to \c{\95to}
\31tr \c{\91tr} 1\3u8 \c{1\9u8} 6\35um \c{6\95um} \31v \c{\91v} \31w
\c{\91w} \31z \c{\91z}
}%
\endgroup
\relax\endinput
%
% -----------------------------------------------------------------
%
% =============== Additional Documentation ===============
%
%
% Older Versions of German Hyphenation Patterns:
% ----------------------------------------------
%
% All older versions of `ghyphen.tex' distributed as
%
% ghyphen.tex/germhyph.tex as of 1986/11/01
% ghyphen.min/ghyphen.max as of 1988/10/10
% ghyphen3.tex as of 1990/09/27 & 1991/02/13
% ghyph31.tex as of 1994/02/13
%
% are out of date and it is recommended to replace them
% with the new version `dehypht.tex' as of 1999/03/03.
%
% If you are using `ghyphen.min' (a minor version of `ghyphen')
% because of limited trie memory space, try this version and if
% the space is exceeded get a newer TeX implementation with
% larger or configurable trie memory sizes.
%
%
%
% Trie Memory Requirements/Space for Hyphenation Patterns:
% --------------------------------------------------------
%
% To load this set of german hyphenation patterns the parameters
% of TeX has to have at least these values:
%
% TeX 3.x:
% IniTeX: trie_size >= 9733 trie_op_size >= 207
% VirTeX: trie_size >= 8375 trie_op_size >= 207
%
% TeX 2.x:
% IniTeX: trie_size >= 8675 trie_op_size >= 198
% VirTeX: trie_size >= 7560 trie_op_size >= 198
%
% If you want to load more than one set of hyphenation patterns
% (in TeX 3.x), the parameters have to be set to a value larger
% than or equal to the sum of all required values for each set.
%
%
% Setting Trie Memory Parameters:
% -------------------------------
%
% Some implementations allow the user to change the default value
% of a set of the internal TeX parameters including the trie memory
% size parameter specifying the used memory for the hyphenation
% patterns.
%
% Web2c 7.x (Source), teTeX 0.9 (Unix, Amiga), fpTeX (Win32)
% and newer:
% The used memory size of the true is usually set high enough.
% If needed set the size of the trie using the keyword `trie_size'
% in the configuration file `texmf/web2c/texmf.cnf'. For details
% see the included documentation.
%
% emTeX (OS/2, MS-DOS, Windows 3.x/9x/NT):
% You can set the used memory size of the trie using the
% `-mt<number>' option on the command line or in the
% TEXOPTIONS environment variable.
%
% PasTeX (Amiga):
% The values for the parameters can be set using the keywords
% `triesize', `itriesize' and `trieopsize' in the configuration
% file.
%
% others (binaries only):
% See the documentation of the implementation if it is possible
% and how to change these values without recompilation.
%
% others (with sources)
% If the trie memory is too small, you have to recompile TeX
% using larger values for `trie_size' and `trie_op_size'.
% Modify the change file `tex.ch' and recompile TeX.
% For details see the documentation included in the sources.
%
%
%
% Necessary Settings in TeX macro files:
% --------------------------------------
%
% \lefthyphenmin, \righthyphenmin:
% You can set both parameters to 2.
%
% \lccode <char>:
% To get correct hyphenation points within words containing
% umlauts or \ss, it's necessary to assign values > 0 to the
% appropriate \lccode <char> positions.
%
% These changes are _not_ done when reading this file and have to
% be included in the language switching mechanism as is done in,
% for example, `german.sty' (\lccode change for ^^Y = \ss in OT1,
% \left-/\righthyphenmin settings).
%
%
%% \CharacterTable
%% {Upper-case \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
%% Lower-case \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
%% Digits \0\1\2\3\4\5\6\7\8\9
%% Exclamation \! Double quote \" Hash (number) \#
%% Dollar \$ Percent \% Ampersand \&
%% Acute accent \' Left paren \( Right paren \)
%% Asterisk \* Plus \+ Comma \,
%% Minus \- Point \. Solidus \/
%% Colon \: Semicolon \; Less than \<
%% Equals \= Greater than \> Question mark \?
%% Commercial at \@ Left bracket \[ Backslash \\
%% Right bracket \] Circumflex \^ Underscore \_
%% Grave accent \` Left brace \{ Vertical bar \|
%% Right brace \} Tilde \~}
%%
\endinput
%%
%% End of file `dehypht.tex'.

1104
src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/eshyph_vo.tex

File diff suppressed because it is too large Load Diff

1122
src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/expander-1.3.1.tm

File diff suppressed because it is too large Load Diff

223
src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/ithyph.tex

@ -0,0 +1,223 @@
%%%%%%%%%%%%%%%%%%%% file ithyph.tex
%%%%%%%%%%%%%%%%%%%%%%%%%%% file ithyph.tex %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Prepared by Claudio Beccari e-mail beccari@polito.it
%
% Dipartimento di Elettronica
% Politecnico di Torino
% Corso Duca degli Abruzzi, 24
% 10129 TORINO
%
% Copyright 1998, 2001 Claudio Beccari
%
% This program can be redistributed and/or modified under the terms
% of the LaTeX Project Public License Distributed from CTAN
% archives in directory macros/latex/base/lppl.txt; either
% version 1 of the License, or any later version.
%
% \versionnumber{4.8d} \versiondate{2001/11/21}
%
% These hyphenation patterns for the Italian language are supposed to comply
% with the Reccomendation UNI 6461 on hyphenation issued by the Italian
% Standards Institution (Ente Nazionale di Unificazione UNI). No guarantee
% or declaration of fitness to any particular purpose is given and any
% liability is disclaimed.
%
% See comments and loading instructions at the end of the file after the
% \endinput line
%
{\lccode`\'=`\' % Apostrophe has its own lccode so that it is treated
% as a letter
%>> 1998/04/14 inserted grouping
%
%\lccode23=23 % Compound word mark is a letter in encoding T1
%\def\W{^^W} % ^^W =\char23 = \char"17 =\char'27
%
\patterns{
.a3p2n % After the Garzanti dictionary: a-pnea, a-pnoi-co,...
.anti1 .anti3m2n
.bio1
.ca4p3s
.circu2m1
.di2s3cine
%.e2x
.fran2k3
.free3
.narco1
.opto1
.orto3p2
.para1
.poli3p2
.pre1
.p2s
%.ri1a2 .ri1e2 .re1i2 .ri1o2 .ri1u2
.sha2re3
.tran2s3c .tran2s3d .tran2s3f .tran2s3l .tran2s3n .tran2s3p .tran2s3r .tran2s3t
.su2b3lu .su2b3r
.wa2g3n
.wel2t1
a1ia a1ie a1io a1iu a1uo a1ya 2at.
e1iu e2w
o1ia o1ie o1io o1iu
%u1u
%
%1\W0a2 1\W0e2 1\W0i2 1\W0o2 1\W0u2
'2
1b 2bb 2bc 2bd 2bf 2bm 2bn 2bp 2bs 2bt 2bv
b2l b2r 2b. 2b'. 2b''
1c 2cb 2cc 2cd 2cf 2ck 2cm 2cn 2cq 2cs 2ct 2cz
2chh c2h 2chb ch2r 2chn c2l c2r 2c. 2c'. 2c'' .c2
1d 2db 2dd 2dg 2dl 2dm 2dn 2dp d2r 2ds 2dt 2dv 2dw
2d. 2d'. 2d'' .d2
1f 2fb 2fg 2ff 2fn f2l f2r 2fs 2ft 2f. 2f'. 2f''
1g 2gb 2gd 2gf 2gg g2h g2l 2gm g2n 2gp g2r 2gs 2gt
2gv 2gw 2gz 2gh2t 2g. 2g'. 2g''
1h 2hb 2hd 2hh hi3p2n h2l 2hm 2hn 2hr 2hv 2h. 2h'. 2h''
1j 2j. 2j'. 2j''
1k 2kg 2kf k2h 2kk k2l 2km k2r 2ks 2kt 2k. 2k'. 2k''
1l 2lb 2lc 2ld 2l3f2 2lg l2h 2lk 2ll 2lm 2ln 2lp
2lq 2lr 2ls 2lt 2lv 2lw 2lz 2l. 2l'. 2l''
1m 2mb 2mc 2mf 2ml 2mm 2mn 2mp 2mq 2mr 2ms 2mt 2mv 2mw
2m. 2m'. 2m''
1n 2nb 2nc 2nd 2nf 2ng 2nk 2nl 2nm 2nn 2np 2nq 2nr
2ns 2nt 2nv 2nz n2g3n 2nheit. 2n. 2n' 2n''
1p 2pd p2h p2l 2pn 3p2ne 2pp p2r 2ps 3p2sic 2pt 2pz 2p. 2p'. 2p''
1q 2qq 2q. 2q'. 2q''
1r 2rb 2rc 2rd 2rf r2h 2rg 2rk 2rl 2rm 2rn 2rp
2rq 2rr 2rs 2rt rt2s3 2rv 2rx 2rw 2rz 2r. 2r'. 2r''
1s2 2shm 2s3s s4s3m 2s3p2n 2stb 2stc 2std 2stf 2stg 2stm 2stn
2stp 2sts 2stt 2stv 2sz 4s. 4s'. 4s''
1t 2tb 2tc 2td 2tf 2tg t2h t2l 2tm 2tn 2tp t2r 2ts
3t2sch 2tt 2tv 2tw t2z 2tzk 2tzs 2t. 2t'. 2t''
1v 2vc v2l v2r 2vv 2v. 2v'. 2v''
1w w2h wa2r 2w1y 2w. 2w'. 2w''
1x 2xt 2xw 2x. 2x'. 2x''
y1ou y1i
1z 2zb 2zd 2zl 2zn 2zp 2zt 2zs 2zv 2zz 2z. 2z'. 2z'' .z2
}} % Pattern end
\endinput
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Information %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
LOADING THESE PATTERNS
These patterns, as well as those for any other language, do not become
effective until they are loaded in a special form into a format file; this
task is performed by the TeX initializer; any TeX system has its own
initializer with its special way of being activated. Before loading these
patterns, then, it is necessary to read very carefully the instructions that
come with your TeX system.
Here I describe how to load the patterns with the freeware TeX system named
MiKTeX version 2.x for Windows 9x, NT, 2000, XP; with minor changes the
whole procedure is applicable with other TeX systems, but the details must
be deduced from your TeX system documentation at the section/chapter "How to
build or to rebuild a format file".
With MikTeX:
a) copy this file and replace the existing file ithyph.tex in the directory
\texmf\tex\generic\hyphen if the existing one has an older version date
and number.
b) select Start|Programs|MiKTeX|MiKTeX options.
c) in the Language tab add a check mark to the line concerning the Italian
language.
d) in the Geneal tab click "Update format files".
e) That's all!
For the activation of these patterns with the specific Italian typesetting
features, use the babel package as this:
\documentclass{article} % Or whatever other class
\usepackage[italian]{babel}
...
\begin{document}
...
\end{document}
ON ITALIAN HYPHENATION
I have been working on patterns for the Italian language since 1987; in 1992
I published
C. Beccari, "Computer aided hyphenation for Italian and Modern
Latin", TUG vol. 13, n. 1, pp. 23-33 (1992)
which contained a set of patterns that allowed hyphenation for both Italian
and Latin; a slightly modified version of the patterns published in the
above paper is contained in LAHYPH.TEX available on the CTAN archives.
From the above patterns I extracted the minimum set necessary for
hyphenating Italian that was made available on the CTAN archives with the
name ITHYPH.tex the version number 3.5 on the 16th of August 1994.
The original pattern set required 37 ops; being interested in a local
version of TeX/LaTeX capable of dealing with half a dozen languages, I
wanted to reduce memory occupation and therefore the number of ops.
Th new version (4.0 released in 1996) of ITHYPH.TEX is much simpler than
version 3.5 and requires just 29 ops while it retains all the power of
version 3.5; it contains many more new patterns that allow to hyphenate
unusual words that generally have a root borrowed from a foreign language.
Updated versions 4.x contain minor additions and the number of ops is
increased to 30 (version 4.7 of 1998/06/01).
This new pattern set has been tested with the same set of difficult Italian
words that was used to test version 3.5 and it yields the same results (a
part a minor change that was deliberately introduced so as to reduce the
typographical hyphenation with hyathi, since hyphenated hyathi are not
appreciated by Italian readers). A new enlarged word set for testing
purposes gets correct hyphen points that were missed or wrongly placed with
version 3.5, although no error had been reported, because such words are of
very specialized nature and are seldom used.
As the previous version, this new set of patterns does not contain any
accented character so that the hyphenation algorithm behaves properly in
both cases, that is with cm and with dc/ec fonts. With LaTeXe terminology
the difference is between OT1 and T1 encodings; with the former encoding
fonts do not contain accented characters, while with the latter accented
characters are present and sequences such as \`a map directly to slot "E0
that contains "agrave".
Of course if you use dc/ec fonts (or any other real or virtual font with T1
encoding) you get the full power of the hyphenation algorithm, while if you
use cm fonts (or any other real or virtual font with OT1 encoding) you miss
some possible break points; this is not a big inconvenience in Italian
because:
1) The Regulation UNI 6015 on accents specifies that compulsory accents
appear only on the ending vowel of oxitone words; this means that it is
almost indifferent to have or to miss the dc/ec fonts because the only
difference consists in how TeX evaluates the end of the word; in practice
if you have these special facilities you get "qua-li-t\`a", while if you
miss them, you get "qua-lit\`a" (assuming that \righthyphenmin > 1).
2) Optional accents are so rare in Italian, that if you absolutely want to
use them in those rare instances, and you miss the T1 encoding
facilities, you should also provide explicit discretionary hyphens as in
"s\'e\-gui\-to".
There is no explicit hyphenation exception list because these patterns
proved to hyphenate correctly a very large set of words suitably chosen in
order to test them in the most heavy circumstances; these patterns were used
in the preparation of a number of books and no errors were discovered.
Nevertheless if you frequently use technical terms that you want hyphenated
differently from what is normally done (for example if you prefer
etymological hyphenation of prefixed and/or suffixed words) you should
insert a specific hyphenation list in the preamble of your document, for
example:
\hyphenation{su-per-in-dut-to-re su-per-in-dut-to-ri}
Should you find any word that gets hyphenated in a wrong way, please, AFTER
CHECKING ON A RELIABLE MODERN DICTIONARY, report to the author, preferably
by e-mail.
Happy multilingual typesetting !

180
src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/patch-0.1.tm

@ -0,0 +1,180 @@
# patch.tcl --
#
# Application of a diff -ruN patch to a directory tree.
#
# Copyright (c) 2019 Christian Gollwitzer <auriocus@gmx.de>
# with tweaks by Andreas Kupries
# - Factored patch parsing into a helper
# - Replaced `puts` with report callback.
package require Tcl 8.5
package provide textutil::patch 0.1
# # ## ### ##### ######## ############# #####################
namespace eval ::textutil::patch {
namespace export apply
namespace ensemble create
}
# # ## ### ##### ######## ############# #####################
proc ::textutil::patch::apply {dir striplevel patch reportcmd} {
set patchdict [Parse $dir $striplevel $patch]
# Apply, now that we have parsed the patch.
dict for {fn hunks} $patchdict {
Report apply $fn
if {[catch {open $fn} fd]} {
set orig {}
} else {
set orig [split [read $fd] \n]
}
close $fd
set patched $orig
set fail false
set already_applied false
set hunknr 1
foreach hunk $hunks {
dict with hunk {
set oldend [expr {$oldstart+[llength $oldcode]-1}]
set newend [expr {$newstart+[llength $newcode]-1}]
# check if the hunk matches
set origcode [lrange $orig $oldstart $oldend]
if {$origcode ne $oldcode} {
set fail true
# check if the patch is already applied
set origcode_applied [lrange $orig $newstart $newend]
if {$origcode_applied eq $newcode} {
set already_applied true
Report fail-already $fn $hunknr
} else {
Report fail $fn $hunknr $oldcode $origcode
}
break
}
# apply patch
set patched [list \
{*}[lrange $patched 0 $newstart-1] \
{*}$newcode \
{*}[lrange $orig $oldend+1 end]]
}
incr hunknr
}
if {!$fail} {
# success - write the result back
set fd [open $fn w]
puts -nonewline $fd [join $patched \n]
close $fd
}
}
return
}
# # ## ### ##### ######## ############# #####################
proc ::textutil::patch::Report args {
upvar 1 reportcmd reportcmd
uplevel #0 [list {*}$reportcmd {*}$args]
##
# apply $fname
# fail-already $fname $hunkno
# fail $fname $hunkno $expected $seen
##
}
proc ::textutil::patch::Parse {dir striplevel patch} {
set patchlines [split $patch \n]
set inhunk false
set oldcode {}
set newcode {}
set n [llength $patchlines]
set patchdict {}
for {set lineidx 0} {$lineidx < $n} {incr lineidx} {
set line [lindex $patchlines $lineidx]
if {[string match ---* $line]} {
# a diff block starts. Current line should be
# --- oldfile date time TZ
# Next line should be
# +++ newfile date time TZ
set in $line
incr lineidx
set out [lindex $patchlines $lineidx]
if {![string match ---* $in] || ![string match +++* $out]} {
#puts $in
#puts $out
return -code error "Patch not in unified diff format, line $lineidx $in $out"
}
# the quoting is compatible with list
lassign $in -> oldfile
lassign $out -> newfile
set fntopatch [file join $dir {*}[lrange [file split $oldfile] $striplevel end]]
set inhunk false
#puts "Found diffline for $fntopatch"
continue
}
# state machine for parsing the hunks
set typechar [string index $line 0]
set codeline [string range $line 1 end]
switch $typechar {
@ {
if {![regexp {@@\s+\-(\d+),(\d+)\s+\+(\d+),(\d+)\s+@@} $line \
-> oldstart oldlen newstart newlen]} {
return code -error "Erroneous hunk in line $lindeidx, $line"
}
# adjust line numbers for 0-based indexing
incr oldstart -1
incr newstart -1
#puts "New hunk"
set newcode {}
set oldcode {}
set inhunk true
}
- { # line only in old code
if {$inhunk} {
lappend oldcode $codeline
}
}
+ { # line only in new code
if {$inhunk} {
lappend newcode $codeline
}
}
" " { # common line
if {$inhunk} {
lappend oldcode $codeline
lappend newcode $codeline
}
}
default {
# puts "Junk: $codeline";
continue
}
}
# test if the hunk is complete
if {[llength $oldcode]==$oldlen && [llength $newcode]==$newlen} {
set hunk [dict create \
oldcode $oldcode \
newcode $newcode \
oldstart $oldstart \
newstart $newstart]
#puts "hunk complete: $hunk"
set inhunk false
dict lappend patchdict $fntopatch $hunk
}
}
return $patchdict
}
# # ## ### ##### ######## ############# #####################
return

91
src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/repeat-0.7.tm

@ -0,0 +1,91 @@
# repeat.tcl --
#
# Emulation of string repeat for older
# revisions of Tcl.
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: repeat.tcl,v 1.1 2006/04/21 04:42:28 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil::repeat {}
# ### ### ### ######### ######### #########
namespace eval ::textutil::repeat {
variable HaveBuiltin [expr {![catch {string repeat a 1}]}]
}
if {0} {
# Problems with the deactivated code:
# - Linear in 'num'.
# - Tests for 'string repeat' in every call!
# (Ok, just the variable, still a test every call)
# - Fails for 'num == 0' because of undefined 'str'.
proc textutil::repeat::StrRepeat { char num } {
variable HaveBuiltin
if { $HaveBuiltin == 0 } then {
for { set i 0 } { $i < $num } { incr i } {
append str $char
}
} else {
set str [ string repeat $char $num ]
}
return $str
}
}
if {$::textutil::repeat::HaveBuiltin} {
proc ::textutil::repeat::strRepeat {char num} {
return [string repeat $char $num]
}
proc ::textutil::repeat::blank {n} {
return [string repeat " " $n]
}
} else {
proc ::textutil::repeat::strRepeat {char num} {
if {$num <= 0} {
# No replication required
return ""
} elseif {$num == 1} {
# Quick exit for recursion
return $char
} elseif {$num == 2} {
# Another quick exit for recursion
return $char$char
} elseif {0 == ($num % 2)} {
# Halving the problem results in O (log n) complexity.
set result [strRepeat $char [expr {$num / 2}]]
return "$result$result"
} else {
# Uneven length, reduce problem by one
return "$char[strRepeat $char [incr num -1]]"
}
}
proc ::textutil::repeat::blank {n} {
return [strRepeat " " $n]
}
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::repeat {
namespace export strRepeat blank
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::repeat 0.7

176
src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/split-0.8.tm

@ -0,0 +1,176 @@
# split.tcl --
#
# Various ways of splitting a string.
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2001 by Reinhard Max <max@suse.de>
# Copyright (c) 2003 by Pat Thoyts <patthoyts@users.sourceforge.net>
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: split.tcl,v 1.7 2006/04/21 04:42:28 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil::split {}
########################################################################
# This one was written by Bob Techentin (RWT in Tcl'ers Wiki):
# http://www.techentin.net
# mailto:techentin.robert@mayo.edu
#
# Later, he send me an email stated that I can use it anywhere, because
# no copyright was added, so the code is defacto in the public domain.
#
# You can found it in the Tcl'ers Wiki here:
# http://mini.net/cgi-bin/wikit/460.html
#
# Bob wrote:
# If you need to split string into list using some more complicated rule
# than builtin split command allows, use following function. It mimics
# Perl split operator which allows regexp as element separator, but,
# like builtin split, it expects string to split as first arg and regexp
# as second (optional) By default, it splits by any amount of whitespace.
# Note that if you add parenthesis into regexp, parenthesed part of separator
# would be added into list as additional element. Just like in Perl. -- cary
#
# Speed improvement by Reinhard Max:
# Instead of repeatedly copying around the not yet matched part of the
# string, I use [regexp]'s -start option to restrict the match to that
# part. This reduces the complexity from something like O(n^1.5) to
# O(n). My test case for that was:
#
# foreach i {1 10 100 1000 10000} {
# set s [string repeat x $i]
# puts [time {splitx $s .}]
# }
#
if {[package vsatisfies [package provide Tcl] 8.3]} {
proc ::textutil::split::splitx {str {regexp {[\t \r\n]+}}} {
# Bugfix 476988
if {[string length $str] == 0} {
return {}
}
if {[string length $regexp] == 0} {
return [::split $str ""]
}
if {[regexp $regexp {}]} {
return -code error \
"splitting on regexp \"$regexp\" would cause infinite loop"
}
set list {}
set start 0
while {[regexp -start $start -indices -- $regexp $str match submatch]} {
foreach {subStart subEnd} $submatch break
foreach {matchStart matchEnd} $match break
incr matchStart -1
incr matchEnd
lappend list [string range $str $start $matchStart]
if {$subStart >= $start} {
lappend list [string range $str $subStart $subEnd]
}
set start $matchEnd
}
lappend list [string range $str $start end]
return $list
}
} else {
# For tcl <= 8.2 we do not have regexp -start...
proc ::textutil::split::splitx [list str [list regexp "\[\t \r\n\]+"]] {
if {[string length $str] == 0} {
return {}
}
if {[string length $regexp] == 0} {
return [::split $str {}]
}
if {[regexp $regexp {}]} {
return -code error \
"splitting on regexp \"$regexp\" would cause infinite loop"
}
set list {}
while {[regexp -indices -- $regexp $str match submatch]} {
lappend list [string range $str 0 [expr {[lindex $match 0] -1}]]
if {[lindex $submatch 0] >= 0} {
lappend list [string range $str [lindex $submatch 0] \
[lindex $submatch 1]]
}
set str [string range $str [expr {[lindex $match 1]+1}] end]
}
lappend list $str
return $list
}
}
#
# splitn --
#
# splitn splits the string $str into chunks of length $len. These
# chunks are returned as a list.
#
# If $str really contains a ByteArray object (as retrieved from binary
# encoded channels) splitn must honor this by splitting the string
# into chunks of $len bytes.
#
# It is an error to call splitn with a nonpositive $len.
#
# If splitn is called with an empty string, it returns the empty list.
#
# If the length of $str is not an entire multiple of the chunk length,
# the last chunk in the generated list will be shorter than $len.
#
# The implementation presented here was given by Bryan Oakley, as
# part of a ``contest'' I staged on c.l.t in July 2004. I selected
# this version, as it does not rely on runtime generated code, is
# very fast for chunk size one, not too bad in all the other cases,
# and uses [split] or [string range] which have been around for quite
# some time.
#
# -- Robert Suetterlin (robert@mpe.mpg.de)
#
proc ::textutil::split::splitn {str {len 1}} {
if {$len <= 0} {
return -code error "len must be > 0"
}
if {$len == 1} {
return [split $str {}]
}
set result [list]
set max [string length $str]
set i 0
set j [expr {$len -1}]
while {$i < $max} {
lappend result [string range $str $i $j]
incr i $len
incr j $len
}
return $result
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::split {
namespace export splitx splitn
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::split 0.8

144
src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/string-0.8.tm

@ -0,0 +1,144 @@
# string.tcl --
#
# Utilities for manipulating strings, words, single lines,
# paragraphs, ...
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2002 by Joe English <jenglish@users.sourceforge.net>
# Copyright (c) 2001-2014 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: string.tcl,v 1.2 2008/03/22 16:03:11 mic42 Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil::string {}
# ### ### ### ######### ######### #########
## API implementation
# @c Removes the last character from the given <a string>.
#
# @a string: The string to manipulate.
#
# @r The <a string> without its last character.
#
# @i chopping
proc ::textutil::string::chop {string} {
return [string range $string 0 [expr {[string length $string]-2}]]
}
# @c Removes the first character from the given <a string>.
# @c Convenience procedure.
#
# @a string: string to manipulate.
#
# @r The <a string> without its first character.
#
# @i tail
proc ::textutil::string::tail {string} {
return [string range $string 1 end]
}
# @c Capitalizes first character of the given <a string>.
# @c Complementary procedure to <p ::textutil::uncap>.
#
# @a string: string to manipulate.
#
# @r The <a string> with its first character capitalized.
#
# @i capitalize
proc ::textutil::string::cap {string} {
return [string toupper [string index $string 0]][string range $string 1 end]
}
# @c unCapitalizes first character of the given <a string>.
# @c Complementary procedure to <p ::textutil::cap>.
#
# @a string: string to manipulate.
#
# @r The <a string> with its first character uncapitalized.
#
# @i uncapitalize
proc ::textutil::string::uncap {string} {
return [string tolower [string index $string 0]][string range $string 1 end]
}
# @c Capitalizes first character of each word of the given <a sentence>.
#
# @a sentence: string to manipulate.
#
# @r The <a sentence> with the first character of each word capitalized.
#
# @i capitalize
proc ::textutil::string::capEachWord {sentence} {
regsub -all {\S+} [string map {\\ \\\\ \$ \\$} $sentence] {[string toupper [string index & 0]][string range & 1 end]} cmd
return [subst -nobackslashes -novariables $cmd]
}
# Compute the longest string which is common to all strings given to
# the command, and at the beginning of said strings, i.e. a prefix. If
# only one argument is specified it is treated as a list of the
# strings to look at. If more than one argument is specified these
# arguments are the strings to be looked at. If only one string is
# given, in either form, the string is returned, as it is its own
# longest common prefix.
proc ::textutil::string::longestCommonPrefix {args} {
return [longestCommonPrefixList $args]
}
proc ::textutil::string::longestCommonPrefixList {list} {
if {[llength $list] <= 1} {
return [lindex $list 0]
}
set list [lsort $list]
set min [lindex $list 0]
set max [lindex $list end]
# Min and max are the two strings which are most different. If
# they have a common prefix, it will also be the common prefix for
# all of them.
# Fast bailouts for common cases.
set n [string length $min]
if {$n == 0} {return ""}
if {0 == [string compare $min $max]} {return $min}
set prefix ""
set i 0
while {[string index $min $i] == [string index $max $i]} {
append prefix [string index $min $i]
if {[incr i] > $n} {break}
}
set prefix
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::string {
# Export the imported commands
namespace export chop tail cap uncap capEachWord
namespace export longestCommonPrefix
namespace export longestCommonPrefixList
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::string 0.8

289
src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/tabify-0.7.tm

@ -0,0 +1,289 @@
#
# As the author of the procs 'tabify2' and 'untabify2' I suggest that the
# comments explaining their behaviour be kept in this file.
# 1) Beginners in any programming language (I am new to Tcl so I know what I
# am talking about) can profit enormously from studying 'correct' code.
# Of course comments will help a lot in this regard.
# 2) Many problems newbies face can be solved by directing them towards
# available libraries - after all, libraries have been written to solve
# recurring problems. Then they can just use them, or have a closer look
# to see and to discover how things are done the 'Tcl way'.
# 3) And if ever a proc from a library should be less than perfect, having
# comments explaining the behaviour of the code will surely help.
#
# This said, I will welcome any error reports or suggestions for improvements
# (especially on the 'doing things the Tcl way' aspect).
#
# Use of these sources is licensed under the same conditions as is Tcl.
#
# June 2001, Helmut Giese (hgiese@ratiosoft.com)
#
# ----------------------------------------------------------------------------
#
# The original procs 'tabify' and 'untabify' each work with complete blocks
# of $num spaces ('num' holding the tab size). While this is certainly useful
# in some circumstances, it does not reflect the way an editor works:
# Counting columns from 1, assuming a tab size of 8 and entering '12345'
# followed by a tab, you expect to advance to column 9. Your editor might
# put a tab into the file or 3 spaces, depending on its configuration.
# Now, on 'tabifying' you will expect to see those 3 spaces converted to a
# tab (and on the other hand expect the tab *at this position* to be
# converted to 3 spaces).
#
# This behaviour is mimicked by the new procs 'tabify2' and 'untabify2'.
# Both have one feature in common: They accept multi-line strings (a whole
# file if you want to) but in order to make life simpler for the programmer,
# they split the incoming string into individual lines and hand each line to
# a proc that does the real work.
#
# One design decision worth mentioning here:
# A single space is never converted to a tab even if its position would
# allow to do so.
# Single spaces occur very often, say in arithmetic expressions like
# [expr (($a + $b) * $c) < $d]. If we didn't follow the above rule we might
# need to replace one or more of them to tabs. However if the tab size gets
# changed, this expression would be formatted quite differently - which is
# probably not a good idea.
#
# 'untabifying' on the other hand might need to replace a tab with a single
# space: If the current position requires it, what else to do?
# As a consequence those two procs are unsymmetric in this aspect, but I
# couldn't think of a better solution. Could you?
#
# ----------------------------------------------------------------------------
#
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
package require textutil::repeat
namespace eval ::textutil::tabify {}
# ### ### ### ######### ######### #########
## API implementation
namespace eval ::textutil::tabify {
namespace import -force ::textutil::repeat::strRepeat
}
proc ::textutil::tabify::tabify { string { num 8 } } {
return [string map [list [MakeTabStr $num] \t] $string]
}
proc ::textutil::tabify::untabify { string { num 8 } } {
return [string map [list \t [MakeTabStr $num]] $string]
}
proc ::textutil::tabify::MakeTabStr { num } {
variable TabStr
variable TabLen
if { $TabLen != $num } then {
set TabLen $num
set TabStr [strRepeat " " $num]
}
return $TabStr
}
# ----------------------------------------------------------------------------
#
# tabifyLine: Works on a single line of text, replacing 'spaces at correct
# positions' with tabs. $num is the requested tab size.
# Returns the (possibly modified) line.
#
# 'spaces at correct positions': Only spaces which 'fill the space' between
# an arbitrary position and the next tab stop can be replaced.
# Example: With tab size 8, spaces at positions 11 - 13 will *not* be replaced,
# because an expansion of a tab at position 11 will jump up to 16.
# See also the comment at the beginning of this file why single spaces are
# *never* replaced by a tab.
#
# The proc works backwards, from the end of the string up to the beginning:
# - Set the position to start the search from ('lastPos') to 'end'.
# - Find the last occurrence of ' ' in 'line' with respect to 'lastPos'
# ('currPos' below). This is a candidate for replacement.
# - Find to 'currPos' the following tab stop using the expression
# set nextTab [expr ($currPos + $num) - ($currPos % $num)]
# and get the previous tab stop as well (this will be the starting
# point for the next iteration).
# - The ' ' at 'currPos' is only a candidate for replacement if
# 1) it is just one position before a tab stop *and*
# 2) there is at least one space at its left (see comment above on not
# touching an isolated space).
# Continue, if any of these conditions is not met.
# - Determine where to put the tab (that is: how many spaces to replace?)
# by stepping up to the beginning until
# -- you hit a non-space or
# -- you are at the previous tab position
# - Do the replacement and continue.
#
# This algorithm only works, if $line does not contain tabs. Otherwise our
# interpretation of any position beyond the tab will be wrong. (Imagine you
# find a ' ' at position 4 in $line. If you got 3 leading tabs, your *real*
# position might be 25 (tab size of 8). Since in real life some strings might
# already contain tabs, we test for it (and eventually call untabifyLine).
#
proc ::textutil::tabify::tabifyLine { line num } {
if { [string first \t $line] != -1 } {
# assure array 'Spaces' is set up 'comme il faut'
checkArr $num
# remove existing tabs
set line [untabifyLine $line $num]
}
set lastPos end
while { $lastPos > 0 } {
set currPos [string last " " $line $lastPos]
if { $currPos == -1 } {
# no more spaces
break;
}
set nextTab [expr {($currPos + $num) - ($currPos % $num)}]
set prevTab [expr {$nextTab - $num}]
# prepare for next round: continue at 'previous tab stop - 1'
set lastPos [expr {$prevTab - 1}]
if { ($currPos + 1) != $nextTab } {
continue ;# crit. (1)
}
if { [string index $line [expr {$currPos - 1}]] != " " } {
continue ;# crit. (2)
}
# now step backwards while there are spaces
for {set pos [expr {$currPos - 2}]} {$pos >= $prevTab} {incr pos -1} {
if { [string index $line $pos] != " " } {
break;
}
}
# ... and replace them
set line [string replace $line [expr {$pos + 1}] $currPos \t]
}
return $line
}
#
# Helper proc for 'untabifyLine': Checks if all needed elements of array
# 'Spaces' exist and creates the missing ones if needed.
#
proc ::textutil::tabify::checkArr { num } {
variable TabLen2
variable Spaces
if { $num > $TabLen2 } {
for { set i [expr {$TabLen2 + 1}] } { $i <= $num } { incr i } {
set Spaces($i) [strRepeat " " $i]
}
set TabLen2 $num
}
}
# untabifyLine: Works on a single line of text, replacing tabs with enough
# spaces to get to the next tab position.
# Returns the (possibly modified) line.
#
# The procedure is straight forward:
# - Find the next tab.
# - Calculate the next tab position following it.
# - Delete the tab and insert as many spaces as needed to get there.
#
proc ::textutil::tabify::untabifyLine { line num } {
variable Spaces
set currPos 0
while { 1 } {
set currPos [string first \t $line $currPos]
if { $currPos == -1 } {
# no more tabs
break
}
# how far is the next tab position ?
set dist [expr {$num - ($currPos % $num)}]
# replace '\t' at $currPos with $dist spaces
set line [string replace $line $currPos $currPos $Spaces($dist)]
# set up for next round (not absolutely necessary but maybe a trifle
# more efficient)
incr currPos $dist
}
return $line
}
# tabify2: Replace all 'appropriate' spaces as discussed above with tabs.
# 'string' might hold any number of lines, 'num' is the requested tab size.
# Returns (possibly modified) 'string'.
#
proc ::textutil::tabify::tabify2 { string { num 8 } } {
# split string into individual lines
set inLst [split $string \n]
# now work on each line
set outLst [list]
foreach line $inLst {
lappend outLst [tabifyLine $line $num]
}
# return all as one string
return [join $outLst \n]
}
# untabify2: Replace all tabs with the appropriate number of spaces.
# 'string' might hold any number of lines, 'num' is the requested tab size.
# Returns (possibly modified) 'string'.
#
proc ::textutil::tabify::untabify2 { string { num 8 } } {
# assure array 'Spaces' is set up 'comme il faut'
checkArr $num
set inLst [split $string \n]
set outLst [list]
foreach line $inLst {
lappend outLst [untabifyLine $line $num]
}
return [join $outLst \n]
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::tabify {
variable TabLen 8
variable TabStr [strRepeat " " $TabLen]
namespace export tabify untabify tabify2 untabify2
# The proc 'untabify2' uses the following variables for efficiency.
# Since a tab can be replaced by one up to 'tab size' spaces, it is handy
# to have the appropriate 'space strings' available. This is the use of
# the array 'Spaces', where 'Spaces(n)' contains just 'n' spaces.
# The variable 'TabLen2' remembers the biggest tab size used.
variable TabLen2 0
variable Spaces
array set Spaces {0 ""}
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::tabify 0.7

112
src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/trim-0.7.tm

@ -0,0 +1,112 @@
# trim.tcl --
#
# Various ways of trimming a string.
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: trim.tcl,v 1.5 2006/04/21 04:42:28 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil::trim {}
# ### ### ### ######### ######### #########
## API implementation
proc ::textutil::trim::trimleft {text {trim "[ \t]+"}} {
regsub -line -all -- [MakeStr $trim left] $text {} text
return $text
}
proc ::textutil::trim::trimright {text {trim "[ \t]+"}} {
regsub -line -all -- [MakeStr $trim right] $text {} text
return $text
}
proc ::textutil::trim::trim {text {trim "[ \t]+"}} {
regsub -line -all -- [MakeStr $trim left] $text {} text
regsub -line -all -- [MakeStr $trim right] $text {} text
return $text
}
# @c Strips <a prefix> from <a text>, if found at its start.
#
# @a text: The string to check for <a prefix>.
# @a prefix: The string to remove from <a text>.
#
# @r The <a text>, but without <a prefix>.
#
# @i remove, prefix
proc ::textutil::trim::trimPrefix {text prefix} {
if {[string first $prefix $text] == 0} {
return [string range $text [string length $prefix] end]
} else {
return $text
}
}
# @c Removes the Heading Empty Lines of <a text>.
#
# @a text: The text block to manipulate.
#
# @r The <a text>, but without heading empty lines.
#
# @i remove, empty lines
proc ::textutil::trim::trimEmptyHeading {text} {
regsub -- "^(\[ \t\]*\n)*" $text {} text
return $text
}
# ### ### ### ######### ######### #########
## Helper commands. Internal
proc ::textutil::trim::MakeStr { string pos } {
variable StrU
variable StrR
variable StrL
if { "$string" != "$StrU" } {
set StrU $string
set StrR "(${StrU})\$"
set StrL "^(${StrU})"
}
if { "$pos" == "left" } {
return $StrL
}
if { "$pos" == "right" } {
return $StrR
}
return -code error "Panic, illegal position key \"$pos\""
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::trim {
variable StrU "\[ \t\]+"
variable StrR "(${StrU})\$"
variable StrL "^(${StrU})"
namespace export \
trim trimright trimleft \
trimPrefix trimEmptyHeading
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::trim 0.7

772
src/mixtemplates/layouts/basic/src/bootsupport/modules/textutil/wcswidth-35.1.tm

@ -0,0 +1,772 @@
###
# This file is automatically generated by the build/build.tcl file
# based on information in the following database:
# http://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt
#
# (This is the 35th edition, thus version 35 for our package)
#
# Author: Sean Woods <yoda@etoyoc.com>
###
package provide textutil::wcswidth 35.1
proc ::textutil::wcswidth_type char {
if {$char == 161} { return A }
if {$char == 164} { return A }
if {$char == 167} { return A }
if {$char == 168} { return A }
if {$char == 170} { return A }
if {$char == 173} { return A }
if {$char == 174} { return A }
if {$char == 176} { return A }
if {$char == 177} { return A }
if {$char >= 178 && $char <= 179 } { return A }
if {$char == 180} { return A }
if {$char >= 182 && $char <= 183 } { return A }
if {$char == 184} { return A }
if {$char == 185} { return A }
if {$char == 186} { return A }
if {$char >= 188 && $char <= 190 } { return A }
if {$char == 191} { return A }
if {$char == 198} { return A }
if {$char == 208} { return A }
if {$char == 215} { return A }
if {$char == 216} { return A }
if {$char >= 222 && $char <= 225 } { return A }
if {$char == 230} { return A }
if {$char >= 232 && $char <= 234 } { return A }
if {$char >= 236 && $char <= 237 } { return A }
if {$char == 240} { return A }
if {$char >= 242 && $char <= 243 } { return A }
if {$char == 247} { return A }
if {$char >= 248 && $char <= 250 } { return A }
if {$char == 252} { return A }
if {$char == 254} { return A }
if {$char == 257} { return A }
if {$char == 273} { return A }
if {$char == 275} { return A }
if {$char == 283} { return A }
if {$char >= 294 && $char <= 295 } { return A }
if {$char == 299} { return A }
if {$char >= 305 && $char <= 307 } { return A }
if {$char == 312} { return A }
if {$char >= 319 && $char <= 322 } { return A }
if {$char == 324} { return A }
if {$char >= 328 && $char <= 331 } { return A }
if {$char == 333} { return A }
if {$char >= 338 && $char <= 339 } { return A }
if {$char >= 358 && $char <= 359 } { return A }
if {$char == 363} { return A }
if {$char == 462} { return A }
if {$char == 464} { return A }
if {$char == 466} { return A }
if {$char == 468} { return A }
if {$char == 470} { return A }
if {$char == 472} { return A }
if {$char == 474} { return A }
if {$char == 476} { return A }
if {$char == 593} { return A }
if {$char == 609} { return A }
if {$char == 708} { return A }
if {$char == 711} { return A }
if {$char >= 713 && $char <= 715 } { return A }
if {$char == 717} { return A }
if {$char == 720} { return A }
if {$char >= 728 && $char <= 731 } { return A }
if {$char == 733} { return A }
if {$char == 735} { return A }
if {$char >= 768 && $char <= 879 } { return A }
if {$char >= 913 && $char <= 929 } { return A }
if {$char >= 931 && $char <= 937 } { return A }
if {$char >= 945 && $char <= 961 } { return A }
if {$char >= 963 && $char <= 969 } { return A }
if {$char == 1025} { return A }
if {$char >= 1040 && $char <= 1103 } { return A }
if {$char == 1105} { return A }
if {$char >= 4352 && $char <= 4447 } { return W }
if {$char == 8208} { return A }
if {$char >= 8211 && $char <= 8213 } { return A }
if {$char == 8214} { return A }
if {$char == 8216} { return A }
if {$char == 8217} { return A }
if {$char == 8220} { return A }
if {$char == 8221} { return A }
if {$char >= 8224 && $char <= 8226 } { return A }
if {$char >= 8228 && $char <= 8231 } { return A }
if {$char == 8240} { return A }
if {$char >= 8242 && $char <= 8243 } { return A }
if {$char == 8245} { return A }
if {$char == 8251} { return A }
if {$char == 8254} { return A }
if {$char == 8308} { return A }
if {$char == 8319} { return A }
if {$char >= 8321 && $char <= 8324 } { return A }
if {$char == 8361} { return H }
if {$char == 8364} { return A }
if {$char == 8451} { return A }
if {$char == 8453} { return A }
if {$char == 8457} { return A }
if {$char == 8467} { return A }
if {$char == 8470} { return A }
if {$char >= 8481 && $char <= 8482 } { return A }
if {$char == 8486} { return A }
if {$char == 8491} { return A }
if {$char >= 8531 && $char <= 8532 } { return A }
if {$char >= 8539 && $char <= 8542 } { return A }
if {$char >= 8544 && $char <= 8555 } { return A }
if {$char >= 8560 && $char <= 8569 } { return A }
if {$char == 8585} { return A }
if {$char >= 8592 && $char <= 8596 } { return A }
if {$char >= 8597 && $char <= 8601 } { return A }
if {$char >= 8632 && $char <= 8633 } { return A }
if {$char == 8658} { return A }
if {$char == 8660} { return A }
if {$char == 8679} { return A }
if {$char == 8704} { return A }
if {$char >= 8706 && $char <= 8707 } { return A }
if {$char >= 8711 && $char <= 8712 } { return A }
if {$char == 8715} { return A }
if {$char == 8719} { return A }
if {$char == 8721} { return A }
if {$char == 8725} { return A }
if {$char == 8730} { return A }
if {$char >= 8733 && $char <= 8736 } { return A }
if {$char == 8739} { return A }
if {$char == 8741} { return A }
if {$char >= 8743 && $char <= 8748 } { return A }
if {$char == 8750} { return A }
if {$char >= 8756 && $char <= 8759 } { return A }
if {$char >= 8764 && $char <= 8765 } { return A }
if {$char == 8776} { return A }
if {$char == 8780} { return A }
if {$char == 8786} { return A }
if {$char >= 8800 && $char <= 8801 } { return A }
if {$char >= 8804 && $char <= 8807 } { return A }
if {$char >= 8810 && $char <= 8811 } { return A }
if {$char >= 8814 && $char <= 8815 } { return A }
if {$char >= 8834 && $char <= 8835 } { return A }
if {$char >= 8838 && $char <= 8839 } { return A }
if {$char == 8853} { return A }
if {$char == 8857} { return A }
if {$char == 8869} { return A }
if {$char == 8895} { return A }
if {$char == 8978} { return A }
if {$char >= 8986 && $char <= 8987 } { return W }
if {$char == 9001} { return W }
if {$char == 9002} { return W }
if {$char >= 9193 && $char <= 9196 } { return W }
if {$char == 9200} { return W }
if {$char == 9203} { return W }
if {$char >= 9312 && $char <= 9371 } { return A }
if {$char >= 9372 && $char <= 9449 } { return A }
if {$char >= 9451 && $char <= 9471 } { return A }
if {$char >= 9472 && $char <= 9547 } { return A }
if {$char >= 9552 && $char <= 9587 } { return A }
if {$char >= 9600 && $char <= 9615 } { return A }
if {$char >= 9618 && $char <= 9621 } { return A }
if {$char >= 9632 && $char <= 9633 } { return A }
if {$char >= 9635 && $char <= 9641 } { return A }
if {$char >= 9650 && $char <= 9651 } { return A }
if {$char == 9654} { return A }
if {$char == 9655} { return A }
if {$char >= 9660 && $char <= 9661 } { return A }
if {$char == 9664} { return A }
if {$char == 9665} { return A }
if {$char >= 9670 && $char <= 9672 } { return A }
if {$char == 9675} { return A }
if {$char >= 9678 && $char <= 9681 } { return A }
if {$char >= 9698 && $char <= 9701 } { return A }
if {$char == 9711} { return A }
if {$char >= 9725 && $char <= 9726 } { return W }
if {$char >= 9733 && $char <= 9734 } { return A }
if {$char == 9737} { return A }
if {$char >= 9742 && $char <= 9743 } { return A }
if {$char >= 9748 && $char <= 9749 } { return W }
if {$char == 9756} { return A }
if {$char == 9758} { return A }
if {$char == 9792} { return A }
if {$char == 9794} { return A }
if {$char >= 9800 && $char <= 9811 } { return W }
if {$char >= 9824 && $char <= 9825 } { return A }
if {$char >= 9827 && $char <= 9829 } { return A }
if {$char >= 9831 && $char <= 9834 } { return A }
if {$char >= 9836 && $char <= 9837 } { return A }
if {$char == 9839} { return A }
if {$char == 9855} { return W }
if {$char == 9875} { return W }
if {$char >= 9886 && $char <= 9887 } { return A }
if {$char == 9889} { return W }
if {$char >= 9898 && $char <= 9899 } { return W }
if {$char >= 9917 && $char <= 9918 } { return W }
if {$char == 9919} { return A }
if {$char >= 9924 && $char <= 9925 } { return W }
if {$char >= 9926 && $char <= 9933 } { return A }
if {$char == 9934} { return W }
if {$char >= 9935 && $char <= 9939 } { return A }
if {$char == 9940} { return W }
if {$char >= 9941 && $char <= 9953 } { return A }
if {$char == 9955} { return A }
if {$char >= 9960 && $char <= 9961 } { return A }
if {$char == 9962} { return W }
if {$char >= 9963 && $char <= 9969 } { return A }
if {$char >= 9970 && $char <= 9971 } { return W }
if {$char == 9972} { return A }
if {$char == 9973} { return W }
if {$char >= 9974 && $char <= 9977 } { return A }
if {$char == 9978} { return W }
if {$char >= 9979 && $char <= 9980 } { return A }
if {$char == 9981} { return W }
if {$char >= 9982 && $char <= 9983 } { return A }
if {$char == 9989} { return W }
if {$char >= 9994 && $char <= 9995 } { return W }
if {$char == 10024} { return W }
if {$char == 10045} { return A }
if {$char == 10060} { return W }
if {$char == 10062} { return W }
if {$char >= 10067 && $char <= 10069 } { return W }
if {$char == 10071} { return W }
if {$char >= 10102 && $char <= 10111 } { return A }
if {$char >= 10133 && $char <= 10135 } { return W }
if {$char == 10160} { return W }
if {$char == 10175} { return W }
if {$char >= 11035 && $char <= 11036 } { return W }
if {$char == 11088} { return W }
if {$char == 11093} { return W }
if {$char >= 11094 && $char <= 11097 } { return A }
if {$char >= 11904 && $char <= 11929 } { return W }
if {$char >= 11931 && $char <= 12019 } { return W }
if {$char >= 12032 && $char <= 12245 } { return W }
if {$char >= 12272 && $char <= 12283 } { return W }
if {$char == 12288} { return F }
if {$char >= 12289 && $char <= 12291 } { return W }
if {$char == 12292} { return W }
if {$char == 12293} { return W }
if {$char == 12294} { return W }
if {$char == 12295} { return W }
if {$char == 12296} { return W }
if {$char == 12297} { return W }
if {$char == 12298} { return W }
if {$char == 12299} { return W }
if {$char == 12300} { return W }
if {$char == 12301} { return W }
if {$char == 12302} { return W }
if {$char == 12303} { return W }
if {$char == 12304} { return W }
if {$char == 12305} { return W }
if {$char >= 12306 && $char <= 12307 } { return W }
if {$char == 12308} { return W }
if {$char == 12309} { return W }
if {$char == 12310} { return W }
if {$char == 12311} { return W }
if {$char == 12312} { return W }
if {$char == 12313} { return W }
if {$char == 12314} { return W }
if {$char == 12315} { return W }
if {$char == 12316} { return W }
if {$char == 12317} { return W }
if {$char >= 12318 && $char <= 12319 } { return W }
if {$char == 12320} { return W }
if {$char >= 12321 && $char <= 12329 } { return W }
if {$char >= 12330 && $char <= 12333 } { return W }
if {$char >= 12334 && $char <= 12335 } { return W }
if {$char == 12336} { return W }
if {$char >= 12337 && $char <= 12341 } { return W }
if {$char >= 12342 && $char <= 12343 } { return W }
if {$char >= 12344 && $char <= 12346 } { return W }
if {$char == 12347} { return W }
if {$char == 12348} { return W }
if {$char == 12349} { return W }
if {$char == 12350} { return W }
if {$char >= 12353 && $char <= 12438 } { return W }
if {$char >= 12441 && $char <= 12442 } { return W }
if {$char >= 12443 && $char <= 12444 } { return W }
if {$char >= 12445 && $char <= 12446 } { return W }
if {$char == 12447} { return W }
if {$char == 12448} { return W }
if {$char >= 12449 && $char <= 12538 } { return W }
if {$char == 12539} { return W }
if {$char >= 12540 && $char <= 12542 } { return W }
if {$char == 12543} { return W }
if {$char >= 12549 && $char <= 12591 } { return W }
if {$char >= 12593 && $char <= 12686 } { return W }
if {$char >= 12688 && $char <= 12689 } { return W }
if {$char >= 12690 && $char <= 12693 } { return W }
if {$char >= 12694 && $char <= 12703 } { return W }
if {$char >= 12704 && $char <= 12730 } { return W }
if {$char >= 12736 && $char <= 12771 } { return W }
if {$char >= 12784 && $char <= 12799 } { return W }
if {$char >= 12800 && $char <= 12830 } { return W }
if {$char >= 12832 && $char <= 12841 } { return W }
if {$char >= 12842 && $char <= 12871 } { return W }
if {$char >= 12872 && $char <= 12879 } { return A }
if {$char == 12880} { return W }
if {$char >= 12881 && $char <= 12895 } { return W }
if {$char >= 12896 && $char <= 12927 } { return W }
if {$char >= 12928 && $char <= 12937 } { return W }
if {$char >= 12938 && $char <= 12976 } { return W }
if {$char >= 12977 && $char <= 12991 } { return W }
if {$char >= 12992 && $char <= 13054 } { return W }
if {$char >= 13056 && $char <= 13311 } { return W }
if {$char >= 13312 && $char <= 19893 } { return W }
if {$char >= 19894 && $char <= 19903 } { return W }
if {$char >= 19968 && $char <= 40943 } { return W }
if {$char >= 40944 && $char <= 40959 } { return W }
if {$char >= 40960 && $char <= 40980 } { return W }
if {$char == 40981} { return W }
if {$char >= 40982 && $char <= 42124 } { return W }
if {$char >= 42128 && $char <= 42182 } { return W }
if {$char >= 43360 && $char <= 43388 } { return W }
if {$char >= 44032 && $char <= 55203 } { return W }
if {$char >= 57344 && $char <= 63743 } { return A }
if {$char >= 63744 && $char <= 64109 } { return W }
if {$char >= 64110 && $char <= 64111 } { return W }
if {$char >= 64112 && $char <= 64217 } { return W }
if {$char >= 64218 && $char <= 64255 } { return W }
if {$char >= 65024 && $char <= 65039 } { return A }
if {$char >= 65040 && $char <= 65046 } { return W }
if {$char == 65047} { return W }
if {$char == 65048} { return W }
if {$char == 65049} { return W }
if {$char == 65072} { return W }
if {$char >= 65073 && $char <= 65074 } { return W }
if {$char >= 65075 && $char <= 65076 } { return W }
if {$char == 65077} { return W }
if {$char == 65078} { return W }
if {$char == 65079} { return W }
if {$char == 65080} { return W }
if {$char == 65081} { return W }
if {$char == 65082} { return W }
if {$char == 65083} { return W }
if {$char == 65084} { return W }
if {$char == 65085} { return W }
if {$char == 65086} { return W }
if {$char == 65087} { return W }
if {$char == 65088} { return W }
if {$char == 65089} { return W }
if {$char == 65090} { return W }
if {$char == 65091} { return W }
if {$char == 65092} { return W }
if {$char >= 65093 && $char <= 65094 } { return W }
if {$char == 65095} { return W }
if {$char == 65096} { return W }
if {$char >= 65097 && $char <= 65100 } { return W }
if {$char >= 65101 && $char <= 65103 } { return W }
if {$char >= 65104 && $char <= 65106 } { return W }
if {$char >= 65108 && $char <= 65111 } { return W }
if {$char == 65112} { return W }
if {$char == 65113} { return W }
if {$char == 65114} { return W }
if {$char == 65115} { return W }
if {$char == 65116} { return W }
if {$char == 65117} { return W }
if {$char == 65118} { return W }
if {$char >= 65119 && $char <= 65121 } { return W }
if {$char == 65122} { return W }
if {$char == 65123} { return W }
if {$char >= 65124 && $char <= 65126 } { return W }
if {$char == 65128} { return W }
if {$char == 65129} { return W }
if {$char >= 65130 && $char <= 65131 } { return W }
if {$char >= 65281 && $char <= 65283 } { return F }
if {$char == 65284} { return F }
if {$char >= 65285 && $char <= 65287 } { return F }
if {$char == 65288} { return F }
if {$char == 65289} { return F }
if {$char == 65290} { return F }
if {$char == 65291} { return F }
if {$char == 65292} { return F }
if {$char == 65293} { return F }
if {$char >= 65294 && $char <= 65295 } { return F }
if {$char >= 65296 && $char <= 65305 } { return F }
if {$char >= 65306 && $char <= 65307 } { return F }
if {$char >= 65308 && $char <= 65310 } { return F }
if {$char >= 65311 && $char <= 65312 } { return F }
if {$char >= 65313 && $char <= 65338 } { return F }
if {$char == 65339} { return F }
if {$char == 65340} { return F }
if {$char == 65341} { return F }
if {$char == 65342} { return F }
if {$char == 65343} { return F }
if {$char == 65344} { return F }
if {$char >= 65345 && $char <= 65370 } { return F }
if {$char == 65371} { return F }
if {$char == 65372} { return F }
if {$char == 65373} { return F }
if {$char == 65374} { return F }
if {$char == 65375} { return F }
if {$char == 65376} { return F }
if {$char == 65377} { return H }
if {$char == 65378} { return H }
if {$char == 65379} { return H }
if {$char >= 65380 && $char <= 65381 } { return H }
if {$char >= 65382 && $char <= 65391 } { return H }
if {$char == 65392} { return H }
if {$char >= 65393 && $char <= 65437 } { return H }
if {$char >= 65438 && $char <= 65439 } { return H }
if {$char >= 65440 && $char <= 65470 } { return H }
if {$char >= 65474 && $char <= 65479 } { return H }
if {$char >= 65482 && $char <= 65487 } { return H }
if {$char >= 65490 && $char <= 65495 } { return H }
if {$char >= 65498 && $char <= 65500 } { return H }
if {$char >= 65504 && $char <= 65505 } { return F }
if {$char == 65506} { return F }
if {$char == 65507} { return F }
if {$char == 65508} { return F }
if {$char >= 65509 && $char <= 65510 } { return F }
if {$char == 65512} { return H }
if {$char >= 65513 && $char <= 65516 } { return H }
if {$char >= 65517 && $char <= 65518 } { return H }
if {$char == 65533} { return A }
if {$char >= 94176 && $char <= 94177 } { return W }
if {$char >= 94208 && $char <= 100337 } { return W }
if {$char >= 100352 && $char <= 101106 } { return W }
if {$char >= 110592 && $char <= 110847 } { return W }
if {$char >= 110848 && $char <= 110878 } { return W }
if {$char >= 110960 && $char <= 111355 } { return W }
if {$char == 126980} { return W }
if {$char == 127183} { return W }
if {$char >= 127232 && $char <= 127242 } { return A }
if {$char >= 127248 && $char <= 127277 } { return A }
if {$char >= 127280 && $char <= 127337 } { return A }
if {$char >= 127344 && $char <= 127373 } { return A }
if {$char == 127374} { return W }
if {$char >= 127375 && $char <= 127376 } { return A }
if {$char >= 127377 && $char <= 127386 } { return W }
if {$char >= 127387 && $char <= 127404 } { return A }
if {$char >= 127488 && $char <= 127490 } { return W }
if {$char >= 127504 && $char <= 127547 } { return W }
if {$char >= 127552 && $char <= 127560 } { return W }
if {$char >= 127568 && $char <= 127569 } { return W }
if {$char >= 127584 && $char <= 127589 } { return W }
if {$char >= 127744 && $char <= 127776 } { return W }
if {$char >= 127789 && $char <= 127797 } { return W }
if {$char >= 127799 && $char <= 127868 } { return W }
if {$char >= 127870 && $char <= 127891 } { return W }
if {$char >= 127904 && $char <= 127946 } { return W }
if {$char >= 127951 && $char <= 127955 } { return W }
if {$char >= 127968 && $char <= 127984 } { return W }
if {$char == 127988} { return W }
if {$char >= 127992 && $char <= 127994 } { return W }
if {$char >= 127995 && $char <= 127999 } { return W }
if {$char >= 128000 && $char <= 128062 } { return W }
if {$char == 128064} { return W }
if {$char >= 128066 && $char <= 128252 } { return W }
if {$char >= 128255 && $char <= 128317 } { return W }
if {$char >= 128331 && $char <= 128334 } { return W }
if {$char >= 128336 && $char <= 128359 } { return W }
if {$char == 128378} { return W }
if {$char >= 128405 && $char <= 128406 } { return W }
if {$char == 128420} { return W }
if {$char >= 128507 && $char <= 128511 } { return W }
if {$char >= 128512 && $char <= 128591 } { return W }
if {$char >= 128640 && $char <= 128709 } { return W }
if {$char == 128716} { return W }
if {$char >= 128720 && $char <= 128722 } { return W }
if {$char >= 128747 && $char <= 128748 } { return W }
if {$char >= 128756 && $char <= 128761 } { return W }
if {$char >= 129296 && $char <= 129342 } { return W }
if {$char >= 129344 && $char <= 129392 } { return W }
if {$char >= 129395 && $char <= 129398 } { return W }
if {$char == 129402} { return W }
if {$char >= 129404 && $char <= 129442 } { return W }
if {$char >= 129456 && $char <= 129465 } { return W }
if {$char >= 129472 && $char <= 129474 } { return W }
if {$char >= 129488 && $char <= 129535 } { return W }
if {$char >= 131072 && $char <= 173782 } { return W }
if {$char >= 173783 && $char <= 173823 } { return W }
if {$char >= 173824 && $char <= 177972 } { return W }
if {$char >= 177973 && $char <= 177983 } { return W }
if {$char >= 177984 && $char <= 178205 } { return W }
if {$char >= 178206 && $char <= 178207 } { return W }
if {$char >= 178208 && $char <= 183969 } { return W }
if {$char >= 183970 && $char <= 183983 } { return W }
if {$char >= 183984 && $char <= 191456 } { return W }
if {$char >= 191457 && $char <= 194559 } { return W }
if {$char >= 194560 && $char <= 195101 } { return W }
if {$char >= 195102 && $char <= 195103 } { return W }
if {$char >= 195104 && $char <= 196605 } { return W }
if {$char >= 196608 && $char <= 262141 } { return W }
if {$char >= 917760 && $char <= 917999 } { return A }
if {$char >= 983040 && $char <= 1048573 } { return A }
if {$char >= 1048576 && $char <= 1114109 } { return A }
return N
}
proc ::textutil::wcswidth_char char {
if {$char >= 4352 && $char <= 4447 } { return 2 }
if {$char >= 8986 && $char <= 8987 } { return 2 }
if {$char == 9001} { return 2 }
if {$char == 9002} { return 2 }
if {$char >= 9193 && $char <= 9196 } { return 2 }
if {$char == 9200} { return 2 }
if {$char == 9203} { return 2 }
if {$char >= 9725 && $char <= 9726 } { return 2 }
if {$char >= 9748 && $char <= 9749 } { return 2 }
if {$char >= 9800 && $char <= 9811 } { return 2 }
if {$char == 9855} { return 2 }
if {$char == 9875} { return 2 }
if {$char == 9889} { return 2 }
if {$char >= 9898 && $char <= 9899 } { return 2 }
if {$char >= 9917 && $char <= 9918 } { return 2 }
if {$char >= 9924 && $char <= 9925 } { return 2 }
if {$char == 9934} { return 2 }
if {$char == 9940} { return 2 }
if {$char == 9962} { return 2 }
if {$char >= 9970 && $char <= 9971 } { return 2 }
if {$char == 9973} { return 2 }
if {$char == 9978} { return 2 }
if {$char == 9981} { return 2 }
if {$char == 9989} { return 2 }
if {$char >= 9994 && $char <= 9995 } { return 2 }
if {$char == 10024} { return 2 }
if {$char == 10060} { return 2 }
if {$char == 10062} { return 2 }
if {$char >= 10067 && $char <= 10069 } { return 2 }
if {$char == 10071} { return 2 }
if {$char >= 10133 && $char <= 10135 } { return 2 }
if {$char == 10160} { return 2 }
if {$char == 10175} { return 2 }
if {$char >= 11035 && $char <= 11036 } { return 2 }
if {$char == 11088} { return 2 }
if {$char == 11093} { return 2 }
if {$char >= 11904 && $char <= 11929 } { return 2 }
if {$char >= 11931 && $char <= 12019 } { return 2 }
if {$char >= 12032 && $char <= 12245 } { return 2 }
if {$char >= 12272 && $char <= 12283 } { return 2 }
if {$char == 12288} { return 2 }
if {$char >= 12289 && $char <= 12291 } { return 2 }
if {$char == 12292} { return 2 }
if {$char == 12293} { return 2 }
if {$char == 12294} { return 2 }
if {$char == 12295} { return 2 }
if {$char == 12296} { return 2 }
if {$char == 12297} { return 2 }
if {$char == 12298} { return 2 }
if {$char == 12299} { return 2 }
if {$char == 12300} { return 2 }
if {$char == 12301} { return 2 }
if {$char == 12302} { return 2 }
if {$char == 12303} { return 2 }
if {$char == 12304} { return 2 }
if {$char == 12305} { return 2 }
if {$char >= 12306 && $char <= 12307 } { return 2 }
if {$char == 12308} { return 2 }
if {$char == 12309} { return 2 }
if {$char == 12310} { return 2 }
if {$char == 12311} { return 2 }
if {$char == 12312} { return 2 }
if {$char == 12313} { return 2 }
if {$char == 12314} { return 2 }
if {$char == 12315} { return 2 }
if {$char == 12316} { return 2 }
if {$char == 12317} { return 2 }
if {$char >= 12318 && $char <= 12319 } { return 2 }
if {$char == 12320} { return 2 }
if {$char >= 12321 && $char <= 12329 } { return 2 }
if {$char >= 12330 && $char <= 12333 } { return 2 }
if {$char >= 12334 && $char <= 12335 } { return 2 }
if {$char == 12336} { return 2 }
if {$char >= 12337 && $char <= 12341 } { return 2 }
if {$char >= 12342 && $char <= 12343 } { return 2 }
if {$char >= 12344 && $char <= 12346 } { return 2 }
if {$char == 12347} { return 2 }
if {$char == 12348} { return 2 }
if {$char == 12349} { return 2 }
if {$char == 12350} { return 2 }
if {$char >= 12353 && $char <= 12438 } { return 2 }
if {$char >= 12441 && $char <= 12442 } { return 2 }
if {$char >= 12443 && $char <= 12444 } { return 2 }
if {$char >= 12445 && $char <= 12446 } { return 2 }
if {$char == 12447} { return 2 }
if {$char == 12448} { return 2 }
if {$char >= 12449 && $char <= 12538 } { return 2 }
if {$char == 12539} { return 2 }
if {$char >= 12540 && $char <= 12542 } { return 2 }
if {$char == 12543} { return 2 }
if {$char >= 12549 && $char <= 12591 } { return 2 }
if {$char >= 12593 && $char <= 12686 } { return 2 }
if {$char >= 12688 && $char <= 12689 } { return 2 }
if {$char >= 12690 && $char <= 12693 } { return 2 }
if {$char >= 12694 && $char <= 12703 } { return 2 }
if {$char >= 12704 && $char <= 12730 } { return 2 }
if {$char >= 12736 && $char <= 12771 } { return 2 }
if {$char >= 12784 && $char <= 12799 } { return 2 }
if {$char >= 12800 && $char <= 12830 } { return 2 }
if {$char >= 12832 && $char <= 12841 } { return 2 }
if {$char >= 12842 && $char <= 12871 } { return 2 }
if {$char == 12880} { return 2 }
if {$char >= 12881 && $char <= 12895 } { return 2 }
if {$char >= 12896 && $char <= 12927 } { return 2 }
if {$char >= 12928 && $char <= 12937 } { return 2 }
if {$char >= 12938 && $char <= 12976 } { return 2 }
if {$char >= 12977 && $char <= 12991 } { return 2 }
if {$char >= 12992 && $char <= 13054 } { return 2 }
if {$char >= 13056 && $char <= 13311 } { return 2 }
if {$char >= 13312 && $char <= 19893 } { return 2 }
if {$char >= 19894 && $char <= 19903 } { return 2 }
if {$char >= 19968 && $char <= 40943 } { return 2 }
if {$char >= 40944 && $char <= 40959 } { return 2 }
if {$char >= 40960 && $char <= 40980 } { return 2 }
if {$char == 40981} { return 2 }
if {$char >= 40982 && $char <= 42124 } { return 2 }
if {$char >= 42128 && $char <= 42182 } { return 2 }
if {$char >= 43360 && $char <= 43388 } { return 2 }
if {$char >= 44032 && $char <= 55203 } { return 2 }
if {$char >= 63744 && $char <= 64109 } { return 2 }
if {$char >= 64110 && $char <= 64111 } { return 2 }
if {$char >= 64112 && $char <= 64217 } { return 2 }
if {$char >= 64218 && $char <= 64255 } { return 2 }
if {$char >= 65040 && $char <= 65046 } { return 2 }
if {$char == 65047} { return 2 }
if {$char == 65048} { return 2 }
if {$char == 65049} { return 2 }
if {$char == 65072} { return 2 }
if {$char >= 65073 && $char <= 65074 } { return 2 }
if {$char >= 65075 && $char <= 65076 } { return 2 }
if {$char == 65077} { return 2 }
if {$char == 65078} { return 2 }
if {$char == 65079} { return 2 }
if {$char == 65080} { return 2 }
if {$char == 65081} { return 2 }
if {$char == 65082} { return 2 }
if {$char == 65083} { return 2 }
if {$char == 65084} { return 2 }
if {$char == 65085} { return 2 }
if {$char == 65086} { return 2 }
if {$char == 65087} { return 2 }
if {$char == 65088} { return 2 }
if {$char == 65089} { return 2 }
if {$char == 65090} { return 2 }
if {$char == 65091} { return 2 }
if {$char == 65092} { return 2 }
if {$char >= 65093 && $char <= 65094 } { return 2 }
if {$char == 65095} { return 2 }
if {$char == 65096} { return 2 }
if {$char >= 65097 && $char <= 65100 } { return 2 }
if {$char >= 65101 && $char <= 65103 } { return 2 }
if {$char >= 65104 && $char <= 65106 } { return 2 }
if {$char >= 65108 && $char <= 65111 } { return 2 }
if {$char == 65112} { return 2 }
if {$char == 65113} { return 2 }
if {$char == 65114} { return 2 }
if {$char == 65115} { return 2 }
if {$char == 65116} { return 2 }
if {$char == 65117} { return 2 }
if {$char == 65118} { return 2 }
if {$char >= 65119 && $char <= 65121 } { return 2 }
if {$char == 65122} { return 2 }
if {$char == 65123} { return 2 }
if {$char >= 65124 && $char <= 65126 } { return 2 }
if {$char == 65128} { return 2 }
if {$char == 65129} { return 2 }
if {$char >= 65130 && $char <= 65131 } { return 2 }
if {$char >= 65281 && $char <= 65283 } { return 2 }
if {$char == 65284} { return 2 }
if {$char >= 65285 && $char <= 65287 } { return 2 }
if {$char == 65288} { return 2 }
if {$char == 65289} { return 2 }
if {$char == 65290} { return 2 }
if {$char == 65291} { return 2 }
if {$char == 65292} { return 2 }
if {$char == 65293} { return 2 }
if {$char >= 65294 && $char <= 65295 } { return 2 }
if {$char >= 65296 && $char <= 65305 } { return 2 }
if {$char >= 65306 && $char <= 65307 } { return 2 }
if {$char >= 65308 && $char <= 65310 } { return 2 }
if {$char >= 65311 && $char <= 65312 } { return 2 }
if {$char >= 65313 && $char <= 65338 } { return 2 }
if {$char == 65339} { return 2 }
if {$char == 65340} { return 2 }
if {$char == 65341} { return 2 }
if {$char == 65342} { return 2 }
if {$char == 65343} { return 2 }
if {$char == 65344} { return 2 }
if {$char >= 65345 && $char <= 65370 } { return 2 }
if {$char == 65371} { return 2 }
if {$char == 65372} { return 2 }
if {$char == 65373} { return 2 }
if {$char == 65374} { return 2 }
if {$char == 65375} { return 2 }
if {$char == 65376} { return 2 }
if {$char >= 65504 && $char <= 65505 } { return 2 }
if {$char == 65506} { return 2 }
if {$char == 65507} { return 2 }
if {$char == 65508} { return 2 }
if {$char >= 65509 && $char <= 65510 } { return 2 }
if {$char >= 94176 && $char <= 94177 } { return 2 }
if {$char >= 94208 && $char <= 100337 } { return 2 }
if {$char >= 100352 && $char <= 101106 } { return 2 }
if {$char >= 110592 && $char <= 110847 } { return 2 }
if {$char >= 110848 && $char <= 110878 } { return 2 }
if {$char >= 110960 && $char <= 111355 } { return 2 }
if {$char == 126980} { return 2 }
if {$char == 127183} { return 2 }
if {$char == 127374} { return 2 }
if {$char >= 127377 && $char <= 127386 } { return 2 }
if {$char >= 127488 && $char <= 127490 } { return 2 }
if {$char >= 127504 && $char <= 127547 } { return 2 }
if {$char >= 127552 && $char <= 127560 } { return 2 }
if {$char >= 127568 && $char <= 127569 } { return 2 }
if {$char >= 127584 && $char <= 127589 } { return 2 }
if {$char >= 127744 && $char <= 127776 } { return 2 }
if {$char >= 127789 && $char <= 127797 } { return 2 }
if {$char >= 127799 && $char <= 127868 } { return 2 }
if {$char >= 127870 && $char <= 127891 } { return 2 }
if {$char >= 127904 && $char <= 127946 } { return 2 }
if {$char >= 127951 && $char <= 127955 } { return 2 }
if {$char >= 127968 && $char <= 127984 } { return 2 }
if {$char == 127988} { return 2 }
if {$char >= 127992 && $char <= 127994 } { return 2 }
if {$char >= 127995 && $char <= 127999 } { return 2 }
if {$char >= 128000 && $char <= 128062 } { return 2 }
if {$char == 128064} { return 2 }
if {$char >= 128066 && $char <= 128252 } { return 2 }
if {$char >= 128255 && $char <= 128317 } { return 2 }
if {$char >= 128331 && $char <= 128334 } { return 2 }
if {$char >= 128336 && $char <= 128359 } { return 2 }
if {$char == 128378} { return 2 }
if {$char >= 128405 && $char <= 128406 } { return 2 }
if {$char == 128420} { return 2 }
if {$char >= 128507 && $char <= 128511 } { return 2 }
if {$char >= 128512 && $char <= 128591 } { return 2 }
if {$char >= 128640 && $char <= 128709 } { return 2 }
if {$char == 128716} { return 2 }
if {$char >= 128720 && $char <= 128722 } { return 2 }
if {$char >= 128747 && $char <= 128748 } { return 2 }
if {$char >= 128756 && $char <= 128761 } { return 2 }
if {$char >= 129296 && $char <= 129342 } { return 2 }
if {$char >= 129344 && $char <= 129392 } { return 2 }
if {$char >= 129395 && $char <= 129398 } { return 2 }
if {$char == 129402} { return 2 }
if {$char >= 129404 && $char <= 129442 } { return 2 }
if {$char >= 129456 && $char <= 129465 } { return 2 }
if {$char >= 129472 && $char <= 129474 } { return 2 }
if {$char >= 129488 && $char <= 129535 } { return 2 }
if {$char >= 131072 && $char <= 173782 } { return 2 }
if {$char >= 173783 && $char <= 173823 } { return 2 }
if {$char >= 173824 && $char <= 177972 } { return 2 }
if {$char >= 177973 && $char <= 177983 } { return 2 }
if {$char >= 177984 && $char <= 178205 } { return 2 }
if {$char >= 178206 && $char <= 178207 } { return 2 }
if {$char >= 178208 && $char <= 183969 } { return 2 }
if {$char >= 183970 && $char <= 183983 } { return 2 }
if {$char >= 183984 && $char <= 191456 } { return 2 }
if {$char >= 191457 && $char <= 194559 } { return 2 }
if {$char >= 194560 && $char <= 195101 } { return 2 }
if {$char >= 195102 && $char <= 195103 } { return 2 }
if {$char >= 195104 && $char <= 196605 } { return 2 }
if {$char >= 196608 && $char <= 262141 } { return 2 }
return 1
}
proc ::textutil::wcswidth {string} {
set width 0
set len [string length $string]
foreach c [split $string {}] {
scan $c %c char
set n [::textutil::wcswidth_char $char]
if {$n < 0} {
return -1
}
incr width $n
}
return $width
}

16
src/mixtemplates/layouts/basic/src/make.tcl

@ -378,7 +378,7 @@ if {$::punkmake::command eq "bootsupport"} {
set project_layouts [glob -nocomplain -dir $project_layout_base -type d -tail *] set project_layouts [glob -nocomplain -dir $project_layout_base -type d -tail *]
foreach layoutname $project_layouts { foreach layoutname $project_layouts {
if {[file exists [file join $project_layout_base $layoutname/src/bootsupport]]} { if {[file exists [file join $project_layout_base $layoutname/src/bootsupport]]} {
set unpublish [list\ set antipaths [list\
README.md\ README.md\
] ]
set sourcemodules $projectroot/src/bootsupport/modules set sourcemodules $projectroot/src/bootsupport/modules
@ -386,7 +386,7 @@ if {$::punkmake::command eq "bootsupport"} {
file mkdir $targetroot file mkdir $targetroot
puts stdout "BOOTSUPPORT layouts/$layoutname: copying from $sourcemodules to $targetroot (if source file changed)" puts stdout "BOOTSUPPORT layouts/$layoutname: copying from $sourcemodules to $targetroot (if source file changed)"
set resultdict [punkcheck::install $sourcemodules $targetroot -overwrite installedsourcechanged-targets -unpublish_paths $unpublish] set resultdict [punkcheck::install $sourcemodules $targetroot -overwrite installedsourcechanged-targets -antiglob_paths $antipaths]
puts stdout [punkcheck::summarize_install_resultdict $resultdict] puts stdout [punkcheck::summarize_install_resultdict $resultdict]
flush stdout flush stdout
} }
@ -420,17 +420,17 @@ file mkdir $target_modules_base
#external libs and modules first - and any supporting files - no 'building' required #external libs and modules first - and any supporting files - no 'building' required
if {[file exists $sourcefolder/vendorlib]} { if {[file exists $sourcefolder/vendorlib]} {
#unpublish README.md from source folder - but only the root one #exclude README.md from source folder - but only the root one
#-unpublish_paths takes relative patterns e.g #-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep. # */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep. # */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root) # **/test.txt will match at any level below the root (but not in the root)
set unpublish [list\ set antipaths [list\
README.md\ README.md\
] ]
puts stdout "VENDORLIB: copying from $sourcefolder/vendorlib to $projectroot/lib (if source file changed)" puts stdout "VENDORLIB: copying from $sourcefolder/vendorlib to $projectroot/lib (if source file changed)"
set resultdict [punkcheck::install $sourcefolder/vendorlib $projectroot/lib -overwrite installedsourcechanged-targets -unpublish_paths $unpublish] set resultdict [punkcheck::install $sourcefolder/vendorlib $projectroot/lib -overwrite installedsourcechanged-targets -antiglob_paths $antipaths]
puts stdout [punkcheck::summarize_install_resultdict $resultdict] puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else { } else {
@ -440,7 +440,7 @@ if {[file exists $sourcefolder/vendorlib]} {
if {[file exists $sourcefolder/vendormodules]} { if {[file exists $sourcefolder/vendormodules]} {
#install .tm *and other files* #install .tm *and other files*
puts stdout "VENDORMODULES: copying from $sourcefolder/vendormodules to $target_modules_base (if source file changed)" puts stdout "VENDORMODULES: copying from $sourcefolder/vendormodules to $target_modules_base (if source file changed)"
set resultdict [punkcheck::install $sourcefolder/vendormodules $target_modules_base -installer make.tcl -overwrite installedsourcechanged-targets -unpublish_paths {README.md}] set resultdict [punkcheck::install $sourcefolder/vendormodules $target_modules_base -installer make.tcl -overwrite installedsourcechanged-targets -antiglob_paths {README.md}]
puts stdout [punkcheck::summarize_install_resultdict $resultdict] puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else { } else {
puts stderr "VENDORMODULES: No src/vendormodules folder found." puts stderr "VENDORMODULES: No src/vendormodules folder found."
@ -526,7 +526,7 @@ foreach src_module_dir $source_module_folderlist {
set overwrite "installedsourcechanged-targets" set overwrite "installedsourcechanged-targets"
#set overwrite "ALL-TARGETS" #set overwrite "ALL-TARGETS"
puts stdout "MODULEFOLDER non_tm_files $src_module_dir - copying to $target_modules_base (if source file changed)" puts stdout "MODULEFOLDER non_tm_files $src_module_dir - copying to $target_modules_base (if source file changed)"
set resultdict [punkcheck::install_non_tm_files $src_module_dir $target_modules_base -installer make.tcl -overwrite $overwrite -unpublish_paths {README.md}] set resultdict [punkcheck::install_non_tm_files $src_module_dir $target_modules_base -installer make.tcl -overwrite $overwrite -antiglob_paths {README.md}]
puts stdout [punkcheck::summarize_install_resultdict $resultdict] puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} }

18
src/modules/punk-0.1.tm

@ -5172,6 +5172,24 @@ namespace eval punk {
return [dirfiles_dict_as_lines -stripbase 1 $contents] return [dirfiles_dict_as_lines -stripbase 1 $contents]
} }
#basic (glob based) list of filenames matching tailglob - recursive - no natsorting
#todo - implement treefiles which acts like dirfiles but allows path globbing in the same way as punk::ns::ns/
#then review if treefiles can replace dirfiles or if both should exist (dirfiles can have literal glob chars in path segments - but that is a rare usecase)
proc treefilenames {basepath {tailglob *}} {
set files [list]
if {![file isdirectory $basepath]} {
return $files
}
#todo - account for vfs where matched path could appear to be a directory but is mounted so could be a desired match?
set dirfiles [glob -nocomplain -dir $basepath -type f $tailglob]
lappend files {*}$dirfiles
set dirdirs [glob -nocomplain -dir $basepath -type d *]
foreach dir $dirdirs {
lappend files {*}[treefilenames $dir $tailglob]
}
return $files
}
#dirfiles dirfiles_dict always deliberately return absolute *unnormalized* path #dirfiles dirfiles_dict always deliberately return absolute *unnormalized* path
#e.g when cwd is c:/repo/jn/shellspy dirfiles ../../ will return something like: #e.g when cwd is c:/repo/jn/shellspy dirfiles ../../ will return something like:
# c:/repo/jn/shellspy/../../blah # c:/repo/jn/shellspy/../../blah

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

@ -14,20 +14,35 @@
# @@ Meta End # @@ Meta End
#*** !doctools
#[manpage_begin punk::cap 0 999999.0a1.0]
#[copyright "2023 JMNoble - BSD licensed"]
#[titledesc {capability provider and handler plugin system}]
#[moddesc {punk capabilities plugin system}]
#[require punk::cap]
#[description]
#[section Overview]
#[para]punk::cap provides management of named capabilities and the provider packages and handler packages that implement a pluggable capability.
#[subsection Concepts]
#[para]A [term capability] may be something like providing a folder of files, or just a data dictionary, and/or an API
#
#[para][term {capability handler}] - a package/namespace which may provide validation and standardised ways of looking up provider data
# registered (or not) using register_capabilityname <capname> <capnamespace>
#
#[para][term {capability provider}] - a package which registers as providing one or more capablities.
#[para]registered using register_package <pkg> <capabilitylist>
#the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability
#A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets.
#*** !doctools
#[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Requirements ## Requirements
##e.g package require frobz ##e.g package require frobz
package require oolib
#concepts:
# A capability may be something like providing a folder of files, or just a data dictionary, and/or an API
#
# capability handler - a package/namespace which may provide validation and standardised ways of looking up provider data
# registered (or not) using register_capabilityname <capname> <capnamespace>
# capability provider - a package which registers as providing one or more capablities.
# registered using register_package <pkg> <capabilitylist>
# the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability
# A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets.
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
@ -35,67 +50,179 @@ namespace eval punk::cap {
variable pkgcapsdeclared [dict create] variable pkgcapsdeclared [dict create]
variable pkgcapsaccepted [dict create] variable pkgcapsaccepted [dict create]
variable caps [dict create] variable caps [dict create]
if {[info commands [namespace current]::interface_caphandler.registry] eq ""} { namespace eval class {
oo::class create [namespace current]::interface_caphandler.registry { if {[info commands [namespace current]::interface_caphandler.registry] eq ""} {
method pkg_register {pkg capname capdict fullcapabilitylist} { #*** !doctools
#handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid #[subsection {Namespace punk::cap::class}]
#overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes. #[para] class definitions
return 1 ;#default to permit #[list_begin itemized] [comment {- punk::cap::class groupings -}]
} # [item]
method pkg_unregister {pkg} { # [para] [emph {handler_classes}]
return ;#unregistration return is ignored - review # [list_begin enumerated]
}
} oo::class create [namespace current]::interface_caphandler.registry {
#*** !doctools
oo::class create [namespace current]::interface_capprovider.registration { #[enum] [emph {CLASS interface_caphandler.registry}]
method get_declarations {} { #[list_begin definitions]
error "interface_capprovider.registration not implemented by provider" method pkg_register {pkg capname capdict fullcapabilitylist} {
} #*** !doctools
} #[call class::[class interface_caphandler.registry] [method pkg_register] [arg pkg] [arg capname] [arg capdict] [arg fullcapabilitylist]]
oo::class create [namespace current]::interface_capprovider.provider { #handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid
variable provider_pkg #overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes.
variable registrationobj return 1 ;#default to permit
constructor {providerpkg} {
variable provider_pkg
if {$providerpkg in [list "" "::"]} {
error "interface_capprovider.provider constructor error. Invalid provider '$providerpkg'"
} }
if {![namespace exists ::$providerpkg]} { method pkg_unregister {pkg} {
error "interface_capprovider.provider constructor error. Invalid provider '$providerpkg' - matching namespace not found" #*** !doctools
#[call class::[class interface_caphandler.registry] [method pkg_unregister] [arg pkg]]
return ;#unregistration return is ignored - review
} }
#*** !doctools
#[list_end]
}
set registrationobj ::${providerpkg}::capsystem::capprovider.registration oo::class create [namespace current]::interface_caphandler.sysapi {
if {[info commands $registrationobj] eq ""} { #*** !doctools
error "capprovider.provider constructor error. Missing capprovider.registration interface at '$obj' (command not found) interface_capprovider.regstration instantiation must precede interface_capprovider.provider" #[enum] [emph {CLASS interface_caphandler.sysapi}]
} #[list_begin definitions]
set provider_pkg [string trim $providerpkg ""]
#*** !doctools
#[list_end]
} }
method register {{capabilityname_glob *}} {
variable provider_pkg #*** !doctools
set all_decls [$registrationobj get_declarations] # [list_end] [comment {- end enumeration handler classes -}]
set register_decls [lsearch -all -inline -index 0 $all_decls $capabilityname_glob]
punk::cap::register_package $provider_pkg $register_decls #*** !doctools
# [item]
# [para] [emph {provider_classes}]
# [list_begin enumerated]
#Provider classes
oo::class create [namespace current]::interface_capprovider.registration {
#*** !doctools
# [enum] [emph {CLASS interface_cappprovider.registration}]
# Your provider package will need to instantiate this object under a sub-namespace called [namespace capsystem] within your package namespace.
# [para]If your package namespace is mypackages::providerpkg then the object command would be at mypackages::providerpkg::capsystem::capprovider.registration
# [para]Example code for your provider package to evaluate within its namespace:
# [example {
#namespace eval capsystem {
# if {[info commands capprovider.registration] eq ""} {
# punk::cap::class::interface_capprovider.registration create capprovider.registration
# oo::objdefine capprovider.registration {
# method get_declarations {} {
# set decls [list]
# lappend decls [list punk.templates {relpath ../templates}]
# lappend decls [list another_capability_name {somekey blah key2 etc}]
# return $decls
# }
# }
# }
#}
#}]
#[para] The above example declares that your package can be registered as a provider for the capabilities named 'punk.templates' and 'another_capability_name'
# [list_begin definitions]
method get_declarations {} {
#***
#[call class::[class interface_capprovider.registration] [method get_declarations]]
#[para] This method must be overridden by your provider using oo::objdefine cappprovider.registration as in the example above.
# There must be at least one 2-element list in the result for the provider to be registerable.
#[para]The first element of the list is the capabilityname - which can be custom to your provider/handler packages - or a well-known name that other authors may use/implement.
#[para]The second element is a dictionary of keys specific to the capability being implemented. It may be empty if the any potential capability handlers for the named capability don't require registration data.
error "interface_capprovider.registration not implemented by provider"
}
#*** !doctools
# [list_end]
} }
method capabilities {} {
oo::class create [namespace current]::interface_capprovider.provider {
#*** !doctools
# [enum] [emph {CLASS interface_capprovider.provider}]
# [para] Your provider package will need to instantiate this directly under it's own namespace with the command name of [emph {provider}]
# [example {
# namespace eval mypackages::providerpkg {
# punk::cap::class::interface_capprovider.provider create provider mypackages::providerpkg
# }
# }]
# [list_begin definitions]
variable provider_pkg variable provider_pkg
variable registrationobj variable registrationobj
constructor {providerpkg} {
#*** !doctools
#[call class::[class interface_capprovider.provider] [method constructor] [arg providerpkg]]
variable provider_pkg
if {$providerpkg in [list "" "::"]} {
error "interface_capprovider.provider constructor error. Invalid provider '$providerpkg'"
}
if {![namespace exists ::$providerpkg]} {
error "interface_capprovider.provider constructor error. Invalid provider '$providerpkg' - matching namespace not found"
}
set capabilities [list] set registrationobj ::${providerpkg}::capsystem::capprovider.registration
set decls [$registrationobj get_declarations] if {[info commands $registrationobj] eq ""} {
foreach decl $decls { error "capprovider.provider constructor error. Missing capprovider.registration interface at '$obj' (command not found) interface_capprovider.regstration instantiation must precede interface_capprovider.provider"
lassign $decl capname capdict
if {$capname ni $capabilities} {
lappend capabilities $capname
} }
set provider_pkg [string trim $providerpkg ""]
}
method register {{capabilityname_glob *}} {
#*** !doctools
#[comment {- -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---}]
#[call class::[class interface_capprovider.provider] [method register] [opt capabilityname_glob]]
#
#[para]This is the mechanism by which a user of your provider package will register your package as a provider of the capability named.
#
#[para]A user of your provider may elect to register all your declared capabilities:
#[example {
# package require mypackages::providerpkg
# mypackages::providerpkg::provider register *
#}]
#[para] Or a specific capability may be registered:
#[example {
# package require mypackages::providerpkg
# mypackages::providerpkg::provider register another_capability_name
#}]
#
variable provider_pkg
set all_decls [$registrationobj get_declarations]
set register_decls [lsearch -all -inline -index 0 $all_decls $capabilityname_glob]
punk::cap::register_package $provider_pkg $register_decls
}
method capabilities {} {
#*** !doctools
#[comment {- -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---}]
#[call class::[class interface_capprovider.provider] [method capabilities]]
#[para] return a list of capabilities supported by this provider package
variable provider_pkg
variable registrationobj
set capabilities [list]
set decls [$registrationobj get_declarations]
foreach decl $decls {
lassign $decl capname capdict
if {$capname ni $capabilities} {
lappend capabilities $capname
}
}
return $capabilities
} }
return $capname #*** !doctools
# [list_end] [comment {- end class definitions -}]
} }
#*** !doctools
# [list_end] [comment {- end enumeration provider_classes }]
#[list_end] [comment {- end itemized list punk::cap::class groupings -}]
} }
} } ;# end namespace class
#Not all capabilities have to be registered.
#A package registering as a provider using register_package can include capabilitynames in it's capabilitylist which have no associated capnamespace (handler). #*** !doctools
#[subsection {Namespace punk::cap}]
#[para] Main punk::cap API for client programs interested in using capability handler packages and associated (registered) provider packages
#[list_begin definitions]
#Not all capability names have to be registered.
#A package registering as a provider using register_package can include capabilitynames in it's capabilitylist which have no associated handler.
#such unregistered capabilitynames may be used just to flag something, or have datamembers significant to callers cooperatively interested in that capname. #such unregistered capabilitynames may be used just to flag something, or have datamembers significant to callers cooperatively interested in that capname.
#we allow registering a capability with an empty handler (capnamespace) - but this means another handler could be registered later. #we allow registering a capability with an empty handler (capnamespace) - but this means another handler could be registered later.
proc register_capabilityname {capname capnamespace} { proc register_capabilityname {capname capnamespace} {
@ -111,7 +238,7 @@ namespace eval punk::cap {
#allow register of existing capname iff there is no current handler #allow register of existing capname iff there is no current handler
#as handlers can be used to validate during provider registration - ideally handlers should be registered before any pkgs call register_package #as handlers can be used to validate during provider registration - ideally handlers should be registered before any pkgs call register_package
#we allow loading a handler later though - but will need to validate existing data from pkgs that have already registered as providers #we allow loading a handler later though - but will need to validate existing data from pkgs that have already registered as providers
if {[set hdlr [get_handler $capname]] ne ""} { if {[set hdlr [capability_get_handler $capname]] ne ""} {
error "register_capabilityname cannot register capability:$capname with handler:$capnamespace. There is already a registered handler:$hdlr" error "register_capabilityname cannot register capability:$capname with handler:$capnamespace. There is already a registered handler:$hdlr"
} }
#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. #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.
@ -121,7 +248,7 @@ namespace eval punk::cap {
} }
if {[llength [set providers [dict get $caps $capname providers]]]} { if {[llength [set providers [dict get $caps $capname providers]]]} {
#some provider(s) were in place before the handler was registered #some provider(s) were in place before the handler was registered
if {[set capreg [get_caphandler_registry $capname]] ne ""} { if {[set capreg [punk::cap::capsystem::get_caphandler_registry $capname]] ne ""} {
foreach pkg $providers { foreach pkg $providers {
set fullcapabilitylist [dict get $pkgcapsdeclared $pkg] set fullcapabilitylist [dict get $pkgcapsdeclared $pkg]
foreach capspec $fullcapabilitylist { foreach capspec $fullcapabilitylist {
@ -163,47 +290,38 @@ namespace eval punk::cap {
} }
} }
proc exists {capname} { proc capability_exists {capname} {
#*** !doctools
# [call [fun capability_exists] [arg capname]]
# Return a boolean indicating if the named capability exists (0|1)
variable caps variable caps
return [dict exists $caps $capname] return [dict exists $caps $capname]
} }
proc has_handler {capname} { proc capability_has_handler {capname} {
#*** !doctools
# [call [fun capability_has_handler] [arg capname]]
#Return a boolean indicating if the named capability has a handler package installed (0|1)
variable caps variable caps
return [expr {[dict exists $caps $capname handler] && [dict get $caps $capname handler] ne ""}] return [expr {[dict exists $caps $capname handler] && [dict get $caps $capname handler] ne ""}]
} }
proc get_handler {capname} { proc capability_get_handler {capname} {
#*** !doctools
# [call [fun capability_get_handler] [arg capname]]
#Return the base namespace of the active handler package for the named capability.
#[para] The base namespace for a handler will always be the package name, but prefixed with ::
variable caps variable caps
if {[dict exists $caps $capname]} { if {[dict exists $caps $capname]} {
return [dict get $caps $capname handler] return [dict get $caps $capname handler]
} }
return "" return ""
} }
#dispatch
#proc call_handler {capname args} {
# if {[set handler [get_handler $capname]] eq ""} {
# error "punk::cap::call_handler $capname $args - no handler registered for capability $capname"
# }
# ${handler}::[lindex $args 0] {*}[lrange $args 1 end]
#}
proc call_handler {capname args} { proc call_handler {capname args} {
if {[set handler [get_handler $capname]] eq ""} { if {[set handler [capability_get_handler $capname]] eq ""} {
error "punk::cap::call_handler $capname $args - no handler registered for capability $capname" error "punk::cap::call_handler $capname $args - no handler registered for capability $capname"
} }
set obj ${handler}::$capname set obj ${handler}::api_$capname
$obj [lindex $args 0] {*}[lrange $args 1 end] $obj [lindex $args 0] {*}[lrange $args 1 end]
} }
proc get_caphandler_registry {capname} {
set ns [get_handler $capname]::capsystem
if {[namespace exists ${ns}]} {
if {[info command ${ns}::caphandler.registry] ne ""} {
if {[info object isa object ${ns}::caphandler.registry]} {
return ${ns}::caphandler.registry
}
}
}
return ""
}
proc get_providers {capname} { proc get_providers {capname} {
variable caps variable caps
if {[dict exists $caps $capname]} { if {[dict exists $caps $capname]} {
@ -214,10 +332,21 @@ namespace eval punk::cap {
#register package with arbitrary capnames from capabilitylist #register package with arbitrary capnames from capabilitylist
#The registered pkg is a module that provides some service to that capname. Possibly just data members, that the capability will use. #The registered pkg is a module that provides some service to that capname. Possibly just data members, that the capability will use.
proc register_package {pkg capabilitylist} { proc register_package {pkg capabilitylist args} {
variable pkgcapsdeclared variable pkgcapsdeclared
variable pkgcapsaccepted variable pkgcapsaccepted
variable caps variable caps
set defaults [dict create\
-nowarnings false
]
dict for {k v} $args {
if {$k ni $defaults} {
error "Unrecognized option $k. Known options [dict keys $defaults]"
}
}
set opts [dict merge $defaults $args]
set warnings [expr {! [dict get $opts -nowarnings]}]
if {[string match ::* $pkg]} { if {[string match ::* $pkg]} {
set pkg [string range $pkg 2 end] set pkg [string range $pkg 2 end]
} }
@ -226,11 +355,23 @@ namespace eval punk::cap {
} else { } else {
set pkg_already_accepted [list] set pkg_already_accepted [list]
} }
package require $pkg
set providerapi ::${pkg}::provider
if {[info commands $providerapi] eq ""} {
error "register_package error. pkg '$pkg' doesn't seem to be a punk::cap capability provider (no object found at $providerapi)"
}
set defined_caps [$providerapi capabilities]
#for each capability #for each capability
# - ensure 1st element is a single word # - ensure 1st element is a single word
# - ensure that if 2nd element (capdict) is present - it is dict shaped # - ensure that if 2nd element (capdict) is present - it is dict shaped
foreach capspec $capabilitylist { foreach capspec $capabilitylist {
lassign $capspec capname capdict lassign $capspec capname capdict
if {$warnings} {
if {$capname ni $defined_caps} {
puts stderr "WARNING: pkg '$pkg' doesn't declare support for capability '$capname'."
}
}
if {[llength $capname] !=1} { if {[llength $capname] !=1} {
error "register_package error. pkg: '$pkg' An entry in the capability list doesn't appear to have a single-word name. Problematic entry:'$capspec'" error "register_package error. pkg: '$pkg' An entry in the capability list doesn't appear to have a single-word name. Problematic entry:'$capspec'"
} }
@ -239,7 +380,9 @@ namespace eval punk::cap {
} }
if {$capspec in $pkg_already_accepted} { if {$capspec in $pkg_already_accepted} {
#review - multiple handlers? if so - will need to record which handler(s) accepted the capspec #review - multiple handlers? if so - will need to record which handler(s) accepted the capspec
puts stderr "register_package pkg $pkg already has capspec marked as accepted: $capspec" if {$warnings} {
puts stderr "WARNING: register_package pkg $pkg already has capspec marked as accepted: $capspec"
}
continue continue
} }
if {[dict exists $caps $capname]} { if {[dict exists $caps $capname]} {
@ -250,7 +393,7 @@ namespace eval punk::cap {
} }
#todo - if there's a caphandler - call it's init/validation callback for the pkg #todo - if there's a caphandler - call it's init/validation callback for the pkg
set do_register 1 ;#default assumption unless vetoed by handler set do_register 1 ;#default assumption unless vetoed by handler
if {[set capreg [get_caphandler_registry $capname]] ne ""} { if {[set capreg [punk::cap::capsystem::get_caphandler_registry $capname]] ne ""} {
#Note that the interface_caphandler.registry instance must be able to handle multiple calls for same pkg #Note that the interface_caphandler.registry instance must be able to handle multiple calls for same pkg
set do_register [$capreg pkg_register $pkg $capname $capdict $capabilitylist] set do_register [$capreg pkg_register $pkg $capname $capdict $capabilitylist]
} }
@ -294,13 +437,13 @@ namespace eval punk::cap {
set pkglist [dict get $cap_info providers] set pkglist [dict get $cap_info providers]
set posn [lsearch $pkglist $pkg] set posn [lsearch $pkglist $pkg]
if {$posn >= 0} { if {$posn >= 0} {
if {[set capreg [get_caphandler_registry $capname]] ne ""} { if {[set capreg [punk::cap::capsystem::get_caphandler_registry $capname]] ne ""} {
#review #review
# it seems not useful to allow the callback to block this unregister action # it seems not useful to allow the callback to block this unregister action
#the pkg may have multiple datasets for each capname so callback will only be called for first dataset we encounter #the pkg may have multiple datasets for each capname so callback will only be called for first dataset we encounter
#vetoing unregister would make this more complex for no particular advantage #vetoing unregister would make this more complex for no particular advantage
#if per dataset deregistration required this should probably be a separate thing #if per dataset deregistration required this should probably be a separate thing
$capreg pkg_unregister $pkg $capreg pkg_unregister $pkg $capname
} }
set pkglist [lreplace $pkglist $posn $posn] set pkglist [lreplace $pkglist $posn $posn]
dict set caps $capname providers $pkglist dict set caps $capname providers $pkglist
@ -311,73 +454,6 @@ namespace eval punk::cap {
} }
} }
#review promote/demote doesn't always make a lot of sense .. should possibly be per cap for multicap pkgs
#The idea is to provide a crude way to preference/depreference packages independently of order the packages were loaded
#e.g a caller or cap-handler can ascribe some meaning to the order of the 'providers' key returned from punk::cap::capabilities <capname>
#The order of providers will be the order the packages were loaded & registered
#the naming: "promote vs demote" operates on a latest-package-in-list has higher preference assumption (matching last pkg loaded)
#Each capability handler could implement specific preferencing methods if finer control needed.
#In some cases the preference/loading order may be inapplicable/irrelevant to a particular capability anyway.
#As this is just a basic mechanism, which can't support independent per-cap preferencing for multi-cap packages -
# it only allows putting the pkgs to the head or tail of the lists.
#Whether particular caps or users of caps do anything with this ordering is dependent on the cap-handler and/or calling code.
proc promote_package {pkg} {
variable pkgcapsdeclared
variable caps
if {[string match ::* $pkg]} {
set pkg [string range $pkg 2 end]
}
if {![dict exists $pkgcapsdeclared $pkg]} {
error "punk::cap::promote_package error pkg'$pkg' not registered. Use register_package \$pkg first"
}
if {[dict size $pkgcapsdeclared] > 1} {
set pkginfo [dict get $pkgcapsdeclared $pkg]
#remove and re-add at end of dict
dict unset pkgcapsdeclared $pkg
dict set pkgcapsdeclared $pkg $pkginfo
dict for {cap cap_info} $caps {
set cap_pkgs [dict get $cap_info providers]
if {$pkg in $cap_pkgs} {
set posn [lsearch $cap_pkgs $pkg]
if {$posn >=0} {
#rewrite package list with pkg at tail of list for this capability
set cap_pkgs [lreplace $cap_pkgs $posn $posn]
lappend cap_pkgs $pkg
dict set caps $cap providers $cap_pkgs
}
}
}
}
}
proc demote_package {pkg} {
variable pkgcapsdeclared
variable caps
if {[string match ::* $pkg]} {
set pkg [string range $pkg 2 end]
}
if {![dict exists $pkgcapsdeclared $pkg]} {
error "punk::cap::promote_package error pkg'$pkg' not registered. Use register_package \$pkg first"
}
if {[dict size $pkgcapsdeclared] > 1} {
set pkginfo [dict get $pkgcapsdeclared $pkg]
#remove and re-add at start of dict
dict unset pkgcapsdeclared $pkg
dict set pkgcapsdeclared $pkg $pkginfo
set pkgcapsdeclared [dict merge [dict create $pkg $pkginfo] $pkgcapsdeclared]
dict for {cap cap_info} $caps {
set cap_pkgs [dict get $cap_info providers]
if {$pkg in $cap_pkgs} {
set posn [lsearch $cap_pkgs $pkg]
if {$posn >=0} {
#rewrite package list with pkg at head of list for this capability
set cap_pkgs [lreplace $cap_pkgs $posn $posn]
set cap_pkgs [list $pkg {*}$cap_pkgs]
dict set caps $cap providers $cap_pkgs
}
}
}
}
}
proc pkgcap {pkg} { proc pkgcap {pkg} {
variable pkgcapsdeclared variable pkgcapsdeclared
variable pkgcapsaccepted variable pkgcapsaccepted
@ -442,19 +518,122 @@ namespace eval punk::cap {
} }
return $cap_list return $cap_list
} }
#*** !doctools
#[list_end] [comment {- end definitions for namespace punk::cap -}]
namespace eval advanced {
#*** !doctools
#[subsection {Namespace punk::cap::advanced}]
#[para] punk::cap::advanced API. Functions here are generally not the preferred way to interact with punk::cap.
#[para] In some cases they may allow interaction in less safe ways or may allow use of features that are unavailable in the base namespace.
#[para] Some functions are here because they are only marginally or rarely useful, and they are here to keep the base API simple.
#[list_begin definitions]
proc promote_provider {pkg} {
#*** !doctools
# [call advanced::[fun promote_provider] [arg pkg]]
#[para]Move the named provider package to the preferred end of the list (tail).
#[para]The active handler may or may not utilise this for preferencing. See documentation for the specific handler package to confirm.
#[para]
#[para] promote/demote doesn't always make a lot of sense .. should preferably be configurable per capapbility for multicap provider pkgs
#[para]The idea is to provide a crude way to preference/depreference packages independently of order the packages were loaded
#e.g a caller or cap-handler can ascribe some meaning to the order of the 'providers' key returned from punk::cap::capabilities <capname>
#[para]The order of providers will be the order the packages were loaded & registered
#[para]the naming: "promote vs demote" operates on a latest-package-in-list has higher preference assumption (matching last pkg loaded)
#[para]Each capability handler could and should implement specific preferencing methods within its own API if finer control needed.
#In some cases the preference/loading order may be inapplicable/irrelevant to a particular capability anyway.
#[para]As this is just a basic mechanism, which can't support independent per-cap preferencing for multi-cap packages -
# it only allows putting the pkgs to the head or tail of the lists.
#[para]Whether particular caps or users of caps do anything with this ordering is dependent on the cap-handler and/or calling code.
variable pkgcapsdeclared
variable caps
if {[string match ::* $pkg]} {
set pkg [string range $pkg 2 end]
}
if {![dict exists $pkgcapsdeclared $pkg]} {
error "punk::cap::promote_package error pkg'$pkg' not registered. Use register_package \$pkg first"
}
if {[dict size $pkgcapsdeclared] > 1} {
set pkginfo [dict get $pkgcapsdeclared $pkg]
#remove and re-add at end of dict
dict unset pkgcapsdeclared $pkg
dict set pkgcapsdeclared $pkg $pkginfo
dict for {cap cap_info} $caps {
set cap_pkgs [dict get $cap_info providers]
if {$pkg in $cap_pkgs} {
set posn [lsearch $cap_pkgs $pkg]
if {$posn >=0} {
#rewrite package list with pkg at tail of list for this capability
set cap_pkgs [lreplace $cap_pkgs $posn $posn]
lappend cap_pkgs $pkg
dict set caps $cap providers $cap_pkgs
}
}
}
}
}
proc demote_provider {pkg} {
#*** !doctools
# [call advanced::[fun demote_provider] [arg pkg]]
#[para]Move the named provider package to the preferred end of the list (tail).
#[para]The active handler may or may not utilise this for preferencing. See documentation for the specific handler package to confirm.
variable pkgcapsdeclared
variable caps
if {[string match ::* $pkg]} {
set pkg [string range $pkg 2 end]
}
if {![dict exists $pkgcapsdeclared $pkg]} {
error "punk::cap::promote_package error pkg'$pkg' not registered. Use register_package \$pkg first"
}
if {[dict size $pkgcapsdeclared] > 1} {
set pkginfo [dict get $pkgcapsdeclared $pkg]
#remove and re-add at start of dict
dict unset pkgcapsdeclared $pkg
dict set pkgcapsdeclared $pkg $pkginfo
set pkgcapsdeclared [dict merge [dict create $pkg $pkginfo] $pkgcapsdeclared]
dict for {cap cap_info} $caps {
set cap_pkgs [dict get $cap_info providers]
if {$pkg in $cap_pkgs} {
set posn [lsearch $cap_pkgs $pkg]
if {$posn >=0} {
#rewrite package list with pkg at head of list for this capability
set cap_pkgs [lreplace $cap_pkgs $posn $posn]
set cap_pkgs [list $pkg {*}$cap_pkgs]
dict set caps $cap providers $cap_pkgs
}
}
}
}
}
} #*** !doctools
#[list_end]
}
#*** !doctools
#[section Internal]
namespace eval capsystem {
#*** !doctools
#[subsection {Namespace punk::cap::capsystem}]
#[para] Internal functions used to communicate between punk::cap and capability handlers
#[list_begin definitions]
proc get_caphandler_registry {capname} {
set ns [::punk::cap::capability_get_handler $capname]::capsystem
if {[namespace exists ${ns}]} {
if {[info command ${ns}::caphandler.registry] ne ""} {
if {[info object isa object ${ns}::caphandler.registry]} {
return ${ns}::caphandler.registry
}
}
}
return ""
}
#*** !doctools
#[list_end]
}
}
@ -462,6 +641,17 @@ namespace eval punk::cap {
## Ready ## Ready
package provide punk::cap [namespace eval punk::cap { package provide punk::cap [namespace eval punk::cap {
variable version variable version
variable pkg punk::cap
set version 999999.0a1.0 set version 999999.0a1.0
variable README.md [string map [list %pkg% $pkg %ver% $version] {
# punk capabilities system
## pkg: %pkg% version: %ver%
punk::cap base namespace
}]
return $version
}] }]
return return
#*** !doctools
#[manpage_end]

123
src/modules/punk/cap.html

@ -0,0 +1,123 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: ; script-src 'self' 'nonce-d717cfb5d902616b7024920ae20346a8494f7832145c90e0' ; style-src 'self' 'unsafe-inline'" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Documentation cap-999999.0a1.0">
<meta name="author" content="JMNoble">
<title>Documentation cap-999999.0a1.0</title>
<style>
body {
margin-left: 10%; margin-right: 10%;
font-family: Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif;
max-width: 90%;
}
pre {
padding-top: 1ex;
padding-bottom: 1ex;
padding-left: 2ex;
padding-right: 1ex;
width: 100%;
color: black;
background: #fff4e4;
border-top: 1px solid black;
border-bottom: 1px solid black;
font-family: Monaco, Consolas, "Liberation Mono", Menlo, Courier, monospace;
}
a {
text-decoration: none
}
pre.synopsis {
background: #cceeff;
}
pre.code code.tclin {
background-color: #ffeeee;
}
pre.code code.tclout {
background-color: #ffffee;
}
code {
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
}
h1,h2, h3,h4 {
font-family: sans-serif;
background: transparent;
}
h1 {
font-size: 120%;
text-align: center;
}
h2.author, h2.date {
text-align: center;
color: black;
}
h2 { font-size: 110%; }
h3, h4 { font-size: 100% }
div.title h1 {
font-family: sans-serif;
font-size: 120%;
background: transparent;
text-align: center;
color: black;
}
div.author h3, div.date h3 {
font-family: sans-serif;
font-size: 110%;
background: transparent;
text-align: center;
color: black ;
}
h2, h3 {
margin-top: 1em;
font-family: sans-serif;
font-size: 110%;
color: #005A9C;
background: transparent;
text-align: left;
}
</style>
</head>
<body>
<h1 class="title">Documentation cap-999999.0a1.0</h1>
<h2 class="author">JMNoble</h2>
<h2 class="date">2023-12-19</h2>
<h2>Concepts:</h2><blockquote>
<p>A <strong>capability</strong> may be something like providing a folder of files, or just a data dictionary, and/or an API</p>
<p><strong>capability handler</strong> - a package/namespace which may provide validation and standardised ways of looking up provider data
registered (or not) using register_capabilityname <capname> <capnamespace></p>
<p><strong>capability provider</strong> - a package which registers as providing one or more capablities.
registered using register_package <pkg> <capabilitylist>
the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability
A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets.</p>
</blockquote>
<h2><strong>exists(capname)</strong></h2>
<blockquote>
<p>return a boolean indicating the existence of a capability</p>
<p>Arguments:</p>
<ul>
<li><em>capname</em> - string indicating the name of the capability
</li></ul>
<table class="table">
<thead>
<tr>
<th>Returns: 0</th>
<th>1</th>
</tr>
</thead>
</table>
</blockquote>
</body>
</html>

29
src/modules/punk/cap.md

@ -0,0 +1,29 @@
---
author: NN
css: mkdoc.css
date: 2023-12-19
title: Documentation cap-999999.0a1.0
---
> concepts:
> A capability may be something like providing a folder of files, or just a data dictionary, and/or an API
> capability handler - a package/namespace which may provide validation and standardised ways of looking up provider data
registered (or not) using register_capabilityname <capname> <capnamespace>
> capability provider - a package which registers as providing one or more capablities.
registered using register_package <pkg> <capabilitylist>
the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability
A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets.
## **exists(capname)**
> return a boolean indicating the existence of a capability
> Arguments:
> - *capname* - string indicating the name of the capability
> Returns: 0|1

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

@ -35,10 +35,14 @@ namespace eval punk::cap::handlers::templates {
namespace eval capsystem { namespace eval capsystem {
#interfaces for punk::cap to call into #interfaces for punk::cap to call into
if {[info commands caphandler.registry] eq ""} { if {[info commands caphandler.registry] eq ""} {
punk::cap::interface_caphandler.registry create caphandler.registry punk::cap::class::interface_caphandler.registry create caphandler.registry
oo::objdefine caphandler.registry { oo::objdefine caphandler.registry {
method pkg_register {pkg capname capdict caplist} { method pkg_register {pkg capname capdict caplist} {
#caplist may not be complete set - which somewhat reduces its utility here regarding any decisions based on the context of this capname/capdict (review - remove this arg?) #caplist may not be complete set - which somewhat reduces its utility here regarding any decisions based on the context of this capname/capdict (review - remove this arg?)
# -- --- --- --- --- --- --- ---- ---
# validation of capdict
# -- --- --- --- --- --- --- ---- ---
if {![dict exists $capdict relpath]} { if {![dict exists $capdict relpath]} {
puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - package '$pkg' is attempting to register with punk::cap as a provider of '$capname' capability, but is missing 'relpath' key" puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - package '$pkg' is attempting to register with punk::cap as a provider of '$capname' capability, but is missing 'relpath' key"
return 0 return 0
@ -54,15 +58,26 @@ namespace eval punk::cap::handlers::templates {
puts stderr "punk::cap::handlers::templates::capsystem pkg_register WARNING - unable to validate relpath location [dict get $capdict relpath] ($tpath) for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability" puts stderr "punk::cap::handlers::templates::capsystem pkg_register WARNING - unable to validate relpath location [dict get $capdict relpath] ($tpath) for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability"
return 0 return 0
} }
# -- --- --- --- --- --- --- ---- ---
# update package internal data
# -- --- --- --- --- --- --- ---- ---
if {$capname ni $::punk::cap::handlers::templates::handled_caps} { if {$capname ni $::punk::cap::handlers::templates::handled_caps} {
lappend ::punk::cap::handlers::templates::handled_caps $capname lappend ::punk::cap::handlers::templates::handled_caps $capname
} }
if {[info commands ::punk::cap::handlers::templates::$capname] eq ""} {
punk::cap::handlers::templates::api create ::punk::cap::handlers::templates::$capname $capname
}
set cname [string map [list . _] $capname] set cname [string map [list . _] $capname]
upvar ::punk::cap::handlers::templates::pkg_folders_$cname pfolders upvar ::punk::cap::handlers::templates::pkg_folders_$cname pfolders
dict lappend pfolders $pkg $tpath dict lappend pfolders $pkg $tpath
# -- --- --- --- --- --- --- ---- ---
# instantiation of api at punk::cap::handlers::templates::api_$capname
# -- --- --- --- --- --- --- ---- ---
if {[info commands ::punk::cap::handlers::templates::$capname] eq ""} {
punk::cap::handlers::templates::class::api create ::punk::cap::handlers::templates::api_$capname $capname
}
return 1 return 1
} }
method pkg_unregister {pkg} { method pkg_unregister {pkg} {
@ -85,36 +100,38 @@ namespace eval punk::cap::handlers::templates {
#handler api for clients of this capability - called via punk::cap::call_handler <capname> <method> ?args? #handler api for clients of this capability - called via punk::cap::call_handler <capname> <method> ?args?
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
namespace export * namespace export *
namespace eval class {
oo::class create api { oo::class create api {
#return a dict keyed on folder with source pkg as value #return a dict keyed on folder with source pkg as value
constructor {capname} { constructor {capname} {
variable capabilityname variable capabilityname
variable cname variable cname
set cname [string map [list . _] $capname] set cname [string map [list . _] $capname]
set capabilityname $capname set capabilityname $capname
} }
method folders {} { method folders {} {
variable capabilityname variable capabilityname
variable cname variable cname
upvar punk::cap::handlers::templates::pkg_folders_$cname pkg_folders upvar punk::cap::handlers::templates::pkg_folders_$cname pkg_folders
package require punk::cap package require punk::cap
set capinfo [punk::cap::capability $capabilityname] set capinfo [punk::cap::capability $capabilityname]
# e.g {punk.templates {handler punk::mix::templates providers ::somepkg}} # e.g {punk.templates {handler punk::mix::templates providers ::somepkg}}
#use the order of pkgs as registered with punk::cap - may have been modified with punk::cap::promote_package/demote_package #use the order of pkgs as registered with punk::cap - may have been modified with punk::cap::promote_package/demote_package
set pkgs [dict get $capinfo providers] set pkgs [dict get $capinfo providers]
set folderdict [dict create] set folderdict [dict create]
foreach pkg $pkgs { foreach pkg $pkgs {
foreach pfolder [dict get $pkg_folders $pkg] { foreach pfolder [dict get $pkg_folders $pkg] {
dict set folderdict $pfolder [list source $pkg sourcetype package] dict set folderdict $pfolder [list source $pkg sourcetype package]
}
} }
return $folderdict
} }
return $folderdict
} }
} }
} }

71
src/modules/punk/docgen-999999.0a1.0.tm

@ -0,0 +1,71 @@
# -*- tcl -*
# Maintenance Instruction: leave the 999999.xxx.x as is and use 'pmix make' or src/make.tcl to update from <pkg>-buildversion.txt
#
# 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) 2023
#
# @@ Meta Begin
# Application punk::docgen 999999.0a1.0
# Meta platform tcl
# Meta license BSD
# @@ Meta End
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Requirements
##e.g package require frobz
package require punk::repo
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
namespace eval punk::docgen {
proc get_doctools_comments {fname} {
#does no validation of doctools commands
#existence of string match #\**!doctools is taken as evidence enough that the file has inline doctools - review
if {![file exists $fname]} {
error "get_doctools_comments file '$fname' not found"
}
set fd [open $fname r]
set data [read $fd]
close $fd
if {![string match "*#\**!doctools*" $data]} {
return
}
set data [string map [list \r\n \n] $data]
set in_doctools 0
set doctools ""
foreach ln [split $data \n] {
set ln [string trim $ln]
if {$in_doctools && [string index $ln 0] != "#"} {
set in_doctools 0
} elseif {[string range $ln 0 1] == "#*"} {
#todo - process doctools ordering hints in tail of line
set in_doctools 1
} elseif {$in_doctools} {
append doctools [string range $ln 1 end] \n
}
}
return $doctools
}
#todo - proc autogen_doctools_comments {fname} {}
# - will probably need to use something like parsetcl - as we won't be able to reliably source in an interp without side-effects and use info body etc.
# - mechanism will be to autodocument namespaces, procs, methods where no #*** doctools indication present - but use existing doctools comments for that particular item if it is present.
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Ready
package provide punk::docgen [namespace eval punk::docgen {
variable pkg punk::docgen
variable version
set version 999999.0a1.0
}]
return

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

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

17
src/modules/punk/mix/cli-0.3.tm

@ -477,7 +477,13 @@ namespace eval punk::mix::cli {
set did_skip 0 ;#flag for stdout/stderr formatting only set did_skip 0 ;#flag for stdout/stderr formatting only
foreach m $src_modules { foreach m $src_modules {
#puts "build_modules_from_source_to_base >>> module $m" set is_interesting 0
if {[string match "foobar" $current_source_dir]} {
set is_interesting 1
}
if {$is_interesting} {
puts "build_modules_from_source_to_base >>> module $current_source_dir/$m"
}
set fileparts [split [file rootname $m] -] set fileparts [split [file rootname $m] -]
set tmfile_versionsegment [lindex $fileparts end] set tmfile_versionsegment [lindex $fileparts end]
if {$tmfile_versionsegment eq $magicversion} { if {$tmfile_versionsegment eq $magicversion} {
@ -582,7 +588,9 @@ namespace eval punk::mix::cli {
#set file_record [punkcheck::installfile_finished_install $basedir $file_record] #set file_record [punkcheck::installfile_finished_install $basedir $file_record]
$event targetset_end OK $event targetset_end OK
} else { } else {
#puts stdout "skipping module $current_source_dir/$m - no change in sources detected" if {$is_interesting} {
puts stdout "skipping module $current_source_dir/$m - no change in sources detected"
}
puts -nonewline stderr "." puts -nonewline stderr "."
set did_skip 1 set did_skip 1
#set file_record [punkcheck::installfile_skipped_install $basedir $file_record] #set file_record [punkcheck::installfile_skipped_install $basedir $file_record]
@ -627,15 +635,18 @@ namespace eval punk::mix::cli {
$event targetset_started $event targetset_started
# -- --- --- --- --- --- # -- --- --- --- --- ---
if {$did_skip} {set did_skip 0; puts -nonewline stdout \n} if {$did_skip} {set did_skip 0; puts -nonewline stdout \n}
puts stderr "Copied already versioned module $current_source_dir/$m to $target_module_dir"
lappend module_list $current_source_dir/$m lappend module_list $current_source_dir/$m
file copy -force $current_source_dir/$m $target_module_dir file copy -force $current_source_dir/$m $target_module_dir
puts stderr "Copied already versioned module $current_source_dir/$m to $target_module_dir"
# -- --- --- --- --- --- # -- --- --- --- --- ---
#set file_record [punkcheck::installfile_finished_install $basedir $file_record] #set file_record [punkcheck::installfile_finished_install $basedir $file_record]
$event targetset_end OK -note "already versioned module" $event targetset_end OK -note "already versioned module"
} else { } else {
puts -nonewline stderr "." puts -nonewline stderr "."
set did_skip 1 set did_skip 1
if {$is_interesting} {
puts stderr "$current_source_dir/$m [$event targetset_source_changes]"
}
#set file_record [punkcheck::installfile_skipped_install $basedir $file_record] #set file_record [punkcheck::installfile_skipped_install $basedir $file_record]
$event targetset_end SKIPPED $event targetset_end SKIPPED
} }

74
src/modules/punk/mix/commandset/doc-999999.0a1.0.tm

@ -18,7 +18,11 @@
## Requirements ## Requirements
##e.g package require frobz ##e.g package require frobz
package require punk ;# for treefilenames
package require punk::repo
package require punk::docgen ;#inline doctools - generate doctools .man files at src/docgen prior to using kettle to producing .html .md etc
package require punk::mix::cli ;#punk::mix::cli::lib used for kettle_call
package require punk::mix::util ;#for path_relative
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
@ -38,6 +42,30 @@ namespace eval punk::mix::commandset::doc {
puts stderr "No current project dir - unable to build docs" puts stderr "No current project dir - unable to build docs"
return return
} }
#user may delete the comment containing "--- punk::docgen::overwrites" and then manually edit, and we won't overwrite
#we still generate output in src/docgen so user can diff and manually update if thats what they prefer
set oldfiles [glob -nocomplain -dir $projectdir/src/doc -type f _module_*]
foreach maybedoomed $oldfiles {
set fd [open $maybedoomed r]
set data [read $fd]
close $fd
if {[string match "*--- punk::docgen overwrites *" $data]} {
file delete -force $maybedoomed
}
}
set generated [lib::do_docgen modules]
if {[dict get $generated count] > 0} {
#review
set doclist [dict get $generated docs]
foreach dinfo $doclist {
lassign $dinfo module fpath
set target $projectdir/src/doc/_module_[file tail $fpath]
if {![file exists $target]} {
file copy $fpath $target
}
}
}
if {[file exists $projectdir/src/doc]} { if {[file exists $projectdir/src/doc]} {
set original_wd [pwd] set original_wd [pwd]
cd $projectdir/src cd $projectdir/src
@ -125,6 +153,7 @@ namespace eval punk::mix::commandset::doc {
cd $original_wd cd $original_wd
} }
proc validate {} { proc validate {} {
#todo - run and validate punk::docgen output
set projectdir [punk::repo::find_project] set projectdir [punk::repo::find_project]
if {$projectdir eq ""} { if {$projectdir eq ""} {
puts stderr "No current project dir - unable to check doc status" puts stderr "No current project dir - unable to check doc status"
@ -154,6 +183,49 @@ namespace eval punk::mix::commandset::doc {
namespace eval lib { namespace eval lib {
variable pkg variable pkg
set pkg punk::mix::commandset::doc set pkg punk::mix::commandset::doc
proc do_docgen {{project_subpath modules}} {
set projectdir [punk::repo::find_project]
set outdir [file join $projectdir src docgen]
set subpath [file join $projectdir $project_subpath]
if {![file isdirectory $subpath]} {
puts stderr "WARNING punk::mix::commandset::doc unable to find subpath $subpath during do_docgen - skipping inline doctools generation"
return
}
if {[file isdirectory $outdir]} {
if {[catch {
file delete -force $outdir
}]} {
error "do_docgen failed to delete existing $outdir"
}
}
file mkdir $outdir
set matched_paths [punk::treefilenames $subpath *.tm]
set count 0
set newdocs [list]
set docgen_header_comments ""
append docgen_header_comments {[comment {--- punk::docgen generated from inline doctools comments ---}]} \n
append docgen_header_comments {[comment {--- punk::docgen DO NOT EDIT DOCS HERE UNLESS YOU REMOVE THESE COMMENT LINES ---}]} \n
append docgen_header_comments {[comment {--- punk::docgen overwrites this file ---}]} \n
foreach fullpath $matched_paths {
set relpath [punk::mix::util::path_relative $subpath $fullpath]
set tailsegs [file split $relpath]
set module_fullname [join $tailsegs ::]
set docname [string map [list :: _] $module_fullname].man ;#todo - something better - need to ensure unique
set doctools [punk::docgen::get_doctools_comments $fullpath]
if {$doctools ne ""} {
puts stdout "generating doctools output from file $relpath"
set outfile [file join $outdir $docname]
set fd [open $outfile w]
fconfigure $fd -translation binary
puts -nonewline $fd $docgen_header_comments$doctools
close $fd
incr count
lappend newdocs [list $module_fullname $outfile]
}
}
return [list count $count docs $newdocs]
}
} }
} }

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

@ -242,7 +242,7 @@ namespace eval punk::mix::commandset::project {
set layout_dir $templatebase/layouts/$opt_layout set layout_dir $templatebase/layouts/$opt_layout
puts stdout ">>> about to call punkcheck::install $layout_dir $projectdir" puts stdout ">>> about to call punkcheck::install $layout_dir $projectdir"
set resultdict [dict create] set resultdict [dict create]
set unpublish [list\ set antipaths [list\
src/doc/*\ src/doc/*\
src/doc/include/*\ src/doc/include/*\
] ]
@ -250,11 +250,11 @@ namespace eval punk::mix::commandset::project {
#default antiglob_dir_core will stop .fossil* from being updated - which is generally desirable as these are likely to be customized #default antiglob_dir_core will stop .fossil* from being updated - which is generally desirable as these are likely to be customized
if {$opt_force} { if {$opt_force} {
puts stdout "copying layout files - with force applied - overwrite all-targets" puts stdout "copying layout files - with force applied - overwrite all-targets"
set resultdict [punkcheck::install $layout_dir $projectdir -installer project.new -overwrite ALL-TARGETS -unpublish_paths $unpublish] set resultdict [punkcheck::install $layout_dir $projectdir -installer project.new -overwrite ALL-TARGETS -antiglob_paths $antipaths]
#file copy -force $layout_dir $projectdir #file copy -force $layout_dir $projectdir
} else { } else {
puts stdout "copying layout files - (if source file changed)" puts stdout "copying layout files - (if source file changed)"
set resultdict [punkcheck::install $layout_dir $projectdir -installer project.new -overwrite installedsourcechanged-targets -unpublish_paths $unpublish] set resultdict [punkcheck::install $layout_dir $projectdir -installer project.new -overwrite installedsourcechanged-targets -antiglob_paths $antipaths]
} }
puts stdout [punkcheck::summarize_install_resultdict $resultdict] puts stdout [punkcheck::summarize_install_resultdict $resultdict]

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

@ -32,7 +32,7 @@ namespace eval punk::mix::templates {
namespace eval capsystem { namespace eval capsystem {
if {[info commands capprovider.registration] eq ""} { if {[info commands capprovider.registration] eq ""} {
punk::cap::interface_capprovider.registration create capprovider.registration punk::cap::class::interface_capprovider.registration create capprovider.registration
oo::objdefine capprovider.registration { oo::objdefine capprovider.registration {
method get_declarations {} { method get_declarations {} {
set decls [list] set decls [list]
@ -46,7 +46,7 @@ namespace eval punk::mix::templates {
} }
if {[info commands provider] eq ""} { if {[info commands provider] eq ""} {
punk::cap::interface_capprovider.provider create provider punk::mix::templates punk::cap::class::interface_capprovider.provider create provider punk::mix::templates
oo::objdefine provider { oo::objdefine provider {
method register {{capabilityname_glob *}} { method register {{capabilityname_glob *}} {
#puts registering punk::mix::templates $capabilityname #puts registering punk::mix::templates $capabilityname

3942
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/mime-1.7.0.tm

File diff suppressed because it is too large Load Diff

228
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punk/cap-0.1.0.tm

@ -14,20 +14,36 @@
# @@ Meta End # @@ Meta End
#*** !doctools
#[manpage_begin punk::cap 0 0.1.0]
#[copyright "2023 JMNoble - BSD licensed"]
#[titledesc {Module API}]
#[moddesc {punk capabilities plugin system}]
#[require punk::cap]
#[description]
#[list_begin definitions]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Requirements ## Requirements
##e.g package require frobz ##e.g package require frobz
package require oolib
#concepts:
# A capability may be something like providing a folder of files, or just a data dictionary, and/or an API # mkdoc markdown
# #' ---
# capability handler - a package/namespace which may provide validation and standardised ways of looking up provider data #' author: JMNoble
# registered (or not) using register_capabilityname <capname> <capnamespace> #' ---
# capability provider - a package which registers as providing one or more capablities. #' ## Concepts:
# registered using register_package <pkg> <capabilitylist> #' > A **capability** may be something like providing a folder of files, or just a data dictionary, and/or an API
# the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability #'
# A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets. #' > **capability handler** - a package/namespace which may provide validation and standardised ways of looking up provider data
#' registered (or not) using register_capabilityname <capname> <capnamespace>
#'
#' > **capability provider** - a package which registers as providing one or more capablities.
#' registered using register_package <pkg> <capabilitylist>
#' the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability
#' A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets.
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
@ -35,32 +51,99 @@ namespace eval punk::cap {
variable pkgcapsdeclared [dict create] variable pkgcapsdeclared [dict create]
variable pkgcapsaccepted [dict create] variable pkgcapsaccepted [dict create]
variable caps [dict create] variable caps [dict create]
if {[info commands [namespace current]::interface_caphandler.registry] eq ""} {
oo::class create [namespace current]::interface_caphandler.registry { namespace eval class {
method pkg_register {pkg capname capdict fullcapabilitylist} { if {[info commands [namespace current]::interface_caphandler.registry] eq ""} {
#handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid #Handler classes
#overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes. oo::class create [namespace current]::interface_caphandler.registry {
return 1 ;#default to permit method pkg_register {pkg capname capdict fullcapabilitylist} {
} #***
method pkg_unregister {pkg} { #[call [class interface_caphandler.registry] [method pkg_register] [arg pkg] [arg capname] [arg capdict] [arg fullcapabilitylist]]
return ;#unregistration return is ignored - review #handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid
#overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes.
return 1 ;#default to permit
}
method pkg_unregister {pkg} {
#***
#[call [class interface_caphandler.registry] [method pkg_unregister] [arg pkg]]
return ;#unregistration return is ignored - review
}
} }
} oo::class create [namespace current]::interface_caphandler.sysapi {
oo::class create [namespace current]::interface_capprovider.registration {
method get_declarations {} {
error "interface_capprovider.registration not implemented by provider"
} }
}
oo::class create [namespace current]::interface_capprovider.provider {
method register {{capabilityname_glob *}} {
#Provider classes
oo::class create [namespace current]::interface_capprovider.registration {
method get_declarations {} {
#***
#[call [class interface_capprovider.registration] [method pkg_unregister] [arg pkg]]
error "interface_capprovider.registration not implemented by provider"
}
} }
method capabilities {} { oo::class create [namespace current]::interface_capprovider.provider {
variable provider_pkg
variable registrationobj
constructor {providerpkg} {
variable provider_pkg
if {$providerpkg in [list "" "::"]} {
error "interface_capprovider.provider constructor error. Invalid provider '$providerpkg'"
}
if {![namespace exists ::$providerpkg]} {
error "interface_capprovider.provider constructor error. Invalid provider '$providerpkg' - matching namespace not found"
}
set registrationobj ::${providerpkg}::capsystem::capprovider.registration
if {[info commands $registrationobj] eq ""} {
error "capprovider.provider constructor error. Missing capprovider.registration interface at '$obj' (command not found) interface_capprovider.regstration instantiation must precede interface_capprovider.provider"
}
set provider_pkg [string trim $providerpkg ""]
}
method register {{capabilityname_glob *}} {
#***
#[call [class interface_capprovider.provider] [method register] [opt capabilityname_glob]]
variable provider_pkg
set all_decls [$registrationobj get_declarations]
set register_decls [lsearch -all -inline -index 0 $all_decls $capabilityname_glob]
punk::cap::register_package $provider_pkg $register_decls
}
method capabilities {} {
#***
#[call [class interface_capprovider.provider] [method capabilities]]
variable provider_pkg
variable registrationobj
set capabilities [list]
set decls [$registrationobj get_declarations]
foreach decl $decls {
lassign $decl capname capdict
if {$capname ni $capabilities} {
lappend capabilities $capname
}
}
return $capname
}
} }
} }
} ;# end namespace class
namespace eval capsystem {
proc get_caphandler_registry {capname} {
set ns [::punk::cap::get_handler $capname]::capsystem
if {[namespace exists ${ns}]} {
if {[info command ${ns}::caphandler.registry] ne ""} {
if {[info object isa object ${ns}::caphandler.registry]} {
return ${ns}::caphandler.registry
}
}
}
return ""
}
} }
#Not all capabilities have to be registered. #Not all capabilities have to be registered.
#A package registering as a provider using register_package can include capabilitynames in it's capabilitylist which have no associated capnamespace (handler). #A package registering as a provider using register_package can include capabilitynames in it's capabilitylist which have no associated capnamespace (handler).
#such unregistered capabilitynames may be used just to flag something, or have datamembers significant to callers cooperatively interested in that capname. #such unregistered capabilitynames may be used just to flag something, or have datamembers significant to callers cooperatively interested in that capname.
@ -88,7 +171,7 @@ namespace eval punk::cap {
} }
if {[llength [set providers [dict get $caps $capname providers]]]} { if {[llength [set providers [dict get $caps $capname providers]]]} {
#some provider(s) were in place before the handler was registered #some provider(s) were in place before the handler was registered
if {[set capreg [get_caphandler_registry $capname]] ne ""} { if {[set capreg [punk::cap::capsystem::get_caphandler_registry $capname]] ne ""} {
foreach pkg $providers { foreach pkg $providers {
set fullcapabilitylist [dict get $pkgcapsdeclared $pkg] set fullcapabilitylist [dict get $pkgcapsdeclared $pkg]
foreach capspec $fullcapabilitylist { foreach capspec $fullcapabilitylist {
@ -131,10 +214,31 @@ namespace eval punk::cap {
} }
} }
proc exists {capname} { proc exists {capname} {
#*** !doctools
# [call [fun exists] [arg capname]]
# Return a boolean indicating if the named capability exists (0|1)
# mkdoc markdown
#'
#' ## **exists(capname)**
#'
#' > return a boolean indicating the existence of a capability
#'
#' > Arguments:
#'
#' > - *capname* - string indicating the name of the capability
#'
#' > Returns: 0|1
#'
variable caps variable caps
return [dict exists $caps $capname] return [dict exists $caps $capname]
} }
proc has_handler {capname} { proc has_handler {capname} {
#*** !doctools
# [call [fun has_handler] [arg capname]]
# Return a boolean indicating if the named capability has a handler package installed (0|1)
variable caps variable caps
return [expr {[dict exists $caps $capname handler] && [dict get $caps $capname handler] ne ""}] return [expr {[dict exists $caps $capname handler] && [dict get $caps $capname handler] ne ""}]
} }
@ -157,20 +261,9 @@ namespace eval punk::cap {
if {[set handler [get_handler $capname]] eq ""} { if {[set handler [get_handler $capname]] eq ""} {
error "punk::cap::call_handler $capname $args - no handler registered for capability $capname" error "punk::cap::call_handler $capname $args - no handler registered for capability $capname"
} }
set obj ${handler}::$capname set obj ${handler}::api_$capname
$obj [lindex $args 0] {*}[lrange $args 1 end] $obj [lindex $args 0] {*}[lrange $args 1 end]
} }
proc get_caphandler_registry {capname} {
set ns [get_handler $capname]::capsystem
if {[namespace exists ${ns}]} {
if {[info command ${ns}::caphandler.registry] ne ""} {
if {[info object isa object ${ns}::caphandler.registry]} {
return ${ns}::caphandler.registry
}
}
}
return ""
}
proc get_providers {capname} { proc get_providers {capname} {
variable caps variable caps
if {[dict exists $caps $capname]} { if {[dict exists $caps $capname]} {
@ -188,6 +281,11 @@ namespace eval punk::cap {
if {[string match ::* $pkg]} { if {[string match ::* $pkg]} {
set pkg [string range $pkg 2 end] set pkg [string range $pkg 2 end]
} }
if {[dict exists $pkgcapsaccepted $pkg]} {
set pkg_already_accepted [dict get $pkgcapsaccepted $pkg]
} else {
set pkg_already_accepted [list]
}
#for each capability #for each capability
# - ensure 1st element is a single word # - ensure 1st element is a single word
# - ensure that if 2nd element (capdict) is present - it is dict shaped # - ensure that if 2nd element (capdict) is present - it is dict shaped
@ -199,6 +297,11 @@ namespace eval punk::cap {
if {[expr {[llength $capdict] %2 != 0}]} { if {[expr {[llength $capdict] %2 != 0}]} {
error "register_package error. pkg:'$pkg' The second element for capname:'$capname' doesn't appear to be a valid dict. Problematic entry: '$capspec'" error "register_package error. pkg:'$pkg' The second element for capname:'$capname' doesn't appear to be a valid dict. Problematic entry: '$capspec'"
} }
if {$capspec in $pkg_already_accepted} {
#review - multiple handlers? if so - will need to record which handler(s) accepted the capspec
puts stderr "register_package pkg $pkg already has capspec marked as accepted: $capspec"
continue
}
if {[dict exists $caps $capname]} { if {[dict exists $caps $capname]} {
set cap_pkgs [dict get $caps $capname providers] set cap_pkgs [dict get $caps $capname providers]
} else { } else {
@ -207,7 +310,7 @@ namespace eval punk::cap {
} }
#todo - if there's a caphandler - call it's init/validation callback for the pkg #todo - if there's a caphandler - call it's init/validation callback for the pkg
set do_register 1 ;#default assumption unless vetoed by handler set do_register 1 ;#default assumption unless vetoed by handler
if {[set capreg [get_caphandler_registry $capname]] ne ""} { if {[set capreg [punk::cap::capsystem::get_caphandler_registry $capname]] ne ""} {
#Note that the interface_caphandler.registry instance must be able to handle multiple calls for same pkg #Note that the interface_caphandler.registry instance must be able to handle multiple calls for same pkg
set do_register [$capreg pkg_register $pkg $capname $capdict $capabilitylist] set do_register [$capreg pkg_register $pkg $capname $capdict $capabilitylist]
} }
@ -219,17 +322,23 @@ namespace eval punk::cap {
dict lappend pkgcapsaccepted $pkg $capspec ;#if pkg is being registered prior to handler-registration - the handler may undo this entry dict lappend pkgcapsaccepted $pkg $capspec ;#if pkg is being registered prior to handler-registration - the handler may undo this entry
} }
} }
#another call to register_pkg with same pkg may have been made (most likely with different capname) so we must append #another call to register_pkg with same pkg may have been made (most likely with different capname) so we must append - but check not already present
#dict lappend pkgcapsdeclared $pkg $capabilitylist #dict lappend pkgcapsdeclared $pkg $capabilitylist
if {[dict exists $pkgcapsdeclared $pkg]} { if {[dict exists $pkgcapsdeclared $pkg]} {
set caps [dict get $pkgcapsdeclared $pkg] set capspecs [dict get $pkgcapsdeclared $pkg]
lappend caps {*}$capabilitylist foreach spec $capspecs {
dict set pkgcapsdeclared $pkg $caps if {$spec ni $capspecs} {
lappend capspecs $spec
}
}
dict set pkgcapsdeclared $pkg $capspecs
} else { } else {
dict set pkgcapsdeclared $pkg $capabilitylist dict set pkgcapsdeclared $pkg $capabilitylist
} }
} }
proc unregister_package {pkg} {
#todo!
proc unregister_package {pkg {capname *}} {
variable pkgcapsdeclared variable pkgcapsdeclared
variable caps variable caps
if {[string match ::* $pkg]} { if {[string match ::* $pkg]} {
@ -245,13 +354,13 @@ namespace eval punk::cap {
set pkglist [dict get $cap_info providers] set pkglist [dict get $cap_info providers]
set posn [lsearch $pkglist $pkg] set posn [lsearch $pkglist $pkg]
if {$posn >= 0} { if {$posn >= 0} {
if {[set capreg [get_caphandler_registry $capname]] ne ""} { if {[set capreg [punk::cap::capsystem::get_caphandler_registry $capname]] ne ""} {
#review #review
# it seems not useful to allow the callback to block this unregister action # it seems not useful to allow the callback to block this unregister action
#the pkg may have multiple datasets for each capname so callback will only be called for first dataset we encounter #the pkg may have multiple datasets for each capname so callback will only be called for first dataset we encounter
#vetoing unregister would make this more complex for no particular advantage #vetoing unregister would make this more complex for no particular advantage
#if per capability deregistration required this should probably be a separate thing (e.g disable_capability?) #if per dataset deregistration required this should probably be a separate thing
$capreg pkg_unregister $pkg $capreg pkg_unregister $pkg $capname
} }
set pkglist [lreplace $pkglist $posn $posn] set pkglist [lreplace $pkglist $posn $posn]
dict set caps $capname providers $pkglist dict set caps $capname providers $pkglist
@ -398,21 +507,22 @@ namespace eval punk::cap {
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Ready ## Ready
package provide punk::cap [namespace eval punk::cap { package provide punk::cap [namespace eval punk::cap {
variable version variable version
variable pkg punk::cap
set version 0.1.0 set version 0.1.0
variable README.md [string map [list %pkg% $pkg %ver% $version] {
# punk capabilities system
## pkg: %pkg% version: %ver%
punk::cap base namespace
}]
return $version
}] }]
return return
#*** !doctools
#[list_end]
#[manpage_end]

74
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punk/cap/handlers/templates-0.1.0.tm

@ -35,10 +35,14 @@ namespace eval punk::cap::handlers::templates {
namespace eval capsystem { namespace eval capsystem {
#interfaces for punk::cap to call into #interfaces for punk::cap to call into
if {[info commands caphandler.registry] eq ""} { if {[info commands caphandler.registry] eq ""} {
punk::cap::interface_caphandler.registry create caphandler.registry punk::cap::class::interface_caphandler.registry create caphandler.registry
oo::objdefine caphandler.registry { oo::objdefine caphandler.registry {
method pkg_register {pkg capname capdict caplist} { method pkg_register {pkg capname capdict caplist} {
#caplist may not be complete set - which somewhat reduces its utility here regarding any decisions based on the context of this capname/capdict (review - remove this arg?) #caplist may not be complete set - which somewhat reduces its utility here regarding any decisions based on the context of this capname/capdict (review - remove this arg?)
# -- --- --- --- --- --- --- ---- ---
# validation of capdict
# -- --- --- --- --- --- --- ---- ---
if {![dict exists $capdict relpath]} { if {![dict exists $capdict relpath]} {
puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - package '$pkg' is attempting to register with punk::cap as a provider of '$capname' capability, but is missing 'relpath' key" puts stderr "punk::cap::handlers::templates::capsystem::pkg_register WARNING - package '$pkg' is attempting to register with punk::cap as a provider of '$capname' capability, but is missing 'relpath' key"
return 0 return 0
@ -52,16 +56,28 @@ namespace eval punk::cap::handlers::templates {
set tpath [file normalize [file join $tmfile [dict get $capdict relpath]]] ;#relpath is relative to the tm *file* - not it's containing folder set tpath [file normalize [file join $tmfile [dict get $capdict relpath]]] ;#relpath is relative to the tm *file* - not it's containing folder
if {![file isdirectory $tpath]} { if {![file isdirectory $tpath]} {
puts stderr "punk::cap::handlers::templates::capsystem pkg_register WARNING - unable to validate relpath location [dict get $capdict relpath] ($tpath) for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability" puts stderr "punk::cap::handlers::templates::capsystem pkg_register WARNING - unable to validate relpath location [dict get $capdict relpath] ($tpath) for package '$pkg' which is attempting to register with punk::cap as a provider of '$capname' capability"
return 0
} }
# -- --- --- --- --- --- --- ---- ---
# update package internal data
# -- --- --- --- --- --- --- ---- ---
if {$capname ni $::punk::cap::handlers::templates::handled_caps} { if {$capname ni $::punk::cap::handlers::templates::handled_caps} {
lappend ::punk::cap::handlers::templates::handled_caps $capname lappend ::punk::cap::handlers::templates::handled_caps $capname
} }
if {[info commands punk::cap::handlers::templates::$capname] eq ""} {
punk::cap::handlers::templates::api create ::punk::cap::handlers::templates::$capname $capname
}
set cname [string map [list . _] $capname] set cname [string map [list . _] $capname]
upvar ::punk::cap::handlers::templates::pkg_folders_$cname pfolders upvar ::punk::cap::handlers::templates::pkg_folders_$cname pfolders
dict lappend pfolders $pkg $tpath dict lappend pfolders $pkg $tpath
# -- --- --- --- --- --- --- ---- ---
# instantiation of api at punk::cap::handlers::templates::api_$capname
# -- --- --- --- --- --- --- ---- ---
if {[info commands ::punk::cap::handlers::templates::$capname] eq ""} {
punk::cap::handlers::templates::class::api create ::punk::cap::handlers::templates::api_$capname $capname
}
return 1 return 1
} }
method pkg_unregister {pkg} { method pkg_unregister {pkg} {
@ -84,36 +100,38 @@ namespace eval punk::cap::handlers::templates {
#handler api for clients of this capability - called via punk::cap::call_handler <capname> <method> ?args? #handler api for clients of this capability - called via punk::cap::call_handler <capname> <method> ?args?
# -- --- --- --- --- --- --- # -- --- --- --- --- --- ---
namespace export * namespace export *
namespace eval class {
oo::class create api { oo::class create api {
#return a dict keyed on folder with source pkg as value #return a dict keyed on folder with source pkg as value
constructor {capname} { constructor {capname} {
variable capabilityname variable capabilityname
variable cname variable cname
set cname [string map [list . _] $capname] set cname [string map [list . _] $capname]
set capabilityname $capname set capabilityname $capname
} }
method folders {} { method folders {} {
variable capabilityname variable capabilityname
variable cname variable cname
upvar punk::cap::handlers::templates::pkg_folders_$cname pkg_folders upvar punk::cap::handlers::templates::pkg_folders_$cname pkg_folders
package require punk::cap package require punk::cap
set capinfo [punk::cap::capability $capabilityname] set capinfo [punk::cap::capability $capabilityname]
# e.g {punk.templates {handler punk::mix::templates providers ::somepkg}} # e.g {punk.templates {handler punk::mix::templates providers ::somepkg}}
#use the order of pkgs as registered with punk::cap - may have been modified with punk::cap::promote_package/demote_package #use the order of pkgs as registered with punk::cap - may have been modified with punk::cap::promote_package/demote_package
set pkgs [dict get $capinfo providers] set pkgs [dict get $capinfo providers]
set folderdict [dict create] set folderdict [dict create]
foreach pkg $pkgs { foreach pkg $pkgs {
foreach pfolder [dict get $pkg_folders $pkg] { foreach pfolder [dict get $pkg_folders $pkg] {
dict set folderdict $pfolder [list source $pkg sourcetype package] dict set folderdict $pfolder [list source $pkg sourcetype package]
}
} }
return $folderdict
} }
return $folderdict
} }
} }
} }

2
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punk/mix-0.2.tm

@ -5,7 +5,7 @@ package require punk::cap::handlers::templates ;#handler for templates cap
punk::cap::register_capabilityname punk.templates ::punk::cap::handlers::templates punk::cap::register_capabilityname punk.templates ::punk::cap::handlers::templates
package require punk::mix::templates ;#registers as provider pkg for 'punk.templates' capability with punk::cap package require punk::mix::templates ;#registers as provider pkg for 'punk.templates' capability with punk::cap
#punk::mix::templates::provider register * punk::mix::templates::provider register *
package require punk::mix::base package require punk::mix::base
package require punk::mix::cli package require punk::mix::cli

3
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punk/mix/cli-0.3.tm

@ -170,7 +170,8 @@ namespace eval punk::mix::cli {
} }
cd $sourcefolder cd $sourcefolder
#use run so that stdout visible as it goes #use run so that stdout visible as it goes
if {![catch {run --timeout=5000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} { if {![catch {run --timeout=55000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} {
#todo - notify if exit because of timeout!
puts stderr "exitinfo: $exitinfo" puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode] set exitcode [dict get $exitinfo exitcode]
} else { } else {

74
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punk/mix/commandset/doc-0.1.0.tm

@ -18,7 +18,11 @@
## Requirements ## Requirements
##e.g package require frobz ##e.g package require frobz
package require punk ;# for treefilenames
package require punk::repo
package require punk::docgen ;#inline doctools - generate doctools .man files at src/docgen prior to using kettle to producing .html .md etc
package require punk::mix::cli ;#punk::mix::cli::lib used for kettle_call
package require punk::mix::util ;#for path_relative
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
@ -38,6 +42,30 @@ namespace eval punk::mix::commandset::doc {
puts stderr "No current project dir - unable to build docs" puts stderr "No current project dir - unable to build docs"
return return
} }
#user may delete the comment containing "--- punk::docgen::overwrites" and then manually edit, and we won't overwrite
#we still generate output in src/docgen so user can diff and manually update if thats what they prefer
set oldfiles [glob -nocomplain -dir $projectdir/src/doc -type f _module_*]
foreach maybedoomed $oldfiles {
set fd [open $maybedoomed r]
set data [read $fd]
close $fd
if {[string match "*--- punk::docgen overwrites *" $data]} {
file delete -force $maybedoomed
}
}
set generated [lib::do_docgen modules]
if {[dict get $generated count] > 0} {
#review
set doclist [dict get $generated docs]
foreach dinfo $doclist {
lassign $dinfo module fpath
set target $projectdir/src/doc/_module_[file tail $fpath]
if {![file exists $target]} {
file copy $fpath $target
}
}
}
if {[file exists $projectdir/src/doc]} { if {[file exists $projectdir/src/doc]} {
set original_wd [pwd] set original_wd [pwd]
cd $projectdir/src cd $projectdir/src
@ -125,6 +153,7 @@ namespace eval punk::mix::commandset::doc {
cd $original_wd cd $original_wd
} }
proc validate {} { proc validate {} {
#todo - run and validate punk::docgen output
set projectdir [punk::repo::find_project] set projectdir [punk::repo::find_project]
if {$projectdir eq ""} { if {$projectdir eq ""} {
puts stderr "No current project dir - unable to check doc status" puts stderr "No current project dir - unable to check doc status"
@ -154,6 +183,49 @@ namespace eval punk::mix::commandset::doc {
namespace eval lib { namespace eval lib {
variable pkg variable pkg
set pkg punk::mix::commandset::doc set pkg punk::mix::commandset::doc
proc do_docgen {{project_subpath modules}} {
set projectdir [punk::repo::find_project]
set outdir [file join $projectdir src docgen]
set subpath [file join $projectdir $project_subpath]
if {![file isdirectory $subpath]} {
puts stderr "WARNING punk::mix::commandset::doc unable to find subpath $subpath during do_docgen - skipping inline doctools generation"
return
}
if {[file isdirectory $outdir]} {
if {[catch {
file delete -force $outdir
}]} {
error "do_docgen failed to delete existing $outdir"
}
}
file mkdir $outdir
set matched_paths [punk::treefilenames $subpath *.tm]
set count 0
set newdocs [list]
set docgen_header_comments ""
append docgen_header_comments {[comment {--- punk::docgen generated from inline doctools comments ---}]} \n
append docgen_header_comments {[comment {--- punk::docgen DO NOT EDIT DOCS HERE UNLESS YOU REMOVE THESE COMMENT LINES ---}]} \n
append docgen_header_comments {[comment {--- punk::docgen overwrites this file ---}]} \n
foreach fullpath $matched_paths {
set relpath [punk::mix::util::path_relative $subpath $fullpath]
set tailsegs [file split $relpath]
set module_fullname [join $tailsegs ::]
set docname [string map [list :: _] $module_fullname].man ;#todo - something better - need to ensure unique
set doctools [punk::docgen::get_doctools_comments $fullpath]
if {$doctools ne ""} {
puts stdout "generating doctools output from file $relpath"
set outfile [file join $outdir $docname]
set fd [open $outfile w]
fconfigure $fd -translation binary
puts -nonewline $fd $docgen_header_comments$doctools
close $fd
incr count
lappend newdocs [list $module_fullname $outfile]
}
}
return [list count $count docs $newdocs]
}
} }
} }

16
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punk/mix/templates-0.1.0.tm

@ -26,17 +26,19 @@ namespace eval punk::mix::templates {
variable pkg punk::mix::templates variable pkg punk::mix::templates
variable cap_provider variable cap_provider
punk::cap::register_package punk::mix::templates [list\ #punk::cap::register_package punk::mix::templates [list\
{punk.templates {relpath ../templates}}\ # {punk.templates {relpath ../templates}}\
] #]
namespace eval capsystem { namespace eval capsystem {
if {[info commands capprovider.registration] eq ""} { if {[info commands capprovider.registration] eq ""} {
punk::cap::interface_capprovider.registration create capprovider.registration punk::cap::class::interface_capprovider.registration create capprovider.registration
oo::objdefine capprovider.registration { oo::objdefine capprovider.registration {
method get_declarations {} { method get_declarations {} {
set decls [list] set decls [list]
lappend decls punk.templates {relpath ../templates} lappend decls [list punk.templates {relpath ../templates}]
lappend decls punk.templates {relpath ../templates2} lappend decls [list punk.templates {relpath ../templates2}]
lappend decls [list punk.test {something blah}]
return $decls return $decls
} }
} }
@ -44,7 +46,7 @@ namespace eval punk::mix::templates {
} }
if {[info commands provider] eq ""} { if {[info commands provider] eq ""} {
punk::cap::interface_capprovider.provider create provider punk::cap::class::interface_capprovider.provider create provider punk::mix::templates
oo::objdefine provider { oo::objdefine provider {
method register {{capabilityname_glob *}} { method register {{capabilityname_glob *}} {
#puts registering punk::mix::templates $capabilityname #puts registering punk::mix::templates $capabilityname

32
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/punkcheck-0.1.0.tm

@ -1078,7 +1078,7 @@ namespace eval punkcheck {
} }
proc install_non_tm_files {srcdir basedir args} { proc install_non_tm_files {srcdir basedir args} {
#set keys [dict keys $args] #set keys [dict keys $args]
#adjust the default anti_glob_dir_core entries so that .fossil-custom, .fossil-settings are copied #adjust the default antiglob_dir_core entries so that .fossil-custom, .fossil-settings are copied
set antiglob_dir_core [punkcheck::default_antiglob_dir_core] set antiglob_dir_core [punkcheck::default_antiglob_dir_core]
set posn [lsearch $antiglob_dir_core ".fossil*"] set posn [lsearch $antiglob_dir_core ".fossil*"]
if {$posn >=0} { if {$posn >=0} {
@ -1168,7 +1168,7 @@ namespace eval punkcheck {
-antiglob_file "" \ -antiglob_file "" \
-antiglob_dir_core "\uFFFF"\ -antiglob_dir_core "\uFFFF"\
-antiglob_dir {}\ -antiglob_dir {}\
-unpublish_paths {}\ -antiglob_paths {}\
-overwrite no-targets\ -overwrite no-targets\
-source_checksum comparestore\ -source_checksum comparestore\
-punkcheck_folder target\ -punkcheck_folder target\
@ -1225,8 +1225,8 @@ namespace eval punkcheck {
# -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
set opt_antiglob_dir [dict get $opts -antiglob_dir] set opt_antiglob_dir [dict get $opts -antiglob_dir]
# -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
set opt_unpublish_paths [dict get $opts -unpublish_paths] ;#todo - combine with config file in source tree .punkcheckpublish (?) set opt_antiglob_paths [dict get $opts -antiglob_paths] ;#todo - combine with config file in source tree .punkcheckpublish (?)
set unpublish_paths_matched [list] set antiglob_paths_matched [list]
# -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- # -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
set known_whats [list no-targets newer-targets older-targets all-targets installedsourcechanged-targets synced-targets] set known_whats [list no-targets newer-targets older-targets all-targets installedsourcechanged-targets synced-targets]
set overwrite_what [string tolower [dict get $opts -overwrite]]; #accept any case for value to allow emphasis by caller e.g -overwrite NEWER-TARGETS set overwrite_what [string tolower [dict get $opts -overwrite]]; #accept any case for value to allow emphasis by caller e.g -overwrite NEWER-TARGETS
@ -1347,11 +1347,11 @@ namespace eval punkcheck {
if {$target_relative_to_punkcheck_dir eq "."} { if {$target_relative_to_punkcheck_dir eq "."} {
set target_relative_to_punkcheck_dir "" set target_relative_to_punkcheck_dir ""
} }
foreach unpub $opt_unpublish_paths { foreach unpub $opt_antiglob_paths {
#puts "testing folder - globmatchpath $unpub $relative_source_dir" #puts "testing folder - globmatchpath $unpub $relative_source_dir"
if {[globmatchpath $unpub $relative_source_dir]} { if {[globmatchpath $unpub $relative_source_dir]} {
lappend unpublish_paths_matched $current_source_dir lappend antiglob_paths_matched $current_source_dir
return [list files_copied {} files_skipped {} sources_unchanged {} punkcheck_records $punkcheck_records unpublish_paths_matched $unpublish_paths_matched srcdir $srcdir tgtdir $tgtdir punkcheck_folder $punkcheck_folder] return [list files_copied {} files_skipped {} sources_unchanged {} punkcheck_records $punkcheck_records antiglob_paths_matched $antiglob_paths_matched srcdir $srcdir tgtdir $tgtdir punkcheck_folder $punkcheck_folder]
} }
} }
@ -1418,16 +1418,16 @@ namespace eval punkcheck {
set relative_target_path [file join $relative_target_dir $m] set relative_target_path [file join $relative_target_dir $m]
set relative_source_path [file join $relative_source_dir $m] set relative_source_path [file join $relative_source_dir $m]
set punkcheck_target_relpath [file join $target_relative_to_punkcheck_dir $m] set punkcheck_target_relpath [file join $target_relative_to_punkcheck_dir $m]
set is_unpublished 0 set is_antipath 0
foreach unpub $opt_unpublish_paths { foreach antipath $opt_antiglob_paths {
#puts "testing file - globmatchpath $unpub vs $relative_source_path" #puts "testing file - globmatchpath $antipath vs $relative_source_path"
if {[globmatchpath $unpub $relative_source_path]} { if {[globmatchpath $antipath $relative_source_path]} {
lappend unpublish_paths_matched $current_source_dir lappend antiglob_paths_matched $current_source_dir
set is_unpublished 1 set is_antipath 1
break break
} }
} }
if {$is_unpublished} { if {$is_antipath} {
continue continue
} }
#puts stdout " checking file : $current_source_dir/$m" #puts stdout " checking file : $current_source_dir/$m"
@ -1642,7 +1642,7 @@ namespace eval punkcheck {
lappend files_copied {*}[dict get $sub_result files_copied] lappend files_copied {*}[dict get $sub_result files_copied]
lappend files_skipped {*}[dict get $sub_result files_skipped] lappend files_skipped {*}[dict get $sub_result files_skipped]
lappend sources_unchanged {*}[dict get $sub_result sources_unchanged] lappend sources_unchanged {*}[dict get $sub_result sources_unchanged]
lappend unpublish_paths_matched {*}[dict get $sub_result unpublish_paths_matched] lappend antiglob_paths_matched {*}[dict get $sub_result antiglob_paths_matched]
set punkcheck_records [dict get $sub_result punkcheck_records] set punkcheck_records [dict get $sub_result punkcheck_records]
} }
@ -1664,7 +1664,7 @@ namespace eval punkcheck {
} }
} }
return [list files_copied $files_copied files_skipped $files_skipped sources_unchanged $sources_unchanged unpublish_paths_matched $unpublish_paths_matched punkcheck_records $punkcheck_records punkcheck_folder $punkcheck_folder srcdir $srcdir tgtdir $tgtdir] return [list files_copied $files_copied files_skipped $files_skipped sources_unchanged $sources_unchanged antiglob_paths_matched $antiglob_paths_matched punkcheck_records $punkcheck_records punkcheck_folder $punkcheck_folder srcdir $srcdir tgtdir $tgtdir]
} }
proc summarize_install_resultdict {resultdict} { proc summarize_install_resultdict {resultdict} {
set msg "" set msg ""

80
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil-0.9.tm

@ -0,0 +1,80 @@
# textutil.tcl --
#
# Utilities for manipulating strings, words, single lines,
# paragraphs, ...
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2002 by Joe English <jenglish@users.sourceforge.net>
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: textutil.tcl,v 1.17 2006/09/21 06:46:24 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil {}
# ### ### ### ######### ######### #########
## API implementation
## All through sub-packages imported here.
package require textutil::string
package require textutil::repeat
package require textutil::adjust
package require textutil::split
package require textutil::tabify
package require textutil::trim
package require textutil::wcswidth
namespace eval ::textutil {
# Import the miscellaneous string command for public export
namespace import -force string::chop string::tail
namespace import -force string::cap string::uncap string::capEachWord
namespace import -force string::longestCommonPrefix
namespace import -force string::longestCommonPrefixList
# Import the repeat commands for public export
namespace import -force repeat::strRepeat repeat::blank
# Import the adjust commands for public export
namespace import -force adjust::adjust adjust::indent adjust::undent
# Import the split commands for public export
namespace import -force split::splitx split::splitn
# Import the trim commands for public export
namespace import -force trim::trim trim::trimleft trim::trimright
namespace import -force trim::trimPrefix trim::trimEmptyHeading
# Import the tabify commands for public export
namespace import -force tabify::tabify tabify::untabify
namespace import -force tabify::tabify2 tabify::untabify2
# Re-export all the imported commands
namespace export chop tail cap uncap capEachWord
namespace export longestCommonPrefix longestCommonPrefixList
namespace export strRepeat blank
namespace export adjust indent undent
namespace export splitx splitn
namespace export trim trimleft trimright trimPrefix trimEmptyHeading
namespace export tabify untabify tabify2 untabify2
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil 0.9

761
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/adjust-0.7.3.tm

@ -0,0 +1,761 @@
# trim.tcl --
#
# Various ways of trimming a string.
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2002-2004 by Johannes-Heinrich Vogeler <vogeler@users.sourceforge.net>
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: adjust.tcl,v 1.16 2011/12/13 18:12:56 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
package require textutil::repeat
package require textutil::string
namespace eval ::textutil::adjust {}
# ### ### ### ######### ######### #########
## API implementation
namespace eval ::textutil::adjust {
namespace import -force ::textutil::repeat::strRepeat
}
proc ::textutil::adjust::adjust {text args} {
if {[string length [string trim $text]] == 0} {
return ""
}
Configure $args
Adjust text newtext
return $newtext
}
proc ::textutil::adjust::Configure {args} {
variable Justify left
variable Length 72
variable FullLine 0
variable StrictLength 0
variable Hyphenate 0
variable HyphPatterns ; # hyphenation patterns (TeX)
set args [ lindex $args 0 ]
foreach { option value } $args {
switch -exact -- $option {
-full {
if { ![ string is boolean -strict $value ] } then {
error "expected boolean but got \"$value\""
}
set FullLine [ string is true $value ]
}
-hyphenate {
# the word exceeding the length of line is tried to be
# hyphenated; if a word cannot be hyphenated to fit into
# the line processing stops! The length of the line should
# be set to a reasonable value!
if { ![ string is boolean -strict $value ] } then {
error "expected boolean but got \"$value\""
}
set Hyphenate [string is true $value]
if { $Hyphenate && ![info exists HyphPatterns(_LOADED_)]} {
error "hyphenation patterns not loaded!"
}
}
-justify {
set lovalue [ string tolower $value ]
switch -exact -- $lovalue {
left -
right -
center -
plain {
set Justify $lovalue
}
default {
error "bad value \"$value\": should be center, left, plain or right"
}
}
}
-length {
if { ![ string is integer $value ] } then {
error "expected positive integer but got \"$value\""
}
if { $value < 1 } then {
error "expected positive integer but got \"$value\""
}
set Length $value
}
-strictlength {
# the word exceeding the length of line is moved to the
# next line without hyphenation; words longer than given
# line length are cut into smaller pieces
if { ![ string is boolean -strict $value ] } then {
error "expected boolean but got \"$value\""
}
set StrictLength [ string is true $value ]
}
default {
error "bad option \"$option\": must be -full, -hyphenate, \
-justify, -length, or -strictlength"
}
}
}
return ""
}
# ::textutil::adjust::Adjust
#
# History:
# rewritten on 2004-04-13 for bugfix tcllib-bugs-882402 (jhv)
proc ::textutil::adjust::Adjust { varOrigName varNewName } {
variable Length
variable FullLine
variable StrictLength
variable Hyphenate
upvar $varOrigName orig
upvar $varNewName text
set pos 0; # Cursor after writing
set line ""
set text ""
if {!$FullLine} {
regsub -all -- "(\n)|(\t)" $orig " " orig
regsub -all -- " +" $orig " " orig
regsub -all -- "(^ *)|( *\$)" $orig "" orig
}
set words [split $orig]
set numWords [llength $words]
set numline 0
for {set cnt 0} {$cnt < $numWords} {incr cnt} {
set w [lindex $words $cnt]
set wLen [string length $w]
# the word $w doesn't fit into the present line
# case #1: we try to hyphenate
if {$Hyphenate && ($pos+$wLen >= $Length)} {
# Hyphenation instructions
set w2 [textutil::adjust::Hyphenation $w]
set iMax [llength $w2]
if {$iMax == 1 && [string length $w] > $Length} {
# word cannot be hyphenated and exceeds linesize
error "Word \"$w2\" can\'t be hyphenated\
and exceeds linesize $Length!"
} else {
# hyphenating of $w was successfull, but we have to look
# that every sylable would fit into the line
foreach x $w2 {
if {[string length $x] >= $Length} {
error "Word \"$w\" can\'t be hyphenated\
to fit into linesize $Length!"
}
}
}
for {set i 0; set w3 ""} {$i < $iMax} {incr i} {
set syl [lindex $w2 $i]
if {($pos+[string length " $w3$syl-"]) > $Length} {break}
append w3 $syl
}
for {set w4 ""} {$i < $iMax} {incr i} {
set syl [lindex $w2 $i]
append w4 $syl
}
if {[string length $w3] && [string length $w4]} {
# hyphenation was successfull: redefine
# list of words w => {"$w3-" "$w4"}
set x [lreplace $words $cnt $cnt "$w4"]
set words [linsert $x $cnt "$w3-"]
set w [lindex $words $cnt]
set wLen [string length $w]
incr numWords
}
}
# the word $w doesn't fit into the present line
# case #2: we try to cut the word into pieces
if {$StrictLength && ([string length $w] > $Length)} {
# cut word into two pieces
set w2 $w
set over [expr {$pos+2+$wLen-$Length}]
incr Length -1
set w3 [string range $w2 0 $Length]
incr Length
set w4 [string range $w2 $Length end]
set x [lreplace $words $cnt $cnt $w4]
set words [linsert $x $cnt $w3 ]
set w [lindex $words $cnt]
set wLen [string length $w]
incr numWords
}
# continuing with the normal procedure
if {($pos+$wLen < $Length)} {
# append word to current line
if {$pos} {append line " "; incr pos}
append line $w
incr pos $wLen
} else {
# line full => write buffer and begin a new line
if {[string length $text]} {append text "\n"}
append text [Justification $line [incr numline]]
set line $w
set pos $wLen
}
}
# write buffer and return!
if {[string length $text]} {append text "\n"}
append text [Justification $line end]
return $text
}
# ::textutil::adjust::Justification
#
# justify a given line
#
# Parameters:
# line text for justification
# index index for line in text
#
# Returns:
# the justified line
#
# Remarks:
# Only lines with size not exceeding the max. linesize provided
# for text formatting are justified!!!
proc ::textutil::adjust::Justification { line index } {
variable Justify
variable Length
variable FullLine
set len [string length $line]; # length of current line
if { $Length <= $len } then {
# the length of current line ($len) is equal as or greater than
# the value provided for text formatting ($Length) => to avoid
# inifinite loops we leave $line unchanged and return!
return $line
}
# Special case:
# for the last line, and if the justification is set to 'plain'
# the real justification is 'left' if the length of the line
# is less than 90% (rounded) of the max length allowed. This is
# to avoid expansion of this line when it is too small: without
# it, the added spaces will 'unbeautify' the result.
#
set justify $Justify
if { ( "$index" == "end" ) && \
( "$Justify" == "plain" ) && \
( $len < round($Length * 0.90) ) } then {
set justify left
}
# For a left justification, nothing to do, but to
# add some spaces at the end of the line if requested
if { "$justify" == "left" } then {
set jus ""
if { $FullLine } then {
set jus [strRepeat " " [ expr { $Length - $len } ]]
}
return "${line}${jus}"
}
# For a right justification, just add enough spaces
# at the beginning of the line
if { "$justify" == "right" } then {
set jus [strRepeat " " [ expr { $Length - $len } ]]
return "${jus}${line}"
}
# For a center justification, add half of the needed spaces
# at the beginning of the line, and the rest at the end
# only if needed.
if { "$justify" == "center" } then {
set mr [ expr { ( $Length - $len ) / 2 } ]
set ml [ expr { $Length - $len - $mr } ]
set jusl [strRepeat " " $ml]
set jusr [strRepeat " " $mr]
if { $FullLine } then {
return "${jusl}${line}${jusr}"
} else {
return "${jusl}${line}"
}
}
# For a plain justification, it's a little bit complex:
#
# if some spaces are missing, then
#
# 1) sort the list of words in the current line by decreasing size
# 2) foreach word, add one space before it, except if it's the
# first word, until enough spaces are added
# 3) rebuild the line
if { "$justify" == "plain" } then {
set miss [ expr { $Length - [ string length $line ] } ]
# Bugfix tcllib-bugs-860753 (jhv)
set words [split $line]
set numWords [llength $words]
if {$numWords < 2} {
# current line consists of less than two words - we can't
# insert blanks to achieve a plain justification => leave
# $line unchanged and return!
return $line
}
for {set i 0; set totalLen 0} {$i < $numWords} {incr i} {
set w($i) [lindex $words $i]
if {$i > 0} {set w($i) " $w($i)"}
set wLen($i) [string length $w($i)]
set totalLen [expr {$totalLen+$wLen($i)}]
}
set miss [expr {$Length - $totalLen}]
# len walks through all lengths of words of the line under
# consideration
for {set len 1} {$miss > 0} {incr len} {
for {set i 1} {($i < $numWords) && ($miss > 0)} {incr i} {
if {$wLen($i) == $len} {
set w($i) " $w($i)"
incr wLen($i)
incr miss -1
}
}
}
set line ""
for {set i 0} {$i < $numWords} {incr i} {
set line "$line$w($i)"
}
# End of bugfix
return "${line}"
}
error "Illegal justification key \"$justify\""
}
proc ::textutil::adjust::SortList { list dir index } {
if { [ catch { lsort -integer -$dir -index $index $list } sl ] != 0 } then {
error "$sl"
}
return $sl
}
# Hyphenation utilities based on Knuth's algorithm
#
# Copyright (C) 2001-2003 by Dr.Johannes-Heinrich Vogeler (jhv)
# These procedures may be used as part of the tcllib
# textutil::adjust::Hyphenation
#
# Hyphenate a string using Knuth's algorithm
#
# Parameters:
# str string to be hyphenated
#
# Returns:
# the hyphenated string
proc ::textutil::adjust::Hyphenation { str } {
# if there are manual set hyphenation marks e.g. "Recht\-schrei\-bung"
# use these for hyphenation and return
if {[regexp {[^\\-]*[\\-][.]*} $str]} {
regsub -all {(\\)(-)} $str {-} tmp
return [split $tmp -]
}
# Don't hyphenate very short words! Minimum length for hyphenation
# is set to 3 characters!
if { [string length $str] < 4 } then { return $str }
# otherwise follow Knuth's algorithm
variable HyphPatterns; # hyphenation patterns (TeX)
set w ".[string tolower $str]."; # transform to lower case
set wLen [string length $w]; # and add delimiters
# Initialize hyphenation weights
set s {}
for {set i 0} {$i < $wLen} {incr i} {
lappend s 0
}
for {set i 0} {$i < $wLen} {incr i} {
set kmax [expr {$wLen-$i}]
for {set k 1} {$k < $kmax} {incr k} {
set sw [string range $w $i [expr {$i+$k}]]
if {[info exists HyphPatterns($sw)]} {
set hw $HyphPatterns($sw)
set hwLen [string length $hw]
for {set l1 0; set l2 0} {$l1 < $hwLen} {incr l1} {
set c [string index $hw $l1]
if {[string is digit $c]} {
set sPos [expr {$i+$l2}]
if {$c > [lindex $s $sPos]} {
set s [lreplace $s $sPos $sPos $c]
}
} else {
incr l2
}
}
}
}
}
# Replace all even hyphenation weigths by zero
for {set i 0} {$i < [llength $s]} {incr i} {
set c [lindex $s $i]
if {!($c%2)} { set s [lreplace $s $i $i 0] }
}
# Don't start with a hyphen! Take also care of words enclosed in quotes
# or that someone has forgotten to put a blank between a punctuation
# character and the following word etc.
for {set i 1} {$i < ($wLen-1)} {incr i} {
set c [string range $w $i end]
if {[regexp {^[:alpha:][.]*} $c]} {
for {set k 1} {$k < ($i+1)} {incr k} {
set s [lreplace $s $k $k 0]
}
break
}
}
# Don't separate the last character of a word with a hyphen
set max [expr {[llength $s]-2}]
if {$max} {set s [lreplace $s $max end 0]}
# return the syllabels of the hyphenated word as a list!
set ret ""
set w ".$str."
for {set i 1} {$i < ($wLen-1)} {incr i} {
if {[lindex $s $i]} { append ret - }
append ret [string index $w $i]
}
return [split $ret -]
}
# textutil::adjust::listPredefined
#
# Return the names of the hyphenation files coming with the package.
#
# Parameters:
# None.
#
# Result:
# List of filenames (without directory)
proc ::textutil::adjust::listPredefined {} {
variable here
return [glob -type f -directory $here -tails *.tex]
}
# textutil::adjust::getPredefined
#
# Retrieve the full path for a predefined hyphenation file
# coming with the package.
#
# Parameters:
# name Name of the predefined file.
#
# Results:
# Full path to the file, or an error if it doesn't
# exist or is matching the pattern *.tex.
proc ::textutil::adjust::getPredefined {name} {
variable here
if {![string match *.tex $name]} {
return -code error \
"Illegal hyphenation file \"$name\""
}
set path [file join $here $name]
if {![file exists $path]} {
return -code error \
"Unknown hyphenation file \"$path\""
}
return $path
}
# textutil::adjust::readPatterns
#
# Read hyphenation patterns from a file and store them in an array
#
# Parameters:
# filNam name of the file containing the patterns
proc ::textutil::adjust::readPatterns { filNam } {
variable HyphPatterns; # hyphenation patterns (TeX)
# HyphPatterns(_LOADED_) is used as flag for having loaded
# hyphenation patterns from the respective file (TeX format)
if {[info exists HyphPatterns(_LOADED_)]} {
unset HyphPatterns(_LOADED_)
}
# the array xlat provides translation from TeX encoded characters
# to those of the ISO-8859-1 character set
set xlat(\"s) \337; # 223 := sharp s "
set xlat(\`a) \340; # 224 := a, grave
set xlat(\'a) \341; # 225 := a, acute
set xlat(\^a) \342; # 226 := a, circumflex
set xlat(\"a) \344; # 228 := a, diaeresis "
set xlat(\`e) \350; # 232 := e, grave
set xlat(\'e) \351; # 233 := e, acute
set xlat(\^e) \352; # 234 := e, circumflex
set xlat(\`i) \354; # 236 := i, grave
set xlat(\'i) \355; # 237 := i, acute
set xlat(\^i) \356; # 238 := i, circumflex
set xlat(\~n) \361; # 241 := n, tilde
set xlat(\`o) \362; # 242 := o, grave
set xlat(\'o) \363; # 243 := o, acute
set xlat(\^o) \364; # 244 := o, circumflex
set xlat(\"o) \366; # 246 := o, diaeresis "
set xlat(\`u) \371; # 249 := u, grave
set xlat(\'u) \372; # 250 := u, acute
set xlat(\^u) \373; # 251 := u, circumflex
set xlat(\"u) \374; # 252 := u, diaeresis "
set fd [open $filNam RDONLY]
set status 0
while {[gets $fd line] >= 0} {
switch -exact $status {
PATTERNS {
if {[regexp {^\}[.]*} $line]} {
# End of patterns encountered: set status
# and ignore that line
set status 0
continue
} else {
# This seems to be pattern definition line; to process it
# we have first to do some editing
#
# 1) eat comments in a pattern definition line
# 2) eat braces and coded linefeeds
set z [string first "%" $line]
if {$z > 0} { set line [string range $line 0 [expr {$z-1}]] }
regsub -all {(\\n|\{|\})} $line {} tmp
set line $tmp
# Now $line should consist only of hyphenation patterns
# separated by white space
# Translate TeX encoded characters to ISO-8859-1 characters
# using the array xlat defined above
foreach x [array names xlat] {
regsub -all {$x} $line $xlat($x) tmp
set line $tmp
}
# split the line and create a lookup array for
# the repective hyphenation patterns
foreach item [split $line] {
if {[string length $item]} {
if {![string match {\\} $item]} {
# create index for hyphenation patterns
set var $item
regsub -all {[0-9]} $var {} idx
# store hyphenation patterns as elements of an array
set HyphPatterns($idx) $item
}
}
}
}
}
EXCEPTIONS {
if {[regexp {^\}[.]*} $line]} {
# End of patterns encountered: set status
# and ignore that line
set status 0
continue
} else {
# to be done in the future
}
}
default {
if {[regexp {^\\endinput[.]*} $line]} {
# end of data encountered, stop processing and
# ignore all the following text ..
break
} elseif {[regexp {^\\patterns[.]*} $line]} {
# begin of patterns encountered: set status
# and ignore that line
set status PATTERNS
continue
} elseif {[regexp {^\\hyphenation[.]*} $line]} {
# some particular cases to be treated separately
set status EXCEPTIONS
continue
} else {
set status 0
}
}
}
}
close $fd
set HyphPatterns(_LOADED_) 1
return
}
#######################################################
# @c The specified <a text>block is indented
# @c by <a prefix>ing each line. The first
# @c <a hang> lines ares skipped.
#
# @a text: The paragraph to indent.
# @a prefix: The string to use as prefix for each line
# @a prefix: of <a text> with.
# @a skip: The number of lines at the beginning to leave untouched.
#
# @r Basically <a text>, but indented a certain amount.
#
# @i indent
# @n This procedure is not checked by the testsuite.
proc ::textutil::adjust::indent {text prefix {skip 0}} {
set text [string trimright $text]
set res [list]
foreach line [split $text \n] {
if {[string compare "" [string trim $line]] == 0} {
lappend res {}
} else {
set line [string trimright $line]
if {$skip <= 0} {
lappend res $prefix$line
} else {
lappend res $line
}
}
if {$skip > 0} {incr skip -1}
}
return [join $res \n]
}
# Undent the block of text: Compute LCP (restricted to whitespace!)
# and remove that from each line. Note that this preverses the
# shaping of the paragraph (i.e. hanging indent are _not_ flattened)
# We ignore empty lines !!
proc ::textutil::adjust::undent {text} {
if {$text == {}} {return {}}
set lines [split $text \n]
set ne [list]
foreach l $lines {
if {[string length [string trim $l]] == 0} continue
lappend ne $l
}
set lcp [::textutil::string::longestCommonPrefixList $ne]
if {[string length $lcp] == 0} {return $text}
regexp "^(\[\t \]*)" $lcp -> lcp
if {[string length $lcp] == 0} {return $text}
set len [string length $lcp]
set res [list]
foreach l $lines {
if {[string length [string trim $l]] == 0} {
lappend res {}
} else {
lappend res [string range $l $len end]
}
}
return [join $res \n]
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::adjust {
variable here [file dirname [info script]]
variable Justify left
variable Length 72
variable FullLine 0
variable StrictLength 0
variable Hyphenate 0
variable HyphPatterns
namespace export adjust indent undent
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::adjust 0.7.3

902
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/dehypht.tex

@ -0,0 +1,902 @@
% This is `dehypht.tex' as of 03 March 1999.
%
% Copyright (C) 1988,1991 Rechenzentrum der Ruhr-Universitaet Bochum
% [german hyphen patterns]
% Copyright (C) 1993,1994,1999 Bernd Raichle/DANTE e.V.
% [macros, adaption for TeX 2]
%
% -----------------------------------------------------------------
% IMPORTANT NOTICE:
%
% This program can be redistributed and/or modified under the terms
% of the LaTeX Project Public License Distributed from CTAN
% archives in directory macros/latex/base/lppl.txt; either
% version 1 of the License, or any later version.
% -----------------------------------------------------------------
%
%
% This file contains german hyphen patterns following traditional
% hyphenation rules and includes umlauts and sharp s, but without
% `c-k' and triple consonants. It is based on hyphen patterns
% containing 5719 german hyphen patterns with umlauts in the
% recommended version of September 27, 1990.
%
% For use with TeX generated by
%
% Norbert Schwarz
% Rechenzentrum Ruhr-Universitaet Bochum
% Universitaetsstrasse 150
% D-44721 Bochum, FRG
%
%
% Adaption of these patterns for TeX, Version 2.x and 3.x and
% all fonts in T1/`Cork'/EC/DC and/or OT1/CM encoding by
%
% Bernd Raichle
% Stettener Str. 73
% D-73732 Esslingen, FRG
% Email: raichle@Informatik.Uni-Stuttgart.DE
%
%
% Error reports in case of UNCHANGED versions to
%
% DANTE e.V., Koordinator `german.sty'
% Postfach 10 18 40
% D-69008 Heidelberg, FRG
% Email: german@Dante.DE
%
% or one of the addresses given above.
%
%
% Changes:
% 1990-09-27 First version of `ghyphen3.tex' (Norbert Schwarz)
% 1991-02-13 PC umlauts changed to ^^xx (Norbert Schwarz)
% 1993-08-27 Umlauts/\ss changed to "a/\3 macros, added macro
% definitions and additional logic to select correct
% patterns/encoding (Bernd Raichle)
% 1994-02-13 Release of `ghyph31.tex' V3.1a (Bernd Raichle)
% 1999-03-03 Renamed file to `dehypht.tex' according to the
% naming scheme using the ISO country code `de', the
% common part `hyph' for all hyphenation patterns files,
% and the additional postfix `t' for traditional,
% removed wrong catcode change of ^^e (the comment
% character %) and ^^f (the character &),
% do _not_ change \catcode, \lccode, \uccode to avoid
% problems with other hyphenation pattern files,
% changed code to distinguish TeX 2.x/3.x,
% changed license conditions to LPPL (Bernd Raichle)
%
%
% For more information see the additional documentation
% at the end of this file.
%
% -----------------------------------------------------------------
%
\message{German Traditional Hyphenation Patterns %
`dehypht' Version 3.2a <1999/03/03>}
\message{(Formerly known under the name `ghyph31' and `ghyphen'.)}
%
%
% Next we define some commands which are used inside the patterns.
% To keep them local, we enclose the rest of the file in a group
% (The \patterns command globally changes the hyphenation trie!).
%
\begingroup
%
%
% Make sure that doublequote is not active:
\catcode`\"=12
%
%
% Because ^^e4 is used in the following macros which is read by
% TeX 2.x as ^^e or %, the comment character of TeX, some trick
% has to be found to avoid this problem. The same is true for the
% character ^^f or & in the TeX 2.x code.
% Therefore in the code the exclamationmark ! is used instead of
% the circumflex ^ and its \catcode is set appropriately
% (normally \catcode`\!=12, in the code \catcode`\!=7).
%
% The following \catcode, \lccode assignments and macro definitions
% are defined in such a way that the following \pattern{...} list
% can be used for both, TeX 2.x and TeX 3.x.
%
% We first change the \lccode of ^^Y to make sure that we can
% include this character in the hyphenation patterns.
%
\catcode`\^^Y=11 \lccode`\^^Y=`\^^Y
%
% Then we have to define some macros depending on the TeX version.
% Therefore we have to distinguish TeX version 2.x and 3.x:
%
\ifnum`\@=`\^^40 % true => TeX 3.x
%
% For TeX 3:
% ----------
%
% Assign appropriate \catcode and \lccode values for all
% accented characters used in the patterns (\uccode changes are
% not used within \patterns{...} and thus not necessary):
%
\catcode"E4=11 \catcode"C4=11 % \"a \"A
\catcode"F6=11 \catcode"D6=11 % \"o \"O
\catcode"FC=11 \catcode"DC=11 % \"u \"U
\catcode"FF=11 \catcode"DF=11 % \ss SS
%
\lccode"C4="E4 \uccode"C4="C4 \lccode"E4="E4 \uccode"E4="C4
\lccode"D6="F6 \uccode"D6="D6 \lccode"F6="F6 \uccode"F6="D6
\lccode"DC="FC \uccode"DC="DC \lccode"FC="FC \uccode"FC="DC
\lccode"DF="FF \uccode"DF="DF \lccode"FF="FF \uccode"FF="DF
%
% In the following definitions we use ??xy instead of ^^xy
% to avoid errors when reading the following macro definitions
% with TeX 2.x (remember ^^e(4) is the comment character):
%
\catcode`\?=7
%
% Define the accent macro " in such a way that it
% expands to single letters in font encoding T1.
\catcode`\"=13
\def"#1{\ifx#1a??e4\else \ifx#1o??f6\else \ifx#1u??fc\else
\errmessage{Hyphenation pattern file corrupted!}%
\fi\fi\fi}
%
% - patterns with umlauts are ok
\def\n#1{#1}
%
% For \ss which exists in T1 _and_ OT1 encoded fonts but with
% different glyph codes, duplicated patterns for both encodings
% are included. Thus you can use these hyphenation patterns for
% T1 and OT1 encoded fonts:
% - define \3 to be code `\^^ff (\ss in font encoding T1)
% - define \9 to be code `\^^Y (\ss in font encoding OT1)
\def\3{??ff}
\def\9{??Y}
% - duplicated patterns to support font encoding OT1 are ok
\def\c#1{#1}
% >>>>>> UNCOMMENT the next line, if you do not want
% >>>>>> to use fonts in font encoding OT1
%\def\c#1{}
%
\catcode`\?=12
%
\else
%
% For TeX 2:
% ----------
%
% Define the accent macro " to throw an error message.
\catcode`\"=13
\def"#1{\errmessage{Hyphenation pattern file corrupted!}}
%
% - ignore all patterns with umlauts
\def\n#1{}
%
% With TeX 2 fonts in encoding T1 can be used, but all glyphs
% in positions > 127 can not be used in hyphenation patterns.
% Thus only patterns with glyphs in OT1 positions are included:
% - define \3 to be code ^^Y (\ss in CM font encoding)
% - define \9 to throw an error message
\def\3{^^Y}
\def\9{\errmessage{Hyphenation pattern file corrupted!}}
% - ignore all duplicated patterns with \ss in T1 encoding
\def\c#1{}
%
\fi
%
%
\patterns{%
.aa6l .ab3a4s .ab3ei .abi2 .ab3it .ab1l .ab1r .ab3u .ad3o4r .alti6
.ana3c .an5alg .an1e .ang8s .an1s .ap1p .ar6sc .ar6ta .ar6tei .as2z
.au2f1 .au2s3 .be5erb .be3na .ber6t5r .bie6r5 .bim6s5t .brot3 .bru6s
.ch6 .che6f5 .da8c .da2r .dar5in .dar5u .den6ka .de5r6en .des6pe
.de8spo .de3sz .dia3s4 .dien4 .dy2s1 .ehren5 .eine6 .ei6n5eh .ei8nen
.ein5sa .en6der .en6d5r .en3k4 .en8ta8 .en8tei .en4t3r .epo1 .er6ban
.er6b5ei .er6bla .er6d5um .er3ei .er5er .er3in .er3o4b .erwi5s .es1p
.es8t .ex1a2 .ex3em .fal6sc .fe6st5a .flu4g3 .furch8 .ga6ner .ge3n4a
\n{.ge5r"o} .ges6 .halb5 .halbe6 .hal6br .haup4 .hau4t .heima6 .he4r3e
.her6za .he5x .hin3 .hir8sc .ho4c .hu3sa .hy5o .ibe5 .ima6ge .in1
.ini6 .is5chi .jagd5 .kal6k5o .ka6ph .ki4e .kop6f3 .kraf6 \n{.k"u5ra}
.lab6br .liie6 .lo6s5k \n{.l"o4s3t} .ma5d .mi2t1 .no6th .no6top
.obe8ri .ob1l .obs2 .ob6st5e .or3c .ort6s5e .ost3a .oste8r .pe4re
.pe3ts .ph6 .po8str .rau4m3 .re5an .ro8q .ru5the \n{.r"u5be}
\n{.r"u8stet} .sch8 .se6e .se5n6h .se5ra .si2e .spi6ke .st4 .sy2n
.tages5 .tan6kl .ta8th .te6e .te8str .to6der .to8nin .to6we .um1
.umpf4 .un1 .une6 .unge5n .ur1c .ur5en .ve6rin .vora8 .wah6l5 .we8ges
.wo6r .wor3a .wun4s .zi4e .zuch8 \n{."ande8re} \n{."och8} aa1c aa2gr
aal5e aa6r5a a5arti aa2s1t aat2s 6aba ab3art 1abdr 6abel aben6dr
ab5erk ab5err ab5esse 1abf 1abg \n{1abh"a} ab1ir 1abko a1bl ab1la
5ablag a6bla\3 \c{a6bla\9} ab4ler ab1lu \n{a8bl"a} \n{5a6bl"o} abma5c
1abn ab1ra ab1re 5a6brec ab1ro ab1s ab8sk abs2z 3abtei ab1ur 1abw
5abze 5abzu \n{ab1"an} \n{ab"au8} a4ce. a5chal ach5art ach5au a1che
a8chent ach6er. a6ch5erf a1chi ach1l ach3m ach5n a1cho ach3re a1chu
ach1w a1chy \n{ach5"af} ack1o acks6t ack5sta a1d 8ad. a6d5ac ad3ant
ad8ar 5addi a8dein ade5o8 adi5en 1adj 1adle ad1op a2dre 3adres adt1
1adv \n{a6d"a} a1e2d ae1r a1er. 1aero 8afa a3fal af1an a5far a5fat
af1au a6fentl a2f1ex af1fr af5rau af1re 1afri af6tent af6tra aft5re
a6f5um \n{8af"a} ag5abe 5a4gent ag8er ages5e 1aggr ag5las ag1lo a1gn
ag2ne 1agog a6g5und a1ha a1he ah5ein a4h3erh a1hi ahl1a ah1le ah4m3ar
ahn1a a5ho ahra6 ahr5ab ah1re ah8rei ahren8s ahre4s3 ahr8ti ah1ru a1hu
\n{ah8"o} ai3d2s ai1e aif6 a3inse ai4re. a5isch. ais8e a3ismu ais6n
aiso6 a1j 1akad a4kade a1ke a1ki 1akko 5akro1 a5lal al5ans 3al8arm
al8beb al8berw alb5la 3album al1c a1le a6l5e6be a4l3ein a8lel a8lerb
a8lerh a6lert 5a6l5eth 1algi al4gli al3int al4lab al8lan al4l3ar
alle3g a1lo a4l5ob al6schm al4the altist5 al4t3re 8a1lu alu5i a6lur
alu3ta \n{a1l"a} a6mate 8ame. 5a6meise am6m5ei am6mum am2n ampf3a
am6schw am2ta a1mu \n{a1m"a} a3nac a1nad anadi5e an3ako an3alp 3analy
an3ame an3ara a1nas an5asti a1nat anat5s an8dent ande4s3 an1ec an5eis
an1e2k 4aner. a6n5erd a8nerf a6n5erke 1anfa 5anfert \n{1anf"a} 3angab
5angebo an3gli ang6lis an2gn 3angri ang5t6 \n{5anh"a} ani5g ani4ka
an5i8on an1kl an6kno an4kro 1anl anma5c anmar4 3annah anne4s3 a1no
5a6n1o2d 5a6n3oma 5a6nord 1anr an1sa 5anschl an4soz an1st 5anstal
an1s2z 5antenn an1th \n{5anw"a} a5ny an4z3ed 5anzeig 5anzieh 3anzug
\n{an1"a} \n{5an"as} \n{a1n"o} \n{an"o8d} a1os a1pa 3apfel a2ph1t
\n{aph5"a6} a1pi 8apl apo1c apo1s a6poste a6poth 1appa ap1pr a1pr
\n{a5p"a} \n{a3p"u} a1ra a4r3af ar3all 3arbei 2arbt ar1c 2a1re ar3ein
ar2gl 2a1ri ari5es ar8kers ar6les ar4nan ar5o6ch ar1o2d a1rol ar3ony
a8ror a3ros ar5ox ar6schl 8artei ar6t5ri a1ru a1ry 1arzt arz1w
\n{ar8z"a} \n{ar"a8m} \n{ar"o6} \n{ar5"om} \n{ar1"u2} a1sa a6schec
asch5l asch3m a6schn a3s4hi as1pa asp5l a8steb as5tev 1asth a6stoc
a1str ast3re 8a1ta ata5c ata3la a6tapf ata5pl a1te a6teli aten5a
ate5ran 6atf 6atg a1th at3hal 1athl 2a1ti 5atlant 3atlas 8atmus 6atn
a1to a6t5ops ato6ra a6t5ort. 4a1tr a6t5ru at2t1h \n{at5t6h"a} 6a1tu
atz1w \n{a1t"a} \n{a1t"u} au1a au6bre auch3a au1e aue4l 5aufent
\n{3auff"u} 3aufga 1aufn auf1t 3auftr 1aufw 3auge. au4kle aule8s 6aum
au8mar aum5p 1ausb 3ausd 1ausf 1ausg au8sin 3auss au4sta 1ausw 1ausz
aut5eng au1th 1auto au\3e8 \c{au\9e8} a1v ave5r6a aver6i a1w a6wes a1x
a2xia a6xio a1ya a1z azi5er. 8a\3 \c{8a\9} 1ba 8ba8del ba1la ba1na
ban6k5r ba5ot bardi6n ba1ro basten6 bau3sp 2b1b bb6le b2bli 2b1c 2b1d
1be be1a be8at. be1ch 8becht 8becke. be5el be1en bee8rei be5eta bef2
8beff be1g2 \n{beh"o8} bei1s 6b5eisen bei3tr b8el bel8o belu3t be3nac
bend6o be6ners be6nerw be4nor ben4se6 bens5el \n{be1n"a} \n{be1n"u}
be1o2 b8er. be1ra be8rac ber8gab. ber1r \n{be1r"u} bes8c bes5erh
bes2p be5tha bet5sc be1un be1ur 8bex be6zwec 2b1f8 bfe6st5e 2b1g2
bga2s5 bge1 2b1h bhole6 1bi bi1bl b6ie bi1el bi1la \n{bil"a5} bi1na
bi4nok bi5str bi6stu bi5tr bit4t5r b1j 2b1k2 \n{bk"u6} bl8 b6la.
6b1lad 6blag 8blam 1blat b8latt 3blau. b6lav 3ble. b1leb b1led
8b1leg 8b1leh 8bleid 8bleih 6b3lein blei3s ble4m3o 4blich b4lind
8bling b2lio 5blit b4litz b1loh 8b1los 1blu 5blum 2blun blut3a blut5sc
\n{3bl"a} \n{bl"as5c} \n{5bl"o} \n{3bl"u} \n{bl"u8sc} 2b1m 2b1n 1bo
bo1ch bo5d6s boe5 8boff 8bonk bo1ra b1ort 2b1p2 b1q 1br brail6 brast8
bre4a b5red 8bref 8b5riem b6riga bro1s b1rup b2ruz \n{8br"oh}
\n{br"os5c} 8bs b1sa b8sang b2s1ar b1sc bs3erl bs3erz b8sof b1s2p
bst1h b3stru \n{b5st"a} b6sun 2b1t b2t1h 1bu bu1ie bul6k b8ure bu6sin
6b1v 2b1w 1by1 by6te. 8b1z bzi1s \n{1b"a} \n{b5"a6s5} \n{1b"u}
\n{b6"u5bere} \n{b"uge6} \n{b"ugel5e} \n{b"ur6sc} 1ca cag6 ca5la ca6re
ca5y c1c 1ce celi4c celich5 ce1ro c8h 2ch. 1chae ch1ah ch3akt cha6mer
8chanz 5chara 3chari 5chato 6chb 1chef 6chei ch3eil ch3eis 6cherkl
6chf 4chh 5chiad 5chias 6chins 8chj chl6 5chlor 6ch2m 2chn6 ch8nie
5cho. 8chob choi8d 6chp ch3ren ch6res \n{ch3r"u} 2chs 2cht cht5ha
cht3hi 5chthon ch6tin 6chuh chu4la 6ch3unt chut6t 8chw 1ci ci5tr c2k
2ck. ck1ei 4ckh ck3l ck3n ck5o8f ck1r 2cks ck5stra ck6s5u c2l 1c8o
con6ne 8corb cos6t c3q 1c6r 8c1t 1cu 1cy \n{5c"a1} \n{c"o5} 1da.
8daas 2dabg 8dabr 6dabt 6dabw 1dac da2gr 6d5alk 8d5amt dan6ce.
dani5er dan8ker 2danl danla6 6dans 8danzi 6danzu d1ap da2r1a8 2d1arb
d3arc dar6men 4d3art 8darz 1dat 8datm 2d1auf 2d1aus 2d1b 2d1c 2d1d
d5de d3d2h \n{dd"amme8} 1de 2deal de5an de3cha de1e defe6 6deff 2d1ehr
5d4eic de5isc de8lar del6s5e del6spr de4mag de8mun de8nep dene6r
8denge. 8dengen de5o6d 2deol de5ram 8derdb der5ein de1ro der1r d8ers
der5um de4s3am de4s3an de4sau de6sil de4sin de8sor de4spr de2su 8deul
de5us. 2d1f df2l 2d1g 2d1h 1di dia5c di5ara dice5 di3chr di5ena di1gn
di1la dil8s di1na 8dind 6dinf 4d3inh 2d1ins di5o6d di3p4t di8sen dis1p
di5s8per di6s5to dis5tra di8tan di8tin d1j 6dje 2dju 2d1k 2d1l 2d1m
2d1n6 dni6 dnje6 1do 6d5obe do6berf 6d5ony do3ran 6dord 2d1org dor4t3h
do6ste 6doth dott8e 2d1p d5q dr4 1drah 8drak d5rand 6dre. 4drech
d6reck 4d3reg 8d3reic d5reife 8drem 8d1ren 2drer 8dres. 6d5rh 1dria
d1ric 8drind droi6 dro5x 1dru 8drut \n{dr"os5c} \n{1dr"u} \n{dr"u5b}
\n{dr"u8sc} 2ds d1sa d6san dsat6 d1sc 5d6scha. 5dschik dse8e d8serg
8dsl d1sp d4spak ds2po \n{d8sp"a} d1st \n{d1s"u} 2dt d1ta d1te d1ti
d1to dt1s6 d1tu \n{d5t"a} 1du du5als du1b6 du1e duf4t3r 4d3uh du5ie
8duml 8dumw 2d1und du8ni 6d5unt dur2c durch3 6durl 6dursa 8durt du1s
du8schr 2d1v 2d1w dwa8l 2d1z \n{1d"a} \n{6d"ah} \n{8d"and} \n{d"a6r}
\n{d"o8bl} \n{d5"ol} \n{d"or6fl} \n{d"o8sc} \n{d5"o4st} \n{d"os3te}
\n{1d"u} ea4ben e1ac e1ah e1akt e1al. e5alf e1alg e5a8lin e1alk e1all
e5alp e1alt e5alw e1am e1and ea6nim e1ar. e5arf e1ark e5arm e3art
e5at. e6ate e6a5t6l e8ats e5att e6au. e1aus e1b e6b5am ebens5e
eb4lie eb4ser eb4s3in e1che e8cherz e1chi ech3m 8ech3n ech1r ech8send
ech4su e1chu eck5an e5cl e1d ee5a ee3e ee5g e1ei ee5isc eei4s3t
ee6lend e1ell \n{ee5l"o} e1erd ee3r4e ee8reng eere6s5 \n{ee5r"a}
ee6tat e1ex e1f e6fau e8fe8b 3effek ef3rom ege6ra eglo6si 1egy e1ha
e6h5ach eh5ans e6hap eh5auf e1he e1hi ehl3a eh1le ehl5ein eh1mu ehn5ec
e1ho ehr1a eh1re ehre6n eh1ri eh1ru ehr5um e1hu eh1w e1hy \n{e1h"a}
\n{e1h"o} \n{e3h"ut} ei1a eia6s ei6bar eich3a eich5r ei4dar ei6d5ei
ei8derf ei3d4sc ei1e 8eifen 3eifri 1eign eil1d ei6mab ei8mag ein1a4
ei8nat ei8nerh ei8ness ei6nete ein1g e8ini ein1k ei6n5od ei8nok ei4nor
\n{e3ins"a} ei1o e1irr ei5ru ei8sab ei5schn ei6s5ent ei8sol ei4t3al
eit3ar eit1h ei6thi ei8tho eit8samt ei6t5um e1j 1ekd e1ke e1ki e1k2l
e1kn ekni4 e1la e2l1al 6elan e6lanf e8lanl e6l5ans el3arb el3arm
e6l3art 5e6lasti e6lauge elbst5a e1le 6elef ele6h e6l5ehe e8leif
e6l5einh 1elek e8lel 3eleme e6lemen e6lente el5epi e4l3err e6l5ersc
elf2l elg2 e6l5ins ell8er 4e1lo e4l3ofe el8soh el8tent 5eltern e1lu
elut2 \n{e1l"a} \n{e1l"u} em8dei em8meis 4emo emo5s 1emp1f 1empt 1emto
e1mu emurk4 emurks5 \n{e1m"a} en5a6ben en5achs en5ack e1nad en5af
en5all en3alt en1am en3an. en3ant en3anz en1a6p en1ar en1a6s 6e1nat
en3auf en3aus en2ce enda6l end5erf end5erg en8dess 4ene. en5eck
e8neff e6n5ehr e6n5eim en3eis 6enem. 6enen e4nent 4ener. e8nerd
e6n3erf e4nerg 5energi e6n5erla en5ers e6nerst en5erw 6enes e6n5ess
e2nex en3glo 2eni enni6s5 ennos4 enns8 e1no e6nober eno8f en5opf
e4n3ord en8sers ens8kl en1sp ens6por en5t6ag enta5go en8terbu en6tid
3entla ent5ric 5entwic 5entwu 1entz enu5i e3ny en8zan \n{en1"of}
\n{e1n"os} \n{e1n"ug} eo1c e5o6fe e5okk e1on. e3onf e5onk e5onl e5onr
e5opf e5ops e5or. e1ord e1org eo5r6h eo1t e1pa e8pee e6p5e6g ep5ent
e1p2f e1pi 5epid e6pidem e1pl 5epos e6pos. ep4p3a e1pr \n{e1p"a} e1q
e1ra. er5aal 8eraba e5rabel er5a6ben e5rabi er3abs er3ach era5e
era5k6l er3all er3amt e3rand e3rane er3ans e5ranz. e1rap er3arc
e3rari er3a6si e1rat erat3s er3auf e3raum 3erbse er1c e1re 4e5re.
er3eck er5egg er5e2h 2erei e3rei. e8reine er5einr 6eren. e4r3enm
4erer. e6r5erm er5ero er5erst e4r3erz er3ess \n{5erf"ul} er8gan.
5ergebn er2g5h \n{5erg"anz} \n{5erh"ohu} 2e1ri eri5ak e6r5iat e4r3ind
e6r5i6n5i6 er5ins e6r5int er5itio er1kl \n{3erkl"a} \n{5erl"os.}
ermen6s er6nab 3ernst 6e1ro. e1rod er1o2f e1rog 6e3roi ero8ide e3rol
e1rom e1ron e3rop8 e2r1or e1ros e1rot er5ox ersch4 5erstat er6t5ein
er2t1h er5t6her 2e1ru eruf4s3 e4r3uhr er3ums e5rus 5erwerb e1ry er5zwa
er3zwu \n{er"a8m} \n{er5"as} \n{er"o8} \n{e3r"os.} \n{e6r1"u2b} e1sa
esa8b e8sap e6s5a6v e1sc esch4l ese1a es5ebe eserve5 e8sh es5ill
es3int es4kop e2sl eso8b e1sp espei6s5 es2po es2pu 5essenz e6stabs
e6staf e6st5ak est3ar e8stob e1str est5res es3ur e2sz \n{e1s"u} e1ta
et8ag etari5e eta8ta e1te eten6te et5hal e5thel e1ti 1etn e1to e1tr
et3rec e8tscha et8se et6tei et2th et2t1r e1tu etu1s et8zent et8zw
\n{e1t"a} \n{e1t"o} \n{e1t"u} eu1a2 eu1e eue8rei eu5fe euin5 euk2
e1um. eu6nio e5unter eu1o6 eu5p 3europ eu1sp eu5str eu8zo e1v eval6s
eve5r6en ever4i e1w e2wig ex1or 1exp 1extr ey3er. e1z \n{e1"a2}
\n{e5"o8} \n{e1"u} e8\3es \c{e8\9es} fa6ch5i fade8 fa6del fa5el.
fal6lo falt8e fa1na fan4gr 6fanl 6fap far6ba far4bl far6r5a 2f1art
fa1sc fau8str fa3y 2f1b2 6f1c 2f1d 1fe 2f1eck fe6dr feh6lei f6eim
8feins f5eis fel5en 8feltern 8femp fe5rant 4ferd. ferri8 fe8stof
fe6str fe6stum fe8tag fet6ta fex1 2ff f1fa f6f5arm f5fe ffe5in ffe6la
ffe8ler ff1f f1fla ff3lei ff4lie ff8sa ff6s5ta 2f1g2 fgewen6 4f1h 1fi
fid4 fi3ds fieb4 fi1la fi8lei fil4m5a f8in. fi1na 8finf fi8scho fi6u
6f1j 2f1k2 f8lanz fl8e 4f3lein 8flib 4fling f2lix 6f3lon 5flop 1flor
\n{5f8l"ac} \n{3fl"ot} 2f1m 2f1n 1fo foh1 f2on fo6na 2f1op fo5ra
for8mei for8str for8th for6t5r fo5ru 6f5otte 2f1p8 f1q fr6 f5ram
1f8ran f8ra\3 \c{f8ra\9} f8re. frei1 5frei. f3reic f3rest f1rib
8f1ric 6frig 1fris fro8na \n{fr"as5t} 2fs f1sc f2s1er f5str
\n{fs3t"at} 2ft f1tak f1te ft5e6h ftere6 ft1h f1ti f5to f1tr ft5rad
ft1sc ft2so f1tu ftwi3d4 ft1z 1fu 6f5ums 6funf fun4ka fu8\3end
\c{fu8\9end} 6f1v 2f1w 2f1z \n{1f"a} \n{f"a1c} \n{8f"arm} \n{6f"aug}
\n{f"a8\3} \n{\c{f"a8\9}} \n{f"ode3} \n{8f"of} \n{3f"or} \n{1f"u}
\n{f"un4f3u} 1ga ga6bl 6gabw 8gabz g3a4der ga8ho ga5isc 4gak ga1la
6g5amt ga1na gan5erb gan6g5a ga5nj 6ganl 8gansc 6garb 2g1arc 2g1arm
ga5ro 6g3arti ga8sa ga8sc ga6stre 2g1atm 6g5auf gau5fr g5aus 2g1b g5c
6gd g1da 1ge ge1a2 ge6an ge8at. ge1e2 ge6es gef2 8geff ge1g2l ge1im
4g3eise geist5r gel8bra gelt8s \n{ge5l"o} ge8nin gen3k 6g5entf
\n{ge3n"a} ge1or ge1ra ge6rab ger8au \n{8gerh"o} ger8ins ge1ro 6g5erz.
\n{ge1r"a} \n{ge1r"u} ge1s ges2p ge5unt 4g3ex3 2g1f8 2g1g g1ha 6g1hei
5ghel. g5henn 6g1hi g1ho 1ghr \n{g1h"o} 1gi gi5la gi8me. gi1na
4g3ins gi3str g1j 2g1k 8gl. 1glad g5lag glan4z3 1glas 6glass 5glaub
g3lauf 1gle. g5leb 3gleic g3lein 5gleis 1glem 2gler 8g3leu gli8a
g2lie 3glied 1g2lik 1g2lim g6lio 1gloa 5glom 1glon 1glop g1los g4loss
g5luf 1g2ly \n{1gl"u} 2g1m gn8 6gn. 1gna 8gnach 2gnah g1nas g8neu
g2nie g3nis 1gno 8gnot 1go goe1 8gof 2gog 5gogr 6g5oh goni5e 6gonist
go1ra 8gord 2g1p2 g1q 1gr4 g5rahm gra8m gra4s3t 6g1rec gre6ge 4g3reic
g5reit 8grenn gri4e g5riem 5grif 2grig g5ring 6groh 2grot gro6\3
\c{gro6\9} 4grut 2gs gs1ab g5sah gs1ak gs1an gs8and gs1ar gs1au g1sc
gs1ef g5seil gs5ein g2s1er gs1in g2s1o gso2r gs1pr g2s1u 2g1t g3te
g2t1h 1gu gu5as gu2e 2gue. 6gued 4g3uh 8gums 6g5unt gu1s gut3h gu2tu
4g1v 2g1w gy1n g1z \n{1g"a} \n{8g"a8m} \n{6g"arm} \n{1g"o} \n{1g"u}
\n{6g"ub} 1haa hab8r ha8del hade4n 8hae ha5el. haf6tr 2hal. ha1la
hal4b5a 6hale 8han. ha1na han6dr han6ge. 2hani h5anth 6hanz 6harb
h3arbe h3arme ha5ro ha2t1h h1atm hau6san ha8\3 \c{ha8\9} h1b2 h1c h1d
he2bl he3cho h3echt he5d6s 5heft h5e6he. hei8ds h1eif 2hein he3ism
he5ist. heit8s3 hek6ta hel8lau 8helt he6mer 1hemm 6h1emp hen5end
hen5klo hen6tri he2nu 8heo he8q her3ab he5rak her3an 4herap her3au
h3erbi he1ro he8ro8b he4r3um her6z5er he4spe he1st heta6 het5am he5th
heu3sc he1xa hey5e h1f2 h1g hgol8 h1h h1iat hie6r5i hi5kt hil1a2
hil4fr hi5nak hin4ta hi2nu hi5ob hirn5e hir6ner hi1sp hi1th hi5tr
5hitz h1j h6jo h1k2 hlabb4 hla4ga hla6gr h5lai hl8am h1las h1la\3
\c{h1la\9} hl1c h1led h3lein h5ler. h2lif h2lim h8linf hl5int h2lip
h2lit h4lor h3lose \n{h1l"as} hme5e h2nee h2nei hn3eig h2nel hne8n
hne4p3f hn8erz h6netz h2nip h2nit h1nol hn5sp h2nuc h2nud h2nul hoch1
1hoh hoh8lei 2hoi ho4l3ar 1holz h2on ho1ra 6horg 5horn. ho3sl hos1p
ho4spi h1p hpi6 h1q 6hr h1rai h8rank h5raum hr1c hrcre8 h1red h3reg
h8rei. h4r3erb h8rert hrg2 h1ric hr5ins h2rom hr6t5erl hr2t1h hr6t5ra
hr8tri h6rum hr1z hs3ach h6s5amt h1sc h6s5ec h6s5erl hs8erle h4sob
h1sp h8spa\3 \c{h8spa\9} h8spel hs6po h4spun h1str h4s3tum hs3und
\n{h1s"u} h5ta. h5tab ht3ac ht1ak ht3ang h5tanz ht1ar ht1at h5taub
h1te h2t1ec ht3eff ht3ehe h4t3eif h8teim h4t3ein ht3eis h6temp h8tentf
hte8ren \n{h6terf"u} h8tergr h4t3erh h6t5ersc h8terst h8tese h8tess
h2t1eu h4t3ex ht1he ht5hu h1ti ht5rak hts3ah ht1sc ht6sex ht8sk ht8so
h1tu htz8 \n{h5t"um} hub5l hu6b5r huh1l h5uhr. huld5a6 hu8lent
\n{hu8l"a} h5up. h1v h5weib h3weis h1z \n{h"a8kl} \n{h"al8s}
\n{h"ama8tu8} \n{h"a8sche.} \n{h"at1s} \n{h"au4s3c} \n{2h"o.}
\n{2h"oe} \n{8h"oi} \n{h"o6s} \n{h"os5c} \n{h"uhne6} \n{h"ul4s3t}
\n{h"utte8re} i5adn i1af i5ak. i1al. i1al1a i1alb i1ald i5alei i1alf
i1alg i3alh i1alk i1all i1alp i1alr i1als i1alt i1alv i5alw i3alz
i1an. ia5na i3and ian8e ia8ne8b i1ang i3ank i5ann i1ant i1anz i6apo
i1ar. ia6rab i5arr i1as. i1asm i1ass i5ast. i1at. i5ats i1au i5azz
i6b5eig i6b5eis ib2le i4blis i6brig i6b5unt \n{i6b"ub} i1che ich5ei
i6cherb i1chi ich5ins ich1l ich3m ich1n i1cho icht5an icht3r i1chu
ich1w ick6s5te ic5l i1d id3arm 3ideal ide8na 3ideol \n{ide5r"o} i6diot
id5rec id1t ie1a ie6b5ar iebe4s3 ie2bl ieb1r ie8bra ie4bre \n{ie8b"a}
ie2dr ie1e8 ie6f5ad ief5f ie2f1l ie4fro ief1t i1ei ie4l3ec ie8lei
ie4lek i3ell i1en. i1end ien6e i3enf i5enn ien6ne. i1enp i1enr
i5ensa ien8stal i5env i1enz ie5o ier3a4b ie4rap i2ere ie4rec ie6r5ein
ie6r5eis ier8er i3ern. ie8rum ie8rund ie6s5che ie6tau ie8tert ie5the
ie6t5ri i1ett ie5un iex5 2if i1fa if5ang i6fau if1fr if5lac i5f6lie
i1fre ift5a if6t5r ig3art 2ige i8gess ig5he i5gla ig2ni i5go ig3rot
ig3s2p i1ha i8ham i8hans i1he i1hi ih1n ih1r i1hu i8hum ih1w 8i1i ii2s
ii2t i1j i1k i6kak i8kerz i6kes ik4ler i6k5unt 2il i5lac i1lag il3ans
i5las i1lau il6auf i1le ile8h i8lel il2fl il3ipp il6l5enn i1lo ilt8e
i1lu \n{i1l"a} i8mart imb2 i8mele i8mid imme6l5a i1mu \n{i1m"a}
\n{i5m"o} ina5he i1nat in1au inau8s 8ind. in4d3an 5index ind2r 3indus
i5nec i2n1ei i8nerw 3infek 1info 5ingeni ing5s6o 5inhab ini5er. 5inj
\n{in8k"at} in8nan i1no inoi8d in3o4ku in5sau in1sp 5inspe 5instit
5instru ins4ze 5intere 5interv in3the in5t2r i5ny \n{in"a2} \n{i1n"ar}
\n{in1"as} \n{in"o8} \n{in5"od} \n{i1n"os} 2io io1a8 io1c iode4 io2di
ioi8 i1ol. i1om. i1on. i5onb ion2s1 i1ont i5ops i5o8pt i1or.
i3oral io3rat i5orc i1os. i1ot. i1o8x 2ip i1pa i1pi i1p2l i1pr i1q
i1ra ir6bl i1re i1ri ir8me8d ir2m1o2 ir8nak i1ro ir5rho ir6schl
ir6sch5r i5rus i5ry \n{i5r"a} i1sa i8samt i6sar i2s1au i8scheh i8schei
isch5m isch3r \n{isch"a8} is8ele ise3ra i4s3erh is3err isi6de i8sind
is4kop ison5e is6por i8s5tum i5sty \n{i5s"o} i1ta it5ab. i2t1a2m
i8tax i1te i8tersc i1thi i1tho i5thr \n{it8h"a} i1ti i8ti8d iti6kl
itmen4 i1to i8tof it3ran it3rau i1tri itri5o it1sc it2se it5spa it8tru
i1tu it6z5erg it6z1w \n{i1t"a} \n{it"a6r5e} \n{it"at2} \n{it"ats5}
\n{i1t"u} i1u iu6r 2i1v i6vad iva8tin i8vei i6v5ene i8verh i2vob i8vur
i1w iwi2 i5xa i1xe i1z ize8n i8zir i6z5w \n{i"a8m} \n{i1"a6r}
\n{i5"at.} \n{i5"av} \n{i1"o8} \n{i"u8} i6\35ers \c{i6\95ers} ja5la
je2t3r 6jm 5jo jo5as jo1ra jou6l ju5cha jugen4 jugend5 jung5s6 ju1s
\n{3j"a} 1ka 8kachs 8kakz ka1la kal5d kam5t ka1na 2kanl 8kapf ka6pl
ka5r6a 6k3arbe ka1ro kar6p5f 4k3arti 8karz \n{ka1r"a} kasi5e ka6teb
kat8ta kauf6s kau3t2 2k1b 2k1c 4k1d kehr6s kehrs5a 8keic 2k1eig 6k5ein
6k5eis ke6lar ke8leis ke8lo 8kemp k5ente. k3entf 8k5ents 6kentz ke1ra
k5erlau 2k1f8 2k1g 2k1h ki5fl 8kik king6s5 6kinh ki5os ki5sp ki5th
\n{8ki8"o} 2k1k2 kl8 1kla 8klac k5lager kle4br k3leib 3kleid kle5isc
4k3leit k3lek 6k5ler. 5klet 2klic 8klig k2lim k2lin 5klip 5klop k3lor
\n{1kl"a} 2k1m kmani5e kn8 6kner k2ni \n{kn"a8} 1k2o ko1a2 ko6de.
ko1i koi8t ko6min ko1op ko1or ko6pht ko3ra kor6d5er ko5ru ko5t6sc k3ou
3kow 6k5ox 2k1p2 k1q 1kr8 4k3rad 2k1rec 4k3reic kre5ie 2krib 6krig
2krip 6kroba 2ks k1sa k6sab ksal8s k8samt k6san k1sc k2s1ex k5spat
k5spe k8spil ks6por k1spr kst8 k2s1uf 2k1t kta8l kt5a6re k8tein kte8re
k2t1h k8tinf kt3rec kt1s 1ku ku1ch kuck8 k3uhr ku5ie kum2s1 kunfts5
kun2s kunst3 ku8rau ku4ro kurz1 ku1st 4kusti ku1ta ku8\3 \c{ku8\9}
6k1v 2k1w ky5n 2k1z \n{1k"a} \n{k"a4m} \n{4k3"ami} \n{k"ase5} \n{1k"o}
\n{k"o1c} \n{k"o1s} \n{1k"u} \n{k"u1c} \n{k"ur6sc} \n{k"u1s} 1la.
8labf 8labh lab2r 2l1abs lach3r la8dr 5ladu 8ladv 6laff laf5t la2gn
5laken 8lamb la6mer 5lampe. 2l1amt la1na 1land lan4d3a lan4d3r lan4gr
8lanme 6lann 8lanw \n{6lan"a} 8lappa lap8pl lap6pr l8ar. la5ra lar4af
la8rag la8ran la6r5a6s l3arbe la8rei 6larm. la8sa la1sc la8sta lat8i
6l5atm 4lauss 4lauto 1law 2lb l8bab l8bauf l8bede l4b3ins l5blo
lbst5an lbst3e 8lc l1che l8chert l1chi lch3m l5cho lch5w 6ld l4d3ei
ld1re \n{l6d"ub} le2bl le8bre lecht6s5 led2r 6leff le4gas 1lehr lei6br
le8inf 8leinn 5leistu 4lektr le6l5ers lemo2 8lemp l8en. 8lends
6lendun le8nend len8erw 6l5ents 4l3entw 4lentz 8lenzy 8leoz 6lepi
le6pip 8lepo 1ler l6er. 8lerbs 6l5erde le8reis le8rend le4r3er 4l3erg
l8ergr 6lerkl 6l5erzie \n{8ler"o} 8lesel lesi5e le3sko le3tha let1s
5leuc 4leuro leu4s3t le5xe 6lexp l1f 2l1g lgend8 l8gh lglie3 lglied6
6l1h 1li li1ar li1as 2lick li8dr li1en lien6n li8ers li8ert 2lie\3
\c{2lie\9} 3lig li8ga8b li1g6n li1l8a 8limb li1na 4l3indu lings5
4l3inh 6linj link4s3 4linkt 2lint 8linv lion5s6t 4lipp 5lipt 4lisam
livi5e 6l1j 6l1k l8keim l8kj lk2l lko8f lkor8 lk2sa lk2se 6ll l1la
ll3a4be l8labt ll8anl ll1b ll1c ll1d6 l1le l4l3eim l6l5eise ller3a
l4leti l5lip l1lo ll3ort ll5ov ll6spr llte8 l1lu ll3urg \n{l1l"a}
\n{l5l"u} \n{l6l"ub} 2l1m l6m5o6d 6ln l1na l1no 8lobl lo6br 3loch.
l5o4fen 5loge. 5lohn 4l3ohr 1lok l2on 4l3o4per lo1ra 2l1ord 6lorg
4lort lo1ru 1los. lo8sei 3losig lo6ve lowi5 6l1p lp2f l8pho l8pn
lp4s3te l2pt l1q 8l1r 2ls l1sa l6sarm l1sc l8sec l6s5erg l4s3ers l8sh
l5s6la l1sp ls4por ls2pu l1str l8suni \n{l1s"u} 2l1t lt5amp l4t3ein
l5ten l6t5eng l6t5erp l4t3hei lt3her l2t1ho l6t5i6b lti1l \n{l8tr"o}
lt1sc lt6ser lt4s3o lt5ums lu8br lu2dr lu1en8 8lu8fe luft3a luf8tr
lu6g5r 2luh l1uhr lu5it 5luk 2l1umf 2l1umw 1lun 6l5u6nio 4l3unte lu5ol
4lurg 6lurs l3urt lu4sto lu3str lu6st5re lu8su lu6tal lu6t5e6g lu8terg
lu3the lu6t5or lu2t1r lu6\35 \c{lu6\95} l1v lve5r6u 2l1w 1ly lya6
6lymp ly1no l8zess l8zo8f l3zwei lz5wu \n{3l"and} \n{l"a5on}
\n{l"a6sc} \n{l"at1s} \n{5l"auf} \n{2l"aug} \n{l"au6s5c} \n{l"a5v}
\n{l1"ol} \n{1l"os} \n{l"o1\36t} \n{\c{l"o1\96t}} \n{6l1"ube} 1ma
8mabg ma5chan mad2 ma5el 4magg mag8n ma1la ma8lau mal5d 8malde mali5e
malu8 ma8lut 2m1amp 3man mand2 man3ds 8mangr mani5o 8m5anst 6mappa
4m3arbe mar8kr ma1r4o mar8schm 3mas ma1sc \n{ma1t"o} 4m5auf ma5yo 2m1b
mb6r 2m1c 2m1d \n{md6s"a} 1me me1ch me5isc 5meld mel8sa 8memp me5nal
men4dr men8schl men8schw 8mentsp me1ra mer4gl me1ro 3mes me6s5ei me1th
me8\3 \c{me8\9} 2m1f6 2m1g 2m1h 1mi mi1a mi6ale mi1la 2m1imm mi1na
\n{mi5n"u} mi4s3an mit1h mi5t6ra 3mitt mitta8 mi6\35 \c{mi6\95} 6mj
2m1k8 2m1l 2m1m m6mad m6m5ak m8menth m8mentw mme6ra m2mn mm5sp mm5ums
mmut5s \n{m8m"an} m1n8 m5ni 1mo mo5ar mo4dr 8mof mo8gal mo4kla mol5d
m2on mon8do mo4n3od mont8a 6m5ony mopa6 mo1ra mor8d5a mo1sc mo1sp 5mot
moy5 2mp m1pa mpfa6 mpf3l mphe6 m1pi mpin6 m1pl mp2li m2plu mpo8ste
m1pr \n{mpr"a5} mp8th mput6 mpu5ts \n{m1p"o} 8m1q 2m1r 2ms ms5au m1sc
msch4l ms6po m3spri m1str 2m1t mt1ar m8tein m2t1h mt6se \n{mt8s"a}
mu5e 6m5uh mumi1 1mun mun6dr muse5e mu1ta 2m1v mvol2 mvoll3 2m1w 1my
2m1z \n{m"a6kl} \n{1m"an} \n{m"a1s} \n{m"a5tr} \n{m"au4s3c} \n{3m"a\3}
\n{\c{3m"a\9}} \n{m"ob2} \n{6m"ol} \n{1m"u} \n{5m"un} \n{3m"ut} 1na.
n5ab. 8nabn n1abs n1abz \n{na6b"a} na2c nach3e 3nacht 1nae na5el
n1afr 1nag 1n2ah na8ha na8ho 1nai 6nair na4kol n1akt nal1a 8naly 1nama
na4mer na1mn n1amp 8n1amt 5nanc nan6ce n1and n6and. 2n1ang 1nani
1nann n1ans 8nanw 5napf. 1n2ar. na2ra 2n1arc n8ard 1nari n8ark
6n1arm 5n6ars 2n1art n8arv 6natm nat6s5e 1naue 4nauf n3aug 5naui n5auk
na5um 6nausb 6nauto 1nav 2nax 3naz 1na\3 \c{1na\9} n1b2 nbau5s n1c
nche5e nch5m 2n1d nda8d n2d1ak nd5ans n2d1ei nde8lac ndel6sa n8derhi
nde4se nde8stal n2dj ndnis5 n6d5or6t nd3rec nd3rot nd8samt nd6sau
ndt1h n8dumd 1ne ne5as ne2bl 6n5ebn 2nec 5neei ne5en ne1g4l 2negy
4n1ein 8neis 4n3e4lem 8nemb 2n1emp nen1a 6n5energ nen3k 8nentb
4n3en3th 8nentl 8n5entn 8n5ents ne1ra ne5r8al ne8ras 8nerbi 6n5erde.
nere5i6d nerfor6 \n{6n5erh"o} \n{8nerl"o} 2n1err n8ers. 6n5ertra
2n1erz nesi3e net1h neu4ra neu5sc 8neu\3 \c{8neu\9} n1f nf5f nf2l
nflei8 nf5lin nft8st n8g5ac ng5d ng8en nge8ram ngg2 ng1h n6glic ng3rip
ng8ru ng2se4 ng2si n2g1um n1gy \n{n8g"al} n1h nhe6r5e 1ni ni1bl
\n{ni5ch"a} ni8dee n6ie ni1en nie6s5te niet5h ni8etn 4n3i6gel n6ik
ni1la 2n1imp ni5na 2n1ind 8ninf 6n5inh ni8nit 6n5inn 2n1ins 4n1int
n6is ni3str ni1th ni1tr n1j n6ji n8kad nk5ans n1ke n8kerla n1ki nk5inh
\n{n5kl"o} n1k2n n8k5not nk3rot \n{n8kr"u} nk5spo nk6t5r n8kuh
\n{n6k"ub} n5l6 nli4mi n1m nmen4s n1na n8nerg nni5o n1no nn4t3ak nnt1h
nnu1e n1ny \n{n1n"a} \n{n1n"o} \n{n1n"u} no5a no4b3la 4n3obs 2nobt
noche8 no6die no4dis no8ia no5isc 6n5o6leu no4mal noni6er 2n1onk n1ony
4n3o4per 6nopf 6nopti no3ra no4ram nor6da 4n1org 2n1ort n6os no1st
8nost. no8tan no8ter noty6pe 6n5ox n1p2 n1q n1r \n{nr"os3} 6ns n1sac
ns3ang n1sc n8self n8s5erf n8serg n6serk ns5erw n8sint n1s2pe n1spr
n6s5tat. n5s6te. n6stob n1str n1ta n4t3a4go nt5anh nt3ark nt3art
n1te nt3eis nte5n6ar nte8nei nter3a nte6rei nt1ha nt6har n3ther nt5hie
n3thus n1ti nti1c n8tinh nti1t ntlo6b ntmen8 n1to nt3o4ti n1tr ntra5f
ntra5ut nt8rea nt3rec nt8rep n4t3rin nt8rop n4t3rot \n{n4tr"u} nt1s
nts6an nt2sk n1tu nt1z \n{n1t"a} \n{n1t"o} \n{n8t"ol} \n{n1t"u} 1nu
nu1a nu5el nu5en 4n1uhr nu5ie 8numl 6n5ums 6n5umw 2n1und 6nuni 6n5unr
2n1unt 2nup 2nu6r n5uri nu3skr nu5ta n1v 8n1w 1nys n1za n6zab n2z1ar
n6zaus nzi4ga n8zof n6z5unt n1zw n6zwir \n{1n"ac} \n{5n"ae} \n{5n"ai}
\n{n8"al} \n{n"a6m} \n{n"a6re} \n{n5"arz} \n{5n"aus} \n{n1"ol}
\n{1n"ot} \n{n5"oz} \n{5n"u.} \n{6n1"u2b} \n{5n"u\3} \n{\c{5n"u\9}}
o5ab. oa2l o8ala o1a2m o1an ob1ac obe4ra o6berh 5o4bers o4beru
obe6ser 1obj o1bl o2bli ob5sk 3obst. ob8sta obst5re ob5sz o1che
oche8b o8chec o3chi och1l och3m ocho8f o3chro och3to o3chu och1w o1d
o2d1ag od2dr ode5i ode6n5e od1tr o5e6b o5e6der. oe8du o1ef o1e2l
o1e2p o1er. o5e8x o1fa of8fan 1offi of8fin of6f5la o5fla o1fr 8o1g
og2n o1ha o1he o6h5eis o1hi ohl1a oh1le oh4l3er 5ohm. oh2ni o1ho
oh1re oh1ru o1hu oh1w o1hy \n{o1h"a} o5ia o1id. o8idi oi8dr o5ids
o5isch. oiset6 o1ism o3ist. o5i6tu o1j o1k ok2l ok3lau \n{o8kl"a}
1okta o1la old5am old5r o1le ole5in ole1r ole3u ol6gl ol2kl olk4s1
ol8lak ol8lauf. ol6lel ol8less o1lo ol1s ol6sk o1lu oly1e2 5olym
o2mab om6an o8mau ombe4 o8merz om5sp o1mu o8munt \n{o1m"a} \n{o1m"o}
o1na ona8m on1ax on8ent o6n5erb 8oni oni5er. on1k on6n5a6b o1no ono1c
o4nokt 1ons onts8 \n{o1n"a} oo8f 1oog oo2pe oo2sa o1pa 3o4pera o3pfli
opf3lo opf3r o1pi o1pl o2pli o5p6n op8pa op6pl o1pr o3p4ter 1opti
\n{o1p"a} \n{o5p"o} o1q o1ra. o3rad o8radd 1oram o6rang o5ras o8rauf
or5cha or4d3a4m or8dei or8deu 1ordn or4dos o1re o5re. ore2h o8r5ein
ore5isc or6enn or8fla or8fli 1orga 5orgel. or2gl o1ri 5o6rient or8nan
\n{or8n"a} o1ro or1r2h or6t5an or8tau or8tere o1rus o1ry \n{o1r"a}
\n{or1"u2} o1sa osa3i 6ose o8serk o1sk o6ske o6ski os2kl os2ko os2kr
osni5e o2s1o2d o3s4per o4stam o6stau o3stra ost3re osu6 o6s5ur o5s6ze
o1ta ot3auf o6taus o1te o6terw o1th othe5u o2th1r o1ti o1to oto1a
ot1re o1tri o1tro ot1sc o3tsu ot6t5erg ot2t3h ot2t5r \n{ot8t"o} o1tu
ou3e ouf1 ou5f6l o5u6gr ou5ie ou6rar ou1t6a o1v o1wa o1we o6wer. o1wi
owid6 o1wo o5wu o1xe oy5al. oy1e oy1i o5yo o1z oza2r 1o2zea ozo3is
\n{o"o8} o\35elt \c{o\95elt} o\31t \c{o\91t} 3paa pa6ce 5pad pag2 1pak
pa1la pa8na8t pani5el pa4nor pan1s2 1pap pap8s pa8rei par8kr paro8n
par5o6ti part8e 5partei 3partn pas6sep pa4tha 1pau 6paug pau3sc p1b
8p5c 4p1d 1pe 4peic pe5isc 2pek pen3k pen8to8 p8er pe1ra pere6 per5ea
per5eb pe4rem 2perr per8ran 3pers 4persi \n{pe3r"u} pe4sta pet2s
p2f1ec p4fei pf1f pf2l 5pflanz pf8leg pf3lei 2pft pf3ta p1g 1ph 2ph.
2p1haf 6phb 8phd 6p5heit ph5eme 6phg phi6e 8phk 6phn p5holl pht2
ph3tha 4ph3the phu6 6phz pi1en pi5err pi1la pi1na 5pinse pioni8e 1pis
pi1s2k pi1th p1k pl8 5pla p2lau 4plei p3lein 2pler 6p5les 2plig p6lik
6p5ling p2liz plo8min 6p1m p1n 1p2o 8poh 5pol po8lan poly1 po3ny po1ra
2porn por4t3h \n{po5r"o} 5poti p1pa p6p5ei ppe6la pp5f p2p1h p1pi pp1l
ppp6 pp5ren pp1s \n{p5p"o} pr6 3preis 1pres 2p3rig 5prinz 1prob 1prod
5prog pro8pt pro6t5a prote5i 8pro\3 \c{8pro\9} \n{pr"a3l} \n{1pr"as}
\n{pr"ate4} \n{1pr"uf} p5schl 2pst 1p2sy p1t p8to8d pt1s 5p6ty 1pu
pu1b2 2puc pu2dr puf8fr 6p5uh pun8s pu8rei pu5s6h pu1ta p1v p3w 5py
py5l p1z \n{p"a6der} \n{p5"a6m} \n{p"a8nu} \n{8p"ar} \n{p"at5h}
\n{p"at1s} qu6 1qui 8rabk ra6bla 3rable ra2br r1abt 6rabz ra4dan ra2dr
5rafal ra4f3er ra5gla ra2g3n 6raha ral5am 5rald 4ralg ra8lins 2rall
ral5t 8ramei r3anal r6and ran8der ran4dr 8ranf 6ranga 5rangi ran8gli
r3angr rans5pa 8ranw r8anz. ra5or 6rapf ra5pl rap6s5er 2r1arb 1rarh
r1arm ra5ro 2r1art 6r1arz ra8tei ra6t5he 6ratl ra4t3ro r5atta raue4n
6raus. r5austa rau8tel raut5s ray1 r1b rb5lass r6bler rb4lie rbon6n
r8brecht \n{rb6s5t"a} r8ces r1che rch1l rch3m rch3re rch3tr rch1w 8rd
r1da r8dachs r8dap rda5ro rde5ins rdio5 r8dir rd3ost r1dr r8drau 1re.
re1ak 3reakt re3als re6am. re1as 4reben re6bl rech5a r8edi re3er
8reff 3refl 2reh 5reha r4ei. reich6s5 8reier 6reign re5imp 4r3eina
6r3einb 6reing 6r5einn 6reinr 4r3eins r3eint reli3e 8r5elt 6rempf
2remt ren5a6b ren8gl r3enni 1reno 5rente 4r3enth 8rentl 4r3entw 8rentz
ren4zw re1on requi5 1rer rer4bl 6rerbs 4r3erd \n{8rerh"o} 8rerkl
4r3erla \n{8rerl"o} 4r3erns \n{6r5ern"a} rer5o 6r5erreg r5ertr r5erwec
\n{r5er"o} re2sa re8schm 2ress re5u8ni 6rewo 2r1ex r1f r8ferd rf4lie
8r1g r8gah rge4bl rge5na rgest4 rg6ne r2gni2 r8gob r4g3ret rg8sel r1h8
r2hy 5rhyt ri1ar ri5cha rid2g r2ie rieg4s5 ri8ei ri1el ri6ele ri1en
ri3er. ri5ers. ri6fan ri8fer ri8fr 1r2ig ri8kn ri5la \n{rim"a8}
ri1na r8inde rin4ga rin6gr 1rinn 6rinner rino1 r8insp 4rinst
\n{ri1n"a} ri5o6ch ri1o2d ri3o6st 2r1ir r2is ri3sko ri8spr \n{ri8st"u}
ri5sv r2it 6r5i6tal ri5tr ri6ve. 8r1j 6rk r1ke rkehrs5 r1ki r3klin
r1k2n rk3str rk4t3an rk6to r6kuh \n{rk"a4s3t} r1l r5li rline5a 6r1m
r6manl rma4p r4m3aph r8minf r8mob rm5sa 2rn r1na rna8be r5ne rn2ei
r6neif r6nex r6nh rn1k r1no r6n5oc rn1sp \n{r1n"a} \n{r1n"u} ro6bern
6robs ro1ch 3rock. ro5de ro1e 4rofe ro8hert 1rohr ro5id ro1in ro5isc
6rolym r2on 6roog ro6phan r3ort ro1s2p ro5s6w ro4tau ro1tr ro6ts 5rout
r1p rpe8re rp2f r2ps r2pt r1q 2rr r1ra r1re rrer6 rr6hos \n{r5rh"o}
r1ri r1ro rro8f rr8or rror5a r1ru r3ry \n{r1r"a} \n{r1r"o} \n{r1r"u}
2r1s r6sab r4sanf rse6e rse5na r2sh r6ska r6ski rs2kl r8sko r2sl rs2p
r6stauf r8sterw r8stran rswi3d4 r2sz 2r1t rt3art r8taut r5tei rt5eige
r8tepe r4t3erh r8terla r4t3hei r5t6hu r4t3int rt5reif rt1sc rt6ser
rt6s5o rt6s5u rt5und r8turt rube6 ru1en 1r4uf ruf4st ru1ie 2r1umg
2r1uml 2rums run8der run4d5r 6rundz 6runf 8runs 2r1unt 2r1ur r6us
ru6sta ru3str ru6tr 1ruts r1v rven1 rvi2c r1w r1x r1za rz5ac r6z5al
r8z1ar r8zerd r6z5erf rz8erh rz4t3h r8zum \n{r"a4ste} \n{r"au8sc}
\n{r1"of} \n{5r"ohr} \n{r"o5le} \n{3r"oll} \n{5r"omis} \n{r1"or}
\n{r"o2sc} \n{3r"ump} 1sa. 1saa s3a4ben sa2bl 2s1abs 6s1abt 6sabw
3sack. 6s3a4der 1saf sa1fa 4s1aff sa5fr 1sag 1sai sa1i2k1 4s1akt 1sal
sa1la 4s3alpi 6salter salz3a 1sam s5anb san2c 1sand s5angeh 6sanl
2s1ans 6s3antr 8s1anw s1ap s6aph 8sapo sap5p6 s8ar. 2s1arb 3sarg
s1arm sa5ro 2s1art 6s1arz 1sas 1sat sat8a 2s1atl sa8tom 3s8aue s5auff
sau5i s6aur 2s1aus 5s6ause 2s1b2 2sca s4ce 8sch. 3scha. 5schade
3schaf 3schal sch5ame 8schanc 8schb 1sche 6schef 8schex 2schf 2schg
2schh 1schi 2schk 5schlag 5schlu \n{6schm"a\3} \n{\c{6schm"a\9}}
6schna\3 \c{6schna\9} 1scho 6schord 6schp 3schri 8schric 8schrig
8schrou 6schs 2scht sch3ta sch3tr 1schu 8schunt 6schv 2schz \n{5sch"o}
\n{5sch"u} 2sco scre6 6scu 2s1d 1se se5an se1ap se6ben se5ec see5i6g
se3erl 8seff se6han se8hi \n{se8h"o} 6s5eid. 2s1eig s8eil 5sein.
sei5n6e 6s5einh 3s8eit 3sel. se4lar selb4 6s3e4lem se8lerl 2s1emp
sen3ac se5nec 6s5ents 4sentz s8er. se8reim ser5inn \n{8serm"a}
8s5erzi \n{6ser"of} se1um 8sexa 6sexp 2s1f2 sfal8ler 2s3g2 sge5b2 s1h
s8hew 5s6hip 5s4hop 1si 2siat si1b sicht6s 6s5i6dee siege6s5 si1en
si5err si1f2 si1g2n si6g5r si8kau sik1i si4kin si2kl \n{si8k"u} si1la
sil6br si1na 2s1inf sin5gh 2s1inh sinne6s5 2s1ins si5ru si5str 4s1j
s1k2 6sk. 2skau skel6c skelch5 s6kele 1s2ki. 3s4kin. s6kiz s8kj
6skn 2skow 3skrib 3skrip 2sku \n{8sk"u} s1l s8lal slei3t s4low 2s1m
s1n 6sna 6snot 1so so1ch 2s1odo so4dor 6s5o4fen solo3 s2on so5of 4sope
so1ra 2s1ord 4sorga sou5c so3un 4s3ox sp2 8spaa 5spal 1span 2spap
s2pec s4peis 1spek s6perg 4spers s6pes 2s1pf 8sphi \n{1s2ph"a} 1spi
spi4e 6s5pig 6spinse 2spis 2spla 2spol 5s6pom 6s5pos 6spoti 1spra
3s8prec 6spreis 5spring 6sprob 1spru s2pul 1s2pur 6spy \n{5sp"an}
\n{1sp"u} s1q 2s1r 2s1s2 sse8nu ssini6s ssoi6r 2st. 1sta 4stafe 2stag
sta3la 6stale 4stalg 8stalk 8stamt 6st5anf 4stans 6stanw 6starb sta4te
6staus 2stb 6stc 6std 1ste 4steil 3s2tel st3elb 8stemb 6steppi 8stese
8stesse 6stf 2stg 2sth st1ha st3hei s8t1hi st1ho st5hu 1sti sti4el
4stigm sti3na 6stind 4stinf sti8r 2stk 2stl 2stm 1sto 6stoll. 4st3ope
6stopf. 6stord 6stp 5stra. 4strai 3s4tral 6s5traum 3stra\3
\c{3stra\9} 3strec 6s3tref 8streib 5streif 6streno 6stres 6strev
5s6tria 6strig 5strik 8strisi 3s4troa s8troma st5rose 4struf 3strum
\n{6str"ag} 2st1s6 2stt 1stu stu5a 4stuc 2stue 8stun. 2stv 2stw s2tyl
6stz \n{1st"a} \n{8st"ag} \n{1st"o} \n{1st"u} \n{8st"uch} \n{4st"ur.}
1su su2b1 3suc su1e su2fe su8mar 6sumfa 8sumk 2s1unt sup1p2 6s5u6ran
6surte 2s1v 2s1w 1sy 8syl. sy5la syn1 sy2na syne4 s1z s4zend 5s6zene.
8szu \n{1s"a} \n{6s5"and} \n{6s"augi} \n{6s"au\3} \n{\c{6s"au\9}}
\n{5s"om} \n{2s1"u2b} \n{1s"uc} \n{s"u8di} \n{1s"un} \n{5s"u\3}
\n{\c{5s"u\9}} taats3 4tab. taba6k ta8ban tab2l ta6bre 4tabs t3absc
8tabz 6t3acht ta6der 6tadr tad6s tad2t 1tafe4 1tag ta6ga6 ta8gei
tage4s tag6s5t tah8 tahl3 tai6ne. ta5ir. tak8ta tal3au 1tale ta8leng
tal5ert 6t5a6mer 6tamp tampe6 2t1amt tan5d6a tan8dr tands5a tani5e
6tanl 2tanr t3ans 8t5antr tanu6 t5anw 8tanwa tan8zw ta8rau 6tarbe
1tari 2tark 2t1arm ta1ro 2tart t3arti 6tarz ta1sc ta6sien ta8stem
ta8sto t5aufb 4taufn 8taus. 5tause 8tausf 6tausg t5ausl 2t1b2 2t1c
t6chu 2t1d te2am tea4s te8ben 5techn 4teff te4g3re te6hau 2tehe te4hel
2t1ehr te5id. teig5l 6teign tei8gr 1teil 4teinh t5einhe 4teis t5eisen
8teiw te8lam te4lar 4telek 8telem te6man te6n5ag ten8erw ten5k tens4p
ten8tro 4t3entw 8tentz te6pli 5teppi ter5a6b te3ral ter5au 8terbar
t5erbe. 6terben 8terbs 4t3erbt t5erde. ter5ebe ter5ein te8rers terf4
\n{8terh"o} \n{6terkl"a} ter8nor ter6re. t8erscha t5e6sel te8stau
t3euro te1xa tex3e 8texp tex6ta 2t1f2 2t1g2 2th. th6a 5tha. 2thaa
6t1hab 6t5haf t5hah 8thak 3thal. 6thals 6t3hand 2t1hau 1the. 3t4hea
t1heb t5heil t3heit t3helf 1theo 5therap 5therf 6t5herz 1thes 1thet
5thi. 2t1hil t3him 8thir 3this t5hj 2th1l 2th1m th1n t5hob t5hof
4tholz 6thopti 1thr6 4ths t1hum 1thy \n{4t1h"a} \n{2t1h"o} \n{t1h"u}
ti1a2m ti1b tie6fer ti1en ti8gerz tig3l ti8kin ti5lat 1tilg t1ind
tin4k3l ti3spa ti5str 5tite ti5tr ti8vel ti8vr 2t1j 2t1k2 2t1l tl8a
2t1m8 2t1n 3tobe 8tobj to3cha 5tocht 8tock tode4 to8del to8du to1e
6t5o6fen to1in toi6r 5toll. to8mene t2ons 2t1ony to4per 5topf. 6topt
to1ra to1s to6ska tos2l 2toti to1tr t8ou 2t1p2 6t1q tr6 tra5cha
tra8far traf5t 1trag tra6gl tra6gr t3rahm 1trai t6rans tra3sc tra6st
3traue t4re. 2trec t3rech t8reck 6t1red t8ree 4t1reg 3treib 4treif
8t3reis 8trepo tre6t5r t3rev 4t3rez 1trib t6rick tri6er 2trig t8rink
tri6o5d trizi5 tro1a 3troc trocke6 troi8d tro8man. tro3ny 5tropf
6t5rosa t5ro\3 \c{t5ro\9} 5trub 5trup trut5 \n{1tr"ag} \n{6t1r"oh}
\n{5tr"ub} \n{tr"u3bu} \n{t1r"uc} \n{t1r"us} 2ts ts1ab t1sac tsa8d
ts1ak t6s5alt ts1an ts1ar ts3auf t3schr \n{t5sch"a} tse6e tsee5i
tsein6s ts3ent ts1er t8serf t4serk t8sh 5t6sik t4s3int ts5ort.
t5s6por t6sprei t1st t6s5tanz ts1th t6stit t4s3tor 1t2sua t2s1uf
t8sum. t2s1u8n t2s1ur 2t1t tt5eif tte6sa tt1ha tt8ret tt1sc tt8ser
tt5s6z 1tuc tuch5a 1tu1e 6tuh t5uhr tu1i tu6it 1tumh 6t5umr 1tums
8tumt 6tund 6tunf 2t1unt tu5ra tu6rau tu6re. tu4r3er 2t1v 2t1w 1ty1
ty6a ty8la 8tym 6ty6o 2tz tz5al tz1an tz1ar t8zec tzeh6 tzehn5 t6z5ei.
t6zor t4z3um \n{t6z"au} \n{5t"ag} \n{6t"ah} \n{t5"alt} \n{t8"an}
\n{t"are8} \n{8t"a8st} \n{6t"au\3} \n{\c{6t"au\9}} \n{t5"offen}
\n{8t"o8k} \n{1t"on} \n{4t"ub} \n{t6"u5ber.} \n{5t"uch} \n{1t"ur.}
u3al. u5alb u5alf u3alh u5alk u3alp u3an. ua5na u3and u5ans u5ar.
ua6th u1au ua1y u2bab ubi5er. u6b5rit ubs2k \n{u5b"o} \n{u8b"ub} 2uc
u1che u6ch5ec u1chi uch1l uch3m uch5n uch1r uch5to ucht5re u1chu uch1w
uck1a uck5in u1d ud4a u1ei u6ela uene8 u6ep u1er uer1a ue8rerl uer5o
u8esc u2est u8ev u1fa u2f1ei u4f3ent u8ferh uf1fr uf1l uf1ra uf1re
\n{uf1r"a} \n{uf1r"u} uf1s2p uf1st uft1s u8gabt u8gad u6gap ugeb8 u8gn
ugo3s4 u1ha u1he u1hi uh1le u1ho uh1re u1hu uh1w \n{u1h"a} \n{u1h"o}
6ui ui5en u1ig u3ins uin8tes u5isch. u1j 6uk u1ke u1ki u1kl u8klu
u1k6n u5ky u1la uld8se u1le ul8lac ul6lau ul6le6l ul6lo ulni8 u1lo
ulo6i ult6a ult8e u1lu ul2vr \n{u1l"a} \n{u1l"o} 3umfan 5umlau umo8f
um8pho u1mu umu8s \n{u5m"o} u1n1a un2al un6at unau2 6und. 5undein
un4d3um 3undzw \n{und"u8} \n{un8d"ub} une2b un1ec une2h un3eis 3unfal
\n{1unf"a} 5ungea \n{3ungl"u} ung2s1 \n{un8g"a} 1u2nif un4it un8kro
unk5s u1no unpa2 uns2p unvol4 unvoll5 u5os. u1pa u1pi u1p2l u1pr
up4s3t up2t1a u1q u1ra ur5abs ura8d ur5ah u6rak ur3alt u6rana u6r5ans
u8rap ur5a6ri u8ratt u1re ur3eig ur8gri u1ri ur5ins 3urlau urmen6
ur8nan u1ro 3ursac ur8sau ur8sei ur4sk 3urtei u1ru uru5i6 uru6r u1ry
ur2za \n{ur6z"a} \n{ur5"a6m} \n{u5r"o} \n{u1r"u} \n{ur"uck3} u1sa
usa4gi u2s1ar u2s1au u8schec usch5wi u2s1ei use8kel u8sl u4st3a4b
us3tau u3s4ter u2s1uf u8surn ut1ac u1tal uta8m u1tan ut1ar u1tas ut1au
u1te u8teic u4tent u8terf u6terin u4t3hei ut5ho ut1hu u1ti utine5
uti6q u1to uto5c u1tr ut1sa ut1s6p ut6stro u1tu utz5w u1u u1v uve5n
\n{uve3r4"a} u1w u1xe u5ya uy5e6 u1yi u2z1eh u8zerh \n{u5"o} u\3e6n
\c{u\9e6n} u\3en5e \c{u\9en5e} 8vanb 6vang 6varb var8d va6t5a va8tei
va2t1r 2v1b 6v5c 6vd 1ve 6ve5g6 ver1 ver5b verb8l ve2re2 verg8 ve2ru8
ve1s ve2s3p ve3xe 2v1f 2v1g 6v5h vi6el vie6w5 vi1g4 vi8leh vil6le.
8vint vi1ru vi1tr 2v1k 2v1l 2v1m 4v5n 8vo8f voi6le vol8lend vol8li
v2or1 vo2re vo8rin vo2ro 2v1p 8vra v6re 2v1s 2v1t 2v1v 4v3w 2v1z
waffe8 wa6g5n 1wah wah8n wa5la wal8din wal6ta wan4dr 5ware wa8ru
war4za 1was w5c w1d 5wech we6fl 1weg we8geng weg5h weg3l we2g1r
weh6r5er 5weise weit3r wel2t welt3r we6rat 8werc 5werdu wer4fl 5werk.
wer4ka wer8ku wer4ta wer8term we2sp we8stend we6steu we8str
\n{we8st"o} wet8ta wich6s5t 1wid wi2dr wiede4 wieder5 wik6 wim6ma
win4d3r 5wirt wisch5l 1wj 6wk 2w1l 8w1n wo1c woche6 wol6f wor6t5r 6ws2
w1sk 6w5t 5wunde. wun6gr wu1sc wu2t1 6w5w wy5a \n{w"arme5} \n{w"a1sc}
1xag x1ak x3a4men 8xamt x1an 8x1b x1c 1xe. x3e4g 1xen xe1ro x1erz
1xes 8xf x1g 8x1h 1xi 8xid xi8so 4xiste x1k 6x1l x1m 8xn 1xo 8x5o6d
8x3p2 x1r x1s6 8x1t x6tak x8terf x2t1h 1xu xu1e x5ul 6x3w x1z 5ya.
y5an. y5ank y1b y1c y6cha y4chia y1d yen6n y5ern y1g y5h y5in y1j
y1k2 y1lak yl1al yla8m y5lax y1le y1lo y5lu y8mn ym1p2 y3mu y1na yno2d
yn1t y1on. y1o4p y5ou ypo1 y1pr y8ps y1r yri3e yr1r2 y1s ys5iat ys8ty
y1t y3w y1z \n{y"a8m} z5a6b zab5l 8za6d 1zah za5is 4z3ak 6z1am 5zange.
8zanl 2z1ara 6z5as z5auf 3zaun 2z1b 6z1c 6z1d 1ze ze4dik 4z3eff 8zein
zei4ta zei8ters ze6la ze8lec zel8th 4zemp 6z5engel zen8zin \n{8zerg"a}
zer8i ze1ro zers8 zerta8 zer8tab zer8tag 8zerz ze8ste zeu6gr 2z1ex
2z1f8 z1g 4z1h 1zi zi1en zi5es. 4z3imp zi1na 6z5inf 6z5inni zin6s5er
8zinsuf zist5r zi5th zi1tr 6z1j 2z1k 2z1l 2z1m 6z1n 1zo zo6gl 4z3oh
zo1on zor6na8 4z1p z5q 6z1r 2z1s8 2z1t z4t3end z4t3hei z8thi 1zu zu3al
zu1b4 zu1f2 6z5uhr zun2a 8zunem zunf8 8zungl zu1o zup8fi zu1s8 zu1z
2z1v zw8 z1wal 5zweck zwei3s z1wel z1wer z6werg 8z5wes 1zwi zwi1s
6z1wo 1zy 2z1z zz8a zzi1s \n{1z"a} \n{1z"o} \n{6z"ol.} \n{z"o1le}
\n{1z"u} \n{2z1"u2b} \n{"a1a6} \n{"ab1l} \n{"a1che} \n{"a3chi}
\n{"ach8sc} \n{"ach8sp} \n{"a5chu} \n{"ack5a} \n{"ad1a} \n{"ad5era}
\n{"a6d5ia} \n{"a1e} \n{"a5fa} \n{"af1l} \n{"aft6s} \n{"ag1h}
\n{"ag3le} \n{"a6g5nan} \n{"ag5str} \n{"a1he} \n{"a1hi} \n{"ah1le}
\n{"ah5ne} \n{1"ahnl} \n{"ah1re} \n{"ah5ri} \n{"ah1ru} \n{"a1hu}
\n{"ah1w} \n{6"ai} \n{"a1isc} \n{"a6ische} \n{"a5ism} \n{"a5j}
\n{"a1k} \n{"al1c} \n{"a1le} \n{"a8lei} \n{"al6schl} \n{"ami1e}
\n{"am8n} \n{"am8s} \n{"a5na} \n{5"anderu} \n{"ane5i8} \n{"ang3l}
\n{"ank5l} \n{"a1no} \n{"an6s5c} \n{"a1pa} \n{"ap6s5c} \n{3"aq}
\n{"ar1c} \n{"a1re} \n{"are8m} \n{5"argern} \n{"ar6gl} \n{"a1ri}
\n{3"armel} \n{"a1ro} \n{"art6s5} \n{"a1ru} \n{3"arztl} \n{"a5r"o}
\n{"a6s5chen} \n{"asen8s} \n{"as1th} \n{"ata8b} \n{"a1te} \n{"ateri4}
\n{"ater5it} \n{"a6thy} \n{"a1ti} \n{3"atk} \n{"a1to} \n{"at8schl}
\n{"ats1p} \n{"a5tu} \n{"aub1l} \n{"au1e} \n{1"aug} \n{"au8ga}
\n{"au5i} \n{"a1um.} \n{"a1us.} \n{1"au\3} \n{\c{1"au\9}} \n{"a1z}
\n{"o1b} \n{"o1che} \n{"o5chi} \n{"och8stei} \n{"och8str} \n{"ocht6}
\n{5"o6dem} \n{5"offn} \n{"o1he} \n{"oh1l8} \n{"oh1re} \n{"o1hu}
\n{"o1is} \n{"o1ke} \n{1"o2ko} \n{1"ol.} \n{"ol6k5l} \n{"ol8pl}
\n{"o1mu} \n{"o5na} \n{"onig6s3} \n{"o1no} \n{"o5o6t} \n{"opf3l}
\n{"op6s5c} \n{"o1re} \n{"or8gli} \n{"o1ri} \n{"or8tr} \n{"o1ru}
\n{5"osterr} \n{"o1te} \n{"o5th} \n{"o1ti} \n{"o1tu} \n{"o1v} \n{"o1w}
\n{"owe8} \n{"o2z} \n{"ub6e2} \n{3"u4ber1} \n{"ub1l} \n{"ub1r}
\n{5"u2bu} \n{"u1che} \n{"u1chi} \n{"u8ch3l} \n{"uch6s5c} \n{"u8ck}
\n{"uck1a} \n{"uck5ers} \n{"ud1a2} \n{"u6deu} \n{"udi8t} \n{"u2d1o4}
\n{"ud5s6} \n{"uge4l5a} \n{"ug1l} \n{"uh5a} \n{"u1he} \n{"u8heh}
\n{"u6h5erk} \n{"uh1le} \n{"uh1re} \n{"uh1ru} \n{"u1hu} \n{"uh1w}
\n{"u3k} \n{"u1le} \n{"ul4l5a} \n{"ul8lo} \n{"ul4ps} \n{"ul6s5c}
\n{"u1lu} \n{"un8da} \n{"un8fei} \n{"unk5l} \n{"un8za} \n{"un6zw}
\n{"u5pi} \n{"u1re} \n{"u8rei} \n{"ur8fl} \n{"ur8fr} \n{"ur8geng}
\n{"u1ri} \n{"u1ro} \n{"ur8sta} \n{"ur8ster} \n{"u1ru} \n{"use8n}
\n{"u8sta} \n{"u8stes} \n{"u6s5tete} \n{"u3ta} \n{"u1te} \n{"u1ti}
\n{"ut8tr} \n{"u1tu} \n{"ut8zei} \n{"u1v} \31a8 \c{\91a8} 5\3a.
\c{5\9a.} \38as \c{\98as} \31b8 \c{\91b8} \31c \c{\91c} \31d \c{\91d}
1\3e \c{1\9e} \35ec \c{\95ec} 8\3e8g \c{8\9e8g} 8\3e8h \c{8\9e8h}
2\31ei \c{2\91ei} 8\3em \c{8\9em} \31f8 \c{\91f8} \31g \c{\91g} \31h
\c{\91h} 1\3i \c{1\9i} \31k \c{\91k} \31l \c{\91l} \31m \c{\91m}
\3mana8 \c{\9mana8} \31n \c{\91n} \31o \c{\91o} \31p8 \c{\91p8} \35q
\c{\95q} \31r \c{\91r} \31s2 \c{\91s2} \3st8 \c{\9st8} \31ta \c{\91ta}
\31te \c{\91te} \3t3hei \c{\9t3hei} \31ti \c{\91ti} \35to \c{\95to}
\31tr \c{\91tr} 1\3u8 \c{1\9u8} 6\35um \c{6\95um} \31v \c{\91v} \31w
\c{\91w} \31z \c{\91z}
}%
\endgroup
\relax\endinput
%
% -----------------------------------------------------------------
%
% =============== Additional Documentation ===============
%
%
% Older Versions of German Hyphenation Patterns:
% ----------------------------------------------
%
% All older versions of `ghyphen.tex' distributed as
%
% ghyphen.tex/germhyph.tex as of 1986/11/01
% ghyphen.min/ghyphen.max as of 1988/10/10
% ghyphen3.tex as of 1990/09/27 & 1991/02/13
% ghyph31.tex as of 1994/02/13
%
% are out of date and it is recommended to replace them
% with the new version `dehypht.tex' as of 1999/03/03.
%
% If you are using `ghyphen.min' (a minor version of `ghyphen')
% because of limited trie memory space, try this version and if
% the space is exceeded get a newer TeX implementation with
% larger or configurable trie memory sizes.
%
%
%
% Trie Memory Requirements/Space for Hyphenation Patterns:
% --------------------------------------------------------
%
% To load this set of german hyphenation patterns the parameters
% of TeX has to have at least these values:
%
% TeX 3.x:
% IniTeX: trie_size >= 9733 trie_op_size >= 207
% VirTeX: trie_size >= 8375 trie_op_size >= 207
%
% TeX 2.x:
% IniTeX: trie_size >= 8675 trie_op_size >= 198
% VirTeX: trie_size >= 7560 trie_op_size >= 198
%
% If you want to load more than one set of hyphenation patterns
% (in TeX 3.x), the parameters have to be set to a value larger
% than or equal to the sum of all required values for each set.
%
%
% Setting Trie Memory Parameters:
% -------------------------------
%
% Some implementations allow the user to change the default value
% of a set of the internal TeX parameters including the trie memory
% size parameter specifying the used memory for the hyphenation
% patterns.
%
% Web2c 7.x (Source), teTeX 0.9 (Unix, Amiga), fpTeX (Win32)
% and newer:
% The used memory size of the true is usually set high enough.
% If needed set the size of the trie using the keyword `trie_size'
% in the configuration file `texmf/web2c/texmf.cnf'. For details
% see the included documentation.
%
% emTeX (OS/2, MS-DOS, Windows 3.x/9x/NT):
% You can set the used memory size of the trie using the
% `-mt<number>' option on the command line or in the
% TEXOPTIONS environment variable.
%
% PasTeX (Amiga):
% The values for the parameters can be set using the keywords
% `triesize', `itriesize' and `trieopsize' in the configuration
% file.
%
% others (binaries only):
% See the documentation of the implementation if it is possible
% and how to change these values without recompilation.
%
% others (with sources)
% If the trie memory is too small, you have to recompile TeX
% using larger values for `trie_size' and `trie_op_size'.
% Modify the change file `tex.ch' and recompile TeX.
% For details see the documentation included in the sources.
%
%
%
% Necessary Settings in TeX macro files:
% --------------------------------------
%
% \lefthyphenmin, \righthyphenmin:
% You can set both parameters to 2.
%
% \lccode <char>:
% To get correct hyphenation points within words containing
% umlauts or \ss, it's necessary to assign values > 0 to the
% appropriate \lccode <char> positions.
%
% These changes are _not_ done when reading this file and have to
% be included in the language switching mechanism as is done in,
% for example, `german.sty' (\lccode change for ^^Y = \ss in OT1,
% \left-/\righthyphenmin settings).
%
%
%% \CharacterTable
%% {Upper-case \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
%% Lower-case \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
%% Digits \0\1\2\3\4\5\6\7\8\9
%% Exclamation \! Double quote \" Hash (number) \#
%% Dollar \$ Percent \% Ampersand \&
%% Acute accent \' Left paren \( Right paren \)
%% Asterisk \* Plus \+ Comma \,
%% Minus \- Point \. Solidus \/
%% Colon \: Semicolon \; Less than \<
%% Equals \= Greater than \> Question mark \?
%% Commercial at \@ Left bracket \[ Backslash \\
%% Right bracket \] Circumflex \^ Underscore \_
%% Grave accent \` Left brace \{ Vertical bar \|
%% Right brace \} Tilde \~}
%%
\endinput
%%
%% End of file `dehypht.tex'.

1104
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/eshyph_vo.tex

File diff suppressed because it is too large Load Diff

1122
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/expander-1.3.1.tm

File diff suppressed because it is too large Load Diff

223
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/ithyph.tex

@ -0,0 +1,223 @@
%%%%%%%%%%%%%%%%%%%% file ithyph.tex
%%%%%%%%%%%%%%%%%%%%%%%%%%% file ithyph.tex %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Prepared by Claudio Beccari e-mail beccari@polito.it
%
% Dipartimento di Elettronica
% Politecnico di Torino
% Corso Duca degli Abruzzi, 24
% 10129 TORINO
%
% Copyright 1998, 2001 Claudio Beccari
%
% This program can be redistributed and/or modified under the terms
% of the LaTeX Project Public License Distributed from CTAN
% archives in directory macros/latex/base/lppl.txt; either
% version 1 of the License, or any later version.
%
% \versionnumber{4.8d} \versiondate{2001/11/21}
%
% These hyphenation patterns for the Italian language are supposed to comply
% with the Reccomendation UNI 6461 on hyphenation issued by the Italian
% Standards Institution (Ente Nazionale di Unificazione UNI). No guarantee
% or declaration of fitness to any particular purpose is given and any
% liability is disclaimed.
%
% See comments and loading instructions at the end of the file after the
% \endinput line
%
{\lccode`\'=`\' % Apostrophe has its own lccode so that it is treated
% as a letter
%>> 1998/04/14 inserted grouping
%
%\lccode23=23 % Compound word mark is a letter in encoding T1
%\def\W{^^W} % ^^W =\char23 = \char"17 =\char'27
%
\patterns{
.a3p2n % After the Garzanti dictionary: a-pnea, a-pnoi-co,...
.anti1 .anti3m2n
.bio1
.ca4p3s
.circu2m1
.di2s3cine
%.e2x
.fran2k3
.free3
.narco1
.opto1
.orto3p2
.para1
.poli3p2
.pre1
.p2s
%.ri1a2 .ri1e2 .re1i2 .ri1o2 .ri1u2
.sha2re3
.tran2s3c .tran2s3d .tran2s3f .tran2s3l .tran2s3n .tran2s3p .tran2s3r .tran2s3t
.su2b3lu .su2b3r
.wa2g3n
.wel2t1
a1ia a1ie a1io a1iu a1uo a1ya 2at.
e1iu e2w
o1ia o1ie o1io o1iu
%u1u
%
%1\W0a2 1\W0e2 1\W0i2 1\W0o2 1\W0u2
'2
1b 2bb 2bc 2bd 2bf 2bm 2bn 2bp 2bs 2bt 2bv
b2l b2r 2b. 2b'. 2b''
1c 2cb 2cc 2cd 2cf 2ck 2cm 2cn 2cq 2cs 2ct 2cz
2chh c2h 2chb ch2r 2chn c2l c2r 2c. 2c'. 2c'' .c2
1d 2db 2dd 2dg 2dl 2dm 2dn 2dp d2r 2ds 2dt 2dv 2dw
2d. 2d'. 2d'' .d2
1f 2fb 2fg 2ff 2fn f2l f2r 2fs 2ft 2f. 2f'. 2f''
1g 2gb 2gd 2gf 2gg g2h g2l 2gm g2n 2gp g2r 2gs 2gt
2gv 2gw 2gz 2gh2t 2g. 2g'. 2g''
1h 2hb 2hd 2hh hi3p2n h2l 2hm 2hn 2hr 2hv 2h. 2h'. 2h''
1j 2j. 2j'. 2j''
1k 2kg 2kf k2h 2kk k2l 2km k2r 2ks 2kt 2k. 2k'. 2k''
1l 2lb 2lc 2ld 2l3f2 2lg l2h 2lk 2ll 2lm 2ln 2lp
2lq 2lr 2ls 2lt 2lv 2lw 2lz 2l. 2l'. 2l''
1m 2mb 2mc 2mf 2ml 2mm 2mn 2mp 2mq 2mr 2ms 2mt 2mv 2mw
2m. 2m'. 2m''
1n 2nb 2nc 2nd 2nf 2ng 2nk 2nl 2nm 2nn 2np 2nq 2nr
2ns 2nt 2nv 2nz n2g3n 2nheit. 2n. 2n' 2n''
1p 2pd p2h p2l 2pn 3p2ne 2pp p2r 2ps 3p2sic 2pt 2pz 2p. 2p'. 2p''
1q 2qq 2q. 2q'. 2q''
1r 2rb 2rc 2rd 2rf r2h 2rg 2rk 2rl 2rm 2rn 2rp
2rq 2rr 2rs 2rt rt2s3 2rv 2rx 2rw 2rz 2r. 2r'. 2r''
1s2 2shm 2s3s s4s3m 2s3p2n 2stb 2stc 2std 2stf 2stg 2stm 2stn
2stp 2sts 2stt 2stv 2sz 4s. 4s'. 4s''
1t 2tb 2tc 2td 2tf 2tg t2h t2l 2tm 2tn 2tp t2r 2ts
3t2sch 2tt 2tv 2tw t2z 2tzk 2tzs 2t. 2t'. 2t''
1v 2vc v2l v2r 2vv 2v. 2v'. 2v''
1w w2h wa2r 2w1y 2w. 2w'. 2w''
1x 2xt 2xw 2x. 2x'. 2x''
y1ou y1i
1z 2zb 2zd 2zl 2zn 2zp 2zt 2zs 2zv 2zz 2z. 2z'. 2z'' .z2
}} % Pattern end
\endinput
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Information %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
LOADING THESE PATTERNS
These patterns, as well as those for any other language, do not become
effective until they are loaded in a special form into a format file; this
task is performed by the TeX initializer; any TeX system has its own
initializer with its special way of being activated. Before loading these
patterns, then, it is necessary to read very carefully the instructions that
come with your TeX system.
Here I describe how to load the patterns with the freeware TeX system named
MiKTeX version 2.x for Windows 9x, NT, 2000, XP; with minor changes the
whole procedure is applicable with other TeX systems, but the details must
be deduced from your TeX system documentation at the section/chapter "How to
build or to rebuild a format file".
With MikTeX:
a) copy this file and replace the existing file ithyph.tex in the directory
\texmf\tex\generic\hyphen if the existing one has an older version date
and number.
b) select Start|Programs|MiKTeX|MiKTeX options.
c) in the Language tab add a check mark to the line concerning the Italian
language.
d) in the Geneal tab click "Update format files".
e) That's all!
For the activation of these patterns with the specific Italian typesetting
features, use the babel package as this:
\documentclass{article} % Or whatever other class
\usepackage[italian]{babel}
...
\begin{document}
...
\end{document}
ON ITALIAN HYPHENATION
I have been working on patterns for the Italian language since 1987; in 1992
I published
C. Beccari, "Computer aided hyphenation for Italian and Modern
Latin", TUG vol. 13, n. 1, pp. 23-33 (1992)
which contained a set of patterns that allowed hyphenation for both Italian
and Latin; a slightly modified version of the patterns published in the
above paper is contained in LAHYPH.TEX available on the CTAN archives.
From the above patterns I extracted the minimum set necessary for
hyphenating Italian that was made available on the CTAN archives with the
name ITHYPH.tex the version number 3.5 on the 16th of August 1994.
The original pattern set required 37 ops; being interested in a local
version of TeX/LaTeX capable of dealing with half a dozen languages, I
wanted to reduce memory occupation and therefore the number of ops.
Th new version (4.0 released in 1996) of ITHYPH.TEX is much simpler than
version 3.5 and requires just 29 ops while it retains all the power of
version 3.5; it contains many more new patterns that allow to hyphenate
unusual words that generally have a root borrowed from a foreign language.
Updated versions 4.x contain minor additions and the number of ops is
increased to 30 (version 4.7 of 1998/06/01).
This new pattern set has been tested with the same set of difficult Italian
words that was used to test version 3.5 and it yields the same results (a
part a minor change that was deliberately introduced so as to reduce the
typographical hyphenation with hyathi, since hyphenated hyathi are not
appreciated by Italian readers). A new enlarged word set for testing
purposes gets correct hyphen points that were missed or wrongly placed with
version 3.5, although no error had been reported, because such words are of
very specialized nature and are seldom used.
As the previous version, this new set of patterns does not contain any
accented character so that the hyphenation algorithm behaves properly in
both cases, that is with cm and with dc/ec fonts. With LaTeXe terminology
the difference is between OT1 and T1 encodings; with the former encoding
fonts do not contain accented characters, while with the latter accented
characters are present and sequences such as \`a map directly to slot "E0
that contains "agrave".
Of course if you use dc/ec fonts (or any other real or virtual font with T1
encoding) you get the full power of the hyphenation algorithm, while if you
use cm fonts (or any other real or virtual font with OT1 encoding) you miss
some possible break points; this is not a big inconvenience in Italian
because:
1) The Regulation UNI 6015 on accents specifies that compulsory accents
appear only on the ending vowel of oxitone words; this means that it is
almost indifferent to have or to miss the dc/ec fonts because the only
difference consists in how TeX evaluates the end of the word; in practice
if you have these special facilities you get "qua-li-t\`a", while if you
miss them, you get "qua-lit\`a" (assuming that \righthyphenmin > 1).
2) Optional accents are so rare in Italian, that if you absolutely want to
use them in those rare instances, and you miss the T1 encoding
facilities, you should also provide explicit discretionary hyphens as in
"s\'e\-gui\-to".
There is no explicit hyphenation exception list because these patterns
proved to hyphenate correctly a very large set of words suitably chosen in
order to test them in the most heavy circumstances; these patterns were used
in the preparation of a number of books and no errors were discovered.
Nevertheless if you frequently use technical terms that you want hyphenated
differently from what is normally done (for example if you prefer
etymological hyphenation of prefixed and/or suffixed words) you should
insert a specific hyphenation list in the preamble of your document, for
example:
\hyphenation{su-per-in-dut-to-re su-per-in-dut-to-ri}
Should you find any word that gets hyphenated in a wrong way, please, AFTER
CHECKING ON A RELIABLE MODERN DICTIONARY, report to the author, preferably
by e-mail.
Happy multilingual typesetting !

180
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/patch-0.1.tm

@ -0,0 +1,180 @@
# patch.tcl --
#
# Application of a diff -ruN patch to a directory tree.
#
# Copyright (c) 2019 Christian Gollwitzer <auriocus@gmx.de>
# with tweaks by Andreas Kupries
# - Factored patch parsing into a helper
# - Replaced `puts` with report callback.
package require Tcl 8.5
package provide textutil::patch 0.1
# # ## ### ##### ######## ############# #####################
namespace eval ::textutil::patch {
namespace export apply
namespace ensemble create
}
# # ## ### ##### ######## ############# #####################
proc ::textutil::patch::apply {dir striplevel patch reportcmd} {
set patchdict [Parse $dir $striplevel $patch]
# Apply, now that we have parsed the patch.
dict for {fn hunks} $patchdict {
Report apply $fn
if {[catch {open $fn} fd]} {
set orig {}
} else {
set orig [split [read $fd] \n]
}
close $fd
set patched $orig
set fail false
set already_applied false
set hunknr 1
foreach hunk $hunks {
dict with hunk {
set oldend [expr {$oldstart+[llength $oldcode]-1}]
set newend [expr {$newstart+[llength $newcode]-1}]
# check if the hunk matches
set origcode [lrange $orig $oldstart $oldend]
if {$origcode ne $oldcode} {
set fail true
# check if the patch is already applied
set origcode_applied [lrange $orig $newstart $newend]
if {$origcode_applied eq $newcode} {
set already_applied true
Report fail-already $fn $hunknr
} else {
Report fail $fn $hunknr $oldcode $origcode
}
break
}
# apply patch
set patched [list \
{*}[lrange $patched 0 $newstart-1] \
{*}$newcode \
{*}[lrange $orig $oldend+1 end]]
}
incr hunknr
}
if {!$fail} {
# success - write the result back
set fd [open $fn w]
puts -nonewline $fd [join $patched \n]
close $fd
}
}
return
}
# # ## ### ##### ######## ############# #####################
proc ::textutil::patch::Report args {
upvar 1 reportcmd reportcmd
uplevel #0 [list {*}$reportcmd {*}$args]
##
# apply $fname
# fail-already $fname $hunkno
# fail $fname $hunkno $expected $seen
##
}
proc ::textutil::patch::Parse {dir striplevel patch} {
set patchlines [split $patch \n]
set inhunk false
set oldcode {}
set newcode {}
set n [llength $patchlines]
set patchdict {}
for {set lineidx 0} {$lineidx < $n} {incr lineidx} {
set line [lindex $patchlines $lineidx]
if {[string match ---* $line]} {
# a diff block starts. Current line should be
# --- oldfile date time TZ
# Next line should be
# +++ newfile date time TZ
set in $line
incr lineidx
set out [lindex $patchlines $lineidx]
if {![string match ---* $in] || ![string match +++* $out]} {
#puts $in
#puts $out
return -code error "Patch not in unified diff format, line $lineidx $in $out"
}
# the quoting is compatible with list
lassign $in -> oldfile
lassign $out -> newfile
set fntopatch [file join $dir {*}[lrange [file split $oldfile] $striplevel end]]
set inhunk false
#puts "Found diffline for $fntopatch"
continue
}
# state machine for parsing the hunks
set typechar [string index $line 0]
set codeline [string range $line 1 end]
switch $typechar {
@ {
if {![regexp {@@\s+\-(\d+),(\d+)\s+\+(\d+),(\d+)\s+@@} $line \
-> oldstart oldlen newstart newlen]} {
return code -error "Erroneous hunk in line $lindeidx, $line"
}
# adjust line numbers for 0-based indexing
incr oldstart -1
incr newstart -1
#puts "New hunk"
set newcode {}
set oldcode {}
set inhunk true
}
- { # line only in old code
if {$inhunk} {
lappend oldcode $codeline
}
}
+ { # line only in new code
if {$inhunk} {
lappend newcode $codeline
}
}
" " { # common line
if {$inhunk} {
lappend oldcode $codeline
lappend newcode $codeline
}
}
default {
# puts "Junk: $codeline";
continue
}
}
# test if the hunk is complete
if {[llength $oldcode]==$oldlen && [llength $newcode]==$newlen} {
set hunk [dict create \
oldcode $oldcode \
newcode $newcode \
oldstart $oldstart \
newstart $newstart]
#puts "hunk complete: $hunk"
set inhunk false
dict lappend patchdict $fntopatch $hunk
}
}
return $patchdict
}
# # ## ### ##### ######## ############# #####################
return

91
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/repeat-0.7.tm

@ -0,0 +1,91 @@
# repeat.tcl --
#
# Emulation of string repeat for older
# revisions of Tcl.
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: repeat.tcl,v 1.1 2006/04/21 04:42:28 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil::repeat {}
# ### ### ### ######### ######### #########
namespace eval ::textutil::repeat {
variable HaveBuiltin [expr {![catch {string repeat a 1}]}]
}
if {0} {
# Problems with the deactivated code:
# - Linear in 'num'.
# - Tests for 'string repeat' in every call!
# (Ok, just the variable, still a test every call)
# - Fails for 'num == 0' because of undefined 'str'.
proc textutil::repeat::StrRepeat { char num } {
variable HaveBuiltin
if { $HaveBuiltin == 0 } then {
for { set i 0 } { $i < $num } { incr i } {
append str $char
}
} else {
set str [ string repeat $char $num ]
}
return $str
}
}
if {$::textutil::repeat::HaveBuiltin} {
proc ::textutil::repeat::strRepeat {char num} {
return [string repeat $char $num]
}
proc ::textutil::repeat::blank {n} {
return [string repeat " " $n]
}
} else {
proc ::textutil::repeat::strRepeat {char num} {
if {$num <= 0} {
# No replication required
return ""
} elseif {$num == 1} {
# Quick exit for recursion
return $char
} elseif {$num == 2} {
# Another quick exit for recursion
return $char$char
} elseif {0 == ($num % 2)} {
# Halving the problem results in O (log n) complexity.
set result [strRepeat $char [expr {$num / 2}]]
return "$result$result"
} else {
# Uneven length, reduce problem by one
return "$char[strRepeat $char [incr num -1]]"
}
}
proc ::textutil::repeat::blank {n} {
return [strRepeat " " $n]
}
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::repeat {
namespace export strRepeat blank
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::repeat 0.7

176
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/split-0.8.tm

@ -0,0 +1,176 @@
# split.tcl --
#
# Various ways of splitting a string.
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2001 by Reinhard Max <max@suse.de>
# Copyright (c) 2003 by Pat Thoyts <patthoyts@users.sourceforge.net>
# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: split.tcl,v 1.7 2006/04/21 04:42:28 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil::split {}
########################################################################
# This one was written by Bob Techentin (RWT in Tcl'ers Wiki):
# http://www.techentin.net
# mailto:techentin.robert@mayo.edu
#
# Later, he send me an email stated that I can use it anywhere, because
# no copyright was added, so the code is defacto in the public domain.
#
# You can found it in the Tcl'ers Wiki here:
# http://mini.net/cgi-bin/wikit/460.html
#
# Bob wrote:
# If you need to split string into list using some more complicated rule
# than builtin split command allows, use following function. It mimics
# Perl split operator which allows regexp as element separator, but,
# like builtin split, it expects string to split as first arg and regexp
# as second (optional) By default, it splits by any amount of whitespace.
# Note that if you add parenthesis into regexp, parenthesed part of separator
# would be added into list as additional element. Just like in Perl. -- cary
#
# Speed improvement by Reinhard Max:
# Instead of repeatedly copying around the not yet matched part of the
# string, I use [regexp]'s -start option to restrict the match to that
# part. This reduces the complexity from something like O(n^1.5) to
# O(n). My test case for that was:
#
# foreach i {1 10 100 1000 10000} {
# set s [string repeat x $i]
# puts [time {splitx $s .}]
# }
#
if {[package vsatisfies [package provide Tcl] 8.3]} {
proc ::textutil::split::splitx {str {regexp {[\t \r\n]+}}} {
# Bugfix 476988
if {[string length $str] == 0} {
return {}
}
if {[string length $regexp] == 0} {
return [::split $str ""]
}
if {[regexp $regexp {}]} {
return -code error \
"splitting on regexp \"$regexp\" would cause infinite loop"
}
set list {}
set start 0
while {[regexp -start $start -indices -- $regexp $str match submatch]} {
foreach {subStart subEnd} $submatch break
foreach {matchStart matchEnd} $match break
incr matchStart -1
incr matchEnd
lappend list [string range $str $start $matchStart]
if {$subStart >= $start} {
lappend list [string range $str $subStart $subEnd]
}
set start $matchEnd
}
lappend list [string range $str $start end]
return $list
}
} else {
# For tcl <= 8.2 we do not have regexp -start...
proc ::textutil::split::splitx [list str [list regexp "\[\t \r\n\]+"]] {
if {[string length $str] == 0} {
return {}
}
if {[string length $regexp] == 0} {
return [::split $str {}]
}
if {[regexp $regexp {}]} {
return -code error \
"splitting on regexp \"$regexp\" would cause infinite loop"
}
set list {}
while {[regexp -indices -- $regexp $str match submatch]} {
lappend list [string range $str 0 [expr {[lindex $match 0] -1}]]
if {[lindex $submatch 0] >= 0} {
lappend list [string range $str [lindex $submatch 0] \
[lindex $submatch 1]]
}
set str [string range $str [expr {[lindex $match 1]+1}] end]
}
lappend list $str
return $list
}
}
#
# splitn --
#
# splitn splits the string $str into chunks of length $len. These
# chunks are returned as a list.
#
# If $str really contains a ByteArray object (as retrieved from binary
# encoded channels) splitn must honor this by splitting the string
# into chunks of $len bytes.
#
# It is an error to call splitn with a nonpositive $len.
#
# If splitn is called with an empty string, it returns the empty list.
#
# If the length of $str is not an entire multiple of the chunk length,
# the last chunk in the generated list will be shorter than $len.
#
# The implementation presented here was given by Bryan Oakley, as
# part of a ``contest'' I staged on c.l.t in July 2004. I selected
# this version, as it does not rely on runtime generated code, is
# very fast for chunk size one, not too bad in all the other cases,
# and uses [split] or [string range] which have been around for quite
# some time.
#
# -- Robert Suetterlin (robert@mpe.mpg.de)
#
proc ::textutil::split::splitn {str {len 1}} {
if {$len <= 0} {
return -code error "len must be > 0"
}
if {$len == 1} {
return [split $str {}]
}
set result [list]
set max [string length $str]
set i 0
set j [expr {$len -1}]
while {$i < $max} {
lappend result [string range $str $i $j]
incr i $len
incr j $len
}
return $result
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::split {
namespace export splitx splitn
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::split 0.8

144
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/string-0.8.tm

@ -0,0 +1,144 @@
# string.tcl --
#
# Utilities for manipulating strings, words, single lines,
# paragraphs, ...
#
# Copyright (c) 2000 by Ajuba Solutions.
# Copyright (c) 2000 by Eric Melski <ericm@ajubasolutions.com>
# Copyright (c) 2002 by Joe English <jenglish@users.sourceforge.net>
# Copyright (c) 2001-2014 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: string.tcl,v 1.2 2008/03/22 16:03:11 mic42 Exp $
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
namespace eval ::textutil::string {}
# ### ### ### ######### ######### #########
## API implementation
# @c Removes the last character from the given <a string>.
#
# @a string: The string to manipulate.
#
# @r The <a string> without its last character.
#
# @i chopping
proc ::textutil::string::chop {string} {
return [string range $string 0 [expr {[string length $string]-2}]]
}
# @c Removes the first character from the given <a string>.
# @c Convenience procedure.
#
# @a string: string to manipulate.
#
# @r The <a string> without its first character.
#
# @i tail
proc ::textutil::string::tail {string} {
return [string range $string 1 end]
}
# @c Capitalizes first character of the given <a string>.
# @c Complementary procedure to <p ::textutil::uncap>.
#
# @a string: string to manipulate.
#
# @r The <a string> with its first character capitalized.
#
# @i capitalize
proc ::textutil::string::cap {string} {
return [string toupper [string index $string 0]][string range $string 1 end]
}
# @c unCapitalizes first character of the given <a string>.
# @c Complementary procedure to <p ::textutil::cap>.
#
# @a string: string to manipulate.
#
# @r The <a string> with its first character uncapitalized.
#
# @i uncapitalize
proc ::textutil::string::uncap {string} {
return [string tolower [string index $string 0]][string range $string 1 end]
}
# @c Capitalizes first character of each word of the given <a sentence>.
#
# @a sentence: string to manipulate.
#
# @r The <a sentence> with the first character of each word capitalized.
#
# @i capitalize
proc ::textutil::string::capEachWord {sentence} {
regsub -all {\S+} [string map {\\ \\\\ \$ \\$} $sentence] {[string toupper [string index & 0]][string range & 1 end]} cmd
return [subst -nobackslashes -novariables $cmd]
}
# Compute the longest string which is common to all strings given to
# the command, and at the beginning of said strings, i.e. a prefix. If
# only one argument is specified it is treated as a list of the
# strings to look at. If more than one argument is specified these
# arguments are the strings to be looked at. If only one string is
# given, in either form, the string is returned, as it is its own
# longest common prefix.
proc ::textutil::string::longestCommonPrefix {args} {
return [longestCommonPrefixList $args]
}
proc ::textutil::string::longestCommonPrefixList {list} {
if {[llength $list] <= 1} {
return [lindex $list 0]
}
set list [lsort $list]
set min [lindex $list 0]
set max [lindex $list end]
# Min and max are the two strings which are most different. If
# they have a common prefix, it will also be the common prefix for
# all of them.
# Fast bailouts for common cases.
set n [string length $min]
if {$n == 0} {return ""}
if {0 == [string compare $min $max]} {return $min}
set prefix ""
set i 0
while {[string index $min $i] == [string index $max $i]} {
append prefix [string index $min $i]
if {[incr i] > $n} {break}
}
set prefix
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::string {
# Export the imported commands
namespace export chop tail cap uncap capEachWord
namespace export longestCommonPrefix
namespace export longestCommonPrefixList
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::string 0.8

289
src/modules/punk/mix/templates/layouts/project/src/bootsupport/modules/textutil/tabify-0.7.tm

@ -0,0 +1,289 @@
#
# As the author of the procs 'tabify2' and 'untabify2' I suggest that the
# comments explaining their behaviour be kept in this file.
# 1) Beginners in any programming language (I am new to Tcl so I know what I
# am talking about) can profit enormously from studying 'correct' code.
# Of course comments will help a lot in this regard.
# 2) Many problems newbies face can be solved by directing them towards
# available libraries - after all, libraries have been written to solve
# recurring problems. Then they can just use them, or have a closer look
# to see and to discover how things are done the 'Tcl way'.
# 3) And if ever a proc from a library should be less than perfect, having
# comments explaining the behaviour of the code will surely help.
#
# This said, I will welcome any error reports or suggestions for improvements
# (especially on the 'doing things the Tcl way' aspect).
#
# Use of these sources is licensed under the same conditions as is Tcl.
#
# June 2001, Helmut Giese (hgiese@ratiosoft.com)
#
# ----------------------------------------------------------------------------
#
# The original procs 'tabify' and 'untabify' each work with complete blocks
# of $num spaces ('num' holding the tab size). While this is certainly useful
# in some circumstances, it does not reflect the way an editor works:
# Counting columns from 1, assuming a tab size of 8 and entering '12345'
# followed by a tab, you expect to advance to column 9. Your editor might
# put a tab into the file or 3 spaces, depending on its configuration.
# Now, on 'tabifying' you will expect to see those 3 spaces converted to a
# tab (and on the other hand expect the tab *at this position* to be
# converted to 3 spaces).
#
# This behaviour is mimicked by the new procs 'tabify2' and 'untabify2'.
# Both have one feature in common: They accept multi-line strings (a whole
# file if you want to) but in order to make life simpler for the programmer,
# they split the incoming string into individual lines and hand each line to
# a proc that does the real work.
#
# One design decision worth mentioning here:
# A single space is never converted to a tab even if its position would
# allow to do so.
# Single spaces occur very often, say in arithmetic expressions like
# [expr (($a + $b) * $c) < $d]. If we didn't follow the above rule we might
# need to replace one or more of them to tabs. However if the tab size gets
# changed, this expression would be formatted quite differently - which is
# probably not a good idea.
#
# 'untabifying' on the other hand might need to replace a tab with a single
# space: If the current position requires it, what else to do?
# As a consequence those two procs are unsymmetric in this aspect, but I
# couldn't think of a better solution. Could you?
#
# ----------------------------------------------------------------------------
#
# ### ### ### ######### ######### #########
## Requirements
package require Tcl 8.2
package require textutil::repeat
namespace eval ::textutil::tabify {}
# ### ### ### ######### ######### #########
## API implementation
namespace eval ::textutil::tabify {
namespace import -force ::textutil::repeat::strRepeat
}
proc ::textutil::tabify::tabify { string { num 8 } } {
return [string map [list [MakeTabStr $num] \t] $string]
}
proc ::textutil::tabify::untabify { string { num 8 } } {
return [string map [list \t [MakeTabStr $num]] $string]
}
proc ::textutil::tabify::MakeTabStr { num } {
variable TabStr
variable TabLen
if { $TabLen != $num } then {
set TabLen $num
set TabStr [strRepeat " " $num]
}
return $TabStr
}
# ----------------------------------------------------------------------------
#
# tabifyLine: Works on a single line of text, replacing 'spaces at correct
# positions' with tabs. $num is the requested tab size.
# Returns the (possibly modified) line.
#
# 'spaces at correct positions': Only spaces which 'fill the space' between
# an arbitrary position and the next tab stop can be replaced.
# Example: With tab size 8, spaces at positions 11 - 13 will *not* be replaced,
# because an expansion of a tab at position 11 will jump up to 16.
# See also the comment at the beginning of this file why single spaces are
# *never* replaced by a tab.
#
# The proc works backwards, from the end of the string up to the beginning:
# - Set the position to start the search from ('lastPos') to 'end'.
# - Find the last occurrence of ' ' in 'line' with respect to 'lastPos'
# ('currPos' below). This is a candidate for replacement.
# - Find to 'currPos' the following tab stop using the expression
# set nextTab [expr ($currPos + $num) - ($currPos % $num)]
# and get the previous tab stop as well (this will be the starting
# point for the next iteration).
# - The ' ' at 'currPos' is only a candidate for replacement if
# 1) it is just one position before a tab stop *and*
# 2) there is at least one space at its left (see comment above on not
# touching an isolated space).
# Continue, if any of these conditions is not met.
# - Determine where to put the tab (that is: how many spaces to replace?)
# by stepping up to the beginning until
# -- you hit a non-space or
# -- you are at the previous tab position
# - Do the replacement and continue.
#
# This algorithm only works, if $line does not contain tabs. Otherwise our
# interpretation of any position beyond the tab will be wrong. (Imagine you
# find a ' ' at position 4 in $line. If you got 3 leading tabs, your *real*
# position might be 25 (tab size of 8). Since in real life some strings might
# already contain tabs, we test for it (and eventually call untabifyLine).
#
proc ::textutil::tabify::tabifyLine { line num } {
if { [string first \t $line] != -1 } {
# assure array 'Spaces' is set up 'comme il faut'
checkArr $num
# remove existing tabs
set line [untabifyLine $line $num]
}
set lastPos end
while { $lastPos > 0 } {
set currPos [string last " " $line $lastPos]
if { $currPos == -1 } {
# no more spaces
break;
}
set nextTab [expr {($currPos + $num) - ($currPos % $num)}]
set prevTab [expr {$nextTab - $num}]
# prepare for next round: continue at 'previous tab stop - 1'
set lastPos [expr {$prevTab - 1}]
if { ($currPos + 1) != $nextTab } {
continue ;# crit. (1)
}
if { [string index $line [expr {$currPos - 1}]] != " " } {
continue ;# crit. (2)
}
# now step backwards while there are spaces
for {set pos [expr {$currPos - 2}]} {$pos >= $prevTab} {incr pos -1} {
if { [string index $line $pos] != " " } {
break;
}
}
# ... and replace them
set line [string replace $line [expr {$pos + 1}] $currPos \t]
}
return $line
}
#
# Helper proc for 'untabifyLine': Checks if all needed elements of array
# 'Spaces' exist and creates the missing ones if needed.
#
proc ::textutil::tabify::checkArr { num } {
variable TabLen2
variable Spaces
if { $num > $TabLen2 } {
for { set i [expr {$TabLen2 + 1}] } { $i <= $num } { incr i } {
set Spaces($i) [strRepeat " " $i]
}
set TabLen2 $num
}
}
# untabifyLine: Works on a single line of text, replacing tabs with enough
# spaces to get to the next tab position.
# Returns the (possibly modified) line.
#
# The procedure is straight forward:
# - Find the next tab.
# - Calculate the next tab position following it.
# - Delete the tab and insert as many spaces as needed to get there.
#
proc ::textutil::tabify::untabifyLine { line num } {
variable Spaces
set currPos 0
while { 1 } {
set currPos [string first \t $line $currPos]
if { $currPos == -1 } {
# no more tabs
break
}
# how far is the next tab position ?
set dist [expr {$num - ($currPos % $num)}]
# replace '\t' at $currPos with $dist spaces
set line [string replace $line $currPos $currPos $Spaces($dist)]
# set up for next round (not absolutely necessary but maybe a trifle
# more efficient)
incr currPos $dist
}
return $line
}
# tabify2: Replace all 'appropriate' spaces as discussed above with tabs.
# 'string' might hold any number of lines, 'num' is the requested tab size.
# Returns (possibly modified) 'string'.
#
proc ::textutil::tabify::tabify2 { string { num 8 } } {
# split string into individual lines
set inLst [split $string \n]
# now work on each line
set outLst [list]
foreach line $inLst {
lappend outLst [tabifyLine $line $num]
}
# return all as one string
return [join $outLst \n]
}
# untabify2: Replace all tabs with the appropriate number of spaces.
# 'string' might hold any number of lines, 'num' is the requested tab size.
# Returns (possibly modified) 'string'.
#
proc ::textutil::tabify::untabify2 { string { num 8 } } {
# assure array 'Spaces' is set up 'comme il faut'
checkArr $num
set inLst [split $string \n]
set outLst [list]
foreach line $inLst {
lappend outLst [untabifyLine $line $num]
}
return [join $outLst \n]
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::textutil::tabify {
variable TabLen 8
variable TabStr [strRepeat " " $TabLen]
namespace export tabify untabify tabify2 untabify2
# The proc 'untabify2' uses the following variables for efficiency.
# Since a tab can be replaced by one up to 'tab size' spaces, it is handy
# to have the appropriate 'space strings' available. This is the use of
# the array 'Spaces', where 'Spaces(n)' contains just 'n' spaces.
# The variable 'TabLen2' remembers the biggest tab size used.
variable TabLen2 0
variable Spaces
array set Spaces {0 ""}
}
# ### ### ### ######### ######### #########
## Ready
package provide textutil::tabify 0.7

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save