etcskel/.emacs.el の各種設定をモジュール化をしてみた

  • ~/.emacs.el がごちゃごちゃしているので,すっきりしたいやんね?
  • ~/.emacs.el って何も無くてもある程度動く方がいいかも!?

第2回 定例IRCミーティング - VineSeed Trac

じゃー,「モジュール化だな.」ってことで約 1 週間ほど試行錯誤して,ようやく形になったので,今日 TestPkg として put してみました.

[VineSeed:17162] [TestPkg] emacs23, mew, wl, yatex

実装方法をできるだけ「簡単に」,「見易く」,「便利に」ということを考えていたら,フックにかけてしまうのが一番すっきりいくかなと思い,基本的には「各モジュール化された設定を after-init-hook に引っかける」という今のような実装に落ち着きました.

以下の内容は,Emacs – VineSeed にまとめてあります.

vine-default の仕組み

site-start.el に以下のような関数とフックを定義してしまいます*1

(defcustom vine-default t
  "A boolean for All Vine Linux default settings"
  :type 'boolean)
(if (equal (getenv "LOGNAME") "root") 
    (setq vine-default nil))

(defvar vine-default-setup-hook nil
  "*List of functions to be called at vine-default-setup")

(defvar after-vine-default-setup-hook nil
  "*List of functions to be called at the end of vine-default-setup")

(defun vine-default-setup ()
  "a function for setup to default configurations of Vine Linux."
  (if vine-default
      (progn
	(run-hooks 'vine-default-setup-hook)
	(run-hooks 'after-vine-default-setup-hook)
	)
    )
  )

(add-hook 'after-init-hook 'vine-default-setup)

たったこれだけです.

VineEmacs デフォルト設定を読み込む処理を after-init-hook に引っかけています.

after-init-hook
  Variable: Normal hook run after loading the init files, `~/.emacs' and `default.el'.
  Plist: variable-documentation

WanderlustMew, YaTeX のような emacs 関連の外部パッケージに対しては,それぞれ *-init.el に以下のような設定を追加します.

(defcustom vine-default-yatex t
  "A boolean for vine-default-yatex"
  :type 'boolean)

(add-hook 'vine-default-setup-hook
	  (lambda()
	    (if vine-default-yatex
		(require 'vine-default-yatex))))

この例では yatex ですが,vine-default-setup-hook に YaTeX の設定を読み込む処理を引っかけているので,after-init-hook で処理されてうまくいきます.シンプルです.

このように各種パッケージの設定をモジュール化 vine-default-*.el としておくと,~/.emacs.el は基本的に何も設定しなくても,Vine Linux のデフォルト設定が読み込まれる仕組みになります.

ちなみに after-vine-default-setup-hook は,各種パッケージ後に部分的に変更したいときなどに使うための主にユーザ向けフックとして用意しています.

また,今まで init-file-user 内で読み込んでいた設定を after-init-hook に引っかけるのが適当なのかどうかの議論の余地はあるかもしれないので,/usr/share/emacs/23.0.91/lisp/startup.el.gz に定義されているフックを以下に列挙しておきます.

(defvar before-init-hook nil
  "Normal hook run after handling urgent options but before loading init files.")

(defvar after-init-hook nil
  "Normal hook run after loading the init files, `~/.emacs' and `default.el'.
There is no `condition-case' around the running of these functions;
therefore, if you set `debug-on-error' non-nil in `.emacs',
an error in one of these functions will invoke the debugger.")

(defvar emacs-startup-hook nil
  "Normal hook run after loading init files and handling the command line.")

(defvar term-setup-hook nil
  "Normal hook run after loading terminal-specific Lisp code.
It also follows `emacs-startup-hook'.  This hook exists for users to set,
so as to override the definitions made by the terminal-specific file.
Emacs never sets this variable itself.")

(defvar inhibit-startup-hooks nil
  "Non-nil means don't run `term-setup-hook' and `emacs-startup-hook'.
This is because we already did so.")

(defvar window-setup-hook nil
  "Normal hook run to initialize window system display.
Emacs runs this hook after processing the command line arguments and loading
the user's init file.")

当初は,~/.emacs.el に (require 'vine-default) のような 1 行を追加する形にしようなど考えていましたが,「~/.emacs.el は空っぽでもそれなりに動く」に反するのと「ちょっと不格好!」なのが気になってしかたなかったので,最終的にフックを使う形に収まりました.

まだ TestPkg なんで,この案自体がおじゃんになってしまう可能性もありますが,etcskel がダイエットできるのと,.emacs.el が見易くなり,かつ,細かく弄りやすくなったので,いい感じだと思います.

たくさんテストにご協力頂いて,ご意見を頂けたら嬉しいです.

おまけ:試行錯誤(2009/04/24 追記)

vine-default の仕組みを考えるときに,

[1] (require 'vine-default) を .emacs.el に記述する形

か,

[2] after-init-hook に vine-default-setup をかける形

にするか,どちらも試して悩みました.

前者の仕組みも後者の仕組みも,大きくわけて以下の 3 つの設定パートにわかれます.

(a) vine-default が提供しない設定,あるいは,vine-default に影響しない設定

(b) vine-default

(c) vine-default に影響する設定,あるいは,vine-default を上書きしたい設定

[1] の場合

.emacs.el 内で以下のように記述することになります.

;; (a)

;; (b): 
(require 'vine-default)

;; (c)

ところが,[1] の欠点は (b) の (require 'vine-default) の位置を常に .emacs.el 内で考えないといけないのです.

Gentoo は (require 'site-gentoo) とするのですが,以前 Gentoo を使っていたときに,この欠点が非常に嫌でした.

[2] の場合

[1] の (b) に相当する位置をあまり考えなくて良くて,(a), (b), (c) がうまくすみわけができます.

(a): .emacs.el

(b): .emacs.el の直後に vine-default-setup により読み込まれる

(c): 必要であれば,各種設定対して,それぞれ .emacs.el の任意の位置に after-vine-default-setup-hook にひっかける

以上のような検討のすえ,[2] を採用しました.

旧版の .emacs.my.el

旧版の .emacs.my.el は (a), (b), (c) のすべてに渡っている可能性がありますが,一応 after-vine-default-setup-hook にひっかけておくつもりです.

なので,別途設定をまとめたいユーザは,.emacs.my.el を使っても使わなくても良く,.emacs.el に直接書き込むか,.emacs.my.el で各種設定を分けれらるのならば,必要に応じてモジュール化して,(a) に属するものは,.emacs.el へそのまま書き込む,(c) のものならば,after-vine-default-setup-hook にひっかけるという整理が必要です.

*1:こちらでは見易さを優先にして,抜粋して書き出しています.