私自身のEmacsの使い方

AIの活用

今年はEmacsの設定やらなんやらにやたらとAIを活用するようになったという点で変革の年だった。 気軽に質問できて、まあまあ正しい回答が返ってくるのは実によい。 実装の案出しだったりリファクタだったりをだいぶGPT-4oやclaude-3.5-sonnetに助けてもらった。

EmacsのAI系パッケージも充実してきた。gptelは当初はopenaiのAPIを使えるだけのシンプルなパッケージだったのに、いろんなLLM backendに対応したり、gptel-rewriteが実装されたりして、リファクタやらなんやらやりやすくなった。elysiumもregionに対する指示をチャットバッファでできて、変更はsmergeで表示できたりできてよい。まだ使いこなせていないがevedelにも期待したい。

magit-gptcommitもまあまあ便利に使っている。前はgpt-commitだったけど、毎回生成したいわけじゃないし、明示的に呼べるmagit-gptcommitはそこそこ具合がよい。

その他使うようになったパッケージ(と、使うのを止めたパッケージ)

perspective

去年からプロジェクト毎に作業環境を分けるためにtabを活用できないか?と思って、 しばらくtabspacesやらactivitesやら試行してきたけれど、結局tab-barの表示を消して、tabspacesやactivitiesを使うのを止めて、perspective.elで作業空間を明示的に分けるようにした。やはり昔からあって今もメンテされているパッケージは強いなと思った次第。

perspectiveの状態をファイルに保存するpersp-state-save/loadも使うけれど、起動時にpersp-state-loadをすると遅いので、最初にユーザー操作でpersp-switchしようとした時に読み込むようにした。あとpersp-state-loadしてないのにsaveされるとイマイチなので、loadしてた後だけemacs終了時にsaveするようにしている。

  (defvar my/perspctive-state-already-loaded nil)
  (defvar my/persp-switch-commands '(persp-switch persp-switch-by-number))

  (defun my/perspective-state-load (&rest _options)
    (when (memq this-command my/persp-switch-commands)
      (unless my/perspctive-state-already-loaded
        (setq my/perspctive-state-already-loaded t)
        (persp-state-load persp-state-default-file))))
  (defun my/perspective-state-save-if-loaded (&rest _options)
    (when my/perspctive-state-already-loaded
      (persp-kill persp-initial-frame-name) ; depotは毎回きれいにして終わる
      (persp-state-save)))

  (dolist (cmd my/persp-switch-commands)
    (advice-add cmd :before #'my/perspective-state-load))
  (add-hook 'persp-state-after-load-hook
  	  (lambda () (setq my/perspctive-state-already-loaded t)))
  (add-hook 'kill-emacs-hook #'my/perspective-state-save-if-loaded)

treemacs

tab-barの表示自体を止めるより前に、sidebarとしてtreemacsを常時表示するのを止めた。

プロジェクト内のファイルを開くならproject-find-fileを使うし、gitの状態はmagit-statusで確認するので、ファイルツリーなんか見ないのである。表示してると遅くなるし幅も食うし、見た目だけならないほうがよいやんということでデフォルトでは表示しないようにした。

tab-barも消してtreemacsも消した今、Emacsの表示はえらいすっきりとした。古くさい見た目かもしれないがそれでいい。俺は風になりたいんだ。

olivetti

sidebar表示は止めたのだが、横が広すぎるのも好みじゃないので、今、Emacsの表示幅は130文字くらいにしている。 l横80文字程度だとソース編集するのにあからさまに狭く感じるからね……。

しかし、org-modeで文章を書くときなんかは130文字だと幅が広すぎて書きづらいで見辛い。そこでolivettiを使うようにした。幅をいい感じに制限してくれてよい。

empx

カーソルがあった所に戻ったりまた進んだりするのに長いことdogearsを使っていた。 ただ、案外必要なタイミングで保存されてなかったりしたために、いろいろhookやadviceで仕込みを入れる必要があって面倒だったり、キーバインドが専用になるのがどうもすっきりしなかったので、Redditで見かけたempxにしてみた。

作者がredditで紹介している通り、「専用の*-back/*-forward関数じゃなくてemacsで標準で持っているxref-go-back/xref-go-forwardを使いたい!」という目的のパッケージで、xref-find-definitionで定義元に飛んだ後に戻る操作と同じで前カーソルがあった所にも戻れるので、覚える操作が減ってすっきりする。

xrefの履歴にカーソル履歴が入るのはどうかな?と思ったが今のところ特に問題は感じない。前述のperspective.elが、xrefの履歴をperspective毎に分けるようにしているので、意図せず他のperspectiveに移動したりしないのもわかりやすい。

avy / ace-window

これは前ブログに書いた通りAvyならなんでもできるを読んだので使うようにした。ace-windowによるwindow移動は慣れたけど、avyは単純な用途以外にはあまり活用できてない。活用が来年の課題かな。

embark

これは一応以前から設定はしていたが活用できていなかった。Embarkを使う15の方法を見て、少しは使えるようになったかもしれないが、より一層の活用は来年の課題かな。

Emacsの展望

emacs-30.1はそろそろ出る。わりと地味なリリースだが、native-compileがデフォルト有効になったり、tree-sitter関連の組み込みが進んだり、jsonが独自パーサに変わって高速化したり、いろいろ着実な進歩はあるはずだ。

ということは次に気になるのはemacs-31だ。

  • scratch/igc。Memory Pool System(MPS)を使って、concurrentでincrementalでgenerationalなGCをemacsにもたらすもの。GC時間の最悪値をかなり改善するはず。emacs-31に間に合えばいいな。
  • TTY child frame。名前の通りchildframeをtty上でも実現するもので、posframeなんかがttyでも使えるようになるはず。これはmasterに入ったのでemacs-31に入るはず。

scratch/igcがいつ本線にマージされるかは気になるところ。

2024年のおわりに

Github copilot of VScodeが無料で使えるようなったり、CursorのようなAI poweredなエディタが目立つようになってきたけれど、EmacsもなんだかけっこうAI関係のパッケージは充実してきているし、負けずについていけたらいいなあと思っている。