eshell で使う anything.el のソース

検索してみたら意外にも見つからなかったので自分で書いてみた。ディレクトリとコマンドの履歴を *eshell* バッファで anything から呼び出すためのソース。自分で使ってみた感じでは cd はかなり便利。Emacsを終了しても履歴も残るし。一方 zsh から anything.el を使うという荒技もあるらしい。anything.elを使ってzshの履歴検索をする - (rubikitch loves (Emacs Ruby CUI Books))

(defvar anything-c-eshell-directory-history
  '((name . "Directory History")
    (candidates . (lambda () 
                    (set-buffer anything-current-buffer) 
                    (delete-dups (ring-elements eshell-last-dir-ring))))
    (action . (("Change Directory" . anything-eshell-change-directory)))))

(defvar anything-c-eshell-command-history
  '((name . "Command History")
    (candidates . (lambda ()
                    (set-buffer anything-current-buffer)
                    (remove-if (lambda (str) (string-match "^cd *" str))
                               (delete-dups (ring-elements eshell-history-ring)))))
    (action . (("Insert" . insert))))) ;; この行をコメントアウトして次の行を使う手もあるが
    ;; (action . (("Execute" . anything-eshell-exec-command))))) ;; 使わないほうが無難

(defun anything-eshell-change-directory (dir)
  (insert (concat "cd " dir))
  (eshell-send-input))

;; (defun anything-eshell-exec-command (command)
;;   (insert command)
;;   (eshell-send-input))

ソースの中の set-buffer は history-ring が buffer-local なので必要。

(defun anything-eshell ()
  (interactive)
  (anything
   (list
    anything-c-eshell-directory-history
    anything-c-source-files-in-current-dir+
    anything-c-eshell-command-history
    anything-c-source-buffers+
    anything-c-source-bookmarks
    anything-c-source-recentf)))

ソースの並べ方は好みで。あとは anything-eshell を適当なキーにバインドするか、普段使いのキーで分岐させる。自分はこんな感じで使っている。

(global-set-key (kbd "C-;") 
                (lambda () (interactive)
                  (cond
                   ((eq major-mode 'eshell-mode) (call-interactively 'anything-eshell))
                   (t (call-interactively 'anything)))))

ついでに履歴のサイズも設定しておく。ただし履歴があまりにも大きいと anything が重くなるかも。

(setq eshell-history-size 10000)
(setq eshell-last-dir-ring-size 1000)

追記
Emacs が突然落ちて履歴が吹っ飛ぶと痛いので自動保存しましょう。
eshell の履歴を自動保存するアドバイス - Tips

追記
.bash_history を候補にするものはこちらにあります。
.bash_history を候補にしてインサートするだけの anything ソース - わからん

追記
コード若干修正
(set-buffer "*eshell*") => (set-buffer anything-current-buffer)