I have been using Emacs (at the moment 26.3) for quite a while (years). I always had
(use-package saveplace
:config
(save-place-mode t))
in my init.el, which makes Emacs use save-place-mode (which comes with vanilla Emacs as saveplace.el) in order to remember the last position in file.
My Problem with saveplace is, that it keeps saving visited files and positions to a list called save-place-alist and only through a hook in kill-emacs-hook it dumps this list to default location ~/.emacs.d/places. But it occurs quite often, that i forget or somehow not normally quit my emacs-daemon. So, the list will be lost.
My approach was to extract the function save-place-alist-to-file from saveplace.el and add it to the kill-buffer-hook so now, everytime i kill a buffer save-place-alist would be saved to disk. This is what my save-place config looks now:
(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))
Everything i fine, as long as i dont modify the kill-buffer-hook by uncommenting the last to lines. The function my-save-place-alist-to-file works properly when called interactively. But when activate the hooks, literally everything brakes. First of all i can not kill buffers anymore. I get this error related to recursion depth:
progn: Variable binding depth exceeds max-specpdl-size
The debugger says:
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()
...
I already did try a lot things to fix this. My first guess was, that the final call of (kill-buffer (current-buffer)) would lead to the infinite recursion. But removing it does not help.
To summarize, my question is:
* Why and where does the infinite recursion happen?