Search code examples
shellemacszshtmuxxterm

Is it possible to send an 'cd' command to xterm from emacs?


In Emacs, I don't like shell-mode/eshell-mode since they cannot take full use of zsh and they suck much.

So I hope to use xterm as the external subprocess.

(global-set-key (kbd "M-<f2>")
                (lambda () (interactive)
                  (start-process "XTerm" nil "xterm")))

And now the PWD of xterm is synced with Emacs default-directory and the term is now a full-feathered one. But there is ONE problem: I the startup time of the sub-rountine is always disappointing.

So I hope starting xterm only once and when in Emacs, if it finds there is a subprocess called XTerm running, 1) switch to it 2)set the PWD of shell running in xterm to default-directory of Emacs.

Is it possible to do so?

If neither is possible, then with tmux, can we achieve this goal?


Solution

  • Here's my setup:

    (defvar terminal-process)
    (defun terminal ()
      "Switch to terminal. Launch if nonexistant."
      (interactive)
      (if (get-buffer "*terminal*")
          (switch-to-buffer "*terminal*")
        (term "/bin/bash"))
      (setq terminal-process (get-buffer-process "*terminal*")))
    
    (global-set-key "\C-t" 'terminal)
    

    Could you elaborate more on the start-up time? Mine is around 0.3s.

    UPD A small snippet from my dired customization

    I've got this in my dired setup:

    (add-hook
     'dired-mode-hook
     (lambda()
       (define-key dired-mode-map (kbd "`")
         (lambda()(interactive)
           (let ((current-dir (dired-current-directory)))
             (term-send-string
              (terminal)
              (format "cd %s\n" current-dir)))))))
    

    where terminal is:

    (defun terminal ()
      "Switch to terminal. Launch if nonexistant."
      (interactive)
      (if (get-buffer "*terminal*")
          (switch-to-buffer "*terminal*")
        (term "/bin/bash"))
      (setq terminal-process (get-buffer-process "*terminal*")))
    

    What this does is it opens a terminal for the same directory as dired buffer, reusing the existing *terminal*, or creating a new one if it's absent.

    To summarize the answer to your question:

    Yes, it's possible. It's done with:

    (term-send-string
     (terminal)
     (format "cd %s\n" default-directory))