Question

I use term-mode to run Bash shells within Emacs. On remote hosts, term-mode's directory tracking feature helpfully sets default-directory to have the host name in it, so that tab completion and file access is done remotely via Tramp. Sometimes, however, I use remote hosts that mostly share the same filesystems as my workstation, as they load the same directories from NFS. In these cases, Tramp slows me down too much. I would like, when using these systems, for Emacs to set the default-directory locally. To do this I have copied term-handle-ansi-terminal-messages from the system term.el to a new file loaded by my .emacs. I replace this part:

((= command-code ?h)
 (setq term-ansi-at-host argument))

with this:

((= command-code ?h)
 (setq term-ansi-at-host-real argument)
 (setq term-ansi-at-host
       ;; if it has an equivalent filesystem group, set to system-name
       (if (term-equivalent-filesystem-host-group-p argument)
           (system-name)
         argument)))

This calls a term-equivalent-filesystem-host-group-p function that tells whether a host should be treated as having an equivalent filesystem.

This method has the desired effect but copying and modifying system Lisp code isn't robust to any future changes in the code. I don't think advising the function would be possible without duplicating half its functionality (either the message loop or the setting of default-directory and ange-ftp-… variables).

Is there a better way to do this?

Was it helpful?

Solution

I think you can get darn close with advice. I'd define advice as follows:

(defadvice term-handle-ansi-terminal-messages
   (before rewrite-remote-paths-to-local (message) activate)
   (when (and (string-match ".*\eAnSiTh.\\([^\r\n]+\\)\r?\n" message)
              (term-equivalent-filesystem-host-group-p (match-string 1 message)))
     (setq term-ansi-at-host-real (match-string 1 message))
     (setq message (replace-match (system-name) t t message 1))))

All this does is look for a substring of the input to term-handle-ansi-terminal-messages that's going to fall into the case in question, and proactively rewrite the path. Now there's no need to fiddle with the internals of term-handle-ansi-terminal-messages, since it'll never see the remote path.

Is this different than modifying the function? I'd say yes, but this is open to interpretation. In particular, I think that the only knowledge the above code depends on is the format of the submessage term-long-function-name-you-already-know is going to look for, which is really an attribute of the terminal protocol, not the internals of term-now-i'm-just-being-silly. There are some potential problems, such as new code that changes behavior based on the 7th character in the match. (This is the lone . in the string-match above.)

Needless to say, I didn't test this code at all.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top