maxima の履歴を helm で呼び出す

maxima.el には maxima-save-input-history という変数があり

(setf maxima-save-input-history t)

と設定しておけば、デフォルトでは "~/.maxima_history" にセッション終了時に入力を保存してくれる。
ただしセッション中には comint-history-isearch-backward で履歴を探すしかなく使い勝手が良いとはいえない。

そこで helm で履歴を検索できるようにする。

以下の関数は前記事、前々記事にあげておいたものを再掲。

(require 'cl-lib)

(defun count-lines-buffer (&optional buf)
  (let* ((curbuf (current-buffer))
         (target (if buf buf curbuf)))
    (set-buffer target)
    (prog1 
        (count-lines (point-min) (point-max))
      (set-buffer curbuf))))

(defun count-lines-file (f)
  (with-temp-buffer
    (insert-file-contents-literally f)
    (count-lines-buffer)))

(defun line-string ()
  (buffer-substring-no-properties (point-at-bol) (point-at-eol)))

(defun read-file-as-list (f)
  (with-temp-buffer
    (insert-file-contents-literally f)
    (goto-char (point-min))
    (cl-loop while (not (eobp))
             collect (line-string)
             do (forward-line 1))))

これらを以下で使う。

入力ごとに履歴をセーブして helm で呼び出せるようにする。
ヒストリーのファイル名はデフォルトのものとは変えておいた。

(defvar *maxima-history-file* "~/.maxima.history")
(defvar *maxima-max-history-size* 2000)
(defvar *maxima-current-history-size* nil)

(defun maxima-current-history-size ()
  (if *maxima-current-history-size*
      *maxima-current-history-size*
    (setf *maxima-current-history-size*
          (count-lines-file (expand-file-name *maxima-history-file*)))))

(defun maxima-save-input ()
  (let* ((f (expand-file-name *maxima-history-file*))
         (curbuf (current-buffer))
         input beg buf)
    (save-excursion
      (inferior-maxima-bol)
      (setf beg (point))
      (re-search-forward "[;$]" nil t)
      (setf input (buffer-substring-no-properties beg (point))))
    (setf buf (find-file-noselect f))
    (set-buffer buf)
    (when (>= (maxima-current-history-size) *maxima-max-history-size*)
      (goto-char (point-min))
      (delete-region (point) (1+ (point-at-eol)))
      (incf *maxima-max-history-size* -1))
    (goto-char (point-max))
    (delete-blank-lines)
    (insert (format "%s\n" input))
    (incf *maxima-max-history-size*)
    (basic-save-buffer)
    (kill-buffer buf)
    (switch-to-buffer curbuf)))

(defvar *helm-source-maxima-history*
  '((name . "maxima history")
    (candidates . (lambda ()
                    (delete-dups
                     (nreverse
                      (read-file-as-list (expand-file-name *maxima-history-file*))))))
    (action . insert)))

(defun helm-maxima-history ()
  (interactive)
  (helm :sources
        (list *helm-source-maxima-history*)))

(add-hook 'inferior-maxima-mode-hook
          (lambda ()
            (define-key inferior-maxima-mode-map (kbd "C-M-;") 'helm-maxima-history))
            (defadvice inferior-maxima-check-and-send-line (around inferior-maxima-check-and-send-line-around-advice)
              (maxima-save-input)
              ad-do-it)
            (ad-activate 'inferior-maxima-check-and-send-line))

helm-maxima-history は C-M-; にバインドしてある。

使っているうちに無用な入力がたまって検索のノイズになりがちなので "~/.maxima.history" を直接編集すると良いです。