2010-09-09 4 views
3

Il y a quelques fonctionnalités emacs, comme flyspell-mode, highlight-beyond-fill-column ou auto-fill-mode, je trouve si utile que je veux leur a permis presque tout le temps. Cependant, il ya toujours certaines conditions dans lesquelles ils n'ont pas beaucoup de sens.habilitantes certains modes emacs ou caractéristiques * presque * toujours

highlight-beyond-fill-column, par exemple, je tendance à vouloir pour à peu près tout ce que je me modifier, mais pour les choses de lecture d'autres ont écrit, comme dans gnous ou lors de la lecture intégré dans la documentation, il est en fait assez ennuyeux.

De même auto-fill-mode est incroyablement pratique lorsque vous écrivez juste du texte. Cependant, il est totalement inutile lors de la programmation.

Pour ces raisons, je ne peux pas simplement activer des fonctionnalités comme celle-ci globalement. Toujours en les activant manuellement n'est pas très pratique aussi bien, mais il faut aussi écrire hooks pour chaque mode ou application que j'utilise dans emacs, évidemment ne pouvant pas tous les couvrir, et finissant toujours par activer ces fonctionnalités manuellement.

Ce que je crois que je suis à la recherche est un moyen de globalement proposer quelques fonctionnalités, mais les désactiver sélectivement à nouveau, en fonction de diverses conditions comme celle qui principaux modes ou mineurs sont utilisés, si le tampon est lu -seulement ou en écriture, ou selon le tampon contenant le texte ou le code source. Je me rends compte qu'à moins la dernière chose pourrait ne pas être facile pour emacs de répondre, mais au moins pour que je crois que je serais bien avec une liste codée en dur de "programmation-modes" j'utilise régulièrement.

Répondre

0

Je le fais

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

Ceci semble être utile pour éditer des fichiers seulement. Cependant, tous les tampons ne sont pas associés à des fichiers, et j'aimerais également activer ou désactiver certains comportements dans ces tampons. Vous avez cependant répondu à certaines parties de ma question. Je vous remercie! – rafl

+0

@rafl Je suis assez sûr que ce crochet est toujours appelé – Anycorn

+0

Je ne crains pas, non. Comme son nom l'indique, il n'est jamais appelé par 'find-file', ce qui n'est en aucun cas le seul moyen de créer des tampons. – rafl

5

Donc, vous voulez un contrôle total sur ce qui est exécuté lorsqu'un mode particulier est ouvert ou un type particulier de fichier ... OK voici ce que vous avez besoin:

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

Avec ce code, vous pouvez faire la personnalisation fine dont vous avez besoin. Ceci est juste un exemple, vous pouvez l'adapter à vos besoins.

+0

Le pointeur vers 'after-change-major-mode-hook' était extrêmement utile. Je vous remercie! – rafl

1

Il semble que vous souhaitiez activer ou désactiver des modes mineurs spécifiques pour des "tampons spécifiques". Habituellement, les "tampons spécifiques" peuvent être distingués par leur mode majeur, ce qui est la façon dont je regarde habituellement ce type de problème. La procédure d'activation ou de désactivation des modes mineurs dépend de l'implémentation du mode mineur que vous essayez d'activer/désactiver et du mode principal que vous essayez d'activer/de désactiver.

activer/désactiver les choses basées sur le mode majeur est via la variable major-mode-hook.C'est là que vous tenez les choses à personnaliser le mode:

(add-hook 'text-mode-hook 'auto-fill-mode) 

Je l'habitude d'écrire ma propre fonction, même si elle est un simple-liner, parce que je vais presque toujours ajouter des choses plus tard:

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

Vous pouvez également faire des choses dans le crochet conditionnel:

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

que je fais habituellement tout cela dans un major-mode-load-hook, de sorte qu'il ne se produit que lorsque le code du major-mode est chargé:

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

Un important mode bien écrit aura une variable définie load-hook (je regarde habituellement au code source du mode pour savoir). Si elle n'a pas de load-hook, vous pouvez simuler un avec la fonction 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)) 

Si vous ne le faites pas dans un load-hook alors vous devez vous assurer que le mode-hook est personnalisable, puis ajouter votre my-mode-hook via personnaliser; Je préférerais avoir tous les éléments au même endroit dans mes .emacs, donc je ne personnalise généralement pas mes hameçons de cette façon.

Si jamais vous trouvez un mode majeur qui n'a pas de major-mode-hook, vous pouvez créer votre propre mode majeur en utilisant define-derived-mode. Vous devrez alors appeler le nouveau mode défini à chaque fois que l'ancien mode était activé.

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

Certains modes mineurs peuvent être activés globalement. Si vous les voulez sur la plupart du temps et qu'il le supporte, vous pouvez l'activer globalement et l'éteindre pour des modes majeurs spécifiques.

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

Si le mode mineur ne peut pas être activé au niveau mondial, ou vous ne voulez pas activé au niveau mondial, il suffit de tourner sur des modes spécifiques, comme indiqué ci-dessus.

+0

Le but de la question était plutôt de ne pas avoir à maintenir des hooks en mode majeur pour chaque mode que j'utilise, mais de maintenir des réglages spécifiques au tampon dans les différents modes majeurs plus généralement. – rafl

+0

@rafl - désolé vous n'avez pas trouvé utile ... –

+0

Non, non. Ne vous méprenez pas. C'était utile et intéressant. Cela ne répondait pas vraiment aux problèmes que la question décrivait. – rafl

1

Voici donc ce que j'ai trouvé après avoir lu l'excellente réponse de [Jérôme Radix] [1]. Surtout le pointeur vers after-change-major-mode-hook a aidé un lot .

je définis maintenant mes paramètres spécifiques à mémoire tampon dans une liste comme ceci:

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

Lorsque les principaux changements de mode, j'itérer puis sur tous ces paramètres, évaluer les conditions définies dans le tampon et appel lambda appropriée si une condition correspond à:

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

l'évaluation de ces conditions est un peu désordonné, mais fonctionne plutôt bien pour moi.

(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")))) 

Il se aussi que je pouvais faire tout mon projet par cadre, que je l'ai fait tout à fait différemment avant, en utilisant ce mécanisme. Je suis très content de ça.

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

Questions connexes