EMACS-DOCUMENT

=============>集思广益

整合iTerm2与Emacs

Emacs中的终端体验又慢有难用,因此我都是用iTerm2作为我的主要终端来用的. 我创建了三个emacs-lisp函数,这些函数会调用AppleScript,使得我可以快速在iTerm和spacemacs之间相互切换.

这个函数返回当前打开文件所在的目录. 若当前buffer为 *scratch* 或类似的buffer,则会返回home目录.

(defun get-file-dir-or-home ()
  "If inside a file buffer, return the directory, else return home"
  (interactive)
  (let ((filename (buffer-file-name)))
    (if (not (and filename (file-exists-p filename)))
        "~/"
      (file-name-directory filename))))

这个函数让我cd到当前编辑文件所在的目录. 若我处于类似 *scratch* buffer中则会cd到 $HOME 目录. 然后进入iTerm2应用.

(defun iterm-goto-filedir-or-home ()
  "Go to present working dir and focus iterm"
  (interactive)
  (do-applescript
   (concat
    " tell application \"iTerm2\"\n"
    "   tell the current session of current window\n"
    (format "     write text \"cd %s\" \n" (get-file-dir-or-home))
    "   end tell\n"
    " end tell\n"
    " do shell script \"open -a iTerm\"\n"
    ))
  )

EDIT: 2016-09-05 我接受Steve Purcell的建议. Emacs已经有了一个名为 default-directory 的变量. 它的值就是当前编辑buffer所在的目录,若当前buffer没有对应的文件,则其值为nil. 因此 (or default-directory "")~ 也能起到相同的作用.

为了防止目录名中包含类似unicode字符或空格这样的特殊字符, 我们需要在将其传递到shell前将其引用起来. 这可以用 shell-quote-argument 来实现. 不过,由于我们需要把这些引用之后的特殊字符作为参数传递到applescript语句中. 因此引用符可能会看起来比较乱. 下面这个函数即使当处于类似 “~/Users/me/Google Drive/pâte à pizza/” 这样的目录中时也能正常工作.

(defun sam--iterm-goto-filedir-or-home ()
  "Go to present working dir and focus iterm"
  (interactive)
  (do-applescript
   (concat
    " tell application \"iTerm2\"\n"
    "   tell the current session of current window\n"
    (format "     write text \"cd %s\" \n"
            ;; string escaping madness for applescript
            (replace-regexp-in-string "\\\\" "\\\\\\\\"
                                      (shell-quote-argument (or default-directory "~"))))
    "   end tell\n"
    " end tell\n"
    " do shell script \"open -a iTerm\"\n"
    ))
  )

最后这个函数仅仅是进入iTerm2应用而不会修改工作目录.

(defun iterm-focus ()
  (interactive)
  (do-applescript
   " do shell script \"open -a iTerm\"\n"
   ))

最后,我用general.el来将这两个函数的快捷键分别设置为SPC '以及SPC ?.

(general-define-key
 :states '(normal visual insert emacs)
 :prefix "SPC"
 "'" '(iterm-focus :which-key "focus iterm")
 "?" '(iterm-goto-filedir-or-home :which-key "focus iterm - goto dir")
 )