Update multi-term buffer name based on PWD

烈酒焚心 提交于 2019-12-19 10:32:24

问题


If I use konsole or other terminal, the terminal tag name can change based on PWD. But in multi-term, the buffer name is *terminal<number>*. This is not very nice. Because when I switch between them, the name is not very informative. So I want to rename it based on PWD.

I find that the Enter key is bind to term-send-raw, so I write a function

(defadvice term-send-raw (around rename-term-name activate)
  (progn
    (rename-buffer 
     (concat "⇒ " 
             (shell-command-to-string "pwd | xargs basename |  tr -d '\n'") 
             (format-time-string " [%M ∞ %S]")))
    ad-do-it))

But the problem is pwd command return the PWD of the terminal buffer, while it is not the PWD of the SHELL in that terminal.

The PWD of the terminal buffer is set by defcustom multi-term-default-dir. And it does not change when the PWD change in the SHELL.

(defcustom multi-term-default-dir "~/"
  "The default directory for terms if current directory doesn't exist."
  :type 'string
  :group 'multi-term)

How can I get the PWD of the SHELL in the terminal?

Regards.


回答1:


AFAIK there is no easy way to retrieve information from a running process.

But if you want to get the current directory you could:

  1. ask the shell to print it
  2. parse and trace the command-line for functions like cd, pushd, popd…
  3. poll /proc/PID/cwd

The first method is described in the header of term.el (M-xfind-libraryRETtermRET).

And now, thank you for your question, you gave me the opportunity to do this:

(defadvice term-send-input (after update-current-directory)
  (let* ((pid (process-id (get-buffer-process (current-buffer))))
         (cwd (file-truename (format "/proc/%d/cwd" pid))))
    (cd cwd)))

(ad-activate 'term-send-input)

It's a naive implementation of the third method and it doesn't work if the user uses su or ssh. However, I don't know if it's possible withouth using the first or the second method.

In your case, you can just replace the cd command with whatever you want.




回答2:


Building off of Daimrod's answer for polling /proc/PID/cwd, I found a way get around the problem that Reed pointed out where the advice doesn't pick up the updated CWD immediately and you have to hit Enter twice.

If you move the CWD update code to its own function and use run-at-time to call it from the advice at a later time, it will pick up the updated CWD correctly. Unfortunately I don't know enough about Emacs' scheduling to explain why this works (any enlightenment would be appreciated).

Here's my code based on Daimrod's. Note I advised term-send-input for line-mode and term-send-return for char-mode. I tested this using multi-term on Emacs 24.3.1:

(defadvice term-send-input (after update-current-directory)
  (run-at-time "0.1 sec" nil 'term-update-dir)
  )

(ad-activate 'term-send-input)

(defadvice term-send-return (after update-current-directory)
  (run-at-time "0.1 sec" nil 'term-update-dir)
  )

(ad-activate 'term-send-return)

(defun term-update-dir ()
  (let* ((pid (process-id (get-buffer-process (current-buffer))))
         (cwd (file-truename (format "/proc/%d/cwd" pid))))
    (unless (equal (file-name-as-directory cwd) default-directory)
      (message (concat "Switching dir to " cwd))
      (cd cwd)))
  )


来源:https://stackoverflow.com/questions/13655782/update-multi-term-buffer-name-based-on-pwd

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!