eshell (Emacs のシェルモード)
Emacs には eshell というコンソールのモードがあります。
これを使えば、 Un*x 系の開発では Emacs 上で編集、コンパイル、デバッグ、実行と全部できるので、ログインして Emacs を起動した後は全部 Emacs 上で作業するということもできます。
ショートカットキーを割り当てる場合、例えば F8 キーに割り当てるには .emacs.el に次のように記述します。
複数の eshell を起動したい場合には C-u をつけて C-u M-x eshell (C-u [F8]) のように実行します。
補完、コマンド履歴操作のキーは次のようになります。
補完はよくある TAB ですが、履歴は他のコンソールのシェルと違って C-p, C-n はバッファの行移動になり、
Alt(Esc) と組み合わせた p, n および矢印キーの上下が履歴となります。
eshell ではバッファーの最後にカーソルがあるのが普通の状態です。 ここからバッファーの切り替え(switch-to-buffer)やウィンドウの移動(other-window) を行ってから戻ると、一文字移動し直さないと入力できないことになり、かなり面倒です。
この現象は多分バグなので、そのうち修正されるとは思いますが、ちょっと調べた感じだと特に解決方法は見つかりませんでした。 そのため場当たり的ではありますが、対処方法を考えてみました。
どうやるかというと advice という機能を利用します。
バッファーの切り替え等のコマンドを実行した後、 eshell モードで EOB の一文字後ろの場合には EOB に移動するようにします。
以下がそのためのコード なので、 ~/.emacs.d/init.el 等に書いてみてください。
これを使えば、 Un*x 系の開発では Emacs 上で編集、コンパイル、デバッグ、実行と全部できるので、ログインして Emacs を起動した後は全部 Emacs 上で作業するということもできます。
起動
eshell の起動は特にショートカットキーは割り当てられていないので、 M-x eshell で起動します。ショートカットキーを割り当てる場合、例えば F8 キーに割り当てるには .emacs.el に次のように記述します。
(global-set-key [f8] 'eshell)一度、 eshell を起動した後、再度 eshell のコマンドを実行すると起動済みの eshell のバッファが表示されます。
複数の eshell を起動したい場合には C-u をつけて C-u M-x eshell (C-u [F8]) のように実行します。
使用法
基本的に他のシェルと同じように使用できます。補完、コマンド履歴操作のキーは次のようになります。
機能 | キー |
---|---|
補完 | [TAB] |
途中まで書いたものにマッチする前の履歴 | M-p, <up> |
途中まで書いたものにマッチする次の履歴 | M-n, <down> |
前の履歴 | <C-up> |
次の履歴 | <C-down> |
![]() | 入門GNU Emacs (UNIX text processing) (1999/09) デボラ キャメロン、エリック レイモンド 他 商品詳細を見る |
![]() | やさしいEmacs‐Lisp講座 (2011/06) 広瀬 雄二 商品詳細を見る |
スポンサーサイト
eshell (Emacs のシェルモード) その2
Emacs の eshell の説明の続きです。
これを変更するには Customize の機能を使用します。
M-x customize-group などで eshell-hist のカスタマイズページを開き、 Eshell Ask To Save History の値を設定します。

Ask がデフォルトの尋ねてくるタイプで、Never, Always save がそれぞれ聞かずに、履歴を保存しないタイプとするタイプです。
また、カスタマイズを使わずに .emacs.el で設定する場合には以下の行を追加します。
これでショートカットキーで実行していた関数などを eshel 上のコマンドとして実行することができます。 簡単な方法は alias を使用することです。
C-h k などでキーに設定されている lisp の関数名を調べ、 ~/.eshell/alias に記述します。
例えば以下のように記述すると "exit-emacs" で Emacs を終了し、 "1" で他のウィンドウを閉じるようになります。
("$*" を使って引数を指定できるようにしていても、エラーとなります。)
こういった場合には emacs-lisp でコマンドを作成する必要があります。
こったものを作ろうとすると lisp の知識が結構必要になりますが、 例にあげたのような簡単なものであれば、 .emacs.el に設定を書く程度の知識で作成できるのではないかと思います。
例えば、 ~/elisp/ex-eshell.el に記述する場合は以下のコードを .emacs.el に記述します。
実際にコマンド名として使用されるのは xxxx の部分です。
引数を固定した場合は簡単です。 関数の引数を呼び出したい関数に渡します。
次のコードはファイルを比較する ediff-files の関数を eshell コマンドにしたものです。
引数が省略された場合には引数に nil が入るので if 文を使って、処理を分けます。
lisp の関数定義で可変引数を使う場合には &rest を使用します。
これを使うと渡された引数の残りがリストとして引数に格納されます。
以下は compile をコマンド化した例です。
- http://yohshiy.blog.fc2.com/blog-entry-41.html
終了時の履歴確認
eshell を開いたままで emacs を終了しようとするととデフォルトでは、 毎回履歴を保存するかどうか聞かれて面倒です。これを変更するには Customize の機能を使用します。
M-x customize-group などで eshell-hist のカスタマイズページを開き、 Eshell Ask To Save History の値を設定します。

Ask がデフォルトの尋ねてくるタイプで、Never, Always save がそれぞれ聞かずに、履歴を保存しないタイプとするタイプです。
また、カスタマイズを使わずに .emacs.el で設定する場合には以下の行を追加します。
(setq eshell-ask-to-save-history 'always)
コマンドの作成(簡易版)
eshell のコマンドを自分で作ることもできます。これでショートカットキーで実行していた関数などを eshel 上のコマンドとして実行することができます。 簡単な方法は alias を使用することです。
C-h k などでキーに設定されている lisp の関数名を調べ、 ~/.eshell/alias に記述します。
例えば以下のように記述すると "exit-emacs" で Emacs を終了し、 "1" で他のウィンドウを閉じるようになります。
alias exit-emacs save-buffers-kill-emacs alias 1 delete-other-windowsただし、この alias を使った方法では、前回のコマンドのエイリアスと違い、引数をとるコマンドは指定できません。
("$*" を使って引数を指定できるようにしていても、エラーとなります。)
コマンドの作成
前項の方法では find-file などの引数をとる関数には使えません。 また、 grep などはそのまま通常のコマンドのようにかけるのに、 コンパイルはコマンドを "" で囲まないといけないので、面倒です。こういった場合には emacs-lisp でコマンドを作成する必要があります。
こったものを作ろうとすると lisp の知識が結構必要になりますが、 例にあげたのような簡単なものであれば、 .emacs.el に設定を書く程度の知識で作成できるのではないかと思います。
作成コマンド記述ファイル
eshell のコマンドは el ファイルに記述し、 eshell ロード時にホックで呼び出すようにします。例えば、 ~/elisp/ex-eshell.el に記述する場合は以下のコードを .emacs.el に記述します。
(setq load-path (append (list "~/elisp" ) load-path)) (add-hook 'eshell-load-hook '(lambda () (load "ex-eshell") ))
引数固定のコマンド
eshell 用のコマンドの lisp 関数の名前は eshell/xxxx の形式にします。実際にコマンド名として使用されるのは xxxx の部分です。
引数を固定した場合は簡単です。 関数の引数を呼び出したい関数に渡します。
次のコードはファイルを比較する ediff-files の関数を eshell コマンドにしたものです。
(defun eshell/ediff (fileA fileB) "差分を表示する" (ediff-files fileA fileB))
省略可能な引数を持つコマンド
引数を省略可能にするには &optional を関数の引数定義の前に記述します。引数が省略された場合には引数に nil が入るので if 文を使って、処理を分けます。
(if 判定条件
(真の場合の処理)
(偽の場合の処理))
以下の関数は find-file を使ってファイルをオープンし、
引数が省略されていた場合は直前に表示していたバッファを表示するコマンドです。
(defun eshell/open (&optional file) "ファイルのオープン。引数を省略した場合は直前のバッファを開く。" (if file ;; 引数あり (find-file file) ;; 引数なし (switch-to-buffer nil) ))
引数を結合して実行するコマンド
渡された引数をスペースで結合して関数を実行するコマンドの作成方法です。 これを使うと compile のような "" で囲んで引数を渡さなければいけない関数をコマンド化できます。lisp の関数定義で可変引数を使う場合には &rest を使用します。
これを使うと渡された引数の残りがリストとして引数に格納されます。
以下は compile をコマンド化した例です。
(defun ex-eshell-join-args (args) (let (cmd) (while args (if cmd (setq cmd (concat cmd " " (car args))) (setq cmd (car args))) (setq args (cdr args))) cmd)) (defun eshell/c (&rest args) "指定したコマンドでコンパイルを実行する。 引数を省略した場合は前のコマンドで実行する" (if args ;; 引数あり (compile (ex-eshell-join-args args)) ;; 引数なし (compile compile-command) ))これで c のコマンドで、コンパイルが実行されます。 また、引数を省略すると直前に実行したコンパイルを再度実行します。
$ c # 一番最初は compile-command のデフォルト値 (make -k など) が実行される $ c gcc -o foo.exe main.c bar.c $ c # 前のコマンド (gcc -o foo.exe main.c bar.c) が実行される)
![]() | やさしいEmacs‐Lisp講座 (2011/06) 広瀬 雄二 商品詳細を見る |
Emacs の eshell でバッファー末尾(EOB)から一文字戻る問題の対応
Emacs の 24.4 か 24.5 わかりませんが、
バッファーの末尾(EOB, End Of Buffer)で何かコマンドを実行するとカーソルが 1 文字戻る
という不具合が入りこんでいました。
ほとんどの場合は大した問題ではないのですが、 eshell
だとかなり不便です。
あまりちゃんとしたものではありませんが、対処方法を考えたので、
今回はそれを紹介します。
eshell ではバッファーの最後にカーソルがあるのが普通の状態です。 ここからバッファーの切り替え(switch-to-buffer)やウィンドウの移動(other-window) を行ってから戻ると、一文字移動し直さないと入力できないことになり、かなり面倒です。
この現象は多分バグなので、そのうち修正されるとは思いますが、ちょっと調べた感じだと特に解決方法は見つかりませんでした。 そのため場当たり的ではありますが、対処方法を考えてみました。
どうやるかというと advice という機能を利用します。
バッファーの切り替え等のコマンドを実行した後、 eshell モードで EOB の一文字後ろの場合には EOB に移動するようにします。
以下がそのためのコード なので、 ~/.emacs.d/init.el 等に書いてみてください。
(defun ex-move-to-eob-if-eshell (&rest args) (when (eq major-mode 'eshell-mode) (let ((pos (point))) (goto-char (+ pos 1)) (unless (eobp) (goto-char pos))))) (advice-add 'switch-to-buffer :after 'ex-move-to-eob-if-eshell) (advice-add 'other-window :after 'ex-move-to-eob-if-eshell) (advice-add 'eshell :after 'ex-move-to-eob-if-eshell)変更するコマンドは 3 つしか書いてませんが、 advice-add を追加すれば、他のコマンドでも移動するようになります。