I've got helm installed to work with comint mode either in eshell or when running python in an inferior comint process. I'd like to preserve the command line history, especially in the python mode.


(setq savehist-additional-variables '(comint-input-ring))

but that seems to result in the savehist file always containing

(setq comint-input-ring 'nil)

Other fields like search-ring, kill-ring, minibuffer-history save fine. Is there a way to do this?

I know this link answers it for a 'real' shell but it doesn't work in this case.

EDIT As requested, what I've tried is the following, and it describes my use-case

(helm-mode 1)
(define-key comint-mode-map (kbd "C-S-l" 'helm-comint-input-ring)

elsewhere in .emacs

(require 'python-mode) ;; Goes to ipython.exe (on windows)

Coding some python, using C-c C-c to send to ipython process.

>>> somefunc()

This now appears if I use C-S-l as a helm-comint-input-ring and I can search on it.

I'd like to preserve these commands as I tend to repeat them across sessions (but with enough variability to not script it away completely).

I agree there could be both eshell, python , other comint buffers running, I suppose you are saying that ipython should preserve the history buffer and I should somehow get savehist to load that? Not sure how.

  • Now that I've looked at your link, this question seems like a duplicate of that. Constantine's answer is applicable here, with appropriate modifications (and the caveat that it assumes a single comint buffer for a given mode). You say it "doesn't work"; please show us what you tried.
    – phils
    Mar 2 '15 at 0:11

I followed this guide: https://oleksandrmanzyuk.wordpress.com/2011/10/23/a-persistent-command-history-in-emacs/ and also took hint of a comment in the similar SO-question you mentioned (which advised using the LOCAL argument of add-hook, but see note below!). So this seems to work for me:

(defun comint-write-history-on-exit (process event)
  "Write comint history of PROCESS when EVENT happened to a file specified in buffer local var 'comint-input-ring-file-name' (defined in turn-on-comint-history)."
  (let ((buf (process-buffer process)))
    (when (buffer-live-p buf)
      (with-current-buffer buf
        (insert (format "\nProcess %s %s" process event))))))

(defun turn-on-comint-history ()
  "Setup comint history.

When comint process started set buffer local var
'comint-input-ring-file-name', so that a file name is specified to write
and read from comint history.

That 'comint-input-ring-file-name' is buffer local is determined by the
4th argument to 'add-hook' below.  And localness is important, because
otherwise 'comint-write-input-ring' will find mentioned var nil."

  (let ((process (get-buffer-process (current-buffer))))
    (when process
      (setq comint-input-ring-file-name
            (format "~/.emacs.d/inferior-%s-history"
                    (process-name process)))
      (set-process-sentinel process

(add-hook 'inf-gf-mode-hook 'turn-on-comint-history nil t)

The history will be saved calling 'comint-send-eof' (usually C-c C-d). (Using 'kill-this-buffer' will not save the history.)

NOTE regarding localness: I'm not really sure what happened today, but I had to run add-hook without LOCAL argument to get it working:

(add-hook 'inf-gf-mode-hook 'turn-on-comint-history nil nil)
  • i wish the history files were encrypted.
    – Ben Hyde
    Jun 28 '17 at 15:48

AFAIK the global binding for comint-input-ring will almost certainly be nil, as it is given a buffer-local value in comint buffers (for the obvious reasons of not blending all the histories of all your comint buffers together).

As such, it won't work with savehist in that way (and perhaps nor would you want it to).

You should work out exactly how you want this to work, bearing in mind that there may be multiple coincidental comint buffers (including multiple buffers using the exact same mode), so that you can work out what you should restore from any given history in a subsequent Emacs instance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.