俺、ちゃんと全部管理してます(org-modeでinit.elを管理する)
init.el(昔で言うところの.emacs)で管理していたEmacsの設定をorg-modeで管理する方法について。
init.elでありがちな問題
まず、init.elだけで管理する場合に問題になるのは:
- とにかく(縦方向に)長くなる。
- elispは、いろいろなことができてしまう反面、パッと見わかりにくい。(elispは、日常的に触れる言語ではないため、脳のコンテキスト・スイッチも難しい。。)
- わかりにくくならないようにと丁寧にコメントを書くと、更に(縦方向に)長くなるという悪循環に陥る。
- 新しい設定を追加する際、どこに追加しようか迷ってしまい、「えい、やー」とやってしまうのd(ry
結果的に、「よくこれで動いてるなあ。。」と不安なファイルになるのだが、毎日それに依存して生きていかなければならない。
数年毎に訪れる「俺、生まれ変わろう」という衝動により、init.elへの大胆な外科手術を行うのだが、半分以上の行が無くなってしまい、「なんか前と挙動が違うけど、気にするな!」と自分を諭しながら、強制的に生まれ変わる。
そんな、無駄な生まれ変わりを繰り返してきてしまったが、ご長寿Emacsには、これからもお世話になる予定なので、自分の設定もマネージブルにしたい。そこで、この問題を解決できる(かもしれない)のが、おなじみの org-mode である。
org-modeにするといいところ
詳しくは述べないが、とにかくorg-modeは、すごい。「いったいお前の目的は何なんだ?」と言うくらい、いろんなことができてしまう。まあ、そもそもEmacs自体がそういうヤツだ (そうだお前は最高だ! Atomが何だ! vimなんぞ来世でも敵じゃ! と必死に言い聞かせてEmacsを使い続ける。。)
とはいえ、org-modeのすごいところは、その基本機能である(折り畳み式)アウトライン機能だ。そして、コードブロックを内包することもできる。すると:
- なんと、init.elだけで管理していたよりも、更に(縦方向に)長くなる。。
- けど、種類毎に塊にして折り畳めるので、最上位のセクションだけなら、1画面で納まる。(「俺、ちゃんと全部管理してます」という気になる。)
- コメント自体もサブセクションにしてしまえばいいので、思う存分に書ける。
- 特定のコードブロックだけを瞬時に別バッファに展開し、編集したら元の位置にきちんと納まってくれる。
- 特定のコードブロックだけを瞬時に別バッファに展開できるので、M-x eval-bufferでテストしやすい。
- Emacs起動時に、init.orgから、init.elに勝手に展開して解釈してくれるので、init.orgだけ管理すればよい。
- Todoの管理もできて、agendaで纏められるので、設定上の課題管理もできてしまう。
と、言葉だけでは、伝わらないかもしれないが、すごくいい。なんといっても、精神的にいい。
どういう風に塊に分けるかが大きな問題だが、それを試行錯誤していくためにも、init.elで管理するより、init.orgで管理する方がよいと思う。
init.orgでの管理方法(org-modeでのEmacs設定)
(1) init.el
org-modeで管理するので、設定内容の本体は、init.orgで記述することになる。しかし、起動時にEmacsが直接org-modeのファイルを解釈できないので、init.elには、「init.orgを解釈してくれ!」という内容を記述する。
(require 'org-install)
(defvar my-config-dir (concat user-emacs-directory "my-config/"))
(org-babel-load-file (expand-file-name "init.org" my-config-dir))
- 1行目 : orgファイルを解釈する必要があるので、requireする
- 2行目 : init.orgが配置されているディレクトリ(ここでは、~/.emacs.d/my-config/)
- 3行目 : .emacs.d/my-config/ の下の my-init.org を解釈するように指示(org-babel-load-file)
3行目が実行されると、init.org内のコードブロックだけを抜き出した、init.elが、同じディレクトリ(~/.emacs.d/my-config/)に作成される。
my-configとかディレクトリを作らずに、init.elと同じ~/.emacs.d/にorgファイルを配置したい場合は、コードブロック抽出後のファイル名が、元のinit.elと衝突するので、init.orgというファイル名は使えない。my-init.orgなど適宜別名にする必要がある。
~/.emacs.d/init.elに、上記以外の設定を書いても良いが、意味があるとは思えない。なので、init.elの内容は、上記の3行のみ。
(2) init.org
org-modeでは、行頭の*でアウトラインを表現できる(塊がつくれる)。また、行頭の*の数(MAX:6)でレベルを定義できる。
なので、例えば:
#+TITLE: Emacsの設定
#+STARTUP: overview
* 基本設定
** 言語設定
** 画面表示
*** フレーム関連
*** バッファ関連
** キーバインディング
* ユーティリティー
** DICT
** DDSKK
** yasnipet
** MEW
* プログラミング
** web-mode
** ruby-mode
** python-mode
...
という感じで自分の管理したい単位で項目を階層化していく(レベルは、簡単に上にも下にも変えられるので、あまり気にしなくていい。はじめは、とにかく、やみくもにでも前に進むことが重要)。すると、それぞれの行で<TAB>することにより、展開/収縮がトグルできる。
ちなみに、1行目と2行目は、org-modeへのOPTIONだが、2行目のSTARTUPに、overviewを指定しているため、ファイルを開いた際の初期表示は、*が1つの行だけに収縮された状態で表示される。その後、自分のみたいところを<TAB>で展開していく流れになる。(これらのOPTIONは、いらなければ、なくてもいい。)
どのレベル(*の数)でも構わないので、その下に設定内容を書くことにしたい場合、次のようにする。
#+BEGIN_SRC emacs-lisp
;; ここに設定コード(elisp)を書く
#+END_SRC
たとえば、こんな感じ:
** キーバインディング
*** シェルと同様に C-h は直前の文字を削除
#+BEGIN_SRC emacs-lisp
(global-set-key (kbd "C-h") 'delete-backward-char)
#+END_SRC
*** F7 で行の折り返し表示を切り換え
#+BEGIN_SRC emacs-lisp
(global-set-key (kbd "<f7>") 'toggle-truncate-lines)
#+END_SRC
この例では、ひとつのコードブロックに1文しか書いていないが、好みで塊の大きさを決めていけばいい。
尚、この例では、まったくシンタックスハイライト(色付け)されていないが、Emacs上では、org-modeのアウトラインも、elispのコードブロックも適切に色付けされるので、かなり見やすい。
後は、Emacs起動時に、コードブロックを抜き出して、解釈してくれるので、構造上は以上なのだが、init.orgを編集していく際の編集方法をいくつか。
コードブロックの挿入
コードブロックを挿入したい場合は、<s とタイプしてから、<TAB>で、#+BEGGIN_SRC…#+END_SRCへ展開してくれる。
但し、emacs-lispだけは、自分でタイプする必要がある。(それも面倒なら、yasnipetで)
<s (ここで<TAB>すると、、)
以下に展開される
#+BEGIN_SRC
#+END_SRC
コードの記述(これ最高!)
コードブロックの中にelispで設定内容を書けばいいのだが、このまま書いてもインデントされないし、対応する括弧も教えてくれない。。特に複数行あると、elispではかなりきついし、5,6行超えたら、もうアウト。。
そこで、コードブロックの中にいるときに、
- C-c ‘ とする
- ウィンドウが分割され、当該ブロックだけを抜き出したバッファが表示される
- このバッファは、emacs-lispモードなので、このバッファがすべてと思って、ここでコードをきれいに書く
- なんなら、テストもここですればいい
- コードが決まったら、再び C-c ‘
すると、当該バッファは閉じられ、init.orgにもどる。もちろん、コードはきれいに反映されている。
設定をorg-modeにする際に、「これは失敗か。。」と少し不安になりかけたば、この機能があることを知ると「うお、こりゃええ、」と流れが変わった。