Version 1 of The RC File

Updated 2001-09-11 17:18:52

Each tclsh or wish can have its own RC file:

  • The RC file is normally named .tclshrc, .wishrc or a variation on that, tied to the specific tclsh. On Windows, it becomes tclshrc.tcl or wishrc.tcl
  • The RC file is automatically sourced when the shell is started interactively (without a script on its commandline)
  • The RC file is not automatically sourced when the shell is started with a script on the commandline
  • RC files have the full language as implemented by the specific shell. itkwishrc thus can use [incr Tcl] and Tk.
  • When the shell is deemed interactive, the global variable $tcl_interactive is true.

Also see Application-specific RC files.


Generally

Use the rc file for items you want to always have available when working interactively. This may be special error analysis procedures, defining a prompt that is more descriptive than a plain %, and more. Because you will be using the tclsh in interactive mode even in debugging scripts intended to run without that level of interactivity, avoid cluttering the global namespace unduely.

Remember, though, that the ~/.tclshrc will be sourced by older tclsh versions if you have them installed, and similarly with wishrc files. You may have to condition some code or usages on version of Tcl provided by the current interpreter, which is the result of [package provide Tcl]. At the same time, if you are using a platform which uses symbolic links, you may wish to combine a tclshrc and itclshrc, expectrc, and the like.

Similarly, one rc file can source another, again saving multiple editing of varied rc files.


Ideas for a useful tclshrc

 global tcl_interactive tcl_prompt1 tcl_prompt2
 # Configure the prompt according to the actual (non-wish) running
 # First, only bother with a prompt IF it is an interactive shell
 # We may wish to source from other scripts just for convenience
 if {[info exists tcl_interactive] && $tcl_interactive > 0} {
   set tcl_prompt1 {global tcl_version
       puts -nonewline "=========\ntclsh$tcl_version > "}
   set tcl_prompt2 {puts -nonewline "continue > "}
   if {[info exists itcl::patchLevel]} {
     set tcl_prompt1 {puts -nonewline "=========\nitclsh$::itcl::patchLevel > "}
     set tcl_prompt2 {puts -nonewline "continue > "}
   } elseif [string match exp_version [info command exp_version]] {
     set tcl_prompt1 {puts -nonewline "========\nexpect[exp_version] > "}
     set tcl_prompt2 {puts -nonewline "continue > "}
   } elseif {[info exists tnm(version)]} {
     set tcl_prompt1 {global tnm
       puts -nonewline "=========\nscotty$tnm(version) > "}
     set tcl_prompt2 {puts -nonewline "  continue >  "}
   } elseif {[llength [info commands pg_connect]] > 0} {
     regsub {tclsh} $tcl_prompt1 {pgtclsh}
   }
 }

 # Convenience procs
 proc showenv {} {
   global env
   foreach k [lsort [array names env]] {
     puts "$k=\"$env($k)\""
   }
 }

Ideas for a useful wishrc

 global tcl_interactive tcl_prompt1 tcl_prompt2 tk_patchLevel 
 # Again, test for tcl_interactive true before setting prompts
 if {[info exists tcl_interactive] && $tcl_interactive > 0} {
   source ~/.tclshrc
   if [string match exp_version [info command exp_version]] {
     set tcl_prompt1 { puts -nonewline "========\nexpectk[exp_version] > "  }
   } elseif [info exists ::itk::patchLevel] {
     set tcl_prompt1 { puts -nonewline "========\nitkwish$::itk::patchLevel > "}
   } elseif [info exists ::itcl::patchLevel] {
     set tcl_prompt1 {
     puts -nonewline "========\n\[i$::itcl::patchLevel\]wish $tk_patchLevel > "}
   } else {
     set tcl_prompt1 {global tk_version
     puts -nonewline "=========\nwish $tk_patchLevel > "}
   }
   set tcl_prompt2 { puts -nonewline "continue > "}
 }

A little tool to list the available packages

Here's a little utility that I'm beginning to find invaluable... Usage: lspackages ? pattern ? lists all the package names and versions installed on the system, along with the 'package require' script that will be executed to loade them. Packages that have already been loaded are prefixed with a '+' sign. [email protected]

 proc lspackages {{pattern *}} {
     # Force the package loader to do its thing:
     # NOTE: this depends on a side effect of the
     # built-in [package unknown].  Other [package unknown]
     # handlers might not meet our expectations.
     eval [package unknown] Tcl [package provide Tcl]
     foreach package [lsort [package names]] {
        if {![string match $pattern $package]} { continue }
        foreach version [package versions $package] {
            set present [expr {
                [string compare $version [package provide $package]]
              ? " " : "+" }]
            set ifneeded \
                [string replace \
                    [string trim \
                        [string map {"\n" " " "\t" " "} \
                            [package ifneeded $package $version]]] \
                    50 end "..."]
            puts [format "%1s%-15s %6s %-55s" \
                $present $package $version $ifneeded]
        }
     }
 }

DKF: My .tclshrc is extremely simple:

 proc % {args} {uplevel 1 $args}

This makes it much easier to mark-n-paste previously entered lines for inputting again as I don't need to be careful with excluding the prompt. :^)


DGP: I made a few revisions above to advise better use of [package].


Examples of clever use of .*rc appear several places. One motivation is "Writing Tk programs so that the user can extend or interact with them without modifying the application". Also, note that "Magic names" has more information on the .*rc mechanism.