Emacs - 无法让buffer-offer-save正常工作

10

我希望Emacs在修改了未关联文件的缓冲区时,能够询问我是否要保存。为了打开一个新的缓冲区(不是访问文件),我在我的.emacs文件中有以下函数:

;; Creates a new empty buffer
(defun new-empty-buffer ()
  "Opens a new empty buffer."
  (interactive)
  (let ((buf (generate-new-buffer "untitled")))
    (switch-to-buffer buf)
    (funcall (and default-major-mode))
    (setq buffer-offer-save t)))

我认为将“buffer-offer-save”设置为非nil值会有所作为。但是,每当我使用“kill-this-buffer”杀死缓冲区时,它都会立即被杀死,而不会询问任何内容。

这在GNU Emacs 23.1.1上发生。

有什么想法吗?

谢谢, W


将缓冲区与文件关联,在 new-empty-buffer 中解决问题,这可行吗? - Cheeso
3个回答

2

编辑以添加buffers-offer-save的使用。 注意:变量buffer-offer-save仅在退出Emacs时使用。

您可以从此代码开始,并根据自己的需求进行自定义:

(add-to-list 'kill-buffer-query-functions 'ask-me-first)
(defun ask-me-first ()
  "prompt when killing a buffer"
  (if (or buffer-offer-save 
          (eq this-command 'kill-this-buffer)
          (and (buffer-modified-p) (not (buffer-file-name))))
      (y-or-n-p (format "Do you want to kill %s without saving? " (buffer-name)))
    t))

进一步思考后,这有点过于严格了,因为你会被提示删除所有被杀死的缓冲区,而Emacs经常使用许多临时缓冲区。如果你只想在尝试交互式删除不与文件关联的缓冲区时提示。

您可以使用以下建议,仅在您尝试交互式删除缓冲区时提示:

(defadvice kill-buffer (around kill-buffer-ask-first activate)
  "if called interactively, prompt before killing"
  (if (and (or buffer-offer-save (interactive-p))
           (buffer-modified-p)
           (not (buffer-file-name)))
      (let ((answ (completing-read
                   (format "Buffer '%s' modified and not associated with a file, what do you want to do? (k)ill (s)ave (a)bort? " (buffer-name))
                   '("k" "s" "a")
                   nil
                   t)))
        (when (cond ((string-match answ "k")
                     ;; kill
                     t)
                    ((string-match answ "s")
                     ;; write then kill
                     (call-interactively 'write-file)
                     t)
                    (nil))
          ad-do-it)

        t)
    ;; not prompting, just do it
    ad-do-it))

new-empty-buffer 函数中将缓冲区关联到一个文件,这样能解决问题吗? - Cheeso
@Cheeso 好吧,在 new-empty-buffer 中这样做会把请求放在错误的位置,就像他创建新缓冲区时一样。话虽如此,他可以修改 new-empty-buffer 来设置一个标志,供建议/函数使用。我想我喜欢不用求助于 new-empty-buffer 的解决方案。 - Trey Jackson
@Cheeso 注意:我的更新解决方案做得更好,并且注意到了new-empty-buffer - 我读了一些相关资料(这对我来说是新的,还有很多要学习)。 - Trey Jackson
@Trey,你的建议非常好用。我能直观地理解你的代码,但是我一定会更详细地学习它。我正在学习Emacs的第一步,我感到很高兴。非常感谢。 - user283155
@Wintergalt 这是因为 'kill-buffer 没有以交互方式被调用 ('kill-this-buffer 会被调用,从而调用 'kill-buffer)。此外,当您切换主模式时,它将杀死所有本地变量-从而将 buffer-offer-save 重置为 nil。请参阅http://www.gnu.org/s/emacs/manual/html_node/elisp/Major-Mode-Conventions.html。我已经更新了以上代码来检查 'kill-this-buffer - Trey Jackson
显示剩余2条评论

1

buffer-offer-save 在手动关闭缓冲区时不会询问是否保存,这没有意义,所以为什么不“扩大”其职责呢?

(defadvice kill-buffer (around kill-buffer-ask activate)
  "If `buffer-offer-save' is non-nil and a buffer is modified,
prompt before closing."
  (if (and buffer-offer-save (buffer-modified-p))
      (when (yes-or-no-p "The document isn't saved. Quit? ")
        ad-do-it)
    ad-do-it))

如果untitled缓冲区是新创建的,则不会提示。如果您使用Elisp中的kill-buffer,则不会提示。它不会提示Emacs系统缓冲区,如*Messages*。但是,如果您创建了一个空缓冲区并在其中写入内容,则会提示。

另请参见我在创建空缓冲区方面的答案


1

修改'new-empty-buffer似乎可以使它按照我打算的方式与Trey's defadvice一起使用。

;; 创建一个新的空缓冲区
(defun new-empty-buffer ()
 "打开一个新的空缓冲区。"
 (interactive)
 (let ((buf (generate-new-buffer "untitled")))
   (switch-to-buffer buf)
   (funcall (and default-major-mode))
   (put 'buffer-offer-save 'permanent-local t)
   (setq buffer-offer-save t)))

这将使buffer-offer-save在我们的新缓冲区中永久本地化,因此当切换主模式时,它不会随着其他局部变量一起被销毁。


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