起動速度のこと
init.elの初期化処理で時間がかかる事は起動後にやるようにした。 参考文書は定番とも言える下記2点。
(defvar my/delayed-configs nil)
(defvar my/delayed-config-timer nil)
(eval-and-compile
(defconst my/prio-low 1)
(defconst my/prio-normal 10)
(defconst my/prio-urgent 100))
(defun my/add-to-delayed-configs (priority config)
"Add CONFIG with PRIORITY to delayed configs."
(push (cons priority config) my/delayed-configs)
;; sort the configs by priority
(setq my/delayed-configs (sort my/delayed-configs (lambda (a b) (> (car a) (car b))))))
(defun my/start-delayed-configs ()
"Execute `my/delayed-configs` list using a timer.
Start a timer to run each config in the list with a default interval of 10ms.
The timer runs until all configs are executed, then it stops.
Customize interval with `my/delayed-config-interval`.
Delayed configs can impact your Emacs environment."
(setq my/delayed-config-timer
(run-with-timer 0.0 0.01 ; start after 0ms with 10ms interval
(lambda ()
(let ((inhibit-message t))
;; if there is a config, execute it
(if-let (config (cdr (pop my/delayed-configs)))
(eval config)
;; if there is no config, cancel the timer
(cancel-timer my/delayed-config-timer)))))))
(add-hook 'after-init-hook 'my/start-delayed-configs)
こんなのを書いて、
(leaf igist
:ensure t
:init
(with-delayed-startup-exec my/prio-low
(leaf-key "C-c o g" 'igist-dispatch)
(setopt igist-current-user-name "nekomimist")
(setopt igist-auth-marker 'igist)))
こんなふうに使っている。leafの:customと:bindも遅延起動できるといいのだが、そういう記法はないので、 with-delayed-startup-execの中でsetoptとleaf-keyを直接使うようにしている。
あとはpackage.elの初期化まわりの処理を見直した。最近のEmacs1はpackage-enable-at-startupがtである限り、(package-initialize)は不要なので、leaf.elの初期化ブロックをそのように変更した。
(unless package-enable-at-startup
(package-initialize))
(package-initialize)はとても遅い処理なのでこれでけっこう早くなる。
Packageの追加/廃止
今年もいろいろ入れかえた。
- el-get -> package-vc
- 今までELPA/NonGNU ELPA/MELPAにないパッケージはel-getを使っていたが、 Emacs 29以上ではpackage-vcでgithubから持ってくれるので、Emacs29以降では el-getを全廃した。
- shackle -> popper
- なんかうまく動いていないのに気付いたので変更。
- project-x
- 標準のproject.elを補うパッケージ。 project-rootの.projectに状態を保存してくれたりする。
- nameframe & nameframe-project
- projectを開くとproject名のframeを開くようになる。 前述のproject-xと組み合わせるとどうかな?ということでトライ中。
- sequential-command -> mosey
- sequential-commandってメンテされてないよねってことでなんとなく。
- treesit-auto
- Emacs29で入ったtreesitter integrationを補うパッケージ。 tree-sitter対応のmajor-modeが使えるならtree-sitterモジュールも入れてくれる等。
- multiple-cursors -> macrursors
- macurosorsはmeowのBEACONモードみたいな挙動でマルチカーソル編集ができる。 multiple-cursorsがcursorを増やすととんでもなく重くなるけど、macrursorsは軽い。
- deft -> xeft
- Xapianでメモを検索できて軽い。 dynamic-moduleはwindowsでも動くんだけど、日本語ファイル名食えない(なぜならUTF-8固定だと思っているから)windows環境はdeftのまま。まあ、windowsが悪いよ。 作者がemacs-develでよく見るYuan Fuなので、メンテの継続性も期待できるんじゃないかなと。
- zetteldeft -> denote
- 前述の通りdeftを止めたので、deftに頼らずnote takingできるdenoteに。 作者がmodus-theme等のProtesilaos Stavrouなので、メンテの継続性も期待できるかなと。
- tabspaces
- Emacsのtab-barの拡張。ただ、あまり活用できてない。
- consult-dir
- ミニバッファで作業中でも開けるconsultベースのdir名入力ツール。わりと便利かも? popperやgptelの作者karthinkなのでメンテの継続性も期待できるかな、と。
- all-the-icons→kind-icon→nerd-icons
- GUIだけならSVGで描画するkind-iconのほうがフォント依存がなくてよい点もあるのだが、EmacsでもWindows Terminalでもnerdフォントが入ったフォント(HackGen_NF)を使っているのでnerd-iconsに移行した。おかげでemacs -nwでもiconが出せる。
- igist
- gistのファイルを一覧で表示したり編集したりできる。便利。
- ibuffers - >bufler
- 標準のibuffersより便利かなと思って入れてみた。 プロジェクト単位で自動グルーピングできるのが便利。
- dired-sidebar -> treemacs
- treemacsで好みの挙動を得ようとしていろいろhookやらを仕込んでいるのがイヤになってdired-sidebarに移行してたんだけど、やっぱり別の方向でいろいろやる羽目になって、だったらtreemacsのほうがよかったやんということに……。
- gptel
- ChatGPTを使えるシンプルなパッケージ……だったけど、最近いろんなものがバックエンドに使えるようになった。個人的にはChatGPTしか使ってないのだが、その範囲ではシンプルで使いやすい。 あと、gptel-requestを使ってカスタム問い合わせ関数を作るのも簡単にできて、非常によい。こんなのを書いて、任意の選択範囲あるは行を、任意のdirectiveで一撃で問い合わせできるようにしている。
(defun my/gptel-query-send (bounds directive)
"Send a query to ChatGPT.
Convert BOUNDS into plain text and add DIRECTIVE before sending it to ChatGPT.
If executed interactively, BOUNDS can be either a region/line and DIRECTIVE
prompts the user for input."
(interactive
(list
(cond
((use-region-p) (cons (region-beginning) (region-end)))
(t (cons (line-beginning-position) (line-end-position))))
(completing-read "ChatGPT Directive: " my/gptel-query-send-directive-history
nil nil nil 'my/gptel-query-send-directive-history)))
(when (string= directive "") (user-error "A directive is required"))
(gptel-request
(buffer-substring-no-properties (car bounds) (cdr bounds)) ; the prompt
:system directive))
- gpt-commit
- gitのdiffを送ってcommit-messageを作ってくれる。便利かどうかはわりと悩ましいかもしれない。
- immortal-scratch
- scratch-bufferを殺しても復活する。定番だとは思うのが、何故か入れてなかった。
- auto-dim-other-buffers
- カーソルのないウィンドウの背景色を変えてくれる。 着目しているウィンドウがどこかがわかりやすくなる。
- pulsar
- カーソルがぽんと飛ぶ操作の後にカーソル行がパルスのように光る。 カーソル位置を見失いづらくなる。
- zoom
- カーソルがいるウィンドウの表示領域が「いい感じ」に拡大される。 わりとよい感じに使えている。
- dogears
- カーソルがいた場所の履歴を辿れる。標準だと俺の使い方にあまり合わないので、いろんな関数でdogears-rememberを呼ぶようにhookに仕込んだちadviceしまくっている。 trail.elの思想のほうが好きな気もするので、悩み中。
- jit-spell
- flyspellだとカーソルがあるあたりにだけしかチェックしないのだけど、こいつはバックグラウンドでispellを起動して全バッファチェックできる。libenchantを使うjinxのほうが軽いのだが、日本語に対する挙動の制御の仕方がよくわからかなったので、jit-spellを使っている。
- zoxide.el
- シェルでzoxideを使っているので一応入れたが、あまり使っていない。
- meow → ×
- Emacsのmodal editingパッケージ。標準のEmacsキーバインドをあまり阻害しないように作られているせいか、無意識にInsertモードに入ってmeowの機能を使わずに編集していることに気付いたので止めた。 ただ、BEACONモードは面白いと思った。
- tree-sitter → × (emacs29以降)
- Emacs29でtree-sitter integrationが入ったので、とりあえず外した。 Emacs28以前では使うようにしてあるけれど、そもそもEmacs28以前はあまり使わない。
- zygospore → ×
- C-x 1で閉じたwindowを再度同じ操作で開けるようにするものなのだが、なんかうまく動かなくなっていたので消した。
1
Emacs27あたりだったはず。
2022年最後の段階で、emacs -nwでのemacs-init-timeが270ms程度。
そんなわけで自宅PCでのemacs-init-timeは0.27秒になった。これ以上はpackage.elを捨てないと難しそうかな
— いずみたすく (@nekomimist) December 29, 2022
2023年末現在は、このpostの頃とあまり変わらず85ms程度。
5900Xから7950X3Dに変えたらemacs -nwのemacs-init-timeは85msくらいになった。15%くらい早くなったかな?
— いずみたすく (@nekomimist) October 14, 2023
WSL2上での速度なので、たとえばnative linuxでやればさらに早くなるだろう。