代码之家  ›  专栏  ›  技术社区  ›  rafl

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

  •  3
  • rafl  · 技术社区  · 14 年前

    有几个Emacs功能,例如 flyspell-mode , highlight-beyond-fill-column auto-fill-mode 我觉得很有用 希望他们能随时启用。然而,总是有一些确定 他们没有什么意义的情况。

    突出显示超出填充列 例如,我想要很多 我自己编辑的所有东西,除了阅读别人写的东西,比如GNUS或 当阅读内置文档时,它实际上非常烦人。

    同样地 自动填充模式 在只写文本时非常方便。然而, 编程时完全没有帮助。

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

    我认为我正在寻找一种在全球范围内启用某些功能的方法,但是 根据不同的情况,如 如果缓冲区是只读或可写的,或者正在使用次要模式,或者 取决于包含文本或源代码的缓冲区。我知道在 至少Emacs不容易回答最后一件事,但至少 我相信我可以用硬编码的“编程模式”列表 有规律地

    5 回复  |  直到 14 年前
        1
  •  2
  •   jrockway    14 年前

    有趣的想法。我建议使用 espect 从扩展 your github .

        2
  •  5
  •   Jérôme Radix    14 年前

    因此,您需要完全控制在打开特定模式或特定类型的文件时执行的操作…好的,这是您需要的:

    ;; 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)
    

    使用此代码,您可以执行所需的细粒度定制。这只是一个例子,你可以根据自己的需要来调整它。

        3
  •  1
  •   Joe Casadonte    14 年前

    听起来,您基本上想打开或关闭“特定缓冲区”的特定次要模式。通常,“特定缓冲区”可以通过它们的主要模式来区分,这就是我通常如何看待这种类型的问题。如何打开或关闭次要模式取决于正在尝试打开/关闭的次要模式和正在尝试打开/关闭的主要模式的实现。

    根据主模式启用/禁用事物的常用方法是通过 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)
    

    您还可以使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 变量已定义(我通常查看模式的源代码以了解)。如果它没有 负载钩 ,可以使用 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))
    

    如果你不在 负载钩 那么你必须确保 mode-hook 可自定义,然后添加 my-mode-hook 通过定制;我宁愿把所有的东西放在我的.emacs中的一个地方,所以我通常不会这样定制我的钩子。

    如果你发现一个主模式没有 主模式钩子 您可以使用创建自己的主要模式 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))))
    

    如果次要模式不能全局启用,或者您不希望它全局启用,只需为特定模式打开它,如上图所示。

        4
  •  1
  •   Community CDub    8 年前

    这就是我在读了《我的根基》之后想到的 回答。尤其是指向 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)))
    

    当主模式改变时,我会迭代所有这些设置,然后评估 缓冲区中定义的条件,如果 条件匹配:

    (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

        5
  •  0
  •   Anycorn    14 年前

    我这样做

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