Subject: Re: bug#76585: ielm clobbers history on C-c C-c, C-d

From: Eli Zaretskii <[email-masked]>
Date: Thu, 27 Feb 2025 16:13:35 +0200

> From: Daniel Colascione <[email-masked]>
> Cc: [email-masked]
> Date: Wed, 26 Feb 2025 19:09:16 -0500
> 
> Eli Zaretskii <[email-masked]> writes:
> 
> > I don't use IELM too often,
> 
> Is there something better?

Not necessarily better, but simpler: "M-:".

> When I start Emacs, if I type M-x ielm, then M-p through history, I
> might observe (most recent first) history entries C, B, and A, with the
> three entries coming from the ielm history file. If I type additional
> ielm commands D and E, then at the next prompt after E, if I hit M-p, I
> see E, and if I hit M-p again, I get D, then C, and so on. If I hit C-c
> C-c, killing the ielm subprocess, then M-x ielm again, then press M-p, I
> see C, B, A --- as if my D, E session had never happened.

Thanks.  Does the below give good results?

diff --git a/lisp/ielm.el b/lisp/ielm.el
index b3cd02b..c651612 100644
--- a/lisp/ielm.el
+++ b/lisp/ielm.el
@@ -521,6 +521,12 @@ ielm--input-history-writer
     (with-current-buffer buf
       (comint-write-input-ring))))
 
+(defun ielm--write-history-on-interrupt (_proc _group)
+  "Save the IELM input history when the process is interrupted."
+  (funcall (ielm--input-history-writer (current-buffer)))
+  ;; Let the rest of the hook functions run as well.
+  nil)
+
 ;;; Major mode
 
 (define-derived-mode inferior-emacs-lisp-mode comint-mode "IELM"
@@ -658,7 +664,9 @@ inferior-emacs-lisp-mode
          '(rear-nonsticky t field output inhibit-line-move-field-capture t))))
     (comint-output-filter (ielm-process) ielm-prompt-internal)
     (set-marker comint-last-input-start (ielm-pm))
-    (set-process-filter (get-buffer-process (current-buffer)) 'comint-output-filter)))
+    (set-process-filter (get-buffer-process (current-buffer)) 'comint-output-filter)
+    (add-hook 'interrupt-process-functions
+              #'ielm--write-history-on-interrupt -1 t)))
 
 (defun ielm-get-old-input nil
   ;; Return the previous input surrounding point