spacemacsについて
最近、spacemacsを使っていて、「これは神じゃね?」とか思っている。それについて書こうと思う。非常に感情的になっているので、注意してほしい。かなり長くなるかもしれないので、それも注意してほしい。ぶっちゃけポエムである。
spaceemacsについては記事がいくつかある。
Vimも秘伝のタレも飲み込むEmacsの超強力ディストリビューションSpacemacsまとめ
6年間使っていたVimからEmacs(Spacemacs)に乗りかえた
しかし、上記の記事では、spacemacsのすばらしさを十分に記述できていないと思ったのだ。
この記事は,spacemacsの機能について取り上げたものでは無く、畏れ多くもspacemacsの僕なりの始めたキッカケの類を書いたものである。spacemacsの入門については、また別に取り上げたいと思う。しかsi、この記事でもspacemacsの機能のいくつかは紹介するつもりである。
spacemacsを使う以前
spacemacsを使う前、僕は、沢山のエディタを触ってきた。一番最初につかったのはEmacsだった。その後、Vim、TextMateやSublime、Atom,VSCodeを触ったりした。
Emacs Lispの高い拡張性
その中で一番しっくり来たのがEmacsであった。理由はいくつかあるが、最も重要だと思う点は、Emacs LispというLispで拡張が書け、そして拡張が容易であるという点である。EmacsはEmacsコマンドという命令によって、カーソルを移動したりできるのだが、Emacs Lispで関数を書くことによってでそのコマンドが作れるのだ。
たとえば、2文字進むコマンドはこのように書けば良い
(defunforward-2-char()(interactive)(forward-char)(forward-char))
雑な説明なのだが、(interactive)という命令によって、今書いている関数をEmacsコマンドにできる。そして、forward-charという命令を2回すれば良いのだ。非常に簡単である。これをEmacsで評価すると、M-x
からコマンドで呼び出せる。
さて、毎回M-x
で、Emacsコマンドを呼び出していたら面倒である。であるから、keymap
という、キーとコマンドが対応させてあるEmacs Lispのオブジェクトがあり、それに登録する。
(define-keyglobal-map(kbd"C-f")'forward-2-char)
Emacsはモードというものがあり、モードに対応したkeymap
があったりして、それによってkeymap
が多層になっている。上記のemacs lispでは、global-map
というkeymap
にC-f
というキーforward-2-char
が対応させてある。global-map
は全てのモードに共通してするkeymap
であり、入力したキー他にkeymap
が無ければglobal-map
で対応したEmacsコマンドが実行される。
僕はこのEmacsの高い拡張性に感動していた。さらに僕はプログラミングを始めて直ぐにLisp
を書いていたので、Emacs Lispでこどもの玩具のようにEmacs Lispでプログラミングを書いていたのだ。
(そしてほとんどの場合、先人達のすばらしいEmacs Lispによって僕のおもちゃのコードは置き変えられていったのだが。僕はそれによってほとんどのおもちゃのコードを消してしまったのだ!!! 今思えば公開すれば良かったのかもしれない。が当時は公開する価値などなく、非常にはずかしいものだ! と思ったものだ。)
Emacsその他のアプリケーションを連携、統合するもの
さて、この素晴しい拡張性によって、沢山の拡張が生まれて来た。そして、Emacsはその拡張性において、エディタというテキスト編集機能というものを超えて、emacsでコードをビルドしたりデバッグしたりするIDEのようなものになったり、メールを送受信するメーラーになったり、カレンダーになったり、ブラウザのようなものになったに、更にまたtwitterクライアントにもなったりもした。
しかし、一部の拡張はすべてEmacs Lispに書かれたものではない。外部のプログラムを利用することによって、生み出された拡張がある。そもそも、ビルドやコンパイルするためには、その言語のコンパイラを利用しなければならないし、純粋にEmacs lispのみで成り立つものでは無い。(Emacs Lispでコンパイラを書くことは可能だろうが、ほとんどの場合は外部アプリケーションと連携するだろう。) Slimeや、 RSenseや、Ensimeやなどの、プログラミングなどはその例として上げられるだろう。
Emacs Lispは外部プログラムと連携する。とすれば、僕は更にもう一歩勧めて見たい。というのも、Emacsは、外部プログラムと外部プログラムとの接合点になるということである。
たとえば、メールからとあるイベント招待状が来たとすると、それから、カレンダーに日時とイベント名を登録し、そしてtodoリストにイベントで準備するものをリストアップしておくみたいなものである。一般のOSの利用だと、アプリ同士が独立しているため、人の手の作業によって行なわれることが多いだろう。しかし、Emacsは、OSの独立したアプリケーションを協調し、アプリ間の作業を自動化できる可能性がある。
この編の話は、詳しくは
lispを(なるべく)書かないコマンド作成講座(菅原泰樹)
emacsは死んだ
Emacsで他の言語とRPC
などの記事を参照すると良いだろう。
Emacsと拡張とキーバインド
Emacsの魅力を語ってきたのだが、しかし、Emacsにも欠点がある。それはデフォルトのキーバインドが良くないのと、キーバインドがたくさんあって思い出すのが大変、 キーの不足問題があるということである。
Emacsのカーソル移動のキーは、C-f
、C-b
、C-p
、C-n
である。これはほどんどの人達にとっては、慣れることが大変である。それぞれのキーがキーボード上では遠い位置になるので、これでカーソル操作というのはなかなか大変であろう。
ただ、フォローしておくと、C-f
、C-b
、C-p
、C-n
は覚えやすくもあるのだ。たとえば、f
はforward
、b
はback
、p
はprevious
、n
はnext
の頭文字だとすれば、なるほど、思い出すヒントとなる。
拡張も含め他のデフォルト設定のキーバインドも、何かの頭文字でキーバインドが作られていることが多い。なので覚えるヒントにはなる。しかし、非常にコマンドが多くなり過ぎて、キーバインドが覚えられなくなるのだ。
そういえば、 Ctrlキー
を押しまくる問題もあるかもである。しかし、僕としては、その問題はキーボードの本質としては、キーの不足問題にあると思っている。というのも、キーボードは沢山のボタンがあるのだが、ほとんどが文字入力に使われてしまい、文字入力でないことを示すサインとしてCtrl
が選ばれた、ということだと思う。
この編の解決として、以前のはてなのブログで書いたことがある。
またこれと類似したものとして、このような深町さんが記事を書かれている。
「Emacsのトラノマキ」連載第16回「元Vimmerが考えるEmacsの再設計」(深町英太郎)
また、更にキーバインドを思い出すものとして which-keyというemacs拡張が作成されたりしている。
つまり、発想としては、キーバインドの不便さも、キーバインドの再設定や、emacsの拡張によって解決してしまおう!!!ということだ。
そして、これらのキーバインドに問題ついて僕はもっと、よりよりものを探して行った。そして、Evilを使って、さらにEmacsの拡張をして、もっとよりより体験のためにすばらしいエディタの環境を作ろうとした。この点について紹介しよう。その前に、Evilについて、述べておこう。
余談だが、Emacsは小指が痛くなるみたいな話がよくあるが、その話は糞だと思う。emacsで小指を鍛えたみたいなことを誇っているような記事が上げられているが、どう考えてもアホである。そんな記事を書いてなんになるんだ。(まぁ一般にはネタとしては面白いかもだが) いままで何やってんだ?という気分である。というのも、適切にemacsを設定、拡張して、ちゃんと使っていれば入力するコマンドも少なく最適化されて、Ctrl
を押しまくるといった自体にはならない筈である。だから、そうならないのはEmacserとしてそれはどうなんだ? と思うのである。なぜ自分のEmacsをキチンとデザインしないのだ? (そもそも、周りの人間でEmacsを勧めて、コマンドの調べ方、拡張の仕方などを教えて使っている人達で小指が痛くなるとかそういうものは見たことが無い)
まぁ、小指問題はEvilを入れてしまうと、一気に解決してしまうことも多い。とりあえず、Evilについて紹介する。
VimとEvil
EvilはEmacsをVimのように使うものだ。(参考: EmacsをVimのごとく使う )
僕はあまり、Vimを書く経験は少ないのだが、Vimも良いエディタと思っている。その魅力としては、やはり、Vimのモード
という考えである。
Vimのモード
というのは、Vimがテキストの編集のためのいくつかのキーバインドの状態を持ち、適切な状況に合わせて、エディタの状態を変え、よりよいキーバインドを使おうというものだ。ノーマルモードで、カーソル移動、インサートモードでテキスト入力、ビジュアルモードでテキスト選択、コマンドラインモードによって、Vimのコマンド実行など、ユーザは適切にモードを選択し、それぞれのモードによってテキストを操作して行く。
Vimは、エディタのモード
によって、エディタの状態を変えながら操作していくため、複雑のように思える。しかし、Vimはそのおかげで、キーバインドが目的に合わせてグルーピングされ整理されるのだ。テキストを編集というのは、様々な目的に分割できる。テキストを選択したり、入力したり、カーソルを移動したり、など。それは、あるテキストを編集するという目的を、別々のよりシンプル目的へ分割しているという見方ができる。Vimはその小さなシンプルな目的を解決するために、モードを作り、キーバインドすれば良い。
また、モードによって、文字挿入にキーを取られない。という利点もある。これによって、キー不足問題は解決する。
一方として欠点としては、いちいちモードを切り変えないといけないということである。Emacsの場合は、テキストを入力しつつ、カーソル移動ができるが、Vimの場合は一拍置かないといけない。だから、Emacsを使っていた物からすれば、近いところに移動したいのに、いちいち切り変えるのは面倒なのだ。ただし、Vimのモード
によって、素早く遠くのところまでカーソルを移動させることができる面は便利ではあるのだ。
Evilは、上記にVimの利点をすべてEmacsに取り込むことができる。Evilでは、Vimのモード
は、ステート
になる(既にEmacsではモード
は別の概念として存在する)。 つまり、Evilはステート
という概念をEmacsに導入し、Emacsに編集状態を作り出すのだ。つまり、カーソルを移動が楽になる、ノーマルステート、テキストを入力するインサートステート、テキストを選択するビジュアルステートなど、が導入されるのだ。
Evilの拡張
さらに、EvilはEmacsであるため拡張することができる。Evilの拡張とは何か? それは、大きく分けて
- 既存のステートにキーバインドを作る
- コマンドラインステートにコマンドを増やす
- 新しいステートを作成する
ということである。
とくに考えなければ、既存のステートにキーバインドを適切に設定するとか、またコマンドラインステートにコマンドを増やす、だろう。そのアプローチでも十分に強力だと思う。
しかし、僕は新しいステートを作成するということに、Evilの魅力を最大限に感じたのだ。そして、いくつかのステートを作ったのだ。たとえば、プログラムをコンパイルや評価をするためのステートや、デバッグのためのステート、通常のカーソル移動を拡張してemacs lispのための移動ステートや、 pareditの特殊な操作のためのステートを作ったのだ。
とすると、沢山のステートが存在するようになり、すると、沢山のステート毎のキーバインド
を覚えなければいけなように思えるだろう。僕はその問題に当たった。その解決のため、僕は、キーマッピングを最初から表示する拡張を作った。which-key.el
のようなものだ。which-key.el
の画像を貼っておく。
今はwhich-key.elをそのまま設定して利用している。
理想のエディタを構築する
ここまで、僕が、Emacsの設定を弄りを、Evilを導入したり、拡張し続けた。それは、別の見方からすると、エディタの再設計であると今にして思う。すると、理想のエディタを構築することに近いのだ。
僕は、どのようなエディタが欲しいのか?ってのを常日頃考えている。僕は最近UXデザインを学び、UXなどの勉強をして、「ユーザが何を欲しいか?」ということを考えるようなった。すると人間は自分が本当に欲しいものを気づくことができないし、説明できないのということに気づくのだ。だから、いろいろなエディタを触ったり、自分で拡張しながら、それを探すのだ。
そのような仮定において、どのようなエディタを考え、僕はエディタをリデザインしたのだ。拡張したか?ということをまとめみよう。
実は、以前、emacs福岡を開催したときに、自分の環境について発表したことがあるのだが、(そのスライドである : http://slides.com/nobukazuhanada/evil#/8 ) その発表で話たことでもある。
どのようなエディタを僕は考えていたか?である。
まず、ノーマルステートの拡張である。ノーマルステートで、カーソルの移動や削除のみならず、コンパイルやファイルオープン、バッファの削除などを設定した。f
でファイルオープン、q
でバッファkill、 c
でコンパイルというキーバインドを設定した。更に、r
でシェルコマンドを呼び出せるようにした。
さらに、コマンドラインステートの拡張である。:make
で、makeコマンドを呼び出し、:rgrep
で、ディレクトリの以下の再帰的な検索、:align
でテキストの整形ができるようにし、:x
でEmacsのM-x
と同じ効果にしたのである。
挿入ステートは、通常のEmacsのキーバインド設定に似たようなものにした。auto-completeや、yasnippet、paredit-modeなどの、キーバインドは変更している。
あと、大きく変更したのは、テキストの移動や削除、置換の特殊なステートを作成したことである。ノーマルステートではx
とd
で削除ができるが、これをd
に統一した。そして、d
が削除やhjkl
で移動やs
で文字置き変えにしたのである。そして、その前に文字の量の単位を設定できるようにし、たとえば、4d
で4文字削除、4lj
で4行移動、などというように、移動量や削除量、置換量を設定できるようにした。
ここまでが、spacemacsを出会う前までの設定であった。僕なりに理想を追求したのである。
Spacemacsの衝撃
ここまで、自分なりに理想のエディタを考えて、設定し、拡張しEmacsを変えていったのだ。とすると、元々の何も設定していない、Emacsとはかなりかけ離れたものになって行くのである。なぜそうなって行くのであろうか?
僕はなんとなく、元々の素のEmacsの操作がやはり良くないのだという思いが生じ始めていた。
「ユーザが拡張できる。拡張しやすさがある。」というのはすごく素晴しい一面がある。しかし、Emacsの場合は、ユーザがそもそも、「拡張しなれけばらなない状態」であったのだ。そのようになるというのは、もともとEmacsがユーザフレンドリィに、ユーザのために考える設計に失敗したのであった。
そう考えていた時、spacemacsを紹介されて、触り始めたのであった。そして、僕は衝撃を受けた。僕はすごくすばらしいものだと思ったのだ。そのいくつかを紹介しよう。
spacemacsはユーザに良く考えられた設計
spacemacsは、EmacsでもVimでも無い。僕の理想とするエディタに近いと僕は思う。その理由としては良く考えられたキーバインドである。(勿論不満が無いわけでは無いが。)
最初から、キーバインドが素晴しいのだ。それは以下の幾つかの点になる。
まず、スペースキー(SPC
)を活用したということである。公式のドキュメントではSPC
をevilのleader key
に設定することにより、RSI
(Repetitive Strain Injury、反復的なストレスによる障害)を低減したとある。
そして、キーバインドがとても覚えやすく設計されているのである。たとえば、ファイル関連の操作であればとりあえずSPC f
を、バッファ関連であればSPC b
を、git関連であればSPC g
を押下するれば良いのである。これは、僕のノーマルステートの拡張と似たような発想であって、すごい良いと思ったのである。
そして、:
を押すと、Vimのコマンド、SPC :
を押すとEmacsのコマンドつまりM-x
を押したのと同じ状態になるのだ。この点において、僕の以前のEvilの設定:x
と似たようなもので、非常にマッチする。
僕がSpacemacsに切り変えて、起ったのは大半のEvilの自作のステートが必要なくなったということである。僕はもともと、ステートを作り過ぎていたのだ。だから、大半の設定ファイルを捨ててしまった。
そして、キーバインドがspacemacsでは思い出しやすいということがある。それは殆どwhich-key.el
であり、それも僕が設定していた拡張を捨てる動機にもなった。最早、キーバインドを沢山覚える必要が無いのである。
spacemacsのその他の利点
そして、spacemacsは通常のemacsをベースにしているので、もちろんemacsの拡張性はある。そしてさらに、spacemacsはlayerという概念があり、これにより、設定をスッキリされることができる。このことに関しては後日別の記事でまとめよう。
あとこれはどうでも良いが、アイコンがカッチョイイし、見た目が良い。
spacemacsは、僕の拡張に近く、さらに超えている面があり、理想に近い
spacemacsは上記以外の様々な点で、良く考えられていると思ったのであり、僕の拡張や設定を非常に近いものであった。それ以上に、spacemacsは僕の拡張を超えていると思ったこともたくさんあった。
もちろん不満もある。
もちろん不満もいくつかはある。なので、設定ファイルを弄り続けているのではある。それらの不満は設定の変更や、拡張をすればいいのだ。
最後に
長くなって申しわけない。ここまで読んでくれたら幸いである。
以上である。
もし、開発を通して「こうであったらな」とかあれば僕に教えてほしい、そういう議論は大好きだ。もしかしたら、更に寄り良いものができるかもしれない。
今後、spacemacsのlayerや、オススメの設定など晒して行くつもりなので、期待してほしい。