Ré-indentation automatique du code elisp lors de l'ajout ou de la suppression de code avant un bloc indenté


18

Disons que j'ai un code elisp comme:

(+ 2 3▮(+ 3
          4))

Existe-t-il un moyen de ré-indenter automatiquement le sexp après le curseur, lorsque j'ajoute ou supprime des symboles?

Donc, après avoir appuyé sur SPC 4 SPC, j'obtiendrais automatiquement:

(+ 2 3 4 ▮(+ 3
             4))

Je peux faire ce manuel en appelant mark-sexpsuivi de indent-region. Y a-t-il de meilleures façons de procéder?


Je ne pense pas qu'il existe de raccourcis clavier par défaut, mais vous pouvez facilement en créer vous-même.
— shosti

Je sais, mais je me demande précisément s'il existe de meilleures façons de procéder. Par exemple, comment electric-indent-modeest bien meilleur que le mappage <return>versnewline-and-indent
— Maciej Goszczycki

Réponses:


14

Au lieu de mark-sexp+ indent-region, vous pouvez appuyer sur C-M-q. Cela va appeler indent-pp-sexp. Pas automatique, mais un peu mieux que d'avoir à invoquer deux commandes.

Ou si vous utilisez paredit-mode, appuyez sur M-q. Cela réindentera toute la définition de fonction dans laquelle vous vous trouvez.


1
(add-hook 'post-self-insert-hook 'indent-pp-sexp)fonctionne bien surprenant.
— Maciej Goszczycki

Cela semble bon. Cela peut être coûteux dans certains modes, mais c'est quand même une bonne approche.
— Dmitry

Pour les utilisateurs de Smartparens, vous pouvez réactiver le defun actuel avec M-x sp-indent-defun. Je lie cela à C-M-q.
— Radon Rosborough

15

Mode de retrait agressif

Depuis que certaines personnes l'ont demandé, j'ai transformé cette réponse en un package .

Si vous avez configuré Melpa, vous pouvez l'installer avec

M-x package-install RET aggressive-indent

Consultez le fichier Lisez - moi pour toutes les options, mais le moyen le plus simple de l'activer est:

(add-hook 'emacs-lisp-mode-hook #'aggressive-indent-mode)

L'ancienne réponse

Ce qui suit effectue l'indentation automatique uniquement sur les tampons elisp. Il a l'avantage de fonctionner également lorsque vous effacez ou tirez des trucs (au lieu de simplement taper). Il est également facile d'ajouter à d'autres modes.

Cette fonction indentera toute expression s dans laquelle le point se trouve actuellement. Vous pouvez le lier à une clé si vous le souhaitez, mais voyez d'abord ci-dessous.

(require 'cl-lib)

(defun endless/indent-defun ()
  "Indent current defun.
Do nothing if mark is active (to avoid deactivating it), or if
buffer is not modified (to avoid creating accidental
modifications)."
  (interactive)
  (ignore-errors
    (unless (or (region-active-p)
                buffer-read-only
                (null (buffer-modified-p)))
      (let ((l (save-excursion (beginning-of-defun 1) (point)))
            (r (save-excursion (end-of-defun 1) (point))))
        (cl-letf (((symbol-function 'message) #'ignore))
          (indent-region l r))))))

Ce crochet fera en sorte que cette fonction sera exécutée après avoir tapé quoi que ce soit, mais uniquement dans les tampons elisp. Cela devrait garder tout toujours en retrait.

(add-hook
 'emacs-lisp-mode-hook
 (lambda ()
   (add-hook 'post-command-hook
             #'endless/indent-defun nil 'local)))

Essayez! Cela fonctionne remarquablement bien.

En outre, en suivant la suggestion de @ holocronweaver dans les commentaires, vous pouvez utiliser quelque chose comme ce qui suit pour les langages de type c:

(define-key c++-mode-map ";"
  (lambda () (interactive)
    (insert ";")
    (endless/indent-defun)))

Ce serait excellent si cela réduisait au silence les messages d'indentation automatique et les langues mieux gérées qui terminent les lignes par des points-virgules.
— holocronweaver

@holocronweaver bien sûr, je peux essayer ça. Quel mode principal comporte des messages de retrait? Et quel est le problème avec les points-virgules?
— Malabarba

Tous les modes que j'ai essayés sur le tronc Emacs ont produit des messages de retrait, y compris elisp. Étant donné que les points-virgules terminent une ligne dans de nombreuses langues, jusqu'à ce que vous tapiez le point-virgule, la ligne suivante saute comme si elle faisait partie de la ligne actuelle.
— holocronweaver

@holocronweaver Réduit au silence les messages. Merci de l'avoir signalé.
— Malabarba

Merci pour le correctif! Une solution au problème de point-virgule consiste à ne mettre en retrait que dans les langues en mode c lorsqu'un point-virgule est tapé.
— holocronweaver du

3

Je ne connais pas de solution préexistante, mais vous pouvez l'utiliser post-self-insert-hookpour y parvenir vous-même:

(defun my-indent-next-sexp ()
  (interactive)
  (mark-sexp)
  (indent-region))

(add-hook 'post-self-insert-hook 'my-indent-next-sexp)

Je m'inquiéterais cependant des problèmes de performances potentiels.


1

Vous pouvez essayer le mode el-fly-indent , qui se comporte mieux que aggressive-indent-modelorsque vous traitez avec Elisp.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.