init-loader.el と package.el を導入して快適 Emacs ライフ - Qiita
に影響されて書きます。
package.elの設定ははじめの方に書く
;; Emacs package system (require 'package) (add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/")) (package-initialize)
package.elを使っているような人であれば、上記のような設定がどこかしらに
あると思うのですが、これは初めの方に書くべきです。具体的には早い段階で
package-initializeを呼ぶべきだからです。
package.elはパッケージ管理だけのツールではない
package.elを使ってパッケージをインストールした場合, デフォルトだと,
"~/.emacs.d/elpa/"以下にパッケージがインストールされますが、単にパッケージを
取得して、バイトコンパイルするだけではなく、autoloadに関するファイルも
生成しています(ファイル名は (パッケージ名)-autoloads.elとなります).
autoloadは遅延ロードを実現するための仕組みで、高速な起動を可能にします。
package.elなしでは手動で行わなければいけない、autoloadの設定を package-initialize
でやってくれるので早い段階で呼び出すべきなのです。
autoload補足
autoloadとはある関数を実行した場合に、指定したファイルをロードすることを
支持する関数です。これにより、まだロードしていない段階でも M-x等で関数が
見えるようになります。下記の例では quickrun関数を実行したら, "quickrun.el"を
ロードする、ということになり, quickru関数を初めて実行したときに quickrun.elの
ロードが行われます。
;; 他にもいろいろ出力されています (autoload 'quickrun "quickrun" "\ Run commands quickly for current buffer With universal prefix argument(C-u), select command-key, With double prefix argument(C-u C-u), run in compile-only-mode \(fn &rest PLIST)" t nil)
autoload cookie
package.el等が autoloadに関する設定を自動生成するために autoload cookieと
呼ばれるものが使われます。以下の ";;;###autoload"がそれです。これは任意の
S式の前に記述することができます。autoload cookieについては別途記事を書く
予定です。
;;;###autoload (defun quickrun-set-default (lang key) "Set `key' as default key in programing language `lang'" (unless (assoc key quickrun/language-alist) (error "%s is not registered." key)) (puthash lang key quickrun/command-key-table)
設定ファイルを読み込む時点では load, requireは原則呼ばない
上記で述べたように package.elを利用することで, 必要となるものは概ね
autoloadの設定が行われているはずなので、設定ファイルの段階で明示的に
load, requireを行う必要は基本ありません。特にプログラミング言語の
major-modeや minor-modeに関するパッケージについては確実に不要です
(Emacs Lispは例外).
もし requireしないと何かしらおかしいという場合は, autoload cookieの
設定が適切でない可能性があります。その場合は作者の方に知らせてあげると
よいでしょう。
ただ以下のようなものは結局するロードすると思うので, load, requireしても
別に問題ないと思います。helmとか dired周りとか Emacs Lisp関係が該当する
かと思います。
- 起動後すぐに使うもの
- システム全般で利用するユーティリティ
遅延ロードされた設定
autoloadとセットでeval-after-loadを使うのが良い? - すぎゃーんメモ
autoloadを利用した設定で注意しないといけないのは, 設定ファイルの
時点ではパッケージのロードが行われていないので、内部関数や変数、
faceを参照するとエラーになることです。該当のパッケージがロードされた
時点でこの設定を行なって欲しいというように書く必要があります。
それを実現するのが eval-after-loadです。例を以下に示します。
以下は diff-mode.elが呼ばれたとき, faceの設定やキーバインドの
設定を行うようになっています。注意して欲しいのは prognの部分の
quoteです。これがないとその場で評価されてしまい、意味がなくなります。
(eval-after-load "diff-mode" '(progn (set-face-attribute 'diff-added-face nil :background nil :foreground "green" :weight 'normal) (set-face-attribute 'diff-removed-face nil :background nil :foreground "firebrick1" :weight 'normal) ;; key bindings (define-key diff-mode-map (kbd "C-M-n") 'diff-file-next) (define-key diff-mode-map (kbd "C-M-p") 'diff-file-prev)))
追記: あるパッケージの関数や変数を参照している箇所があれば,
それは eval-after-loadに入れるべきと基本考えてください。
eval-after-loadは使い勝手があんまりということで、楽に書くための
拡張を書いている方や、改善策をブログ記事にされている方などいるので
気になる方は調べてみるとよいでしょう。
具体的な設定例
quickrun
quickrunであれば, キーバインドの設定だけで基本良いです。(独自のコマンドを
定義するような場合は loadする必要があります。loadはしなくていいですが、
設定のための関数を呼ぶと autoloadにより自動的にロードされます)
(global-set-key (kbd "M-g M-q") 'quickrun)
go言語
go-mode.elがロードされた時点(goファイルを開いた時点), gocodeを利用した
go-autocomplete.elを loadして、キーバインドを設定しています。
(eval-after-load "go-mode" '(progn ;; 追記 go-autocompleteは autoloadの設定が現状適切でないため (require 'go-autocomplete) (define-key go-mode-map (kbd "C-c C-d") 'my/helm-go) (define-key go-mode-map (kbd "M-.") 'godef-jump)))