Emacs
AdventCalendar
emacs-lisp
init.el
AdventCalendar2015
.emacsDay 5

init.elの設定をコンピューターごとに分岐させる

More than 3 years have passed since last update.

Emacsの大きな特徴の一つは、Mac OS X、Linux、Windowsなどといった異なったOSでも、同じUI、ほぼ同じ設定で使えることだと思っています。

とはいえ、OSなどの環境ごとに設定を切り替える必要がある部分や、切り替えた方が便利な部分があることも事実。ここでは、init.el(.emacs)の設定をOSなどの環境に合わせて切り替える方法を考えます。


切り替えに使う変数


system-type変数

system-type変数を使うと、OSごとに設定を切り替えられます。主なOSの種類は次のとおり。


  • gnu/linux

  • darwin

  • windows-nt

詳細は、C-h vdescribe-variable)でsystem-typeを調べてください。

たとえば、次のようなMac OS Xだけで有効な設定を~/.emacs.d/init-darwin.elファイルに記述したとします。

;; Mac OS X用の文字コード指定

(setq file-name-coding-system 'utf-8-hfs)
(setq locale-coding-system 'utf-8-hfs)

この設定は、init.elに次の記述をすることでMac OS Xの場合だけ、呼び出すことができます。LinuxやWindowsなど、Mac OS X以外のOSの場合は呼び出しません。

(when (equal system-type 'darwin)

(load-file "~/.emacs.d/init-darwin.el"))


window-system変数

window-system変数は、ウインドウシステムごとに設定を切り替えられます。主なウィンドウシステムの主な種類は次のとおり。


  • nil

  • x

  • w32

  • mac

  • ns

詳細は、C-h vwindow-systemを調べてください。

Mac OS Xの場合はmacの場合が多いと思うのですが、nsの場合もあるかもしれません。自分のEmacsで調べるにはESC-:eval-expression)でwindow-systemを評価してください。

たとえば、次のようなMac OS XのEmacsアプリ(非ターミナル)だけで有効にしたい設定を~/.emacs.d/init-mac-gui.elファイルに記述したとします。

ここでは、環境変数およびexce-path、フレーム、フォントなどを設定しています。

;; Mac OS Xのpath_helperでPATHを取得し、あらためてPATHとして設定

(let ((shell-file-name "/bin/bash"))
(setenv "PATH"
(shell-command-to-string
"eval $(/usr/libexec/path_helper -s) && printf $PATH")))

;; Emacs変数exec-pathに、環境変数PATHの内容を設定
(setq exec-path nil)

(dolist
(dir (split-string (getenv "PATH") "[:\n]"))
(when (file-directory-p dir)
(add-to-list 'exec-path dir t)))

;; 標準のフォントサイズとフォントファミリーの設定
(set-face-attribute 'default nil
:height 120
:family "Menlo")

;; キャラクターセットごとにフォントファミリーを設定
(dolist
(list
'(
(jisx0201 "Osaka")
(japanese-jisx0213.2004-1 "Hiragino Kaku Gothic ProN")
(japanese-jisx0213-2 "Hiragino Kaku Gothic ProN")
))
(let ((charset (car list))
(fontfamily (nth 1 list)))
(cond
((not (member charset charset-list))
(message "Character set %s is not found." charset))
((not (member fontfamily (font-family-list)))
(message "Font family %s is not found." fontfamily))
((set-fontset-font t charset (font-spec :family fontfamily))))))

;; フレームの設定
(dolist
(val
'(
(foreground-color . "black")
(background-color . "gray99")
(cursor-color . "DarkOliveGreen")
(cursor-type . box)
))
(add-to-list 'default-frame-alist val))

;; commandキーをEmacsのMetaキーに
(setq mac-command-modifier 'meta)

;; ミニバッファにカーソルを移動する際、自動的にキーボードをASCIIモードにする
(mac-auto-ascii-mode 1)

;; Mac OS Xのキー設定
(dolist
(map
'(
("<M-f1>" other-frame) ; Mac OS Xの他アプリと同様に、command + F1でアプリケーションの次のウィンドウを操作対象にする
))
(let ((key (car map)) (func (nth 1 map)))
(if (not (functionp func)) (message "%s is not defined." func)
(global-set-key (kbd key) func))))

(cd "~")

この設定は、init.elに次の記述をすることで呼び出すことができます。

(when (equal system-type 'darwin)

(load-file "~/.emacs.d/init-mac-gui.el"))

system-typewindow-systemの違いは、コンソール(端末)上でEmacsを使う場合にあらわれます。

たとえばMac OS Xでsystem-typeは、コンソール上のEmacsでもEmacsアプリでもdarwinです。一方window-systemは、コンソール上のEmacsではnil、Emacsアプリではmac(またはns)です。

環境変数およびexce-path、フレーム、フォントなどの設定はコンソール上のEmacsでは不要なため、上記のinit-mac-gui.elではwindow-systemを使って設定を分岐させています。

コンソール上でEmacsを使わない人は、window-systemsystem-typeのどちらか一方を使えば十分かもしれません。


system-name変数

system-name変数を使うと、コンピューターのホスト名を取得できるため、コンピューターごとに設定を切り替えられます。

ただし、素のsystem-nameでは、DNSドメイン名の付いたFQDNしか取得できません。

そこで、ドメイン名を除いたシンプルなホスト名を格納する変数system-name-simpleを定義しました。

(defvar system-name-simple

(replace-regexp-in-string "\\..*\\'" "" (system-name))
"The simple host name of the machine Emacs is running on, which is without domain information.")

たとえば、ホスト名がtigerのコンピューターだけで有効にしたい設定を次の~/.emacs.d/init-tiger.elファイルに記述したとします。

;; フレームの設定

(when (equal window-system 'mac)
(dolist
(val
'(
(width . 180)
(height . 55)
(top . 22)
(left . 0)
))
(add-to-list 'default-frame-alist val)))

ここでは、Emacsアプリの場合にフレームの大きさを設定するようにしています。画面の大きさが異なるMacコンピューターを複数台つかっている場合は、コンピューターごとにフレームの大きさを設定したくなると思います。

この設定は、system-name-simpleを定義してから次の記述をすることで呼び出すことができます。

(when (equal system-name-simple "tiger")

(load-file "~/.emacs.d/init-tiger.el"))


さいごに

system-typewindow-systemsystem-nameなどの変数を使いこなせば、環境ごとにEmacsの設定を分岐させられます。init.elに記述する設定を、共通部分と特定のシステムやコンピューター向けの部分と分けられるので、保守性や利便性が上がります。

init.elの記述を分けるという点では、Advent Calender2日目のinit.elから設定を追い出してパッケージ化しようで記載された「私のinit.el長すぎ!!」問題対策と相通ずる部分もあるかとおもいます。

なお、環境ごとに設定を変えるためのEmacsパッケージとして、init-loaderがあるようです。私自身は、syste-typeなどを使う方がシンプルでわかりやすいと思うので、使っていません。

それでは、素敵な年末とEmacsライフを。