【问题标题】:Update multi-term buffer name based on PWD根据 PWD 更新多项缓冲区名称
【发布时间】:2012-12-01 02:28:54
【问题描述】:

如果我使用 konsole 或其他终端,终端标签名称可以根据 PWD 更改。但在多术语中,缓冲区名称为*terminal<number>*。这不是很好。因为当我在它们之间切换时,名称不是很丰富。所以我想根据 PWD 重命名它。

我发现Enter键绑定到term-send-raw,所以我写了一个函数

(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))

但问题是pwd 命令返回终端缓冲区的PWD,而不是该终端中SHELLPWD

终端缓冲区的PWDdefcustom multi-term-default-dir 设置。当SHELL 中的PWD 更改时,它不会更改。

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

如何在终端中获取 SHELL 的 PWD?

问候。

【问题讨论】:

    标签: emacs elisp


    【解决方案1】:

    AFAIK 没有简单的方法可以从正在运行的进程中检索信息。

    但如果你想获取当前目录,你可以:

    1. 让shell打印出来
    2. 解析和跟踪 cd、pushd、popd 等函数的命令行
    3. 轮询 /proc/PID/cwd

    第一种方法在term.el的头部描述(M-xfind-libraryRETtermRET)。 p>

    现在,谢谢你的提问,你给了我这个机会:

    (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)
    

    这是第三种方法的幼稚实现,如果用户使用sussh,它就不起作用。不过不知道是不是可以不使用第一种还是第二种方法。

    在您的情况下,您可以将 cd 命令替换为您想要的任何命令。

    【讨论】:

    • 不错的方法。我尝试了第二种方法,它有点复杂。非常感谢。 :-)
    • 通知功能在绑定到term-send-raw 时效果很好(在字符模式下按 Enter 时发送)。唯一的缺点是,在按下 Enter 后,update-current-directory 在 shell 有机会实际更改目录之前运行。一种解决方法是按两次 Enter。
    【解决方案2】:

    基于 Daimrod 对轮询 /proc/PID/cwd 的回答,我找到了一种解决问题的方法,即 Reed 指出的建议不会立即获取更新的 CWD 并且您必须按两次 Enter。

    如果您将 CWD 更新代码移动到其自己的函数中,并稍后使用 run-at-time 从通知中调用它,它将正确获取更新后的 CWD。不幸的是,我对 Emacs 的调度了解不多,无法解释为什么会这样(任何启发将不胜感激)。

    这是我基于 Daimrod 的代码。注意我建议 line-mode 使用 term-send-input,char-mode 使用 term-send-return。我在 Emacs 24.3.1 上使用 multi-term 对此进行了测试:

    (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)))
      )
    

    【讨论】:

      【解决方案3】:

      大多数终端的窗口名称来自命令echo -en。在zsh 你可以把它放在你的~/.zshenv

      precmd() { echo -en "\e]0;`basename ${PWD}`\a" }
      

      这将获得PWD 环境变量的基本名称。理想情况下,multi-term 会做类似的事情并将其放入 multi-term-buffer-name,这是保存其缓冲区名称的变量。

      是的,这不是一个完整的解决方案。我也想要一个!

      【讨论】:

        【解决方案4】:

        试试这个:

        (defun open-or-jump-to-multi-term ()
          (interactive)
          (if (string-prefix-p "*terminal<" (buffer-name))
              (delete-window)
            (progn
              (setq bufname (concat "*terminal<" (directory-file-name (file-name-directory (buffer-file-name))) ">"))
              (if (get-buffer-process bufname)
            (switch-to-buffer-other-window bufname)
              (progn
            
            (split-window-right)
            (other-window 1)
            (multi-term)
            (rename-buffer bufname)
            )
              )))
          )
        (global-set-key (kbd "C-`") 'open-or-jump-to-multi-term)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多