几乎*始终启用某些emacs模式或功能*

时间:2010-09-09 07:39:43

标签: emacs

有一些emacs功能,例如flyspell-modehighlight-beyond-fill-columnauto-fill-mode,我认为我非常有用 几乎所有时间都希望它们启用。但是,总有一定的 他们没有多大意义的条件。

例如,

highlight-beyond-fill-column,我倾向于非常想要 我编辑自己的一切,但是用于阅读别人写的东西,比如Gnus或者 在阅读内置文档时,实际上非常烦人。

同样地,auto-fill-mode在编写Text时非常方便。然而, 在编程时它完全没有用。

出于这些原因,我不能只在全局范围内启用这样的功能。总是 手动启用它们也不是很实用,但必须编写 显然,我正在emacs中使用的每个模式或应用程序的钩子 无法覆盖所有这些,并且仍然最终启用这些功能 手动

我认为我正在寻找的是一种全局启用某些功能的方法,但是 根据各种主要条件,选择性地将它们关闭 如果缓冲区是只读或可写的,则使用或次要模式 取决于包含文本或源代码的缓冲区。我确实意识到了 至少最后一件事可能不容易让emacs回答,但至少对于 我相信我会使用硬编码的“编程模式”列表 定期

5 个答案:

答案 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)

有趣的想法。我建议使用 来自espectyour 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"))))

事实证明,我可以完成我所有的每个项目设置,我做得很好 不同之前,使用这种机制。我很高兴。

1:Enabling certain emacs modes or features *almost* always

答案 4 :(得分:0)

我这样做

(require 'linum)
;(global-linum-mode t)
(add-hook 'find-file-hook (lambda ()
                            (if (not(equal major-mode 'term-mode))
                                (linum-mode nil))))
相关问题