dired-details-rをいじったついでに、前々から気になっていた挙動を手元で二点修正した。
- ファイル操作でアイコンが崩れることがある
- リモート(tramp)越しに沢山のファイルがあるディレクトリを開こうとすると待たされる
(ちなみに、アイコンの幅が不揃いでズレている件はフォントファイルをFontForgeで加工して解決した)
修正点
ファイル操作でアイコンが崩れることがある
evaporate
オーバーレイは基本的にevaporateにした方が安全。diredはファイルを移動したり削除したりしたときに行を消すので、その時に自動的にオーバーレイも消えてくれる。
(defun all-the-icons-dired--add-overlay (pos string) "Add overlay to display STRING at POS." (let ((ov (make-overlay (1- pos) pos))) (overlay-put ov 'all-the-icons-dired-overlay t) - (overlay-put ov 'after-string string))) + (overlay-put ov 'after-string string) + (overlay-put ov 'evaporate t)))
after-readin-hookのみで更新
基本的にafter-readin-hookのタイミングで更新すれば十分なはず。……だけど、すでにdired-readinはadviceをかけてるな……。不十分だったらこれはキャンセル。
-(defun all-the-icons-dired--refresh-advice (fn &rest args) - "Advice function for FN with ARGS." - (prog1 (apply fn args) - (when all-the-icons-dired-mode - (all-the-icons-dired--refresh)))) - -(defvar all-the-icons-dired-advice-alist - '((dired-aux dired-create-directory all-the-icons-dired--refresh-advice) - (dired-aux dired-do-create-files all-the-icons-dired--refresh-advice) - (dired-aux dired-do-kill-lines all-the-icons-dired--refresh-advice) - (dired-aux dired-do-rename all-the-icons-dired--refresh-advice) - (dired-aux dired-insert-subdir all-the-icons-dired--refresh-advice) - (dired-aux dired-kill-subdir all-the-icons-dired--refresh-advice) - (dired wdired-abort-changes all-the-icons-dired--refresh-advice) - (dired dired-internal-do-deletions all-the-icons-dired--refresh-advice) - (dired-narrow dired-narrow--internal all-the-icons-dired--refresh-advice) - (dired-subtree dired-subtree-insert all-the-icons-dired--refresh-advice) - (dired-subtree dired-subtree-remove all-the-icons-dired--refresh-advice) - (dired dired-readin all-the-icons-dired--refresh-advice) - (dired dired-revert all-the-icons-dired--refresh-advice) - (find-dired find-dired-sentinel all-the-icons-dired--refresh-advice)) - "A list of file, adviced function, and advice function.") +(defun all-the-icons-dired--after-readin-hook () + (when all-the-icons-dired-mode + (if (> (line-number-at-pos (point-max)) 1000) + ;; If there are many files, it will be very slow, so disable icons. + (all-the-icons-dired--remove-all-overlays) + (all-the-icons-dired--refresh)))) (defun all-the-icons-dired--setup () "Setup `all-the-icons-dired'." (setq-local tab-width 1) - (pcase-dolist (`(,file ,sym ,fn) all-the-icons-dired-advice-alist) - (with-eval-after-load file - (advice-add sym :around fn))) - (all-the-icons-dired--refresh)) + (add-hook 'dired-after-readin-hook #'all-the-icons-dired--after-readin-hook nil t)) (defun all-the-icons-dired--teardown () "Functions used as advice when redisplaying buffer." (kill-local-variable 'tab-width) - (pcase-dolist (`(,file ,sym ,fn) all-the-icons-dired-advice-alist) - (with-eval-after-load file - (advice-remove sym fn))) + (remove-hook 'dired-after-readin-hook #'all-the-icons-dired--after-readin-hook t) (all-the-icons-dired--remove-all-overlays))
(2023-04-10追記: ファイル数が1000を超えたらアイコンを表示しないようにした。重いので)
現在ナローイングされている範囲だけ削除
上の修正をしたせいか(?)、iキーでサブディレクトリを追加したら追加したもの以外が消えてしまったので。いや、 all-the-icons-dired–remove-all-overlaysではwidenしているのに、all-the-icons-dired–refreshでwidenしていないからとも言えるかもしれない。
そもそもevaporateにしたから自動的に消えるので不要かもしれない(?)
(defun all-the-icons-dired--remove-all-overlays () "Remove all `all-the-icons-dired' overlays." (save-restriction (widen) (mapc #'delete-overlay (all-the-icons-dired--overlays-in (point-min) (point-max))))) +(defun all-the-icons-dired--remove-narrowed-overlays () + "Remove all `all-the-icons-dired' overlays." + (mapc #'delete-overlay + (all-the-icons-dired--overlays-in (point-min) (point-max)))) (defun all-the-icons-dired--refresh () "Display the icons of files in a dired buffer." - (all-the-icons-dired--remove-all-overlays) + (all-the-icons-dired--remove-narrowed-overlays)
リモート(tramp)越しに沢山のファイルがあるディレクトリを開こうとすると長時間待たされる
ファイル毎にファイル種別判別のための関数を呼んでいるのが原因。リモートの場合は避ける。
(defun all-the-icons-dired--refresh () "Display the icons of files in a dired buffer." (all-the-icons-dired--remove-narrowed-overlays) (save-excursion (goto-char (point-min)) (while (not (eobp)) (when (dired-move-to-filename nil) (let ((case-fold-search t)) - (when-let* ((file (dired-get-filename 'relative 'noerror)) + (when-let* ((file (dired-get-filename nil 'noerror)) ;;フルパスで取得 - (icon (if (file-directory-p file) - (all-the-icons-icon-for-dir file - :face 'all-the-icons-dired-dir-face - :v-adjust all-the-icons-dired-v-adjust) - (apply 'all-the-icons-icon-for-file file - (append - `(:v-adjust ,all-the-icons-dired-v-adjust) - (when all-the-icons-dired-monochrome - `(:face ,(face-at-point)))))))) + (icon + (if (save-excursion (forward-line 0) (looking-at-p dired-re-dir)) ;;file-directory-pはリモートアクセスを引き起こすので避ける + (if (file-remote-p file) + ;; all-the-icons-icon-for-dirの中でも file-*-p 関数を使っているので避ける + (all-the-icons-octicon "file-directory" :height 1.0 :v-adjust -0.1 + :face 'all-the-icons-dired-dir-face + :v-adjust all-the-icons-dired-v-adjust) + (all-the-icons-icon-for-dir file + :face 'all-the-icons-dired-dir-face + :v-adjust all-the-icons-dired-v-adjust)) + (apply 'all-the-icons-icon-for-file file + (append + `(:v-adjust ,all-the-icons-dired-v-adjust) + (when all-the-icons-dired-monochrome + `(:face ,(face-at-point)))))))) (if (member file '("." "..")) - (all-the-icons-dired--add-overlay (point) " \t") - (all-the-icons-dired--add-overlay (point) (concat icon "\t")))))) + (all-the-icons-dired--add-overlay (point) " ") ;;この辺は個人的な修正。タブを記号で表示しているので。どのみち位置は揃わないのでフォントの方を加工して揃えた。 + (all-the-icons-dired--add-overlay (point) (concat icon " ")))) (forward-line 1))))
[…] 今回の一番の目的はimage-dired対応です。ファイル名の前に存在するオーバーレイの幅を計算に入れてレイアウトします。all-the-icons-diredのオーバーレイも一緒に考慮しなければならなかったのでそうしました。all-the-icons-diredは独自に色々手を入れているのでオリジナルでは未確認です。image-diredもサムネイルの幅が揃うように手元では独自に手を入れています。動作が遅くなったり不安定になる可能性が若干あるので無効化する変数も用意してあります。サムネイルのサイズは非同期生成や画像の編集操作で変化するのでその際はレイアウトが崩れます。gを押してください。 […]