Eshellをカスタマイズしてみた

eshellを日常使いできるレベルまでもっていきたかったのでやってみた。ネット上にころがってる記事は10年前くらいのものが大半だったので2020年で使ってる人いない説はある。


全体的な設定はここにある https://takeokunn.github.io/.emacs.d/

基本設定

全体はこんな感じ。configは他記事を参考に必要そうなものを設定した。

(leaf eshell
  :after (counsel)
  :config
  (with-eval-after-load 'eshell
    ;; function
    (defun eshell/ff (&rest args)
      (find-file (car args)))

    ;; config
    (setq eshell-cmpl-ignore-case t)
    (setq eshell-glob-include-dot-dot nil)
    (setq eshell-ask-to-save-history (quote always))
    (setq eshell-history-size 100000)
    (setq eshell-hist-ignoredups t)

    ;; alias
    (defvar *shell-alias* '(("ll" "ls -la")
                            ("cdd" "cd ~/Desktop")))
    (defvar eshell-command-aliases-list (append *shell-alias*))))

函数定義

eshellでは eshell/xxx というように命名規則通りに函数を定義するとshellから呼びだせる。

(defun eshell/hello ()
  (message "hello world"))
~/.g/g/takeokunn/.emacs.d:master* λ hello
hello world

https://github.com/emacs-mirror/emacs/tree/master/lisp/eshellに組み込みの函数郡があるようだ。

alias

eshell-command-aliases-list にappendするような感じで定義する。あまりaliasは好きではないので最小限だけ定義した。

(defvar *shell-alias* '(("ll" "ls -la")
                        ("cdd" "cd ~/Desktop")))
(defvar eshell-command-aliases-list (append *shell-alias*))

eshell-z

url: xuchunyang/eshell-z

eshellでもzを使えるようにした。デフォルトでは C-q だが、neotreeに割り振っていたので C-c C-q にした。

(leaf eshell-z
  :ensure t
  :bind (("C-c C-q" . eshell-z)))

aweshell

url: takeokunn/aweshell

aweshellはmelpaで提供されてるわけでもないし、複数のeshell packageの複合のようなものだ。なのでleaf(use-package)で入るというよりはlocalにcloneしてきて読み込ませるようにした。ghqユーザなので takeokunn/aweshell-setup を 叩くと入るようにした。

(defun takeokunn/aweshell-setup ()
  (shell-command-to-string "ghq get https://github.com/takeokunn/aweshell.git"))

(when (file-directory-p "~/.ghq/github.com/takeokunn/aweshell")
  (add-to-list 'load-path (expand-file-name "~/.ghq/github.com/takeokunn/aweshell")
  ;; settings
  )

manateelazycat/aweshellをforkしてfishのhistoryも食わせることにした。

magnars/s.elの文字列操作はすごい便利。苦手な正規表現の確認は re-builder で頑張って書いた。

https://github.com/takeokunn/aweshell/commit/0eb17239753997bbb2ed6d16b22384bf70ebfa35#diff-ffbc0de9cb8dae612595caaa308c875dR844-R858

(defun aweshell-parse-fish-history ()
  "Parse the fish history."
  (if (file-exists-p "~/.local/share/fish/fish_history")
      (let (collection fish_history)
        (aweshell-reload-shell-history)
        (setq collection
              (nreverse
               (with-temp-buffer (insert-file-contents (file-truename "~/.local/share/fish/fish_history"))
                                 (mapcar #'(lambda (x) (cadr x)) (s-match-strings-all "^- cmd: \\(.*\\)$" (buffer-string))))))
        (when (and collection (> (length collection) 0)
                   (setq fish_history collection))
          fish_history))
    nil))

自分のemacs.dには以下のように設定した。 takeokunn/counsel-aweshell-history でaweshellのhistoryをisearchできるようにして C-c C-r に割りあてた。

eshell-prompt-function にはシンプルな epe-theme-lambda にした。

(defun takeokunn/aweshell-setup ()
  (shell-command-to-string "ghq get https://github.com/takeokunn/aweshell.git"))

(when (file-directory-p "~/.ghq/github.com/takeokunn/aweshell")
  (add-to-list 'load-path (expand-file-name "~/.ghq/github.com/takeokunn/aweshell"))
  (require 'aweshell)
  (with-eval-after-load 'aweshell
    (defun takeokunn/counsel-aweshell-history ()
      (interactive)
      (ivy-read "Aweshell history: " (aweshell-parse-shell-history)))

    (add-hook 'eshell-mode-hook
              (lambda () (define-key eshell-mode-map (kbd "C-c C-r") 'takeokunn/counsel-aweshell-history)))
    (setq aweshell-auto-suggestion-p nil
          eshell-highlight-prompt t
          eshell-prompt-function 'epe-theme-lambda)))

aweshellのお陰で綺麗なshell環境が整った。cdやcatで余計な補完が入るのがストレスなのでaweshell自体の処理を修正しようと思う。

あと、tmuxと同じような体験でpane分割できるようにも設定したい。