Emacs saveplace保存-place-alist到文件时杀缓冲区。为什么我在使用hook时出现递归深度问题?

问题描述 投票:0回答:1

我使用Emacs(目前是26.3)已经有一段时间了(几年)。我总是有

(use-package saveplace
  :config
  (save-place-mode t))

在我 init.el,这使得Emacs使用 save-place-mode (这是与vanilla Emacs一起出现的,作为 saveplace.el),以便记住文件中的最后一个位置。

我的问题 存放处 是,它一直将访问过的文件和位置保存到一个名为 save-place-alistkill-emacs-hook 它将这个列表转储到默认位置 ~/.emacs.d/places. 但它经常发生,我忘记或以某种方式不正常退出我的emacs-daemon。所以,这个列表会丢失。

我的方法是提取函数 save-place-alist-to-filesaveplace.el 并将其加入 kill-buffer-hook 所以现在,每当我杀死一个缓冲区的时候。save-place-alist 会被保存到磁盘上。这就是我现在的保存位置配置。

(defun my-save-place-alist-to-file ()
(interactive)
(save-place-to-alist)
  (let ((file (expand-file-name save-place-file))
        (coding-system-for-write 'utf-8))
    (with-current-buffer (get-buffer-create " *Saved Places*")
      (delete-region (point-min) (point-max))
      (when save-place-forget-unreadable-files
        (save-place-forget-unreadable-files))
      (insert (format ";;; -*- coding: %s -*-\n"
                      (symbol-name coding-system-for-write)))
      (let ((print-length nil)
            (print-level nil))
        (pp save-place-alist (current-buffer)))
      (let ((version-control
             (cond
              ((null save-place-version-control) nil)
              ((eq 'never save-place-version-control) 'never)
              ((eq 'nospecial save-place-version-control) version-control)
              (t
               t))))
        (condition-case nil
            ;; Don't use write-file; we don't want this buffer to visit it.
            (write-region (point-min) (point-max) file)
          (file-error (message "Saving places: can't write %s" file)))
        (kill-buffer (current-buffer))))))

(use-package saveplace
  :config
  (save-place-mode t)
  ;; (remove-hook 'kill-buffer-hook 'save-place-to-alist)
  ;; (add-hook 'kill-buffer-hook 'my-save-place-alist-to-file))

一切都很好,只要我不修改我的文件 kill-buffer-hook 通过取消最后一行的注释。函数 my-save-place-alist-to-file 当交互式调用时,工作正常。但是当激活钩子的时候,几乎所有的东西都会刹车。首先,我不能再杀死缓冲区了。我得到了这个与递归深度有关的错误。

progn: Variable binding depth exceeds max-specpdl-size

调试器说:

Debugger entered--Lisp error: (error "Variable binding depth exceeds max-specpdl-size")
  generate-new-buffer(" *temp*")
  pp-to-string((("/home/.../test.txt" . 33)))
  pp((("/home/.../test.txt" . 33)) #<buffer  *Saved Places*>)
  (let ((print-length nil) (print-level nil)) (pp save-place-alist (current-buffer)))
  (save-current-buffer (set-buffer (get-buffer-create " *Saved Places*")) (delete-region (point-min) (point-max)) (if save-place-forget-unreadable-files (progn (save-place-forget-unreadable-files))) (insert (format ";;; -*- coding: %s -*-\n" (symbol-name coding-system-for-write))) (let ((print-length nil) (print-level nil)) (pp save-place-alist (current-buffer))) (let ((version-control (cond ((null save-place-version-control) nil) ((eq (quote never) save-place-version-control) (quote never)) ((eq (quote nospecial) save-place-version-control) version-control) (t t)))) (condition-case nil (write-region (point-min) (point-max) file) (file-error (message "Saving places: can't write %s" file))) (kill-buffer (current-buffer))))
  (let ((file (expand-file-name save-place-file)) (coding-system-for-write (quote utf-8))) (save-current-buffer (set-buffer (get-buffer-create " *Saved Places*")) (delete-region (point-min) (point-max)) (if save-place-forget-unreadable-files (progn (save-place-forget-unreadable-files))) (insert (format ";;; -*- coding: %s -*-\n" (symbol-name coding-system-for-write))) (let ((print-length nil) (print-level nil)) (pp save-place-alist (current-buffer))) (let ((version-control (cond ((null save-place-version-control) nil) ((eq ... save-place-version-control) (quote never)) ((eq ... save-place-version-control) version-control) (t t)))) (condition-case nil (write-region (point-min) (point-max) file) (file-error (message "Saving places: can't write %s" file))) (kill-buffer (current-buffer)))))
  my-save-place-alist-to-file()
  kill-buffer(#<buffer  *temp*-840370>)
  #f(compiled-function () #<bytecode 0x1c65c75>)()
  pp-to-string((("/home/.../test.txt" . 33)))
  pp((("/home/.../test.txt" . 33)) #<buffer  *Saved Places*>)
  (let ((print-length nil) (print-level nil)) (pp save-place-alist (current-buffer)))
  (save-current-buffer (set-buffer (get-buffer-create " *Saved Places*")) (delete-region (point-min) (point-max)) (if save-place-forget-unreadable-files (progn (save-place-forget-unreadable-files))) (insert (format ";;; -*- coding: %s -*-\n" (symbol-name coding-system-for-write))) (let ((print-length nil) (print-level nil)) (pp save-place-alist (current-buffer))) (let ((version-control (cond ((null save-place-version-control) nil) ((eq (quote never) save-place-version-control) (quote never)) ((eq (quote nospecial) save-place-version-control) version-control) (t t)))) (condition-case nil (write-region (point-min) (point-max) file) (file-error (message "Saving places: can't write %s" file))) (kill-buffer (current-buffer))))
  (let ((file (expand-file-name save-place-file)) (coding-system-for-write (quote utf-8))) (save-current-buffer (set-buffer (get-buffer-create " *Saved Places*")) (delete-region (point-min) (point-max)) (if save-place-forget-unreadable-files (progn (save-place-forget-unreadable-files))) (insert (format ";;; -*- coding: %s -*-\n" (symbol-name coding-system-for-write))) (let ((print-length nil) (print-level nil)) (pp save-place-alist (current-buffer))) (let ((version-control (cond ((null save-place-version-control) nil) ((eq ... save-place-version-control) (quote never)) ((eq ... save-place-version-control) version-control) (t t)))) (condition-case nil (write-region (point-min) (point-max) file) (file-error (message "Saving places: can't write %s" file))) (kill-buffer (current-buffer)))))
  my-save-place-alist-to-file()
  kill-buffer(#<buffer  *temp*-437350>)
  #f(compiled-function () #<bytecode 0x1c65c35>)()
  pp-to-string((("/home/.../test.txt" . 33)))
  pp((("/home/.../test.txt" . 33)) #<buffer  *Saved Places*>)
  (let ((print-length nil) (print-level nil)) (pp save-place-alist (current-buffer)))
  (save-current-buffer (set-buffer (get-buffer-create " *Saved Places*")) (delete-region (point-min) (point-max)) (if save-place-forget-unreadable-files (progn (save-place-forget-unreadable-files))) (insert (format ";;; -*- coding: %s -*-\n" (symbol-name coding-system-for-write))) (let ((print-length nil) (print-level nil)) (pp save-place-alist (current-buffer))) (let ((version-control (cond ((null save-place-version-control) nil) ((eq (quote never) save-place-version-control) (quote never)) ((eq (quote nospecial) save-place-version-control) version-control) (t t)))) (condition-case nil (write-region (point-min) (point-max) file) (file-error (message "Saving places: can't write %s" file))) (kill-buffer (current-buffer))))
  (let ((file (expand-file-name save-place-file)) (coding-system-for-write (quote utf-8))) (save-current-buffer (set-buffer (get-buffer-create " *Saved Places*")) (delete-region (point-min) (point-max)) (if save-place-forget-unreadable-files (progn (save-place-forget-unreadable-files))) (insert (format ";;; -*- coding: %s -*-\n" (symbol-name coding-system-for-write))) (let ((print-length nil) (print-level nil)) (pp save-place-alist (current-buffer))) (let ((version-control (cond ((null save-place-version-control) nil) ((eq ... save-place-version-control) (quote never)) ((eq ... save-place-version-control) version-control) (t t)))) (condition-case nil (write-region (point-min) (point-max) file) (file-error (message "Saving places: can't write %s" file))) (kill-buffer (current-buffer)))))
  my-save-place-alist-to-file()
...

我已经尝试了很多方法来解决这个问题. 我的第一个猜测是,最后调用的 (kill-buffer (current-buffer)) 会导致无限递归。但去掉它也无济于事。

总结一下,我的问题是: * 为什么会发生无限递归?* 为什么会发生无限递归?

emacs elisp dot-emacs
1个回答
0
投票

我尝试了 @choroba 提到的,在我的init.el中添加了一个 "save-place-mode t"。

(let 'kill-buffer-hook nil
...
) 

围绕整个部分后 (save-place-to-alist) 这确实消除了无限递归的问题!但后来又出现了另一个问题:每当我切换缓冲区时,这个hooked都会被调用。但后来又出现了另一个问题:每当我切换缓冲区时,这个hooked都会被调用,which-key上下跳动,而且在很多场合都会被调用。每次写到 ~/.emacs.d/places. 所以这不是我想要的。

同时,我找到了一个方便的解决方案:添加函数 kill-buffer-hook 不过after-save-hook. 这对我来说已经足够了:)

我的最后 save-place-设置对我来说很好,现在看起来是这样的。

(defun my-save-place-alist-to-file ()
  (interactive)
  (save-place-to-alist)
  (let ((file (expand-file-name save-place-file))
        (coding-system-for-write 'utf-8))
    (with-current-buffer (get-buffer-create " *Saved Places*")
      (delete-region (point-min) (point-max))
      (when save-place-forget-unreadable-files
        (save-place-forget-unreadable-files))
      (insert (format ";;; -*- coding: %s -*-\n"
                      (symbol-name coding-system-for-write)))
      (let ((print-length nil)
            (print-level nil))
        (pp save-place-alist (current-buffer)))
      (let ((version-control
             (cond
              ((null save-place-version-control) nil)
              ((eq 'never save-place-version-control) 'never)
              ((eq 'nospecial save-place-version-control) version-control)
              (t
               t))))
        (condition-case nil
            ;; Don't use write-file; we don't want this buffer to visit it.
            (write-region (point-min) (point-max) file nil) ; 4th arg nil means: do not append!
          (file-error (message "Saving places: can't write %s" file))
          (kill-buffer (current-buffer)))))))

(use-package saveplace
  :config
  (save-place-mode t)
  (add-hook 'after-save-hook 'my-save-place-alist-to-file)) ; after-save-hook seems to be the best place for this
© www.soinside.com 2019 - 2024. All rights reserved.