Включение определенных режимов или функций emacs * почти * всегда - PullRequest
3 голосов
/ 09 сентября 2010

Есть несколько функций emacs, таких как flyspell-mode, highlight-beyond-fill-column или auto-fill-mode, я нахожу настолько полезными, что я хочу, чтобы они были включены почти всегда.Тем не менее, всегда есть определенные условия, в которых они не имеют особого смысла. Например,

highlight-beyond-fill-column, я стремлюсь практически ко всему, что редактирую сам, но для чтения того, что написали другие, напримерGnus или при чтении встроенной документации, это на самом деле довольно раздражает.

Точно так же auto-fill-mode невероятно удобно при написании только текста.Тем не менее, это совершенно бесполезно при программировании.

По этим причинам я не могу просто включить такие функции в глобальном масштабе.Всегда включать их вручную не очень практично, но приходится писать хуки для каждого режима или приложения, которые я использую в emacs, очевидно, что не могу охватить все из них, и все равно в конечном итоге включить эти функциивручную.

Мне кажется, что я ищу способ глобально включить некоторые функции, но выборочно отключить их снова, в зависимости от различных условий, таких как использование основных или вспомогательных режимов, если буфертолько для чтения или записи, или в зависимости от буфера, содержащего текст или исходный код.Я понимаю, что, по крайней мере, последняя вещь может быть непростой для emacs, но, по крайней мере, я уверен, что мне будет хорошо с жестко запрограммированным списком «режимов программирования», которые я регулярно использую.

Ответы [ 5 ]

5 голосов
/ 09 сентября 2010

Итак, вам нужен полный контроль над тем, что выполняется при открытии определенного режима или файла определенного типа ... Хорошо, вот что вам нужно:

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

С помощью этого кода вы можете выполнить детальную настройку, которая вам требуется. Это всего лишь пример, вы можете адаптировать его к вашим потребностям.

2 голосов
/ 22 октября 2010

Интересная идея. Я рекомендую использовать espect расширение от вашего github .

1 голос
/ 11 сентября 2010

Итак, вот что я придумала после прочтения [Jérôme Radix] [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)))

Когда основной режим меняется, я затем перебираю все эти настройки, оцениваю определенные условия в буфере, и вызвать соответствующую лямбду, если условия соответствуют:

(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: Включение определенных режимов или функций emacs * почти * всегда

1 голос
/ 11 сентября 2010

Звучит так, будто вы в основном хотите включить или выключить определенные второстепенные режимы для "определенных буферов". Обычно «конкретные буферы» можно отличить по их основному режиму, как я обычно смотрю на этот тип проблемы. Как включить или выключить второстепенные режимы, зависит от реализации как второстепенного режима, который вы пытаетесь включить / выключить, так и основного режима, в котором вы пытаетесь включить / выключить его.

Обычный способ включить / отключить вещи в основном режиме - через переменную 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))))

Если вспомогательный режим нельзя включить глобально или вы не хотите, чтобы он был включен глобально, просто включите его для определенных режимов, как показано выше.

0 голосов
/ 09 сентября 2010

Я делаю это

(require 'linum)
;(global-linum-mode t)
(add-hook 'find-file-hook (lambda ()
                            (if (not(equal major-mode 'term-mode))
                                (linum-mode nil))))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...