How to use a package

In general, using a package is simple: just call package require with the package name as argument. However, things are not quite that simple, as a) the package has to be known to Tcl, and b) you have to make sure that you are requiring the right package. Mostly, this is tricky only if you are writing stand-alone applications that use portions of Tycho.

Packages that need packages, are the happiest packages...

Let's assume that you have created a new package (see How to create a new package). This package uses one or more of the other Tycho packages, such as, say, the tycho.kernel.gui package. All you need to do is ensure that your package load script contains the line:
  package require tycho.kernel.gui
For robustness, you should specify the version number, so that anyone that tries to use your package with an old version of tycho.kernel.gui will get an error message:
  package require tycho.kernel.gui 2.0
Now, tycho.kernel.gui depends on functionality defined in tycho.kernel.basic and tycho.kernel.model. Don't worry about it: as long as tycho.kernel.gui has a properly constructed package load file, you will get these as well. In other words, you only have to "require" the packages that you know you are interested in.

As another example, suppose that you had an application that used an HTML viewer and the Slate canvas package. Your package load file would in that case contain:

  package require tycho.kernel.html
  package require tycho.edit.slate

If your package contains optional GUI functionality but might be run from a non-graphical Tcl shell, then you can use something like this:

  # Only load the graphical packages only if running with Tk
  if [info exists tk_version] {
      package require tycho.kernel.gui
      package require tycho.kernel.html
  } else {
      package require tycho.kernel.basic
  }

Command-line scripts

Command-line scripts are a little tricky, because Tcl has such a lame package mechanism. The problem is that, in order to find a package, Tcl has to know what directories to look for packages in -- and what it does is look in the directories in the auto_path variable.

So how does auto_path get set? Why, by your Tcl code... Actually, it isn't that bad, but because there is no standard way of telling Tcl where to look for packages, shell scripts that run Tcl need to go through some contortions to find the packages they need.

The first and simplest way of having Tcl find packages is to install the package in the Tcl library directory. Tcl knows where that is, at least, and initializes auto_path to contain it. If you can't install there (because you don't have directory write access, for example), then you have to rely on environment variables (see Where to install a package). Here is a typical startup script; in the following, pkg is the package tail in lowercase, PKG is the package tail in uppercase and Package is the full package name. For example, if the package is tycho.util.tydoc, then pkg is tydoc, PKG is TYDOC, and Package is tycho.util.tydoc.

#! /bin/sh
# Command-line program for the Package utility \
    exec itclsh "$0" "$@"

# Author: author

# Create the tycho namespace
namespace ::tycho

# Set up the auto_path. What we do here is simply append
# paths to the auto_path in the order that is likely to
# be most rapid for finding the needed packages. Note that
# it is important to append all possible paths before doing
# a package require, in case this package requires other
# packages.

# Try PKG_LIBRARY
if [info exists env(PKG_LIBRARY)] {
    if { [lsearch -exact $auto_path $env(PKG_LIBRARY)] }  {
	lappend auto_path $env(PKG_LIBRARY)
    }
}

# Try TCL_PACKAGES
if [info exists env(TCL_PACKAGES)] {
    if { [lsearch -exact $auto_path $env(TCL_PACKAGES)] == -1 }  {
	lappend auto_path $env(TCL_PACKAGES)
    }
}

# Try TYCHO, or PTOLEMY if there is no TYCHO
if ![info exists env(TYCHO)] {
    if [info exists env(PTOLEMY)] {
	# TYCHO is not set, but PTOLEMY is.
	if [file exists [file join $env(PTOLEMY) tycho]] {
	    set env(TYCHO) [file join $env(PTOLEMY) tycho]
	}
    } 
}
if [info exists env(TYCHO)] {
    if { [lsearch -exact $auto_path $env(TYCHO)] == -1 }  {
	lappend auto_path $env(TYCHO)
    }
}

# Try loading the package. If it doesn't work, print a helpful
# error message and exit
if [catch {package require Package} err] {
    puts "Cannot load \"Package\"\
	    Error was:\n--start--\n$errorInfo\n--end--\n\
	    The auto_path variable lists the directories that were searched.\n\
	    auto_path = $auto_path\n\
	    You can:\n\
	    1. Install Package in a subdirectory of your \
	    Tcl library\n\
	    2. Install Package in the directory given by the \
	    TCL_PACKAGES variable\n\
	    3. Set the PKG_LIBRARY variable to point to the \
	    pkg directory\n\
	    4. Set the TYCHO variable to point to your \
	    Tycho installation\n\
	    5. Set the PTOLEMY variable to point to your \
	    Ptolemy installation\n"
    exit
}

# Print startup sig
puts "Package, version 1.0"

# Run the main procedure
eval pkg $argv

# Done


Copyright © 1998, The Regents of the University of California. All rights reserved.
Last updated: 06/11/98, comments to: johnr@eecs.berkeley.edu