12

I can't make Emacs remember the history for *ielm* buffers between sessions. As far as I can tell, such history is recorded in the buffer-local variable comint-input-ring. Therefore I have added the following expression to my init file:

(setq desktop-locals-to-save
    (append desktop-locals-to-save
            '((comint-input-ring . 50))))

It doesn't work. I know that the desktop package is working because Emacs remembers the global variables that I have added to desktop-globals-to-save in my init file.

--

EDIT: savehist does not work either. I suppose that is because comint-input-ring is a buffer-local variable.

Eleno
  • 1,428
  • 11
  • 17
  • 1
    No time now to check why it might not work for desktop. But you can try using `savehist.el` and adding this variable to the list of vars to save. – Drew Dec 08 '14 at 14:50
  • Thanks, Drew, but I had thought about `savehist` already (sorry for not mentioning it). As far as I could see, it was for global variables only, whilst `comint-input-ring` is buffer-local. Now, I have tried it anyway, without success. – Eleno Dec 08 '14 at 15:11
  • WARNING: The following solution is *blasphemy*!!!! Comment out inside `comint.el` the following two lines of code: `(put 'comint-input-ring 'permanent-local t)` and `(make-local-variable 'comint-input-ring)`. Then, add `comint-input-ring` to `desktop-locals-to-save`. Finally, re-byte-compile the applicable files, restart Emacs and enjoy living life to the fullest. – lawlist Dec 03 '17 at 02:50

1 Answers1

9

You can save the buffer-local value of comint-input-ring in a global variable when an *ielm* buffer is killed and restore it in inferior-emacs-lisp-mode-hook:

;; global copy of the buffer-local variable
(defvar ielm-comint-input-ring nil)

(defun set-ielm-comint-input-ring ()
  ;; create a buffer-local binding of kill-buffer-hook
  (make-local-variable 'kill-buffer-hook)
  ;; save the value of comint-input-ring when this buffer is killed
  (add-hook 'kill-buffer-hook #'save-ielm-comint-input-ring)
  ;; restore saved value (if available)
  (when ielm-comint-input-ring
    (message "Restoring comint-input-ring...")
    (setq comint-input-ring ielm-comint-input-ring)))

(defun save-ielm-comint-input-ring ()
  (message "Saving comint-input-ring...")
  (setq ielm-comint-input-ring comint-input-ring))

(require 'ielm)
(add-hook 'inferior-emacs-lisp-mode-hook #'set-ielm-comint-input-ring)

Now you should be able to add ielm-comint-input-ring to savehist-additional-variables to get the behavior you want. (I tested this approach; you should be able to use desktop-locals-to-save too, though.)

Constantine
  • 9,072
  • 1
  • 34
  • 49
  • 3
    You should use the `LOCAL` argument to `add-hook`, rather than manually calling `make-local-variable` on `kill-buffer-hook`. The latter could cause problems when subsequently trying to add callbacks to the hook globally. – phils Mar 02 '15 at 01:20
  • 1
    I was very pleased to find that this worked for `inf-mongo` as well (or, presumably, any other mode that uses `comint`) That is so helpful, and also taught me a little more elisp... thanks! – Blake Miller Sep 11 '16 at 22:15
  • Add `(add-hook 'savehist-save-hook (lambda () (and (get-buffer "*ielm*") (kill-buffer "*ielm*"))))` to make it save the latest history in your `*ielm*` buffer in case you don't explicitly kill that buffer before exiting emacs. – Peter Slotko Apr 01 '22 at 05:08