Version 30 of Integrating Tcl and Emacs on Windows

Updated 2018-07-13 22:18:10 by pooryorick

Emacs has the wonderful "inferior tcl" process which allows us to start Tcl in an Emacs window. Unfortunately, this doesn't work automatically on Windows, Emacs is unable to make the Tcl interpreter start in the "interactive" mode. The problem is that Tcl calls istty() to determine whether tcl_interactive should be set and whether prompts should be displayed. But the Windows version of Emacs can not make istty() return the right value so this doesn't happen and tclsh thinks it's running non-interactive.

One solution is to change the tclsh code, but not everyone can or wants to do that. Another solution is to simulate the command loop in pure Tcl. This works without any changes to Tcl or Emacs, so here is the code that I currently use:

namespace eval CmdInput {

    # We want to allow shell commands to execute automatically
    # as in normal interactive use.  The "unknown" proc checks
    # that "info script" returns "", before it enables that
    # behaviour, so we subclass "info".  In Tcl 8.4 we could simply
    # call 'info script ""' I believe, but 8.3 and earlier don't do
    # that.
    variable this_script [info script]
    proc info {args} {
        set result [uplevel [concat __org_info $args]]
        set cmd [lindex $args 0]

        variable this_script
        if {"script" == $cmd && "$result" == $this_script} {
            return ""
        } else {
            return $result
        }
    }
    rename ::info ::__org_info ;# using a namespace proc here cores
    proc ::info {args} "uplevel \[concat [namespace which info] \$args\]"

    proc loop {} {
        # preparations
        fconfigure stdin  -buffering line
        fconfigure stdout -buffering line
        fconfigure stderr -buffering line
        set ::tcl_interactive 1

        if {[file exists ~/tclshrc.tcl]} {
            namespace eval :: {uplevel \#0 source ~/tclshrc.tcl}
        }

        # input loop
        while {1} {
            catch {uplevel \#0 $::tcl_prompt1}
            flush stdout
            set cmd {}
            while {1} {
                append cmd [gets stdin] "\n"
                if {[info complete $cmd]} {
                    break
                }
                catch {uplevel \#0 $::tcl_prompt2}
                flush stdout
            }
            history add $cmd
            catch {uplevel \#0 $cmd} result
            puts $result
        }
        return ""
    }
}

catch {CmdInput::loop} result 
puts $result
exit 0

To use this code: Save it to a file called cmd-input.tcl. In Emacs customize the variable tcl-application to read "tclsh83.exe" and the variable tcl-command-switches to include "c:/your-path-here/cmd-input.tcl" (this is with Emacs 21.1, Emacs 20 used other names for the variables, I believe).

I hope this is clear, if not or if you have ideas for improvement, you can always contact me at mailto:[email protected] . Just to clarify: This code is free to use by everybody, but I don't give any guarantees for anything. See also: Who owns the content on this Wiki.


Note: Jim Graham has a similar thing called interp.tcl on his homepage [L1 ].


2003-12-01 VI I just set tcl_interactive 1. Works fine for me after that. A proc in the tclshrc will make it even easier.


Even easier, add the following to your .emacs file:

  (add-hook 'inferior-tcl-mode-hook
          (lambda ()
             (tcl-send-string (inferior-tcl-proc) "set ::tcl_interactive 1\n")))

This will automatically set tcl_interactive whenever you launch the inferior-tcl-mode


A similar solution has been added to tcl.el in Emacs CVS. So it should work out-of-the-box when Emacs 22 is released. (It still doesn't work if you're using wish, though).


Nathan: I am using EMACS 22.0.50.1 and activestate tcl 8.4.13 and the integration works fine out-of-the-box except when my tcl code calls any file dialog box (tk_getOpenFile) at which point it hangs. I can call other dialogs (tk_messageBox) without any problem. Any ideas on what could be the cause?


escargo 2006-11-17: I'm using Emacs 21.3 (the latest version I found). When I'm editing Tcl programs, the Tcl menu shows a choice, Tcl Help, that's grayed out. I don't know what I might need to add nor where in order to enable Tcl mode help. Any suggestions? (Knowing where later versions of Windows Emacs could be found might be helpful too.)