Emacs能像BBEdit一样跟踪文件吗?

4
为了引用一个 Sublime Text 的功能请求(请参见这里):
BBEdit 在 OS X 上有此功能:
- 在 BBEdit 中打开 "myfile.txt"
- 在 Finder 中将“ myfile.txt” 重命名为“ myfile2.txt”
- 现在,在 BBEdit 中,该文档显示为“ myfile2.txt”,保存该文件时会更新“ myfile2.txt”

这比 ST2 的使用情况要好得多:
- 在 Sublime Text 2 中,打开 "myfile.txt"
- 在 Finder 中将“ myfile.txt”重命名为“ myfile2.txt”
- 现在,ST2中的文档在静默创建一个重复的文件“ myfile.txt”。 这会导致我的工作区中出现两个略有不同版本的相同文件,从而引起头痛。

与 Sublime Text 一样,Emacs 也会发生类似的情况。 因此,我希望找到一种使 Emacs 实现与 BBEdit 相同操作的方法。

我在 Google 上搜索了一下,但实际上我不确定在这里应该搜索什么。 是否有一个具体术语可以描述这个问题? 不管怎样,我都没有找到任何有趣的东西。

是否有任何现有的方法可以做到这一点? 还是它将变得相当复杂? 这篇文章说,“NSURL”的“书签”功能就是在这里使用的。


1
以下是一些可能有助于您搜索的术语:“FSEvents”是OS X用于监视文件的较低级别API,似乎(从快速搜索中)没有任何尝试使emacs意识到它。Linux使用类似的东西叫做“inotify”,emacs也不使用它,但是在inotify和emacs之间的交互的想法似乎至少在互联网上被提到过。 - cobbal
1个回答

6

来自最新Emacs主干(未发布版本)NEWS文件的消息:

支持文件系统通知

现在,Emacs支持通知文件系统更改,如创建、修改和删除文件。这需要使用`glib' API或'inotify' API(仅适用于GNU / Linux系统)。在MS-Windows系统上,这适用于Windows XP及更高版本。

因此,您请求的功能对GNU / Linux和Windows用户可行,不幸的是,在OS X上没有(在Emacs中)生成文件通知的支持。

下面的代码应该可以实现您想要的功能(尽管它还没有经过彻底测试)。它需要最新(未发布的)Emacs版本。

(require 'filenotify)
(require 'cl-lib)

(defvar my-file-to-fd-hash (make-hash-table))

(defun my-file-notify-add-rename-watch (&optional file)
  (let ((file-name (or file buffer-file-name)))
    (when file-name
      (puthash file-name
               (file-notify-add-watch file-name
                          '(change)
                          'my-handle-file-change)
               my-file-to-fd-hash))))

(defun my-file-notify-rm-rename-watch (&optional file)
  (let* ((file-name (or file
                buffer-file-name))
         (fd (gethash file-name my-file-to-fd-hash)))
    ;; Stop watching the file
    (when fd
      (file-notify-rm-watch fd)
      (remhash file-name my-file-to-fd-hash))))

(add-to-list 'find-file-hook 'my-file-notify-add-rename-watch)
(add-to-list 'kill-buffer-hook 'my-file-notify-rm-rename-watch)

(defun my-handle-file-change (event)
  (let* ((fd (cl-first event))
         (action (cl-second event))
         (file (cl-third event))
         (renamed-to (cl-fourth event))
         (visiting-buffer (get-file-buffer file)))
    ;; Ignore events other than `rename` and also the `rename` events
    ;; generated due to emacs backing up file
    (when (and (eq action 'renamed)
           (not (backup-file-name-p renamed-to)))
      (message (format "File %s was renamed" file))

      ;; If file is not open ignore the notification
      (when visiting-buffer
        (with-current-buffer visiting-buffer
          (set-visited-file-name renamed-to))
        (my-file-notify-rm-rename-watch file)
        (my-file-notify-add-rename-watch renamed-to)))))

哇,太棒了。谢谢!在挂钩上为每个访问的文件激活这个功能是一个好主意吗? - Naomi Slater
嗨,@NoahSlater,那段代码只是一个例子。它并不是用于init文件的,你在使用之前可能需要根据自己的需求进行修改。 - user2053036
还有,我还没有测试过它。 - user2053036
这不应该是一个包安装,甚至可以合并到主要的emacs中吗? - Martin Algesten

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接