Dreaming in Greater Boston

M-x shellからemacs-eatに乗り換える

1 はじめに

これまで emacs上で使うシェルとして、 M-x shell を使っていたのですが、いくつか不満点がありました。

1.1 リモートシェルの指定がうまくいかない

MacからLinuxマシンにリモートでログインすることが多いのですが、ローカルのMacではMacOS標準のzshを、リモートでは bash を使いたいのです。

trampのドキュメントを読むと tramp-default-remote-shell を操作するとよいとあるので、

(setq tramp-default-remote-shell "/bin/bash")

としても何故かデフォルトのまま /bin/sh を使おうとして、それでよいか聞いてきます。ここで /bin/bash に修正すれば使えるのですが、毎回聞いてくるので地味に面倒です。

一方で、

(setq explicit-shell-file-name "/bin/bash")

のようにすると、リモートだけでなくローカルまで bash にしてしまいます。Macがzshでないと文句を言うので、これは困ります。

1.2 つい、terminalのキーバインドを使おうとしてしまう

M-x shell ではコマンドラインのヒストリー操作をするのにCtrlキーや矢印キーでなく、メタキーを使う(M-p, M-r 等)のですが、つい矢印キーを押して、カーソルが動いてしまいます。

わかっているのですが、気を抜いた時に想定外の挙動をするので、地味に不満を感じていました。

2 emacs-eat

emacsから使うターミナル/シェルとして eat の評判が良いので乗り換えを検討することにしました。 eatは M-x shell と違って、ターミナルとして使うモード(デフォルトのsemi charモード)と、表示履歴をemacsのキー操作で検索したりコピペしたりするモード(emacsモード)に分かれています。ほぼターミナルとして振る舞うsemi charモードで普段は十分間に合うため、emacsのキーバンドで表示履歴を操作するemacsモードを独立させたのは理がかなっていると思います。

C-c C-e でemacsモードに、 C-c C-j でsemi charモードになることを覚えるだけで、あとは何となく感覚的に使えると思います。semi charモードでも厳選されたごく一部のemacsキーバインドが使えます。

このemacs-eatですが、使えるようになるまでに結構試行錯誤し、以下のような問題にぶつかりました。

2.1 リモートシェルが指定できない

まずは、リモートシェルにローカルと同じ zsh を探しに行ってエラーになり、リモートでは全く使い物にならない問題がありました。eatの マニュアル を読むと eat-tramp-shells 変数を設定するように書いてあるのですが、設定しても挙動が変わりません。

このためしばらく使用を断念して放置していたのですが、最近、私のemacsから参照しているソースコード(eat.el)を眺めていて、codeberg上の最新eat.elと差があることに気が付きました。NonGNUからパッケージインストールした手元にある版では"tramp"で検索してもヒットしないのです。package-list-packagesからはアップデートできないため、最新版なはずなのですが。

そこで、NonGNU版をアンインストールして、git cloneしてきたcodeberg版を指定したところ、やっと eat-tramp-shells の設定が有効になりました。こんなことってあるんですね。。。

2.2 M-o が効かない

私は Mastering Emacs の推奨に従って、ウインドウ間のカーソル移動に M-o を使っています。標準は C-x o に割り当てられていますが、頻繁に使用する操作なので、よりストロークの少ないキーバインドにグローバルで設定しています。

ところが、eatのデフォルトモードであるsemi charモードでは M-o のグローバル設定が無視されてしまいます。eatでは、semi charモードのキーバインドをカスタマイズできるのですが、 M-o を追記しても挙動が変わりません。

検索したところ、全く同じ問題で悩んでいた人のQ&Aが redditのページ にあったので、解決策をそのまま使ったところ M-o でウインドウ間のカーソル移動ができるようになりました。この人も Mastering Emacs に倣ったのでしょうか。

2.3 TERMが認識されない

まだ最終的に解決していないのがこの問題です。手動でeatをセットアップしたためか、$TERMに(正しく)設定されているeat-truecolorが認識されず、 clear コマンドや C-l が動きません。マニュアルを読んで変数を確認しても問題なく、少なくともローカルでは$TERMINFOに正しいディレクトリが設定されています。

このままでは使い勝手が悪いので、workaroundとして eat-term-namexterm-256color を設定しています。

2.4 init.elの設定

eat関係の設定は以下です。

(use-package eat
  :load-path "~/.emacs.d/site-lisp/emacs-eat" ;; git cloneしてきたものを指定
  :config  ;; M-o をターミナルに渡さないようにする設定
  (customize-set-variable ;; has :set code
   'eat-semi-char-non-bound-keys
   (append
    (list (vector meta-prefix-char ?o))
    eat-semi-char-non-bound-keys)))
(setq eat-tramp-shells '(("ssh" . "/bin/bash"))) ;; リモートでbashを使う設定
(setq eat-term-name "xterm-256color") ;; $TERMが認識されないことのworkaround

3 emacs-eatを使ってみて

まだ使い始めて間がありませんが、 M-x shell の不満点は解消され、使いやすくなったと思います。 emacs上でシェル/ターミナルを多用するため、ちょっとした改善でも大きな差が出ます。