blob: d4a29784ff529f7fcd5298ae22806ac1a5722332 [file] [log] [blame]
# This file is an aid in sourcing other tcl files. It provides the following advantages:
# - It shortens the number of lines of code needed to intelligently source files.
# - Its my_source procedure provides several benefits (see my_source prolog below).
# By convention, this file, or a link to this file, must exist in one of the directories named in the PATH
# environment variable.
# Example use:
# source [exec bash -c "which source.tcl"]
# my_source [list print.tcl opt.tcl]
set path_list [split $::env(PATH) :]
proc tcl_which { file_name } {
# Search the PATH environment variable for the first executable instance of $file_name and return the full
# path. On failure, return a blank string.
# This procedure runs much faster than [exec bash -c "which $file_name"].
# Description of argument(s):
# file_name The name of the file to be found.
global path_list
foreach path $path_list {
set file_path $path/$file_name
if { [file executable $file_path] } { return $file_path }
}
return ""
}
if { ![info exists sourced_files] } {
set sourced_files [list]
}
proc my_source { source_files } {
# Source each file in the source_files list.
# This procedure provides the following benefits verses just using the source command directly.
# - Use of PATH environment variable to locate files.
# - Better error handling.
# - Will only source each file once.
# - If "filex" is not found, this procedure will try to find "filex.tcl".
# Description of argument(s):
# source_files A list of file names to be sourced.
global sourced_files
global env
foreach file_name $source_files {
set file_path [tcl_which $file_name]
if { $file_path == "" } {
# Does the user specify a ".tcl" extension for this file?
set tcl_ext [regexp -expanded {\.tcl$} $file_name]
if { $tcl_ext } {
append message "**ERROR** Programmer error - Failed to find"
append message " \"${file_name}\" source file:\n"
append message $::env(PATH)
puts stderr $message
exit 1
}
set file_path [tcl_which ${file_name}.tcl]
if { $file_path == "" } {
append message "**ERROR** Programmer error - Failed to find either"
append message " \"${file_name}\" or \"${file_name}.tcl\" source file:"
append message $::env(PATH)
puts stderr $message
exit 1
}
}
# Adjust name (in case we found the .tcl version of a file).
set full_file_name "[file tail $file_path]"
# Have we already attempted to source this file?
if { [lsearch -exact $sourced_files $full_file_name] != -1 } { continue }
# Add the file name to the list of sourced files. It is important to add
# this file to the list BEFORE we source the file. Otherwise, if there is
# a recursive source (a sources b, b sources c, c sources a), we will get
# into an infinite loop.
lappend sourced_files $full_file_name
if { [catch { uplevel 1 source $file_path } result] } {
append message "**ERROR** Programmer error - Failed to source"
append message " \"${file_path}\":\n${result}"
puts stderr $message
exit 1
}
}
}