Я использую Emacs (на данный момент 26.3) довольно давно (годы). У меня всегда было
(use-package saveplace
:config
(save-place-mode t))
в моем init.el
, что заставляет Emacs использовать save-place-mode
(который поставляется с ванильным Emacs как saveplace.el
) для запоминания последней позиции в файле.
Моя проблема с saveplace заключается в том, что он сохраняет сохраненные файлы и позиции в список с именем save-place-alist
и только через хук в kill-emacs-hook
сбрасывает этот список в местоположение по умолчанию ~/.emacs.d/places
. Но это случается довольно часто, что я забываю или как-то обычно не покидаю свой emacs-демон. Итак, список будет потерян.
Мой подход заключался в том, чтобы извлечь функцию save-place-alist-to-file
из saveplace.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))
приведет к бесконечной рекурсии. Но его удаление не помогает.
Подводя итог, мой вопрос:
* Почему и где происходит бесконечная рекурсия?