Untill now I thought, that tcl's source command behaves like the C #include
command, that it's possible to source a file with relative path, which
itself again sources a file with a relative path from itself. But that's the
mistake; source uses always the current path for the source command, even in
sourced files.
Is there a command similar to #include or do I have to use absolute path
names or the cd and pwd commands?
Bye
Stefan
You can use a relative path name in a source command. Your script
must first figure out where it is, and can then create a relative
path. Something like:
# in file1.tcl
# figure out where I am
set mydir [file dir [info script]]
# create relative path to next script
set s [file join $mydir "../lib/nextscript.tcl"]
source $s
Ooooorrrrrr, if you're really working with a "package" of script, you
should look over the loading and package mechanisms which can make
this whole process *very* simple. See the 'source' page on the wiki
at http://mini.net/tcl/source
Don't we have a basic write-up on multi-file applications, source,
auto_index and all that good stuff? I couldn't find it. :-(
Bob
--
Bob Techentin techenti...@mayo.edu
Mayo Foundation (507) 538-5495
200 First St. SW FAX (507) 284-9171
Rochester MN, 55901 USA http://www.mayo.edu/sppdg/
"Stefan Kuhr" <Stefa...@mch.siemens.de> wrote in message
news:a7cbcc$5iv$1...@news.mch.sbs.de...
What's about the following?
Regards
Martin Lemburg
----------------------
# proc to go through the search path of include files
# to source a given file
#
# !! you can use glob pattern in the scriptFileName !!
#
proc !include {scriptFileName} {
global !includePath;
if {![info exists !includePath]} {
set !includePath [list [pwd]];
}
foreach directory ${!includePath} {
set filePattern [file join $directory $scriptFileName];
set fileNames [glob -nocomplain $filePattern];
set fileName [lindex $fileNames 0];
switch -exact -- [llength $fileNames] {
0 {}
1 {
if {[file readable $fileName]} {
return [source $fileName];
}
error "script file \"$fileName\" not readable";
}
default {
error "too many files matching \"$scriptFileName\" found";
}
}
}
error "script file \"$scriptFileName\" not found, check your path";
}
# build path from variables or given directories
# e.g. to be used with variables like auto_path,
# tcl_library, or if existent tk_library
#
# !! you can use glob pattern in directories !!
#
proc !includePath {args} {
global !includePath;
if {![llength $args]} {
return ${!includePath};
}
foreach arg $args {
if {[uplevel [list info exists $arg]]} {
!includePath [uplevel [list set $arg]];
} elseif {[uplevel #0 [list info exists $arg]]} {
!includePath [uplevel #0 [list set $arg]];
} else {
foreach directory $arg {
if {[lsearch -exact ${!includePath} $directory] < 0} {
lappend !includePath $directory;
}
}
}
}
return ${!includePath};
}
# build search path for include files
#
!includePath \
tcl_library auto_path \
[pwd] \
[file join [pwd] lib];
# source a file inside the search path
#
!include dummy.tcl
Now I wrote a little include procedure by myself. Therefore I use pushd and
popd to change to the directory of the files to source. But your suggestion
doesn't need to change the path, which might be an great advantage ...
> Ooooorrrrrr, if you're really working with a "package" of script, you
> should look over the loading and package mechanisms which can make
> this whole process *very* simple. See the 'source' page on the wiki
> at http://mini.net/tcl/source
Sorry, I didn't found what you mean.
# include can be used instead of source to allow a C #inlude like use.
# path defines the path of the script files to source
# args all following arguments are the file names of the script files
# to source.
proc ::include {path args} {
set result ""
pushd $path
foreach script $args {
set result [
uplevel 1 "
source $script
"
]
}
popd
return $result
}
Bye
Stefan
Oh, default include pathes. That's very interesting. Thanks!
Bye
Stefan
I couldn't find a write-up on the wiki, but this is what I am
referring to.
If you're building a library of tcl scripts (which is implied by
asking about sourcing files in relative directory names), you should
consider using utilizing one of Tcl's auto-loading mechanisms.
If you put a bunch of library scripts in a directory (or set of
relative directories), you can use the auto_mkindex command
(documented on Tcl's library manual page) to generate a special index
file named tclIndex. This index file contains references to all the
procedures defined in all the files.
You can then modify your application's auto_path variable to include
this new library directory. The auto-loading mechanism will scan the
index, and when you call one of the indexed procedures, it will know
where to find it. No 'source' commands required.
Tcl's 'package' mechanism is even more sophisticated, and can
distinguish between different versions of a library.