123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- namespace eval ::tcl::tm {
- variable paths {}
- set pkgpattern {^([_[:alpha:]][:_[:alnum:]]*)-([[:digit:]].*)[.]tm$}
- namespace export path
- namespace ensemble create -command path -subcommands {add remove list}
- }
- proc ::tcl::tm::add {args} {
- variable paths
- set newpaths $paths
- foreach p $args {
- if {$p in $newpaths} {
- continue
- }
- set pos [lsearch -glob $newpaths ${p}/*]
- if {$pos >= 0} {
- return -code error \
- "$p is ancestor of existing module path [lindex $newpaths $pos]."
- }
- foreach ep $newpaths {
- if {[string match ${ep}/* $p]} {
- return -code error \
- "$p is subdirectory of existing module path $ep."
- }
- }
- set newpaths [linsert $newpaths 0 $p]
- }
- set paths $newpaths
- return
- }
- proc ::tcl::tm::remove {args} {
- variable paths
- foreach p $args {
- set pos [lsearch -exact $paths $p]
- if {$pos >= 0} {
- set paths [lreplace $paths $pos $pos]
- }
- }
- }
- proc ::tcl::tm::list {} {
- variable paths
- return $paths
- }
- proc ::tcl::tm::UnknownHandler {original name args} {
- variable paths
- variable pkgpattern
- if {[llength $paths]} {
- set pkgpath [string map {:: /} $name]
- set pkgroot [file dirname $pkgpath]
- if {$pkgroot eq "."} {
- set pkgroot ""
- }
- set satisfied 0
- foreach path $paths {
- if {![interp issafe] && ![file exists $path]} {
- continue
- }
- set currentsearchpath [file join $path $pkgroot]
- if {![interp issafe] && ![file exists $currentsearchpath]} {
- continue
- }
- set strip [llength [file split $path]]
- catch {
- foreach file [glob -nocomplain -directory $currentsearchpath *.tm] {
- set pkgfilename [join [lrange [file split $file] $strip end] ::]
- if {![regexp -- $pkgpattern $pkgfilename --> pkgname pkgversion]} {
- continue
- }
- try {
- package vcompare $pkgversion 0
- } on error {} {
- continue
- }
- if {([package ifneeded $pkgname $pkgversion] ne {})
- && (![interp issafe])
- } {
- continue
- }
- package ifneeded $pkgname $pkgversion \
- "[::list package provide $pkgname $pkgversion];[::list source -encoding utf-8 $file]"
- if {($pkgname eq $name)
- && [package vsatisfies $pkgversion {*}$args]} {
- set satisfied 1
- }
- }
- }
- }
- if {$satisfied} {
- return
- }
- }
- if {[llength $original]} {
- uplevel 1 $original [::linsert $args 0 $name]
- }
- }
- proc ::tcl::tm::Defaults {} {
- global env tcl_platform
- regexp {^(\d+)\.(\d+)} [package provide Tcl] - major minor
- set exe [file normalize [info nameofexecutable]]
- roots [::list \
- [file dirname [info library]] \
- [file join [file dirname [file dirname $exe]] lib] \
- ]
- if {$tcl_platform(platform) eq "windows"} {
- set sep ";"
- } else {
- set sep ":"
- }
- for {set n $minor} {$n >= 0} {incr n -1} {
- foreach ev [::list \
- TCL${major}.${n}_TM_PATH \
- TCL${major}_${n}_TM_PATH \
- ] {
- if {![info exists env($ev)]} continue
- foreach p [split $env($ev) $sep] {
- path add $p
- }
- }
- }
- return
- }
- proc ::tcl::tm::roots {paths} {
- regexp {^(\d+)\.(\d+)} [package provide Tcl] - major minor
- foreach pa $paths {
- set p [file join $pa tcl$major]
- for {set n $minor} {$n >= 0} {incr n -1} {
- set px [file join $p ${major}.${n}]
- if {![interp issafe]} {set px [file normalize $px]}
- path add $px
- }
- set px [file join $p site-tcl]
- if {![interp issafe]} {set px [file normalize $px]}
- path add $px
- }
- return
- }
- if {![interp issafe]} {::tcl::tm::Defaults}
|