世の中には2種類のEmacs使いがいる。
shellの上でEmacsを使う者と、Emacsの上でshellを使う者だ。
という格言があるかは知りませんが、
ともかくEmacsの上で、快適にshellを使うまでの設定を書いていきます。
さぁ、みんなでEmacsに依存しよう!
1. なんでEmacsの上でshellを使うのか
楽しいからです。
というのがまぁホントのところで。
最後の方で書きますが、やっぱりTerminalを出さないと不便な場面はありますし、
やらなきゃいけない設定も、それなりにあります。
でも、もう少し真面目にメリットを書いておくと、
-
常にEmacsのキーバインドの支配下で、開発作業ができる
-
Emacs(エディタ)から離れずに、すばやくshellに移動できる
-
shellでいじったファイルを編集するときも速い
- すぐ
C-x C-f <ファイル名>
すればいい
- すぐ
-
compass watch
とかmongod
とか開発用サーバーとか、起動して放っておく系のコマンドをやらせておくのにちょうどいい- 非表示にしてbufferには残しておく
こんな感じです。
「おもしろそう!」って思った方のみ先へお進みください。
2. どのshellを使うか
ひとくちに「Emacs上でshellを使う」と言っても、実は色々種類があります。
以下の4つが有名です。全部試しに起動してみて、好みで選ぶのがいいと思います。
- shell (
M-x shell
で起動) - term (
M-x term
で起動) - eshell (
M-x eshell
で起動) -
multi-term (
M-x multi-term
で起動・elispのインストール必要)
また、shellの画面を出すのではなく、単発でコマンドを実行したい場合には、M-! <コマンド>
というのもあります。
M-! open .
とか叩くと、Finderでいまいるディレクトリが瞬時に出てきて便利ですよ。
3. eshellがおもしろい
自分はeshell派です。理由は以下。
- Emacs Lispだけで書かれていておもしろい
- (らしい。中身をちゃんとは見てない)
- そのため、Emacsのコマンドもそのまま打てる
-
M-x
とM-!
でできたshell、と考えられる
- 安定している
- デフォルトで入っている
- 補完などもちゃんと動き、Emacsらしいshellになっている
- shellの出力をそのまま切り取って、別のbufferに貼る、なども自由自在
- 複数shellにも対応。(2つ目以降を
c-u M-x eshell
で起動)
よって、本記事は基本的にeshellの話です。
multi-termとかの方が、.bashrcに乗っかれる点では便利なはず。
termやmulti-termが気になる方は、こちらの記事あたりが読みやすいです。
4. $PATHをTerminalと揃える
Emacsのshellで悩ましいのが、
.bashrcなどの設定をどう引き継ぐかという問題です。
(というかTerminal環境がいくつもあるときの問題)
eshellは、bashではない独自言語なshellなので、
当然.bashrcは読んでくれません。
特に辛いのはPATHですね。いつも使うコマンドが打てないと、
Terminalに帰りたくなります。でも負けてはいけません。
解決方法はいろいろあるんですが、自分はこの手法がスマートと思います。
ざっくりいうと、
- .bashrcの中で、$PATHをファイル出力する処理を書いておく
- eshellの方で、そのファイルを環境変数として読み込む処理を書く
という流れです。実際のコードはこんな感じ。
## create emacs env file
perl -wle \
'do { print qq/(setenv "$_" "$ENV{$_}")/ if exists $ENV{$_} } for @ARGV' \
PATH > ~/.emacs.d/shellenv.el
;; load environment value
(load-file (expand-file-name "~/.emacs.d/shellenv.el"))
(dolist (path (reverse (split-string (getenv "PATH") ":")))
(add-to-list 'exec-path path))
これで、Terminalを起動するたびに、最新の$PATHが出され、
eshellと同期できます。
5. aliasの設定
もうひとつ、.bashrcとかでよく書くものといえば、aliasですね。
これもeshell用の設定を書きましょう。
参考はこちら。
eshell-command-aliases-listという変数に追加していくと、
できるようです。
ほんとうはPATHと同じように、Terminalと同期したいところですが、
lispの知識はへっぽこもいいところなので、
listで追加するように書き換えるくらいしかできず、現在こんな感じです。
;; set eshell aliases
(setq eshell-command-aliases-list
(append
(list
(list "desk" "cd ~/Desktop")
(list "swipl" "/opt/local/bin/swipl"))
eshell-command-aliases-list))
まぁ自分はそんなにalias使ってないので、いいんですが。
6. rvmも使えるようにする
$PATHをちゃんと設定しても、動かないコマンドが一部あります。
例えばrvmです。
rvmは、Rubyのバージョンを切り替える時に、
$PATHの内容を書き換えることで対応してるのですが、
これがEmacs内の$PATHまでは書き換えてくれないみたいなのです。
解決策としては(それでもちょっと不便ですが)、rvm.elというのがあります。
これを入れておけば、M-x rvm-use 1.9.3
とかで、
ちゃんとeshellのRubyも切り替わります。
本当はrvmのコードに手を加える、とかもありなのかしら。
なおnodebrew・perlbrewは、上記の$PATH設定をちゃんとやれば、
正常に動きました。
7. まだ微妙なところ
リモートログインが不便
eshell上でssh、とかもちゃんと使えるんですが、remoteの側でのshellで、補完などが効きません。
あるいは、tramp通信した後にeshellを開けば、
補完は効きますが、ちょっと訳の分からない環境になっているので、
大事な作業をする時なんかは避けたい感じです。
そんなわけで、自分は現在「remoteに入るときはTerminal」
というスタイルでやってます。
いちおう、remoteとlocalでアプリケーションが分かれてる、ってのも悪くないです。
なお、moshはコケます。
環境変数系のところで怒られてるので、がんばればいけるはず。
input redirectionが使えない
mysql -u root -p < hoge.sql
←こういうのができません。
output redirectionとpipeは使えるので、
まぁcat hoge.sql | mysql -u root -p
とかすればOKではあります。
8. まとめ
けっこうめんどくさいですね、はい。
Emacs使いは意地っ張りだなぁという感もしております。
まぁEmacsが好きな人は、Emacsのコンテキストで
何でも扱えるところが好きなんだと思うので、導入すれば、それなりの便利さはあります。
あと、もっと詰めていけばelispの勉強にもなりますね。(特にeshellは)