使用tmux执行Emacs中的当前行


我认为,如果一个操作每天重复太多,就得想办法让它自动化。

我在工作的时候,常常都是一边开terminal一边开emacs。有这样一个操作每天都在重复:在Emacs中copy一行,到terminal中粘贴执行。

注意这个操作和在Emacs中直接执行shell是不同的。因为,很多时候这一行不是shell脚本,对我来说,可能是交换机的命令,我需要放到串口去执行。 也可能,terminal是登陆到remote的,这时候直接在Emacs中执行shell脚本也达不到要求。

因为我的terminal中一定是在运行tmux的,tmux又可以借助xsel把系统clipboard中的内容放入当前的buffer中。实现自动化的方法就变得很简单了。

  1. 在Emacs中拷贝当前行,注意在结尾加一个回车。
  2. 调用shell把系统clipboard中的内容放入tmux的当前buffer中。这点我搞了一个shell脚本来做,该脚本就是把当前系统clipboard中的内容放入当前tmux的buffer中:
    #!/bin/bash
    
    xsel -ob | tmux load-buffer - ; tmux paste-buffer
    
    exit 0
    
  3. 如果有需要,使用wmctrl切换到对应的窗口中。

关于最后一点,是否切换到terminal窗口,我使用行尾空格来判断(反正行尾空格基本没什么用)。 如果行尾有空格,才切换到terminal,否则移动到下一行。Emacs可以开启行尾空格显示:

(setq show-trailing-whitespace t)

我是在ubuntu下,terminal使用的是 lilyterm 。 需要安装的软件如下:

apt-get install wmctrl xsel

其中xsel可以提取系统clipboard内容,wmctrl可以用来进行窗口切换。

最后函数如下:

(defun peng-lilyterm-tmux-run-current-line ()
  "Run current line in tmux.
If line is end up with space, switch to lilyterm. Else, just move to next line in Emacs."
  (interactive)
  (let* ((origin-line (thing-at-point 'line))
         (switch-to (equal (s-right 1 (s-chomp (thing-at-point 'line))) " "))
         (line (concat origin-line "\n")))
    (kill-new line)

    (start-process "paste" nil "bash" "/home/pengpengxp/bin/p_paste_to_tmux.sh")
    (if switch-to
        (shell-command "wmctrl -xa lilyterm.Lilyterm")
      (next-line))))

  1. 函数中的脚本文件 /home/pengpengxp/bin/p_paste_to_tmux.sh 里就是 上文 提到的。
  2. 如果你的terminal不是lilyterm,就改一下最后的 lilyterm.Lilyterm 就可以了。 可以使用
    wmctrl -xl
    命令来查当前打开的所有的窗口。

如果你觉得本文不错,欢迎 donate