バブちゃんへ贈る Emacs の歩き方
December 13, 2021
この記事は Emacs Advent Calendar 2021 の14日目の記事です.
はじめに #
Emacs を始めたての頃はパッケージ導入の際の設定は理解しないままネットからコピペすることが多いと思う.この記事では,パッケージ導入から自分に適した設定までの一連の動作を一人で行えるようになることに重点を置く.
タイトルにあるバブちゃんとは,Emacs の基本的な操作に慣れ始めて,コピペを駆使すればパッケージ導入を行うことができるようになった人を指す.いわばハイハイができるようになった状態である.この記事では,そんなバブちゃんが Emacs 内での二足歩行を会得する際の助けになるような情報提供を目指す.
記事の前半では便利な tips やパッケージの紹介を行い,後半では前半に紹介した内容を活用してパッケージの設定を行った実例を紹介する.
想定読者 #
- 息をするように
C-b, C-f, C-n, C-p
などの移動ができる C-c, M-x
などの基本的な表記を理解している- 以下の記事で解説されている内容が5割くらい理解できていれば (たぶん) 大丈夫
この記事で扱わないこと #
- elisp 全般
- パッケージの導入方法
setq
やcustom-set-variables
等を用いた変数の設定方法
tips #
ここではパッケージ導入とその設定を行う際に知っておくと役に立つ built-in 機能を紹介する.
パッケージ検索 #
M-x list-packages
でインストール可能なパッケージ一覧を見ることができる.(package-archives
の設定が済んでいる前提)
このバッファ内で iserch
等の検索をかければ気になるパッケージに出会える可能性がある.パッケージをクリックまたは RET
すればパッケージの説明と,github上で管理されていればそのリンクを見ることができる.
パッケージの説明はパッケージファイルの冒頭に書かれている #
多くの場合,パッケージファイルの冒頭にパッケージの説明が書かれている.親切なパッケージでは推奨設定が記載されていることもある.
ユーザーオプションは defcustom
で定義されている
#
パッケージファイル内で grep すれば設定可能なオプションが見つかる.
以下の画像では consult-grep
で集めた情報を embark-export
で抽出している.このバッファで n/p
を押すとファイルをまたいでプレビューしてくれるため,複数ファイルで構成されているパッケージをカスタマイズしたい時に便利.
関数や変数の定義へ M-.
でジャンプ
#
xref-find-definitions
(M-.
) でポイント下にあるシンボルの定義へとジャンプすることができる.
ジャンプした後に迷子にならないために #
ジャンプ前にどこにいたのか覚えておくのは至難の技だと思う.少なくとも私はジャンプした瞬間に全てを忘れてしまう.
そんな鶏のような人のために, Emacs には以下2種類の便利な機能が用意されている.
C-u C-SPC
or(set-mark-command 4)
set-mark-command
自体は範囲選択でおなじみのC-SPC
だが,これに prefix キーC-u
を付けて実行するとジャンプ前のところに戻ってくれる.(ただし,移動は同じバッファ内に限る).ちなみに,prefixとしてC-u
を入力すると関数には 4 が渡される.Emacs には
mark-ring
というものがあり,そこにポイントの位置が保存されている.保存タイミングはC-SPC
や前述のM-.
が実行されたとき,他にも様々.C-u C-SPC
を実行するとmark-ring
を遡るようにしてポイントを移動してくれるという仕組み.
switch-to-prev-buffer
バッファの並び順で一つ前のバッファに移動するコマンド.定義ジャンプした際に別ファイルに飛ばされたら
C-u C-SPC
で帰ってくることはできない.そんなときはM-x switch-to-prev-buffer
を実行すれば元の場所に戻ることができる.実行しすぎて元いたバッファを通り過ぎた場合は
M-x switch-to-next-buffer
を実行すればバッファを進めることで帰って来ることができる.私は
C-x C-p, C-x C-p
にバインドして使っている.(global-set-key (kbd "C-x C-p") #'switch-to-prev-buffer) (global-set-key (kbd "C-x C-n") #'switch-to-next-buffer)
describe-*
を実行すればたいてい分かる
#
歩き回っていると未知のものに多々遭遇する.そんなときは M-x describe-*
を実行すれば Emacs さんが describe してくれる.
describe-variable
: 変数の中身確認ならこれdescribe-function
: 関数定義の確認ならこれdescribe-symbol
: alias や macro はこっちで見つかることがあるdescribe-key
: キーバインドに割り当てられたコマンドを調べたいときはこれ.describe-key
の実行後に調べたいキーバインドを入力すると describe してくれる.
そもそも elisp が良く分からん #
*scratch*
バッファ (lisp-interaction-mode
) で C-j
しよう.ポイントの直前のシンボルやS式を評価して,結果を下に表示してくれる.
Emacs の中を歩き回るときや新しい elisp を学ぶとき,理解できないものに多々直面する.そんなときに実行結果を確認しながら試行錯誤すれば理解の助けとなる.
lisp-interaction-mode
以外では C-j
による結果の確認はできない.代わりに C-x C-e
(eval-last-sexp
) を実行しよう.結果は *Message*
バッファに出力される.
エラー箇所を知りたい #
*Message*
バッファにエラーは出るけど,それがどのタイミングで発生しているか分からないことがある.そんなときは M-x toggle-debug-on-error
or (setq debug-on-error t)
を実行しよう.エラーが発生したときに,その詳細な箇所を教えてくれる.
便利な外部パッケージ #
ここでは歩き回る際に便利なパッケージを紹介する.
Helpful #
describe-*
実行時に表示される情報がリッチになる.ドキュメントに加え,定義や reference も表示される.
command-log-mode #
実行したキーバインドとコマンドを表示してくれる.キーボードを触っていて「今なにが起こった?!」となることは多々ある.そんなときは M-x command-log-mode
をオンにして M-x cml/toggle-command-log-buffer
を実行すれば,実行したキーバインドとコマンドが表示されるバッファが開く.
実例 #
ここでは前半に紹介した tips を活用して設定を行なった実例を2つ紹介する.
Example 1 #
パッケージ設定ではないが, s-[hjkl]
で window
の移動をしたくなって設定したことがあるので,それを紹介する.
まず describe-function
(helpful-function
) でいい感じの関数がないか調べる. move left
で調べるとそれっぽい関数が見つかった.
関連する windmove-right
なども見つかり,バインドして動作確認したら望むものだったので採用.
Example 2 #
最近,bib ファイルから TeX や org へと適切なフォーマットで参考文献を挿入するために citar というパッケージを導入した.
便利な反面,参考文献の挿入の際に少々面倒な点があったため,その点の改善の過程を紹介する.
このパッケージを用いて TeX で参考文献を挿入するには以下3ステップを踏む必要がある.
文献選択
挿入フォーマット (cite, citet, citep など) の選択
Prenoteの入力
上二つは必要だとしても,三つ目はいらない.そもそも Prenote ってなんだ.Enter を連打するのも面倒くさいので,なんとかしてこれを消したかった.
とりあえず関数定義へ #
現在手元にある情報は citar-insert-citation
を実行したらその最後に Prenote の入力画面が出るということ.
まずはこの関数が何をしているのか調べる. describe-function
(or helpful-function
) で citar-insert-citation
を検索してゴニョゴニョする.
なるほど,分からん.
grep
で Prenote という文字を探す
#
elisp 何も分からないマンなので,Prenote という文字で grep
して関係していそうなところを探していく.
まずはパッケージのある場所へ移動する.describe (or helpful) のバッファに親切にリンクが表示されているのでそれをクリックすれば飛べる.
バッファ内で prenote
で検索しても見つからなかった. find-file
をしてみると,このパッケージは複数ファイルで構成されていて prenote
は別ファイルのどこかで定義されていそうなことが分かる.
そんなときは grep
で串刺し検索.私は consult-grep
を使っている.
とりあえず上から見ていくとそれっぽいものが見つかった.大量の cite コマンドも見覚えがある.そう言えば cite コマンドが大量に出るのも邪魔に感じていた.これをいじればいい感じになりそうな気がする.
試行錯誤のために *scratch*
バッファへとコピペ.不要な部分を削って setq
で再定義してみる.
動作確認してみると期待通りに反映されていた.今回は運よく一発で期待通りになったが,普段は上記の工程を繰り返す.
おわりに #
本投稿ではパッケージ導入とその設定を行う際に活用可能な tips や外部パッケージの紹介を行った.この記事が Emacs という沼に沈んで行く際の重石になれば幸いである.
最後におすすめリンクをいくつか紹介してこの記事を締めたいと思う.
- 2020年代のEmacs入門
- 全人類必読の Emacs 入門記事
- Emacsの次世代ミニバッファ補完UI
- Emacs のミニバッファ補完 UI の紹介を行っている全人類必読の記事
- emacs-from-scratch
- Emacs を真っ新な状態から設定していく記事/動画