Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

source like #include

19 views
Skip to first unread message

Stefan Kuhr

unread,
Mar 21, 2002, 5:06:50 AM3/21/02
to
Hello!

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


Bob Techentin

unread,
Mar 21, 2002, 8:37:43 AM3/21/02
to
Yes, source is different from #include. You're actually running the
source script through the interpreter. So nested source commands all
execute from the same directory.

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...

Martin Lemburg

unread,
Mar 21, 2002, 9:30:46 AM3/21/02
to
"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

Stefan Kuhr

unread,
Mar 21, 2002, 9:54:15 AM3/21/02
to
Hello Bob!

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


Stefan Kuhr

unread,
Mar 21, 2002, 10:08:28 AM3/21/02
to
Hello Martin!

Oh, default include pathes. That's very interesting. Thanks!


Bye

Stefan


Bob Techentin

unread,
Mar 21, 2002, 10:53:01 AM3/21/02
to

"Stefan Kuhr" <Stefa...@mch.siemens.de> wrote

>
> > 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.
>

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.

0 new messages