init .el 【init.el】
10年前のEmacs設定を現代仕様に更新した

久しぶりにEmacsの設定ファイルを開いたら、動作はしているものの、プラグインの多くは開発が停滞していたり、より良い後継が登場していたりすることがわかりました。

2013年から2017年頃に書いた設定が多いので、現代のEmacs環境に合わせて設定を一新することにしました。

関連記事

1. 古い設定の解析から始める

まず、既存のinit.elを読んで、どのような機能を使っていたのかを確認しました。設定ファイルには各機能を追加した日付がコメントで記録されており、2013年から2017年にかけて少しずつ機能が追加されていった様子が見て取れました。

現代の選択肢(2025年) 古い構成 新しい構成 状態 auto-complete 補完 company-mode 活発に開発中 停滞 GNU Global タグジャンプ eglot (LSP) Emacs 29標準 →LSP主流 linum 行番号表示 display-line -numbers-mode 標準機能化 wombat カラーテーマ kanagawa 和風配色 好み次第

1.1. Backspaceのキーバインド

最初に目についたのは、キーバインドの変更です。

(global-set-key "\C-h" 'delete-backward-char)
(global-set-key "\C-ch" 'help)
Code language: PHP (php)

C-hキーは通常Emacsではヘルプを表示するキーですが、これをBackspaceとして使えるように変更していました。ヘルプ機能は別のキー(C-c h)に移動しています。これは多くのエディタでC-hがBackspaceとして機能することに慣れているユーザーにとっては自然な変更です。

1.2. 不要なバックアップを自動保存しない

また、バックアップファイル(ファイル名の末尾に~が付くもの)と自動保存ファイル(#で囲まれたファイル名)を作らない設定もされていました。

(setq make-backup-files nil)
(setq auto-save-default nil)
Code language: JavaScript (javascript)

これらのファイルはバージョン管理システムを使っている場合は不要になることが多く、ディレクトリが散らかるのを防ぐための設定です。

1.3. 日付を挿入するキーバインド

他にも、日付を挿入する独自関数を定義していました。

(defun insert-current-time()
  (interactive)
  (insert (format-time-string "%Y-%m-%d" (current-time))))

(global-set-key "\C-c\C-j" 'insert-current-time)
Code language: PHP (php)

C-c C-jを押すと、現在の日付が「2025-01-28」という形式で挿入されます。メモやログを取る際に便利な機能です。

1.4. コード補完の仕組み(auto-complete)

設定の中核をなしていたのがauto-completeというプラグインでした。

(require 'auto-complete-config)
(add-to-list 'ac-dictionary-directories "~/.emacs.d/ac-dict")
(ac-config-default)
Code language: PHP (php)

これはコードを書いているときに自動的に候補を表示してくれる機能です。たとえば、関数名の一部を入力すると、残りの文字を補完してくれます。プログラミングの効率を大きく向上させる重要な機能といえます。

1.5. GNU Globalによるコードナビゲーション(gtags)

大規模なプログラムを扱う際に欠かせないのが、関数の定義場所にジャンプする機能です。設定ファイルにはgtags(GNU Global)の設定がありました。

(autoload 'gtags-mode "gtags" "" t)
(setq gtags-mode-hook
      '(lambda ()
         (local-set-key "\M-t" 'gtags-find-tag)
         (local-set-key "\M-r" 'gtags-find-rtag)
         (local-set-key "\M-s" 'gtags-find-symbol)
         (local-set-key "\C-t" 'gtags-pop-stack)))
Code language: PHP (php)

M-tを押すと、カーソル位置の関数の定義に飛べます。M-rでその関数を呼び出している場所を検索できます。大きなコードベースを読むときには必須の機能です。

1.6. 行番号表示とバックアップの無効化(linum)

(require 'linum)
(setq linum-format "%4d ")
(global-linum-mode t)
Code language: PHP (php)

linumというプラグインで行番号を表示していました。

1.7. プログラミング言語用のモード

設定ファイルには複数の言語モードが含まれていました。

  • Common Lisp: clispを評価エンジンとして設定
  • Haxe: ゲーム開発言語のサポート
  • PowerShell: Windowsスクリプト言語
  • Visual Basic: VBScriptや.basファイルの編集

ただし、これらの言語は現在使っていないため、今回の更新では削除することにしました。

1.8. 外観のカスタマイズ

カラーテーマはwombatという暗めのテーマを使用していました。

(load-theme 'wombat t)

フォントはRicty Diminishedというプログラミング向けフォントで、日本語表示にも対応したものでした1。フォントサイズは120(12ポイント相当)に設定されていました。

2. 現代のEmacs環境を調査する

古い設定を理解したところで、次に各プラグインの現状を調べました。
多くのプラグインには後継が登場していたり、Emacs本体に標準機能として取り込まれていたりすることがわかりました。

2.1. company-mode(auto-completeの後継)

auto-completeは開発が停滞しており、現在はcompany-modeが主流になっています2。company-modeは「complete anything」の略で、より柔軟な設計になっています。

重要なのは、company-modeがEmacsの標準的な補完システム(completion-at-point)と統合されている点です。これにより、さまざまなプログラミング言語で一貫した補完体験が得られます。

2.2. LSPへの移行(GNU Globalの代替)

GNU Globalは現在も開発されています3
しかし、より現代的な選択肢としては LSP(Language Server Protocol)があります4
LSPはMicrosoftが提唱した仕組みで、エディタと言語解析ツールを分離することで、一つの言語サーバーを複数のエディタで使い回せるようにしたものです。

Emacsには2つの主要なLSPクライアントがあります。

  • lsp-mode: 多機能だが設定が複雑
  • eglot: Emacs 29から標準搭載5、シンプルで軽量

今回は軽量さを重視してeglotを選びました。
設定もほとんど不要で、プログラミング言語のモードを有効にするだけで自動的に動作します。

2.3. linumの置き換え:標準機能への統合

行番号表示のlinumは、Emacs 26以降ではdisplay-line-numbers-modeという標準機能に置き換えられました6

(global-display-line-numbers-mode 1)
Code language: PHP (php)

この標準機能の方が高速で、大きなファイルでもパフォーマンスが低下しません。
linumは外部プラグインとして別途読み込む必要がありましたが、新しい機能は最初から組み込まれています。

2.4. markdown-modeは現役

唯一、そのまま継続使用できるプラグインがmarkdown-modeでした。
調べてみると、2025年2月にバージョン2.7がリリースされるなど、今でも活発に開発が続いています7。Markdown記法の編集に特化した機能が充実しており、これは引き続き使用します。

2.5. カラーテーマの選択:kanagawa

カラーテーマは好みの問題ですが、今回はkanagawa-themesを選びました。
これは葛飾北斎の「神奈川沖浪裏」からインスピレーションを得た和風の配色テーマです8

kanagawa-themesには3つのバリエーションがあります。

  • kanagawa-wave: オリジナル版
  • kanagawa-dragon: より暗い配色
  • kanagawa-lotus: 明るい配色

調査中に一つハマったポイントがありました。
最初は単に'kanagawaというテーマ名で読み込もうとしてエラーが出ました。
正しくは'kanagawa-waveのようにバリエーション名まで指定する必要があったのです。

3. 新しい設定ファイルの作成

ここまでの調査をもとに、新しい設定ファイルを作成しました。

新しい設定ファイルの構成 ① パッケージ管理 MELPA + use-package ② 基本設定 キーバインド・UTF-8 ③ プラグイン導入 • company-mode • eglot • markdown-mode use-packageの利点 ✓ 設定が構造化 ✓ 自動インストール :ensure t ✓ 遅延読み込み :hook :defer ✓ 可搬性向上

3.1. パッケージ管理の基礎設定(MELPAリポジトリ)

まず、パッケージをインストールできるようにMELPAリポジトリを追加します。

(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
Code language: PHP (php)

MELPAは、Emacs用のパッケージが集まっている場所です9
ここを追加することで、何千ものプラグインを簡単にインストールできるようになります。

次にuse-packageをインストールします。
これはパッケージの設定を整理して書くための便利なツールです。

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))
Code language: PHP (php)

3.2. 基本設定の移行

キーバインドやバックアップ無効化など、古い設定から引き継ぐ部分はそのまま残しました。
これらは時代が変わっても有用な設定だからです。

(setq make-backup-files nil)
(setq auto-save-default nil)
(set-default-coding-systems 'utf-8)
(prefer-coding-system 'utf-8)
(show-paren-mode t)

(global-set-key (kbd "C-h") 'delete-backward-char)
(global-set-key (kbd "C-c h") 'help)
(global-set-key (kbd "M-1") 'shell-command)

(defun insert-current-time()
  (interactive)
  (insert (format-time-string "%Y-%m-%d" (current-time))))
(global-set-key (kbd "C-c C-j") 'insert-current-time)
Code language: PHP (php)

3.3. 行番号表示の更新

linumdisplay-line-numbers-modeに置き換えました。

(global-display-line-numbers-mode 1)
Code language: PHP (php)

たった1行ですが、これで以前と同じ機能が実現できます。
さらに、相対行番号表示にすることも可能です。

(setq display-line-numbers-type 'relative)

これを設定すると、現在の行からの距離が表示されるようになります。
上下に何行移動すればよいかが一目でわかるため、Vimユーザーには馴染みのある表示方法です。

3.4. フォント設定の継続

Ricty Diminishedフォントは引き続き使用します。
プログラミング向けに設計されたフォントで、0(ゼロ)とO(オー)、1(いち)とl(エル)が明確に区別できるなど、コードの可読性が高いからです。

(when (display-graphic-p)
  (set-face-attribute 'default nil
                      :family "Ricty Diminished"
                      :height 120)
  (set-fontset-font t 'japanese-jisx0208 
                    (font-spec :family "Ricty Diminished")))
Code language: JavaScript (javascript)

3.5. カラーテーマの適用

kanagawa-themesを導入します。
use-packageを使うと、設定が簡潔になります。

(use-package kanagawa-themes
  :ensure t
  :config
  (load-theme 'kanagawa-dragon t))
Code language: PHP (php)

:ensure tは「インストールされていなければ自動的にインストールする」という意味です。
これにより、新しい環境でこの設定ファイルを使う際も、自動的に必要なパッケージがインストールされます。

3.6. company-modeの設定

コード補完をcompany-modeに切り替えます。

(use-package company
  :ensure t
  :config
  (global-company-mode)
  (setq company-idle-delay 0.2)
  (setq company-minimum-prefix-length 2)
  :bind
  (:map company-active-map
        ("C-n" . company-select-next)
        ("C-p" . company-select-previous)))
Code language: CSS (css)

company-idle-delayは、文字を入力してから補完候補が表示されるまでの待ち時間です。
0.2秒に設定しました。
company-minimum-prefix-lengthは、何文字入力したら補完を開始するかの設定で、2文字としています。

キーバインドも設定しました。
C-nで次の候補、C-pで前の候補に移動できます。

3.7. eglotによるLSP対応

プログラミング言語のインテリジェントな補完や定義ジャンプを実現するため、eglotを導入します。

(use-package eglot
  :ensure t
  :hook ((c-mode . eglot-ensure)
         (c++-mode . eglot-ensure)
         (python-mode . eglot-ensure))
  :config
  (setq eldoc-echo-area-use-multiline-p nil))
Code language: CSS (css)

:hookの設定により、C言語、C++、Pythonのファイルを開いたときに自動的にeglotが起動します。
それぞれの言語に対応したLSPサーバー(clangd、pylsなど)が必要ですが、一度設定すれば関数定義へのジャンプや、より精度の高い補完が可能になります。

3.8. Markdown編集の継続

markdown-modeは変わらず使用します。

(use-package markdown-mode
  :ensure t
  :mode (("\\.md\\'" . markdown-mode)
         ("\\.markdown\\'" . markdown-mode))
  :config
  (setq markdown-command "markdown"))
Code language: JavaScript (javascript)

:modeの設定により、.md.markdownという拡張子のファイルを開くと自動的にmarkdown-modeが有効になります。

4. 完成した設定ファイル

最終的な設定ファイルは以下のようになりました。

;; パッケージ管理の初期化
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)

;; use-packageのインストール
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

;; 基本設定
(setq make-backup-files nil)
(setq auto-save-default nil)
(set-default-coding-systems 'utf-8)
(prefer-coding-system 'utf-8)
(show-paren-mode t)

;; キーバインド
(global-set-key (kbd "C-h") 'delete-backward-char)
(global-set-key (kbd "C-c h") 'help)
(global-set-key (kbd "M-1") 'shell-command)

;; 日付挿入
(defun insert-current-time()
  (interactive)
  (insert (format-time-string "%Y-%m-%d" (current-time))))
(global-set-key (kbd "C-c C-j") 'insert-current-time)

;; 行番号表示
(global-display-line-numbers-mode 1)

;; フォント設定
(when (display-graphic-p)
  (set-face-attribute 'default nil
                      :family "Ricty Diminished"
                      :height 120)
  (set-fontset-font t 'japanese-jisx0208 
                    (font-spec :family "Ricty Diminished")))

;; カラーテーマ
(use-package kanagawa-themes
  :ensure t
  :config
  (load-theme 'kanagawa-wave t))

;; コード補完
(use-package company
  :ensure t
  :config
  (global-company-mode)
  (setq company-idle-delay 0.2)
  (setq company-minimum-prefix-length 2)
  :bind
  (:map company-active-map
        ("C-n" . company-select-next)
        ("C-p" . company-select-previous)))

;; LSPクライアント
(use-package eglot
  :ensure t
  :hook ((c-mode . eglot-ensure)
         (c++-mode . eglot-ensure)
         (python-mode . eglot-ensure))
  :config
  (setq eldoc-echo-area-use-multiline-p nil))

;; Markdown編集
(use-package markdown-mode
  :ensure t
  :mode (("\\.md\\'" . markdown-mode)
         ("\\.markdown\\'" . markdown-mode))
  :config
  (setq markdown-command "markdown"))
Code language: PHP (php)

4.1. 移行で得られたもの

この更新により、いくつかの利点が得られました。

まず、メンテナンス性が向上しました。use-packageにより設定が構造化され、どのパッケージがどのような設定をしているのかが明確になりました。
新しい環境にこの設定ファイルを持っていけば、必要なパッケージが自動的にインストールされます。

そして、現代の開発スタイルに対応できるようになりました。
LSPにより、さまざまな言語で統一されたインテリジェントな補完が得られます。
言語ごとに個別のプラグインを探してインストールする必要がなくなりました。

5. 残された課題

一方で、いくつかの課題も残っています。

eglotを使うには各言語のLSPサーバーをインストールする必要があります。
たとえば、C/C++ではclangd、Pythonではpylsppyrightなどです。
これらは別途インストール手順が必要です。

10年前の設定を読み解き、現代の構成に更新する過程で、Emacsのエコシステムがどのように進化してきたのかを実感できました。

プラグインの開発が停滞しても、コミュニティは新しい解決策を生み出し続けています。
auto-completeからcompany-mode、GNU GlobalからLSP、linumから標準機能へ。
それぞれの移行には理由があり、より良いユーザー体験を目指した改善でした。

同時に、変わらない部分もあります。
キーバインドのカスタマイズやフォント設定など、個人の好みや作業スタイルに合わせた調整は、時代が変わっても重要です。

  1. Ricty Diminishedは、Rictyフォントから生成規則だけを取り出して、InconsolataとCircle M+ 1mを合成したプログラミング用フォントです。日本語と英語の文字幅バランスが最適化されています。 – プログラミング用フォント Ricty Diminished
  2. auto-completeの最終更新は2015年頃で、その後メンテナンスが停滞しています。一方、company-modeは現在も活発に開発が続いています。 – Switching from AC · company-mode/company-mode Wiki
  3. GNU Globalの最新版は6.6.13(2024年リリース)で、universal-ctagsとの統合もサポートしています。ただし、LSPの普及により利用は減少傾向にあります。 – GNU Global source code tagging system
  4. LSPはMicrosoftが2016年に発表したプロトコルで、エディタと言語解析機能を分離することで、複数のエディタで同じ言語サーバーを利用できるようにした仕組みです。 – Language Server Protocol
  5. eglotはEmacs 29.1(2023年7月リリース)から標準パッケージとして組み込まれました。 – Eglot: The Emacs Client for the Language Server Protocol
  6. display-line-numbers-modeはEmacs 26.1で導入され、linumよりも高速で大きなファイルでも性能低下が少ないという利点があります。 – Display Line Numbers Mode (GNU Emacs Manual)
  7. markdown-mode 2.7は2025年2月26日にリリースされました。このパッケージは2007年から開発が続いている長寿プロジェクトです。 – Markdown Mode for Emacs
  8. kanagawa-themesは元々Neovim用に開発されたテーマで、葛飾北斎の代表作「富嶽三十六景 神奈川沖浪裏」の色彩からインスピレーションを得ています。 – GitHub – Fabiokleis/kanagawa-emacs
  9. MELPA(Milkypostman’s Emacs Lisp Package Archive)は、5,000以上のEmacsパッケージをホストしているコミュニティ運営のリポジトリです。2012年に開始され、現在も活発に運営されています。 – MELPA – Milkypostman’s Emacs Lisp Package Archive