有一些emacs功能,例如flyspell-mode
,
highlight-beyond-fill-column
或auto-fill-mode
,我认为我非常有用
几乎所有时间都希望它们启用。但是,总有一定的
他们没有多大意义的条件。
highlight-beyond-fill-column
,我倾向于非常想要
我编辑自己的一切,但是用于阅读别人写的东西,比如Gnus或者
在阅读内置文档时,实际上非常烦人。
同样地,auto-fill-mode
在编写Text时非常方便。然而,
在编程时它完全没有用。
出于这些原因,我不能只在全局范围内启用这样的功能。总是 手动启用它们也不是很实用,但必须编写 显然,我正在emacs中使用的每个模式或应用程序的钩子 无法覆盖所有这些,并且仍然最终启用这些功能 手动
我认为我正在寻找的是一种全局启用某些功能的方法,但是 根据各种主要条件,选择性地将它们关闭 如果缓冲区是只读或可写的,则使用或次要模式 取决于包含文本或源代码的缓冲区。我确实意识到了 至少最后一件事可能不容易让emacs回答,但至少对于 我相信我会使用硬编码的“编程模式”列表 定期
答案 0 :(得分:5)
因此,您希望完全控制在打开特定模式或特定类型的文件时执行的内容...确定这就是您所需要的:
;; The function where you could put all your customization
(defun my-func ()
(turn-on-auto-fill))
;; This is an example, customize it like you need it.
(defvar functions-to-call
`(((c-mode c++-mode) ".h$" (my-func))
((cperl-mode perl-mode) nil (my-func)))
"A list of triples, used for storing functions.
A triplet is composed of a symbol for the major mode (or a list of symbols),
a regular expression to match against the buffer's file name,
and the functions to call when both the major mode and regular expr match.")
(defun call-mode-functions ()
"call functions, based on major mode and buffer name regexp matching"
(interactive)
(let ((l functions-to-call))
(while l
(let* ((elt (car l))
(modes (if (listp (car elt)) (car elt) (list (car elt))))
(re (cadr elt))
(fcts (caddr elt)))
(when (and (member major-mode modes)
(or (null re)
(string-match re (buffer-file-name))))
(while fcts
(funcall (car fcts))
(setq fcts (cdr fcts)))
(setq l nil)))
(setq l (cdr l)))))
(add-hook 'after-change-major-mode-hook 'call-mode-functions)
使用此代码,您可以进行所需的细粒度自定义。这只是一个例子,您可以根据自己的需要进行调整。
答案 1 :(得分:2)
有趣的想法。我建议使用 来自espect的your github扩展名。
答案 2 :(得分:1)
听起来你基本上想要为“特定缓冲区”打开或关闭特定的小模式。通常,“特定缓冲区”可以通过它们的主要模式来区分,这就是我通常看待这类问题的方式。如何打开或关闭小模式取决于您尝试打开/关闭的次要模式的实现以及您尝试打开/关闭它的主要模式。
基于主模式启用/禁用内容的常用方法是通过major-mode-hook
变量。这是您坚持自定义模式的地方:
(add-hook 'text-mode-hook 'auto-fill-mode)
我经常编写自己的函数,即使它是一个简单的单行程序,因为我几乎总是会在以后添加内容:
(defun my-text-mode-hook ()
"Stuff to do when `text-mode' is invoked."
(auto-fill-mode 1))
(add-hook 'text-mode-hook 'my-text-mode-hook)
你也可以在钩子条件下做事:
(defun my-text-mode-hook ()
"Stuff to do when `text-mode' is invoked."
;; skip modes based on text-mode
(when (eq major-mode 'text-mode)
(auto-fill-mode 1))
)
(add-hook 'text-mode-hook 'my-text-mode-hook)
我通常在major-mode-load-hook
中执行所有操作,因此只有在加载主模式代码时才会发生这种情况:
(defun my-tnt-load-hook ()
(defun my-tnt-im-mode-hook ()
"Hook for TNT's im-mode hook."
(flyspell-mode 1)
(setq fill-column (- (frame-width) 5)))
(add-hook 'tnt-im-mode-hook 'my-tnt-im-mode-hook)
(add-hook 'tnt-chat-mode-hook 'my-tnt-im-mode-hook))
(add-hook 'tnt-load-hook 'my-tnt-load-hook)
编写良好的主模式将定义load-hook
变量(我通常会查看模式的源代码以找出)。如果它没有load-hook
,您可以使用eval-after-load
函数模拟一个:
(defun my-view-mode-after-load-hook ()
"Stuff to do after view mode loads."
(defun my-view-mode-hook ()
"Stuff to run in `view-mode'."
(flyspell-mode 0))
(add-hook 'view-mode-hook 'my-view-mode-hook)
(define-key view-mode-map "b" 'View-scroll-page-backward)
(define-key view-mode-map [(delete)] 'View-scroll-page-backward)
(define-key view-mode-map "q" 'View-kill-and-leave)
(define-key view-mode-map "Q" 'View-quit))
(eval-after-load 'view '(my-view-mode-after-load-hook))
如果您未在load-hook
中执行此操作,则必须确保mode-hook
可自定义,然后通过自定义添加my-mode-hook
;我宁愿把所有的东西放在我的.emacs中的一个地方,所以我通常不会这样定制我的钩子。
如果您发现没有major-mode-hook
的主模式,您可以使用define-derived-mode
创建自己的主模式。然后,只要旧模式是,就必须调用新定义的模式。
(defun replace-alist-mode (alist oldmode newmode)
(dolist (aitem alist)
(if (eq (cdr aitem) oldmode)
(setcdr aitem newmode))))
(define-derived-mode hooked-foobar-mode foobar-mode "Foobar")
(replace-alist-mode auto-mode-alist 'foobar-mode 'hooked-foobar-mode)
(defun my-hooked-foobar-mode-hook ()
"Hook to run when `hooked-foobar-mode' is called."
(flyspell-mode 0))
(add-hook 'hooked-foobar-mode-hook 'my-hooked-foobar-mode-hook)
可以全局启用一些次要模式。如果您在大多数时间需要它们并且它支持它,您可以全局打开它,然后为特定主要模式关闭它。
(global-font-lock-mode 1)
;; example of how to do it without a defun
(add-hook 'text-mode-hook (function
(lambda () ""
(interactive)
(font-lock-mode 0))))
如果无法全局启用次要模式,或者您不希望全局启用次要模式,只需为特定模式启用它,如上所示。
答案 3 :(得分:1)
所以这就是我在阅读[JérômeRadix] [1]之后想出来的
答复。特别是指向after-change-major-mode-hook
的指针帮助了
很多。
我现在在列表中定义我的缓冲区特定设置:
;; no `highlight-beyond-fill-column' for w3m and gnus
'((((:not ((:mode "^gnus") (:mode w3m-mode))))
(lambda () (highlight-beyond-fill-column)))
;; `flyspell-mode` and `auto-fill-mode` for text-ish buffers
(((:mode message-mode)
(:mode org-mode)
(:mode pod-mode)
(:mode markdown-mode)
(:name "\\.\\(txt\\|mkn\\)$"))
(lambda ()
(flyspell-mode)
(auto-fill-mode)))
;; indenting with tabs for certain projects
(((:name t :fun (lambda () (and (not eproject-root)
(eproject-maybe-turn-on)))))
(lambda () (setq indent-tabs-mode t)))
当主要模式改变时,我然后迭代所有这些设置,进行评估 缓冲区中定义的条件,如果是,则调用相应的lambda 条件匹配:
(add-hook 'after-change-major-mode-hook
(lambda () (rafl:apply-buffer-settings rafl:buffer-settings)))
(defun rafl:apply-buffer-settings (settings)
(dolist (setting rafl:buffer-settings)
(let ((condition (car setting))
(action (cadr setting)))
(when (rafl:evaluate-buffer-condition condition)
(funcall action)))))
评估这些条件有点混乱,但对我来说效果很好。
(defun rafl:evaluate-buffer-condition (con)
(cond
((functionp con)
(funcall con))
((listp con)
(cond
((listp (car con))
(reduce
(lambda (a b) (or a b))
(cons nil (mapcar #'rafl:evaluate-buffer-condition con))))
(t
(reduce
(lambda (a b) (and a b))
(cons
t
(let (ret)
(while con
(let ((k (pop con))
(v (pop con)))
(push (cond
((eq k :fun)
(funcall v))
((eq k :not)
(when (not (listp v))
(error ":not requires a list"))
(not (rafl:evaluate-buffer-condition v)))
((eq k :mode)
(if (stringp v)
(string-match-p v (symbol-name major-mode))
(eq v major-mode)))
((eq k :name)
(cond
((and (buffer-file-name) (stringp v))
(string-match-p v (buffer-file-name)))
((buffer-file-name)
v)
(t
(not v))))
(t
(error "unknown cond")))
ret)))
ret))))))
(t
(error "invalid condition"))))
事实证明,我可以完成我所有的每个项目设置,我做得很好 不同之前,使用这种机制。我很高兴。
答案 4 :(得分:0)
我这样做
(require 'linum)
;(global-linum-mode t)
(add-hook 'find-file-hook (lambda ()
(if (not(equal major-mode 'term-mode))
(linum-mode nil))))