1

有时,我会手动设置与默认字体不同的字体系列和大小,并且我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 这将没有任何效果,因为它会立即被杀死。

第二件事是你里面的东西run-mode-hooks是在my-preserve-bufface-cmmh. 它应该被定义为一个反引号钩子函数 `(lambda () ...),你可以在其中拼接你想要保留的值。另一种方法是使用词法绑定(谷歌)。

第二件事在以下示例中进行了演示(逐步评估):

(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 的答案/示例,我将接受它,因为它确实回答了这个问题。

然而,我也将回答我自己的问题,因为我确实提出了一个更通用的解决方案的工作代码。在发现我还希望保持我的字体大小更改并且它们来自 之后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 回答