1

ときどき、デフォルトとは異なる font-family と size を手動で設定しますbuffer-face-mode。(正確には、マウスを使用してダイアログボックスから選択します。) 一度設定すると、モードを変更してもそのバッファに設定されたままにしたいので、カスタマイズを試みました。アイデアは、change-major-mode-hook後で呼び出される関数で、設定されている場合、バッファフェイスを保存する(バッファローカルが殺される直前に実行される)を追加することでした-それはうまくいくようです。しかし、その関数はあまりにも早く呼び出されたようで、モードの変更が終わったときにbuffer-face-modeアクティブではありません。

今までのカスタマイズはこちら

(defun my-preserve-bufface-cmmh ()
  "Keep the state of buffer-face-mode between major-mode changes"
  (if (and (local-variable-p 'buffer-face-mode) buffer-face-mode)
      (delay-mode-hooks
    (message "face is %s" buffer-face-mode-face) ; Just to show me it has the right face
    (let ((my-inner-face buffer-face-mode-face))
      (run-mode-hooks
       (message "inner %s" my-inner-face) ; it still has the right face here
       (setq buffer-face-mode-face my-inner-face)
       (buffer-face-mode))))))

(add-hook 'change-major-mode-hook
      'my-preserve-bufface-cmmh)

マイナーモードが設定されたバッファでメジャーモードを変更すると、メッセージが実行され、カスタムフェイスが表示buffer-face-modeされます。新しいモードが設定された後、... の組み合わせで ... が実行されると思っていましたが、どうやらそうではないdelay-mode-hooksようrun-mode-hooksです。setq buffer-face-mode-face(buffer-face-mode)

このカスタマイズは「近い」/私の要望に応じて回収できますか? よりクリーンな方法はありますか?

4

2 に答える 2

1

まずdelayed-mode-hooks、それ自体がローカル変数です。つまり、これで設定した場合、(delay-mode-hooks (run-mode-hooks ...))即座change-major-mode-hook に殺されるため効果はありません。

2 つ目は、 your 内のものは 内run-mode-hooksで評価されるということmy-preserve-bufface-cmmhです。`(lambda () ...)保持したい値をスプライスする逆引用符で囲まれたフック関数として定義する必要が あります。別の方法は、レキシカル バインディングを使用することです (これは google)。

2番目のことは、次の例で示されています(段階的に評価されます):

(defun test (str)
  (let ((mytest (concat "hello " str)))
    (add-hook 'my-own-hook `(lambda () (message "mytest:%S" ,mytest)))))


(test "you")

(run-hooks 'my-own-hook)

(test "world")

(run-hooks 'my-own-hook)

(put  :myface 'test)

フォントをバッファローカルに保持したい場合は、kill-all-local-variablesなどの存続するローカル変数を使用する必要がありますbuffer-file-name。そこにプロパティをフックできます:

編集: シンボルにバッファ ローカル値がある場合でも、そのプロパティはバッファ ローカルではありません。したがって、以前のアプローチは機能しませんでした。ベター: 独自の永続的なバッファー ローカル変数を作成します。

(defvar-local my-preserve-bufface nil
  "Keep the state of buffer-face-mode between major-mode changes")

(put 'my-preserve-bufface 'permanent-local t)

(defun my-preserve-bufface-put ()
  "Keep the state of buffer-face-mode between major-mode changes"
  (and (local-variable-p 'buffer-face-mode)
       buffer-face-mode
       (setq my-preserve-bufface buffer-face-mode-face)))

(defun my-preserve-bufface-get ()
  "Keep the state of buffer-face-mode between major-mode changes"
    (and my-preserve-bufface
         (setq buffer-face-mode-face my-preserve-bufface)
         (buffer-face-mode)))

(add-hook 'change-major-mode-hook 'my-preserve-bufface-put)
(add-hook 'after-change-major-mode-hook 'my-preserve-bufface-get)
于 2013-10-17T17:54:54.607 に答える
1

教育的なコメント、特に @ user2708138 からの回答/例に感謝します。質問に回答するので、これを受け入れます。

それでも、より一般的な解決策である実用的なコードを思いついたので、私自身の質問にも答えます。font-size の変更も維持したいと思っていて、それらが からのものであることがわかった後、私はこの道をたどりましたtext-scale-mode。このコードは、保持するマイナー モードのリストを読み取ります。使用する変数を特定する必要はありません。(人間がそれらを理解するのはそれほど難しいことではありませんが、私は emacs にそれをやってもらいたいと思っていました)。

残念ながら、マイナーモードで使用される変数を取得する関数は私が知っているわけではありませんが、興味のあるモードはマイナーモード-var-name という規則を使用しているため、このコードはそのパターンのバッファーローカル変数をフィルター処理するだけです.

; Save & restore minor modes I wish to be "permanent" if set
(setq my-preserve-minor-modes '(buffer-face-mode text-scale-mode))

(defun my-preserve-minor-modes-cmmh ()
  "Keep the state of desired-permanent minor modes between major-mode changes. Assumes that associated buffer-local minor-mode variables to save begin with `minor-mode-'"
  (setq my-restore-minor-modes-acmmh nil)
  (dolist (mm my-preserve-minor-modes)
    (when (and (local-variable-p mm) (symbol-value mm))
      (push mm my-restore-minor-modes-acmmh)))
  (when my-restore-minor-modes-acmmh
    (add-hook 'after-change-major-mode-hook 'my-restore-minor-modes-acmmh)
    ; Predicate-list showing if symbol starts with a preserved mode
    (let ((mm-p-l `(lambda (locvar-nm)
             (or ,@(mapcar (lambda (mm)
                     `(and (< ,(length (symbol-name mm))
                          (length locvar-nm))
                       (string-prefix-p ,(symbol-name mm)
                                locvar-nm)))
                   my-restore-minor-modes-acmmh)))))
      ; For each found minor mode, create fn to restore its buf-local variables
      (dolist (locvar (buffer-local-variables))
    (if (and (listp locvar) (funcall mm-p-l (symbol-name (car locvar))))
          (push `(lambda()(setq ,(car locvar) ',(cdr locvar)))
            my-restore-minor-modes-acmmh))))))


(defun my-restore-minor-modes-acmmh ()
  "After major-mode change, restore minor-mode state, and remove self from hook. It restores state by calling the function stored in the variable my-restore-minor-modes-acmmh."
  (remove-hook 'after-change-major-mode-hook 'my-restore-minor-modes-acmmh)
  (dolist (restore-f my-restore-minor-modes-acmmh) (funcall restore-f)))

(add-hook 'change-major-mode-hook 'my-preserve-minor-modes-cmmh)

私はプロパティについて知っていpermanent-localましたが、望ましくない副作用については確信が持てませんでした...おそらく私の側の不当なパラノイア!

マイナー モードの変数のリストを取得する方法がある場合、またはユーザーにマイナー モードごとに変数の連想リストを指定させる方法がある場合、私の答えは改善される可能性があります。どちらの場合も、buffer-local-variablesもうループする必要はありません。おそらく、これらすべてpermanent-localを作成するだけで十分であり、コードをかなり単純化できます。とにかく、(あなたの助けと素晴らしいマニュアルを見て)これらすべてを理解することは非常に教育的でした.

于 2013-10-17T23:49:25.753 に答える