Не могу найти пакет из приложения, написанного на Tcl - PullRequest
0 голосов
/ 04 мая 2020

Благодаря комментариям, лучше понять проблему немного. Переменные:

thufir@dur:~/tcl/packages$ 
thufir@dur:~/tcl/packages$ echo 'puts $auto_path' | tclsh
/usr/share/tcltk/tcl8.6 /usr/share/tcltk /usr/lib /usr/local/lib/tcltk /usr/local/share/tcltk /usr/lib/tcltk/x86_64-linux-gnu /usr/lib/tcltk /usr/lib/tcltk/tcl8.6
thufir@dur:~/tcl/packages$ 
thufir@dur:~/tcl/packages$ echo 'puts $tcl_pkgPath' | tclsh
/usr/local/lib/tcltk /usr/local/share/tcltk           /usr/lib/tcltk/x86_64-linux-gnu /usr/lib/tcltk /usr/share/tcltk         /usr/lib/tcltk/tcl8.6 /usr/lib
thufir@dur:~/tcl/packages$ 

код:

thufir@dur:~/tcl/packages$ 
thufir@dur:~/tcl/packages$ ll
total 16
drwxrwxr-x 2 thufir thufir 4096 May  4 02:22 ./
drwxrwxr-x 6 thufir thufir 4096 May  4 02:22 ../
-rw-rw-r-- 1 thufir thufir  215 May  4 02:21 foo.tcl
-rw-rw-r-- 1 thufir thufir 1207 May  4 02:20 tutstack.tcl
thufir@dur:~/tcl/packages$ 
thufir@dur:~/tcl/packages$ cat foo.tcl 
package require tutstack 1.0

set stack [tutstack::create]
foreach num {1 2 3 4 5} { tutstack::push $stack $num }

while { ![tutstack::empty $stack] } {
    puts "[tutstack::pop $stack]"
}

tutstack::destroy $stack
thufir@dur:~/tcl/packages$ 
thufir@dur:~/tcl/packages$ cat tutstack.tcl 
# Register the package
package provide tutstack 1.0
package require Tcl      8.5

# Create the namespace
namespace eval ::tutstack {
    # Export commands
    namespace export create destroy push pop peek empty

    # Set up state
    variable stack
    variable id 0
}

# Create a new stack
proc ::tutstack::create {} {
    variable stack
    variable id

    set token "stack[incr id]"
    set stack($token) [list]
    return $token
}

# Destroy a stack
proc ::tutstack::destroy {token} {
    variable stack

    unset stack($token)
}

# Push an element onto a stack
proc ::tutstack::push {token elem} {
    variable stack

    lappend stack($token) $elem
}

# Check if stack is empty
proc ::tutstack::empty {token} {
    variable stack

    set num [llength $stack($token)]
    return [expr {$num == 0}]
}

# See what is on top of the stack without removing it
proc ::tutstack::peek {token} {
    variable stack

    if {[empty $token]} {
    error "stack empty"
    }

    return [lindex $stack($token) end]
}

# Remove an element from the top of the stack
proc ::tutstack::pop {token} {
    variable stack

    set ret [peek $token]
    set stack($token) [lrange $stack($token) 0 end-1]
    return $ret
}
thufir@dur:~/tcl/packages$ 
thufir@dur:~/tcl/packages$ tclsh foo.tcl 
can't find package tutstack 1.0
    while executing
"package require tutstack 1.0"
    (file "foo.tcl" line 1)
thufir@dur:~/tcl/packages$ 

Насколько я понимаю, мне нужно скомпилировать список или карту расположения пакетов.

Ответы [ 2 ]

1 голос
/ 04 мая 2020

Проблема в том, что Tcl не находит индексный файл (который должен называться pkgIndex.tcl) для вашего пакета. Если бы вы внедрили пакет weather 1.0 в виде файла weather.tcl, то вы, вероятно, хотели бы иметь индексный файл, похожий на этот в том же каталоге :

package ifneeded weather 1.0 [list source [file join $dir weather.tcl]]

Это говорит «чтобы загрузить версию 1.0 пакета weather, запустите этот скрипт», где скрипт генерируется во время выполнения и связывает $dir in (это переменная, всегда определяемая в контексте, в котором запускается загрузчик индекса пакета package ifneeded).

После этого вам нужно разрешить Tcl найти файл индекса. Это можно сделать, поместив этот каталог или его непосредственный родительский элемент в глобальный список Tcl auto_path; либо сделайте это внутри своего скрипта перед загрузкой каких-либо пакетов (очень полезно для приложений, имеющих внутренние пакеты), либо вы можете инициализировать это и вне Tcl, установив переменную окружения TCLLIBPATH. Обратите внимание, что значением этой переменной является список Tcl каталогов, а не системный путь, такой как env(PATH). Это имеет значение, если у вас есть обратные слэши или пробелы в именах каталогов, или если вы хотите иметь несколько элементов в списке. К счастью, вы можете избежать всех этих проблем в случае добавления одного каталога в качестве переменной среды, даже в Windows, используя / вместо \ и следуя обычной практике установки и не оставляя пробела в именах. При добавлении пути во время запуска приложения это проще: вы просто используете lappend, возможно, вот так (очень рано в вашем основном скрипте):

lappend auto_path [file join [file dirname [info script]] my_app_pacakges]
# If the script is in foo/bar.tcl then packages are in or below foo/my_app_packages
0 голосов
/ 05 мая 2020

результат, который запускается:

thufir@dur:~/tcl/foo$ 
thufir@dur:~/tcl/foo$ tree
.
├── api
│   ├── pkgIndex.tcl
│   └── tutstack.tcl
└── main.tcl

1 directory, 3 files
thufir@dur:~/tcl/foo$ 
thufir@dur:~/tcl/foo$ cat main.tcl 
lappend auto_path /home/thufir/tcl/foo/api
package require tutstack 1.0


set stack [tutstack::create]
foreach num {1 2 3 4 5} { tutstack::push $stack $num }

while { ![tutstack::empty $stack] } {
    puts "[tutstack::pop $stack]"
}

tutstack::destroy $stack
thufir@dur:~/tcl/foo$ 
thufir@dur:~/tcl/foo$ cat api/pkgIndex.tcl 
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

package ifneeded tutstack 1.0 [list source [file join $dir tutstack.tcl]]
thufir@dur:~/tcl/foo$ 
thufir@dur:~/tcl/foo$ cat api/tutstack.tcl 
# Register the package
package provide tutstack 1.0
package require Tcl      8.5

# Create the namespace
namespace eval ::tutstack {
    # Export commands
    namespace export create destroy push pop peek empty

    # Set up state
    variable stack
    variable id 0
}

# Create a new stack
proc ::tutstack::create {} {
    variable stack
    variable id

    set token "stack[incr id]"
    set stack($token) [list]
    return $token
}

# Destroy a stack
proc ::tutstack::destroy {token} {
    variable stack

    unset stack($token)
}

# Push an element onto a stack
proc ::tutstack::push {token elem} {
    variable stack

    lappend stack($token) $elem
}

# Check if stack is empty
proc ::tutstack::empty {token} {
    variable stack

    set num [llength $stack($token)]
    return [expr {$num == 0}]
}

# See what is on top of the stack without removing it
proc ::tutstack::peek {token} {
    variable stack

    if {[empty $token]} {
    error "stack empty"
    }

    return [lindex $stack($token) end]
}

# Remove an element from the top of the stack
proc ::tutstack::pop {token} {
    variable stack

    set ret [peek $token]
    set stack($token) [lrange $stack($token) 0 end-1]
    return $ret
}
thufir@dur:~/tcl/foo$ 
thufir@dur:~/tcl/foo$ tclsh main.tcl 
5
4
3
2
1
thufir@dur:~/tcl/foo$ 

генерация файла конфигурации:

thufir@dur:~/tcl/foo/api$ 
thufir@dur:~/tcl/foo/api$ tclsh
% 
%                                             
% pkg_mkIndex . *.tcl
% 
% exit
thufir@dur:~/tcl/foo/api$ 
...