読者です 読者をやめる 読者になる 読者になる

by shigemk2

当面は技術的なことしか書かない

アドバイス after around など

Emacs Lisp
;; オリジナルの関数が呼び出された後に挙動を追加する
;; (defadvice 関数名 (クラス アドバイス名 activate
;;   アドバイス本体))
;; アドバイス名は単一ならば何でもよい
(defun g1 () (princ "g1"))
(defadvice g1 (after after-test activate)
  (princ "/after"))
(with-output-to-string (g1))		; => "g1/after"

(defun g2 () 1)
;; 間違った例
;; afterアドバイスは返り値を加工するだけで、オリジナルの
;; 返り値は保存される
(defadvice g2 (after ad-return-value-wrong activate)
  (+ ad-return-value 3))
(g2)					; => 4
;; 正しい例 (setqする必要がある)
(defadvice g2 (after ad-return-value-test activate)
  (setq ad-return-value (+ ad-return-value 3)))
(g2)					; => 4

;; オリジナルの関数を包み込むaroundアドバイス
;; (defvar switch-to-buffer-other-window-display-function nil)
;; (defadvice switch-to-buffer-other-window (around display-customize
;; 						 activate)
;;   (if switch-to-buffer-other-window-display-function
;;       ;; 設定されているときはその関数を引数そのままで呼ぶ
;;       (apply switch-to-buffer-other-window-display-function
;; 	     (ad-get-args 0))
;;     ;; 設定されていないときは普通に呼ぶ
;;     ad-do-it))
;; ;; 画面分割せずに切り替えられる
;; (let ((switch-to-buffer-other-window-display-function
;;        'switch-to-buffer))
;;   (switch-to-buffer-other-window "*scratch*"))

;; いろいろなアドバイスの挙動
(defun h () (princ '*))
(defadvice h (around advice-place-test1 activate)
  (princ 'R1)
  ad-do-it
  (princ 'R1))
(defadvice h (after advice-place-test1 activate)
  (princ 'A1))
(defadvice h (before advice-place-test1 activate)
  (princ 'B1))
(defadvice h (after advice-place-test2 activate)
  (princ 'A2))
(defadvice h (before advice-place-test2 activate)
  (princ 'B2))
(defadvice h (around advice-place-test2 activate)
  (princ 'R2)
  ad-do-it
  (princ 'R2))
(with-output-to-string (h))		; => "B2B1R2R1*R1R2A2A1"


;; アドバイスはad-enable-adviceで有効にし、
;; ad-disable-adviceで無効にする
(defun adtest () 'unadviced)		; => adtest
(defadvice adtest (around enable-test activate) (setq ad-return-value
						      'adviced))
(adtest)				; => adviced
;; 無効にする
(ad-disable-advice 'adtest 'around 'enable-test)
;; まだ反映されていない
(adtest)				; => adviced
;; ad-activate 関数 で反映される
(ad-activate 'adtest)			; => adtest
(adtest)				; => unadviced
;; 有効にする
(ad-enable-advice 'adtest 'around 'enable-test)
(ad-activate 'adtest)
(adtest)				; => adviced

;; ad-activate-regexp アドバイス名の正規表現で、
;; アドバイス名にマッチする関数のアドバイスを反映させる
(defun adtestf1 () 'unadviced)
(defun adtestf2 () 'unadviced)
(defadvice adtestf1 (around adtest1 activate) (setq ad-return-value 'advided))
(defadvice adtestf2 (around adtest1 activate) (setq ad-return-value 'advided))
(list (adtestf1) (adtestf2))		; => (advided advided)
;; アドバイス名adtest1のアドバイスをまとめて無効にする
(ad-disable-regexp "adtest1")
(ad-activate-regexp "adtest1")
(list (adtestf1) (adtestf2))		; => (unadviced unadviced)
;; アドバイス名adtest1のアドバイスをまとめて有効にする
(ad-enable-regexp "adtest1")
(ad-activate-regexp "adtest1")
(list (adtestf1) (adtestf2))		; => (advided advided)

P253

Emacs Lispテクニックバイブル

Emacs Lispテクニックバイブル