2024-06-30 Sun. 10:09:59 JST
Emacs
by kiyozzy
Emacs の imenu-list はプロセスで1つしか使用できない。本設定はフレーム毎に使用できるようにする。
グローバル変数を frame parameter として扱うことで実現する。
Emacsの設定ファイルなどに記載する。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; imenu-listをframe毎に使用できるようにする
;; imenu-listはプロセスで1つしか使用できない。本設定はframe毎に使用できるようにする。
;; グローバル変数を frame parameter として扱うことで実現する。
;; 2024-06-30 Sun. 10:07:20 JST : 初版作成
(when (require 'imenu-list nil t)
;; frame 作成時にグローバル変数に対応する frame parameter を用意する
(defun my-imenu-list-hook-after-make-frame-functions (frame)
(modify-frame-parameters frame (list (cons 'fimenu-list-buffer-name (format "*Ilist-%s*" (frame-parameter frame 'window-id)))))
(modify-frame-parameters frame (list (cons 'fimenu-list--imenu-entries nil)))
(modify-frame-parameters frame (list (cons 'fimenu-list--line-entries nil)))
(modify-frame-parameters frame (list (cons 'fimenu-list--displayed-buffer nil)))
(modify-frame-parameters frame (list (cons 'fimenu-list--last-location nil)))
)
(add-hook 'after-make-frame-functions 'my-imenu-list-hook-after-make-frame-functions)
;; "imenu-list"から始まる関数の around advice
(defun my-imenu-list-around-advice (orig-fun &rest args)
"My around advice for functions starting with `imenu-list`."
(if (or (boundp 'my-imenu-list-variable-using) (not (display-graphic-p)))
;; 既に frame parameter からローカル変数化しているならば元の関数を呼び出すのみ。
;; CUIの時も元の関数を呼び出すのみ(グローバル変数を使う)。
(apply orig-fun args)
;; まだローカル変数化していないならば frame parameter からローカル変数化する
(let* ((imenu-list-buffer-name (frame-parameter nil 'fimenu-list-buffer-name))
(imenu-list--imenu-entries (frame-parameter nil 'fimenu-list--imenu-entries))
(imenu-list--line-entries (frame-parameter nil 'fimenu-list--line-entries))
(imenu-list--displayed-buffer (frame-parameter nil 'fimenu-list--displayed-buffer))
(imenu-list--last-location (frame-parameter nil 'fimenu-list--last-location))
(my-imenu-list-variable-using t) ;; ローカル変数化済フラグ
(split-height-threshold nil) ;; windowは常に水平分割
(split-width-threshold 0) ;; windowは常に水平分割
(result (apply orig-fun args))) ;; 元の関数を呼び出す
;; ローカル変数化した内容を frame parameter に保存する
;; imenu-list-buffer-name は元々 defconst で変更されないので更新不要
(modify-frame-parameters nil (list (cons 'fimenu-list--imenu-entries imenu-list--imenu-entries)))
(modify-frame-parameters nil (list (cons 'fimenu-list--line-entries imenu-list--line-entries)))
(modify-frame-parameters nil (list (cons 'fimenu-list--displayed-buffer imenu-list--displayed-buffer)))
(modify-frame-parameters nil (list (cons 'fimenu-list--last-location imenu-list--last-location)))
;; 元の関数の結果を返す
result)))
;; "imenu-list"から始まる関数に advice-add する
(mapatoms
(lambda (sym)
(when (and (symbolp sym)
(fboundp sym)
(string-prefix-p "imenu-list" (symbol-name sym)))
(advice-add sym :around #'my-imenu-list-around-advice))))
;; imenu-list バッファの mode-line フォーマット
(setq imenu-list-mode-line-format
'("%e" mode-line-front-space mode-line-mule-info mode-line-client
mode-line-modified mode-line-remote mode-line-frame-identification
(:propertize "%b" face mode-line-buffer-id) " "
(:eval (buffer-name
;; frame parameter から表示バッファ名を取得する。
;; CUIの時はグローバル変数を使う。
(if (display-graphic-p)
(frame-parameter nil 'fimenu-list--displayed-buffer)
imenu-list--displayed-buffer)
)) " "
mode-line-end-spaces))
)