From 824158a20b49b6284cef5de16e32d9fd22ccaa7d Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Fri, 15 Dec 2023 06:01:23 +1100 Subject: [PATCH] punk::cap improvements --- src/modules/punk/cap-999999.0a1.0.tm | 338 +++++++++++++----- .../punk/cap/scriptlibs-999999.0a1.0.tm | 52 +++ .../punk/cap/scriptlibs-buildversion.txt | 3 + .../punk/cap/templates-999999.0a1.0.tm | 102 ++++++ .../punk/cap/templates-buildversion.txt | 3 + src/modules/punk/mix-0.2.tm | 5 +- .../mix/commandset/project-999999.0a1.0.tm | 10 +- .../punk/mix/templates-999999.0a1.0.tm | 2 + src/punk86.vfs/lib/app-shellspy/shellspy.tcl | 4 +- 9 files changed, 418 insertions(+), 101 deletions(-) create mode 100644 src/modules/punk/cap/scriptlibs-999999.0a1.0.tm create mode 100644 src/modules/punk/cap/scriptlibs-buildversion.txt create mode 100644 src/modules/punk/cap/templates-999999.0a1.0.tm create mode 100644 src/modules/punk/cap/templates-buildversion.txt diff --git a/src/modules/punk/cap-999999.0a1.0.tm b/src/modules/punk/cap-999999.0a1.0.tm index bdcbbc31..bf36180c 100644 --- a/src/modules/punk/cap-999999.0a1.0.tm +++ b/src/modules/punk/cap-999999.0a1.0.tm @@ -19,15 +19,138 @@ ## Requirements ##e.g package require frobz - +#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 +# capability provider - a package which registers as providing one or more capablities. +# registered using register_package +# 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. # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ namespace eval punk::cap { - variable pkgcap [dict create] + variable pkgcapsdeclared [dict create] + variable pkgcapsaccepted [dict create] variable caps [dict create] + if {[info commands [namespace current]::callbackbase] eq ""} { + oo::class create [namespace current]::callbackbase { + method pkg_register {pkg 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. + return 1 ;#default to permit + } + method pkg_unregister {pkg} { + return ;#unregistration return is ignored - review + } + } + } + #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). + #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. + proc register_capabilityname {capname capnamespace} { + variable caps + variable pkgcapsdeclared + variable pkgcapsaccepted + if {$capnamespace ne ""} { + #normalize with leading :: in case caller passed in package name rather than fully qualified namespace + if {![string match ::* $capnamespace]} { + set capnamespace ::$capnamespace + } + } + #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 + #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 ""} { + 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. + dict set caps $capname handler $capnamespace + if {![dict exists $caps $capname providers]} { + dict set caps $capname providers [list] + } + if {[llength [set providers [dict get $caps $capname providers]]]} { + #some provider(s) were in place before the handler was registered + if {[set cb [get_handler_callback $capname]] ne ""} { + foreach pkg $providers { + set fullcapabilitylist [dict get $pkgcapsdeclared $pkg] + foreach capspec $fullcapabilitylist { + lassign $capspec cn capdict + if {$cn ne $capname} { + continue + } + set do_register [$cb pkg_register $pkg $capdict $fullcapabilitylist] + set list_accepted [dict get $pkgcapsaccepted $pkg] + if {$do_register} { + if {$capspec ni $list_accepted} { + dict lappend pkgcapsaccepted $pkg $capspec + } + } else { + set posn [lsearch $list_accepted $capspec] + if {$posn >=0} { + set list_accepted [lreplace $list_accepted $posn $posn] + dict set pkgcapsaccepted $pkg $list_accepted + } + } + } + #check if any accepted for this cap and remove from caps as necessary + set count 0 + foreach accepted_capspec [dict get $pkgcapsaccepted $pkg] { + if {[lindex $accepted_capspec 0] eq $capname} { + incr count + } + } + if {$count == 0} { + set pkgposn [lsearch $providers $pkg] + if {$pkgposn >= 0} { + set updated_providers [lreplace $providers $posn $posn] + dict set caps $capname providers $updated_providers + } + } + } + + } + + } + } + proc exists {capname} { + variable caps + return [dict exists $caps $capname] + } + proc get_handler {capname} { + variable caps + if {[dict exists $caps $capname]} { + return [dict get $caps $capname handler] + } + return "" + } + proc get_handler_callback {capname} { + set ns [get_handler $capname] + if {[namespace exists $ns]} { + if {[info exists ${ns}::callback]} { + if {[info object isa object ${ns}::callback]} { + return ${ns}::callback + } + } + } + return "" + } + proc get_providers {capname} { + variable caps + if {[dict exists $caps $capname]} { + return [dict get $caps $capname providers] + } + return [list] + } + + #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. proc register_package {pkg capabilitylist} { - variable pkgcap + variable pkgcapsdeclared + variable pkgcapsaccepted variable caps if {[string match ::* $pkg]} { set pkg [string range $pkg 2 end] @@ -35,165 +158,194 @@ namespace eval punk::cap { #for each capability # - ensure 1st element is a single word # - ensure that if 2nd element (capdict) is present - it is dict shaped - foreach c $capabilitylist { - lassign $c capname capdict + foreach capspec $capabilitylist { + lassign $capspec capname capdict 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:'$c'" + error "register_package error. pkg: '$pkg' An entry in the capability list doesn't appear to have a single-word name. Problematic entry:'$capspec'" } 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: '$c'" + error "register_package error. pkg:'$pkg' The second element for capname:'$capname' doesn't appear to be a valid dict. Problematic entry: '$capspec'" } if {[dict exists $caps $capname]} { - set cap_pkgs [dict get $caps $capname] + set cap_pkgs [dict get $caps $capname providers] } else { + dict set caps $capname [dict create handler "" providers [list]] set cap_pkgs [list] } - if {$pkg ni $cap_pkgs} { - dict lappend caps $capname $pkg + #todo - if there's a cap handler - call it's init/validation callback for the pkg + set do_register 1 ;#default assumption unless vetoed by handler + if {[set cb [get_handler_callback $capname]] ne ""} { + #Note that callback must be able to handle multiple calls for same pkg + set do_register [$cb pkg_register $pkg $capdict $capabilitylist] + } + if {$do_register} { + if {$pkg ni $cap_pkgs} { + lappend cap_pkgs $pkg + dict set caps $capname providers $cap_pkgs + } + dict lappend pkgcapsaccepted $pkg $capspec ;#if pkg is being registered prior to handler-registration - the handler may undo this entry } } - dict set pkgcap $pkg $capabilitylist + dict set pkgcapsdeclared $pkg $capabilitylist } + proc unregister_package {pkg} { + variable pkgcapsdeclared + variable caps + if {[string match ::* $pkg]} { + set pkg [string range $pkg 2 end] + } + if {[dict exists $pkgcapsdeclared $pkg]} { + #remove corresponding entries in caps + set capabilitylist [dict get $pkgcapsdeclared $pkg] + foreach c $capabilitylist { + set do_unregister 1 + lassign $c capname _capdict + set cap_info [dict get $caps $capname] + set pkglist [dict get $cap_info providers] + set posn [lsearch $pkglist $pkg] + if {$posn >= 0} { + if {[set cb [get_handler_callback $capname]] ne ""} { + #review + # 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 + #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?) + $cb pkg_unregister $pkg + } + set pkglist [lreplace $pkglist $posn $posn] + dict set caps $capname providers $pkglist + } + } + #delete the main registration record + dict unset pkgcapsdeclared $pkg + } + } + + #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 + #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 pkgcap + variable pkgcapsdeclared variable caps if {[string match ::* $pkg]} { set pkg [string range $pkg 2 end] } - if {![dict exists $pkgcap $pkg]} { + if {![dict exists $pkgcapsdeclared $pkg]} { error "punk::cap::promote_package error pkg'$pkg' not registered. Use register_package \$pkg first" } - if {[dict size $pkgcap] > 1} { - set pkginfo [dict get $pkgcap $pkg] + if {[dict size $pkgcapsdeclared] > 1} { + set pkginfo [dict get $pkgcapsdeclared $pkg] #remove and re-add at end of dict - dict unset pkgcap $pkg - dict set pkgcap $pkg $pkginfo - foreach {cap cap_pkgs} $caps { + 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 $cap_pkgs + dict set caps $cap providers $cap_pkgs } } } } } proc demote_package {pkg} { - variable pkgcap + variable pkgcapsdeclared variable caps if {[string match ::* $pkg]} { set pkg [string range $pkg 2 end] } - if {![dict exists $pkgcap $pkg]} { + if {![dict exists $pkgcapsdeclared $pkg]} { error "punk::cap::promote_package error pkg'$pkg' not registered. Use register_package \$pkg first" } - if {[dict size $pkgcap] > 1} { - set pkginfo [dict get $pkgcap $pkg] + if {[dict size $pkgcapsdeclared] > 1} { + set pkginfo [dict get $pkgcapsdeclared $pkg] #remove and re-add at start of dict - dict unset pkgcap $pkg - dict set pkgcap $pkg $pkginfo - set pkgcap [dict merge [dict create $pkg $pkginfo] $pkgcap] - foreach {cap cap_pkgs} $caps { + 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 $cap_pkgs + dict set caps $cap providers $cap_pkgs } } } } } - proc unregister_package {pkg} { - variable pkgcap - variable caps + proc pkgcap {pkg} { + variable pkgcapsdeclared + variable pkgcapsaccepted if {[string match ::* $pkg]} { set pkg [string range $pkg 2 end] } - if {[dict exists $pkgcap $pkg]} { - #remove corresponding entries in caps - set capabilitylist [dict get $pkgcap $pkg] - foreach c $capabilitylist { - lassign $c capname _capdict - set pkglist [dict get $caps $capname] - set posn [lsearch $pkglist $pkg] - if {$posn >= 0} { - set pkglist [lreplace $pkglist $posn $posn] - dict set caps $capname $pkglist - } + if {[dict exists $pkgcapsdeclared $pkg]} { + set accepted "" + if {[dict exists $pkgcapsaccepted $pkg]} { + set accepted [dict get $pkgcapsaccepted $pkg] } - #delete the main registration record - dict unset pkgcap $pkg - } - } - proc registered_package {pkg} { - variable pkgcap - if {[string match ::* $pkg]} { - set pkg [string range $pkg 2 end] - } - if {[dict exists $pkgcap $pkg]} { - return [dict get $pkgcap $pkg] + return [dict create declared [dict get $pkgcapsdeclared $pkg] accepted $accepted] } else { return } } - proc registered_packages {} { - variable pkgcap - return $pkgcap + proc pkgcaps {} { + variable pkgcapsdeclared + variable pkgcapsaccepted + set result [dict create] + foreach {pkg capsdeclared} $pkgcapsdeclared { + set accepted "" + if {[dict exists $pkgcapsaccepted $pkg]} { + set accepted [dict get $pkgcapsaccepted $pkg] + } + dict set result $pkg declared $capsdeclared + dict set result $pkg accepted $accepted + } + return $result } proc capabilities {{glob *}} { variable caps - set keys [lsort [dict keys $caps $glob]] + set capnames [lsort [dict keys $caps $glob]] set cap_list [list] - foreach k $keys { - lappend cap_list [list $k [dict get $caps $k]] + foreach capname $capnames { + lappend cap_list [list $capname [dict get $caps $capname]] } return $cap_list } - namespace eval templates { - #return a dict keyed on folder with source pkg as value - proc folders {} { - package require punk::cap - set caplist [punk::cap::capabilities templates] - # e.g {templates {punk::mix::templates ::somepkg}} - set templates_record [lindex $caplist 0] - set pkgs [lindex $templates_record 1] - - set folderdict [dict create] - foreach pkg $pkgs { - set caplist [punk::cap::registered_package $pkg] - set templates_entries [lsearch -all -inline -index 0 $caplist templates] ;#we generally expect only one - but if multiple exist - use them - foreach templates_info $templates_entries { - lassign $templates_info _templates templates_dict - if {[dict exists $templates_dict relpath]} { - set provide_statement [package ifneeded $pkg [package require $pkg]] - set tmfile [lindex $provide_statement end] - #set tmdir [file dirname [lindex $provide_statement end]] - set tpath [file normalize [file join $tmfile [dict get $templates_dict relpath]]] ;#relpath is relative to the tm *file* - not it's containing folder - #relpath relative to file is important for tm files that are zip/tar based containers - if {[file isdirectory $tpath]} { - dict set folderdict $tpath [list source $pkg sourcetype package] - } else { - puts stderr "punk::cap::templates::folders WARNING - unable to determine base folder for package '$pkg' which is registered with punk::mix as a provider of 'templates' capability" - } - } else { - puts stderr "punk::cap::templates::folders WARNING - registered pkg 'pkg' has capability 'templates' but no 'relpath' key - unable to use as source of templates" - } - } + proc capabilitynames {{glob *}} { + variable caps + return [lsort [dict keys $caps $glob]] + } + #return only those capnames which have at least one provider + proc capabilitynames_provided {{glob *}} { + variable caps + set keys [lsort [dict keys $caps $glob]] + set cap_list [list] + foreach k $keys { + if {[llength [dict get $caps $k providers]] > 0} { + lappend cap_list $k } - return $folderdict } - - - + return $cap_list } + } diff --git a/src/modules/punk/cap/scriptlibs-999999.0a1.0.tm b/src/modules/punk/cap/scriptlibs-999999.0a1.0.tm new file mode 100644 index 00000000..7d97b548 --- /dev/null +++ b/src/modules/punk/cap/scriptlibs-999999.0a1.0.tm @@ -0,0 +1,52 @@ +# -*- tcl -*- +# Maintenance Instruction: leave the 999999.xxx.x as is and use 'pmix make' or src/make.tcl to update from -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::cap::scriptlibs 999999.0a1.0 +# Meta platform tcl +# Meta license +# @@ Meta End + + + +# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +## Requirements +##e.g package require frobz + + + + +# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +namespace eval punk::cap::scriptlibs { + + + + +} + + + + + + + + + + + + + + +# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +## Ready +package provide punk::cap::scriptlibs [namespace eval punk::cap::scriptlibs { + variable pkg punk::cap::scriptlibs + variable version + set version 999999.0a1.0 +}] +return \ No newline at end of file diff --git a/src/modules/punk/cap/scriptlibs-buildversion.txt b/src/modules/punk/cap/scriptlibs-buildversion.txt new file mode 100644 index 00000000..f47d01c8 --- /dev/null +++ b/src/modules/punk/cap/scriptlibs-buildversion.txt @@ -0,0 +1,3 @@ +0.1.0 +#First line must be a semantic version number +#all other lines are ignored. diff --git a/src/modules/punk/cap/templates-999999.0a1.0.tm b/src/modules/punk/cap/templates-999999.0a1.0.tm new file mode 100644 index 00000000..85d61284 --- /dev/null +++ b/src/modules/punk/cap/templates-999999.0a1.0.tm @@ -0,0 +1,102 @@ +# -*- tcl -*- +# Maintenance Instruction: leave the 999999.xxx.x as is and use 'pmix make' or src/make.tcl to update from -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::cap::templates 999999.0a1.0 +# Meta platform tcl +# Meta license +# @@ Meta End + + + +# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +## Requirements +##e.g package require frobz + + + + +# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +#register using: +# punk::cap::register_capabilityname templates ::punk::cap::templates + +#By convention and for consistency, we don't register here during package loading - but require the calling app to do it. +# (even if it tends to be done immediately after package require anyway) +# registering capability handlers can involve validating existing provider data and is best done explicitly as required. +# It is also possible for a capability handler to be registered to handle more than one capabilityname + +# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +namespace eval punk::cap::templates { + variable callback + set callback [namespace current]::callback + if {[info commands $callback] eq ""} { + punk::cap::callbackbase create $callback + oo::objdefine $callback { + method pkg_register {pkg capdict fullcaplist} { + if {![dict exists $capdict relpath]} { + return 0 + } + return 1 + } + method pkg_unregister {pkg} { + + } + } + } + #return a dict keyed on folder with source pkg as value + proc folders {} { + package require punk::cap + set caplist [punk::cap::capabilities templates] + # e.g {templates {punk::mix::templates ::somepkg}} + set templates_record [lindex $caplist 0] + set pkgs [dict get [lindex $templates_record 1] providers] + + set folderdict [dict create] + foreach pkg $pkgs { + set provide_statement [package ifneeded $pkg [package require $pkg]] + set tmfile [lindex $provide_statement end] + if {![file exists $tmfile]} { + puts stderr "punk::cap::templates::folders WARNING - unable to determine base folder for package '$pkg' which is registered with punk::cap as a provider of 'templates' capability" + continue + } + + set caplist [dict get [punk::cap::pkgcap $pkg] accepted] + set templates_entries [lsearch -all -inline -index 0 $caplist templates] ;#we generally expect only one - but if multiple exist - use them + foreach templates_info $templates_entries { + lassign $templates_info _templates templates_dict + if {[dict exists $templates_dict relpath]} { + #set tmdir [file dirname [lindex $provide_statement end]] + set tpath [file normalize [file join $tmfile [dict get $templates_dict relpath]]] ;#relpath is relative to the tm *file* - not it's containing folder + #relpath relative to file is important for tm files that are zip/tar based containers + if {[file isdirectory $tpath]} { + dict set folderdict $tpath [list source $pkg sourcetype package] + } else { + puts stderr "punk::cap::templates::folders WARNING - unable to determine relpath location [dict get $templates_dict relpath] for package '$pkg' which is registered with punk::cap as a provider of 'templates' capability" + } + } else { + puts stderr "punk::cap::templates::folders WARNING - registered pkg '$pkg' has capability 'templates' but has an entry with no 'relpath' key - unable to use as source of templates" + } + } + } + return $folderdict + } + + +} + + + + +# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +## Ready +package provide punk::cap::templates [namespace eval punk::cap::templates { + variable pkg punk::cap::templates + variable version + set version 999999.0a1.0 +}] +return \ No newline at end of file diff --git a/src/modules/punk/cap/templates-buildversion.txt b/src/modules/punk/cap/templates-buildversion.txt new file mode 100644 index 00000000..f47d01c8 --- /dev/null +++ b/src/modules/punk/cap/templates-buildversion.txt @@ -0,0 +1,3 @@ +0.1.0 +#First line must be a semantic version number +#all other lines are ignored. diff --git a/src/modules/punk/mix-0.2.tm b/src/modules/punk/mix-0.2.tm index 2988b428..2bb4e096 100644 --- a/src/modules/punk/mix-0.2.tm +++ b/src/modules/punk/mix-0.2.tm @@ -1,6 +1,9 @@ package require punk::cap -package require punk::mix::templates ;#registers 'templates' capability with punk::cap +package require punk::cap::templates ;#handler for templates cap +# punk::cap::register_capabilityname templates ::punk::cap::templates +package require punk::mix::templates ;#registers as provider pkg for 'templates' capability with punk::cap + package require punk::mix::base package require punk::mix::cli diff --git a/src/modules/punk/mix/commandset/project-999999.0a1.0.tm b/src/modules/punk/mix/commandset/project-999999.0a1.0.tm index 50678745..7102ded3 100644 --- a/src/modules/punk/mix/commandset/project-999999.0a1.0.tm +++ b/src/modules/punk/mix/commandset/project-999999.0a1.0.tm @@ -305,7 +305,7 @@ namespace eval punk::mix::commandset::project { #todo - tag substitutions in src/doc tree - cd $projectdir + ::cd $projectdir if {[file exists $projectdir/src/modules]} { foreach m $opt_modules { @@ -323,7 +323,7 @@ namespace eval punk::mix::commandset::project { #generate www/man/md output in 'embedded' folder which should be checked into repo for online documentation if {[file exists $projectdir/src]} { - cd $projectdir/src + ::cd $projectdir/src #---------- set installer [punkcheck::installtrack new project.new $projectdir/src/.punkcheck] $installer set_source_target $projectdir/src/doc $projectdir/src/embedded @@ -357,7 +357,7 @@ namespace eval punk::mix::commandset::project { $installer destroy } - cd $projectdir + ::cd $projectdir if {![punk::repo::is_fossil_root $projectdir]} { set first_fossil 1 @@ -742,7 +742,7 @@ namespace eval punk::mix::commandset::project { set workingdir [lindex $workdirs 0] puts stdout "1 result. Changing dir to $workingdir" if {[file exists $workingdir]} { - cd $workingdir + ::cd $workingdir return $workingdir } else { puts stderr "path $workingdir doesn't appear to exist" @@ -753,7 +753,7 @@ namespace eval punk::mix::commandset::project { if {[string trim $answer] in $col_rowids} { set index [expr {$answer - 1}] set workingdir [lindex $workdirs $index] - cd $workingdir + ::cd $workingdir puts stdout [pmix stat] return $workingdir } diff --git a/src/modules/punk/mix/templates-999999.0a1.0.tm b/src/modules/punk/mix/templates-999999.0a1.0.tm index 00a43070..34f23a5c 100644 --- a/src/modules/punk/mix/templates-999999.0a1.0.tm +++ b/src/modules/punk/mix/templates-999999.0a1.0.tm @@ -25,6 +25,8 @@ package require punk::cap namespace eval punk::mix::templates { punk::cap::register_package punk::mix::templates [list\ {templates {relpath ../templates}}\ + {templates {relpath ../templates2}}\ + {templates {boguskey ../templates}}\ ] } diff --git a/src/punk86.vfs/lib/app-shellspy/shellspy.tcl b/src/punk86.vfs/lib/app-shellspy/shellspy.tcl index 18bd243b..6b0232bb 100644 --- a/src/punk86.vfs/lib/app-shellspy/shellspy.tcl +++ b/src/punk86.vfs/lib/app-shellspy/shellspy.tcl @@ -1083,7 +1083,7 @@ source [file normalize $scriptname] } } - foreach tclscript_flavour [list tclline punkline tkline tkshellline help] { + foreach tclscript_flavour [list tclline punkline tkline tkshellline libscript help] { if {[dict exists $arglist dispatch $tclscript_flavour result error]} { catch { set colour [punk::ansi::a+ yellow bold]; set reset [punk::ansi::a] @@ -1102,7 +1102,7 @@ source [file normalize $scriptname] if {[dict exists $arglist errorCode]} { exit [dict get $arglist errorCode] } - foreach tclscript_flavour [list tclline punkline tkline tkshellline help] { + foreach tclscript_flavour [list tclline punkline tkline tkshellline libscript help] { if {[dict exists $arglist dispatch $tclscript_flavour result result]} { puts -nonewline stdout [dict get $arglist dispatch $tclscript_flavour result result] exit 0