Comment éditer elisp sans se perdre entre parenthèses

13

Je modifie du code elisp de linum.el:

(custom-set-variables '(linum-format 'dynamic))
(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
            ad-do-it))

J'ai pu corriger un bogue où l'indentation était décalée en modifiant (count-lines (point-min) (point-max))en (+ (count-lines (point-min) (point-max)) 1). C'était facile.

Mais maintenant, je veux le modifier pour que la largeur minimale soit de 2 en ajoutant un if-conditionnel où (concat " %" (number-to-string w) "2d ")si le nombre de lignes est <10.

Cela devrait être facile! Ajoutez un conditionnel et copiez / collez le concat. Un morceau de gâteau, non? Je veux dire, je sais ce que je suis censé faire, mais je touche rarement elisp et je suis toujours intimidé quand je dois modifier quoi que ce soit avec beaucoup de parenthèses.

Le style «correct», d'après ce que je comprends, consiste à structurer le code en fonction de l'indentation et à envelopper la parenthèse de fin à la fin d'une ligne plutôt que seule. Venant d'autres langages de style «C», j'ai du mal à lire et à écrire du code de cette manière. Alors ma question est: qu'est-ce que je fais mal? Comment suis-je censé éditer elisp et naviguer dans le code de sorte que je n'ai pas à m'asseoir là et à compter toutes les parenthèses?

Lorsque je travaille avec quelque chose dans elisp qui devient trop profond, je dois fermer ma porte, tirer les stores et commencer à positionner la parenthèse de style K & R afin que je puisse non seulement lire, mais modifier le sacré truc sans paniquer.

Évidemment, je fais tout cela mal. Comment puis-je toucher des élisp comme ça sans crainte?

Veuillez noter que ma question est de savoir comment naviguer et modifier elisp pas comme une question de style. J'utilise déjà ce qui suit comme guide de style: https://github.com/bbatsov/emacs-lisp-style-guide

Mises à jour:

Comment formater correctement elisp avant de vous embarrasser sur emacs.stackexchange:

Marquez votre élisp et jouez M-x indent-region.

La solution du problème:

Pour ceux qui veulent savoir comment effectuer une justification à droite pour un linum d'une largeur minimale de deux, voici la solution:

(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                     (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (if (> w 1)
                           (concat " %" (number-to-string w) "d ")
                         " %2d ")))
    ad-do-it))
Zhro
la source
1
Tout le monde a du mal à lire le lisp qui vient de C. Cela prend juste du temps, mais finalement cela devient extrêmement naturel. Vous pouvez également probablement résoudre votre problème en changeant le format linum en une chaîne de format comme "% 2d".
Jordon Biondo du
Je ne peux pas simplement l'utiliser %2dparce qu'une fois que la largeur passe à 3 caractères ou plus, elle passe de justifié à droite à justifié à gauche.
Zhro
Il y a quelques bibliothèques qui mettent en évidence les parenthèses correspondantes qui sont inestimables (à mon avis), par exemple highlight-parentheses; rainbow-delimiters; etc. Voici ma propre version simplifiée highlight-parenthesesqui permet de faire défiler sans supprimer les dernières parenthèses colorisées: stackoverflow.com/a/23998965/2112489 À l'avenir, c'est une question par client / thread.
lawlist
1
Cela ressemble beaucoup à votre problème, c'est vraiment la lecture , pas l'édition du code Elisp. Vous semblez avoir des problèmes pour comprendre la structure de Lisp, ce qui nuit à votre édition.
PythonNut
1
Pour votre défense, c'est un morceau de code assez mal échancré. J'ai mal lu moi-même les 3 premières fois à cause de cela. Aussi, paredit .
Malabarba

Réponses:

12

Il existe un certain nombre de packages de modules complémentaires qui pourraient vous aider, tels que paredit, smartparens et lispy. Ces packages facilitent la navigation et la manipulation du code lisp afin que vous puissiez penser dans les expressions s et laisser l'éditeur s'inquiéter de l'équilibrage des parenthèses.

Emacs possède également de nombreuses commandes intégrées pour gérer les sexps et les listes qui valent la peine d'être apprises et peuvent vous aider à vous habituer davantage à la structure du code lisp. Ceux-ci sont généralement liés par un C-M-préfixe, tel que:

  • C-M-f/ C-M-bpour avancer / reculer de sexp
  • C-M-n/ C-M-ppour avancer / reculer par liste
  • C-M-u/ C-M-dpour monter / descendre d'un niveau
  • C-M-t pour échanger les deux sexps autour du point
  • C-M-k tuer un sexp
  • C-M-SPC pour marquer un sexp
  • C-M-q pour ré-indenter un sexp

L'exemple de code que vous avez fourni pourrait être plus clair si vous corrigez l'indentation: placez le point au début de (defadvice...et appuyez sur C-M-qpour ré-indenter l'expression entière. Pour remplacer le (concat...je commencerais par mettre un point au début de ce sexp et frapper C-M-opour diviser la ligne tout en préservant l'indentation. Ajoutez ensuite votre (if..., et utilisez les commandes ci-dessus pour passer à la fin d'une liste pour ajouter une autre parenthèse fermante, revenir au début pour ré-indenter, etc.

Vous pouvez également activer show-paren-modecette option, qui mettra en surbrillance le paren correspondant lorsque le point se trouve au début ou à la fin d'une liste. Vous pouvez préférer mettre en surbrillance l'expression entière plutôt que le paren correspondant, essayez donc de le personnaliser show-paren-style.

Comme @Tyler l'a mentionné dans les commentaires sur une autre réponse, vous devriez jeter un œil au manuel pour en savoir plus sur ces commandes et les commandes associées.

glucas
la source
Notez que cela C-M-qpeut être appelé avec un argument de préfixe ( C-u C-M-q) pour afficher jolie expression au point. Cela va tout casser sur des lignes et des retraits séparés afin que l'imbrication soit très évidente. En général, vous ne voulez pas que votre code lisp ressemble à cela, mais il pourrait être utile de comprendre un peu de code sans passer manuellement par K&R complet. (Et vous pouvez toujours C-x uannuler).
glucas
6

Un bon moyen d'éditer LISP consiste à manipuler l'AST, au lieu des caractères ou des lignes individuels. Je fais ça avec mon package lispy que j'ai commencé il y a 2 ans. Je pense que cela peut prendre un peu de pratique pour apprendre à bien le faire, mais même en utilisant simplement les bases devrait déjà vous aider.

Je peux expliquer comment je procéderais pour effectuer ce changement:

Étape 1

La position de départ est généralement d'avoir le point avant le sexp de niveau supérieur. Voici |le point.

|(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
            ad-do-it))

Vous voudrez que le code soit correctement mis en retrait, alors appuyez iune fois. Il le réintroduira bien.

Étape 2

Vous voudrez marquer "d "avec une région, car un objet manipulable dans lispyest soit une liste, qui n'a pas besoin d'être marquée, ou une séquence de symboles ou / et de listes qui doit être marquée avec une région.

Appuyez sur atpour le faire. La acommande permet de marquer n'importe quel symbole unique dans la liste parent, et test l'index de ce symbole particulier.

Étape 3

  1. Pour envelopper la région actuelle avec (), appuyez sur (.
  2. Appuyez C-fpour avancer d'un caractère et insérer if.
  3. Appuyez à (nouveau pour insérer ().
  4. Insérez > w 10.
  5. C-f C-m pour déplacer la chaîne vers une nouvelle ligne.

Étape 4

Pour cloner la chaîne:

  1. Marquez le symbole ou la chaîne au point avec M-m.
  2. Appuyez sur c.

Si vous souhaitez désactiver la région de manière fantaisiste et mettre le point au tout début de la chaîne, vous pouvez appuyer sur idm:

  1. i sélectionnera le contenu interne de la chaîne.
  2. d permutera le point et marquera.
  3. m désactivera la région

Ou vous pourriez le faire m C-b C-b C-bdans ce cas, ou C-g C-b C-b C-b. Je pense que idmc'est mieux, car c'est la même quelle que soit la longueur de la chaîne. Je pense que C-x C-x C-f C-g cela fonctionnerait également quelle que soit la longueur de la chaîne.

Enfin, insérez 2pour obtenir le code de fin:

(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                     (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) (if (> w 10)
                                                             "2|d "
                                                           "d "))))
    ad-do-it))

Sommaire

La séquence complète est: at( C-f, if, (, > w 10, C-f C-m M-m cidm, 2.

Notez que si vous comptez l'insertion de code, les seules clés non liées à la manipulation AST étaient deux C-fet une C-m.

abo-abo
la source
3
Lispy semble intéressant! Pour l'OP: vous pouvez développer des flux de travail similaires avec paredit: emacsrocks.com/e14.html et développer la région: github.com/magnars/expand-region.el , ou simplement jouer avec les commandes de correspondance de parenthèses intégrées: gnu. org / software / emacs / manual / html_node / emacs / Parentheses.html
Tyler
Je suis sûr que vous deviniez quand vous vous êtes attaché à résoudre le problème pour moi; merci pour la tentative. J'ai réussi à me frayer un chemin à travers elle en utilisant votre code comme exemple. Voir ma mise à jour pour la bonne solution.
Zhro
6

Vous vous y habituerez au fil du temps, mais bien sûr, vous pouvez faire beaucoup pour l'accélérer:

Échancrure

Il y a une méthode à cette folie. En lisp, vous pouvez le faire:

(a-fun (another-fun (magic-macro 1)))

Supposons que ce 1soit vraiment une grande expression et que vous souhaitiez l'indenter sur sa propre ligne.

(a-fun (another-fun (magic-macro 
  1)))

C'est trompeur. 1est indenté d'un seul emplacement, même s'il s'agit de trois niveaux d'imbrication plus élevés! Mieux vaut le mettre par son parent.

(a-fun (another-fun (magic-macro 
                      1)))

Si nous utilisons ce schéma sur votre propre code, nous obtenons ceci:

(custom-set-variables '(linum-format 'dynamic))
(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                      (+ (count-lines (point-min) (point-max)) 1))))       
          (linum-format 
            (concat " %" (number-to-string w) "d ")))
     ad-do-it))

Notez la forte corrélation entre l'indentation et le niveau d'imbrication. Les lignes avec un niveau d'imbrication plus élevé sont toujours plus en retrait que les lignes avec moins.

Cela seul aidera beaucoup. Vous pouvez facilement voir la "forme" du code, et la plupart des autres langues vous ont appris à associer l'indentation avec des blocs et des blocs avec une forme d'imbrication (explicite ou implicite).

Comme exercice, j'ai supprimé les parenthèses non essentielles du code. Vous devriez être capable à la fois de lire le code et de fournir les parenthèses manquantes, étant donné les connaissances de base d'Elisp (à savoir, quelles sont les fonctions et les valeurs, et la structure de let*).

custom-set-variables '(linum-format 'dynamic)
defadvice linum-update-window (around linum-dynamic activate)
  let* w length number-to-string
                  + 
                    count-lines (point-min) (point-max) 
                    1       
         linum-format 
           concat " %" (number-to-string w) "d "
     ad-do-it
PythonNut
la source
1
Notez que dans Emacs, appuyer sur tab définira presque toujours correctement l'indentation comme décrit ici - vous ne devriez jamais le faire en ajoutant des espaces à la main!
Tyler
Lier "Cm" à newline-and-indentpour emacs-lisp-mode et lisp-interaction-mode résout votre premier exemple, PythonNut. Et TAB fera le travail le reste du temps.
Davor Cubranic
5

J'inclus cela comme une réponse différente.

Parfois, l'indentation vous fera défaut. Votre recours est alors d'utiliser quelque chose comme rainbow-delimiters:

entrez la description de l'image ici

Cela rend le niveau d'imbrication de tout paren explicite et facilement analysé.

Il y a cependant un gros problème: les parens distraient ridiculement. Il y a un équilibre important ici. rainbow-delimitersmettra normalement beaucoup d'emphase sur les parens au détriment du reste de votre code! Mais si vous atténuez l'arc-en-ciel, il devient de plus en plus difficile à scanner.

Si vous pouvez trouver un ensemble de visages qui équilibre bien cela, alors utilisez-le par tous les moyens.

Cela dit, une solution (celle qui me fait glousser de joie) est d'avoir deux visages et de basculer entre eux à la volée. Lorsque vous faites d'autres choses, les visages sont dilués et s'estompent à l'arrière-plan:

entrez la description de l'image ici

Mais lorsque vous mettez le point sur une paren, il frappe les parens afin que vous puissiez voir les niveaux d'imbrication:

entrez la description de l'image ici

Et voici le code pour le faire:

(defvar rainbow-delimiters-switch nil
  "t if rainbow-delimiters are currently punched")
(defvar rainbow-delimiters-face-cookies nil
  "a list of face-remap-add-relative cookies to reset")

(make-variable-buffer-local 'rainbow-delimiters-switch)
(make-variable-buffer-local 'rainbow-delimiters-face-cookies)

(add-hook 'prog-mode-hook #'rainbow-delimiters-mode)
(add-hook 'text-mode-hook #'rainbow-delimiters-mode)

(with-eval-after-load 'rainbow-delimiters
  (set-face-foreground 'rainbow-delimiters-depth-1-face "#889899")
  (set-face-foreground 'rainbow-delimiters-depth-2-face "#9b7b6b")
  (set-face-foreground 'rainbow-delimiters-depth-3-face "#7b88a5")
  (set-face-foreground 'rainbow-delimiters-depth-4-face "#889899")
  (set-face-foreground 'rainbow-delimiters-depth-5-face "#839564")
  (set-face-foreground 'rainbow-delimiters-depth-6-face "#6391aa")
  (set-face-foreground 'rainbow-delimiters-depth-7-face "#9d748f")
  (set-face-foreground 'rainbow-delimiters-depth-8-face "#7b88a5")
  (set-face-foreground 'rainbow-delimiters-depth-9-face "#659896")

  (defun rainbow-delimiters-focus-on ()
    "Punch the rainbow-delimiters"
    (setq rainbow-delimiters-face-cookies
      (list
        (face-remap-add-relative 'rainbow-delimiters-depth-1-face
          '((:foreground "#3B9399") rainbow-delimiters-depth-1-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-2-face
          '((:foreground "#9B471D") rainbow-delimiters-depth-2-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-3-face
          '((:foreground "#284FA5") rainbow-delimiters-depth-3-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-4-face
          '((:foreground "#3B9399") rainbow-delimiters-depth-4-face))
            (face-remap-add-relative 'rainbow-delimiters-depth-5-face
          '((:foreground "#679519") rainbow-delimiters-depth-5-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-6-face
          '((:foreground "#0E73AA") rainbow-delimiters-depth-6-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-7-face
          '((:foreground "#9D2574") rainbow-delimiters-depth-7-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-8-face
          '((:foreground "#284FA5") rainbow-delimiters-depth-8-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-9-face
          '((:foreground "#199893") rainbow-delimiters-depth-9-face)))
      rainbow-delimiters-switch t))

  (defun rainbow-delimiters-focus-off ()
    "Reset the rainbow-delimiters faces"
    (mapc #'face-remap-remove-relative rainbow-delimiters-face-cookies)
    (setq rainbow-delimiters-switch nil))

  (defun rainbow-delimiters-focus-on-maybe ()
    "Punch the rainbow-delimiters if the point is on a paren"
    (when (looking-at "[][(){}]")
      (unless (or rainbow-delimiters-switch (minibufferp))
        (rainbow-delimiters-focus-on))))

  (defun rainbow-delimiters-focus-off-maybe ()
    "Reset the rainbow-delimiters if the point is not on a paren"
    (unless (looking-at "[][(){}]")
      (when rainbow-delimiters-switch
        (rainbow-delimiters-focus-off))))

  (run-with-idle-timer 0.6 t 'rainbow-delimiters-focus-on-maybe)
  (run-with-idle-timer 0.1 t 'rainbow-delimiters-focus-off-maybe))
PythonNut
la source
C'est cool! Une raison pour laquelle vous avez choisi les délimiteurs arc-en-ciel plutôt que les parenthèses de surbrillance pour commencer?
Tyler
@Tyler sans raison particulière, bien que je m'en tienne toujours aux délimiteurs arc-en-ciel maintenant (mais c'est peut-être parce que j'y suis habitué). Je n'avais tout simplement pas entendu parler de parenthèses surlignées jusqu'à très récemment.
PythonNut du
4

Si vous indentez votre code, vous devez vraiment l'indenter correctement. Les développeurs Lisp attendent de ce à quoi devrait ressembler un retrait correct. Cela ne signifie pas que le code se ressemble tout de même. Il existe encore différentes façons de formater le code.

  • combien de temps une ligne doit-elle être?
  • comment distribuer un appel de fonction / macro sur des lignes?
  • combien d'espaces d'indentation doit-il y avoir?
(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
            ad-do-it))

Je m'attendrais à ce que l'indentation montre un certain confinement. Mais pas dans votre code.

Par défaut, votre code peut être indenté comme ceci. D'autres réponses décrivent comment vous pouvez le faire avec l'aide d'Emacs:

(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                     (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
    ad-do-it))

Je m'attendrais à ce que les letvariables liées commencent sur la même colonne verticale. Je m'attendrais également à ce que le corps du letsoit moins échancré. Nous apprenons comment un letdoit être mis en retrait. Une fois que vous vous entraînez un peu, c'est un modèle visuel facile à reconnaître.

Les principaux blocs de construction visuels dans le code sont defadvice, let*et un tas d'appels de fonction. Le defdans le nom me dit que c'est une définition suivie d'un nom, d'une liste d'arguments et d'un corps.

Ainsi j'aime voir

defadvice name arglist
  body

Le let*serait:, let*une liste de fixations et un corps.

Ainsi j'aime voir:

let*  list of bindings
  body

Plus détaillé:

let*   binding1
       binding2
       binding3
  body

Pour un appel de fonction, j'aime voir:

FUNCTIONNAME ARG1 ARG2 ARG3

ou

FUNCTIONNAME ARG1
             ARG2
             ARG3

ou

FUNCTIONNAME
  ARG1
  ARG2
  ARG3

Celui qui est utilisé dépend de la durée des arguments. Nous ne voulons pas faire des lignes trop longues et chaque argument sur sa propre ligne nous permet d'avoir plus de structure.

Vous devez donc écrire votre code en utilisant ces modèles et vous devez vous assurer que le lecteur peut facilement identifier ces modèles dans votre code.

Les parenthèses doivent entourer directement leurs constructions.

(sin 10)

(sin
  10)

Évitez les exemples d'espaces:

(  sin 10  )

ou

(
   sin
)

ou

(sin 10
)

En Lisp, les parenthèses n'ont pas de fonction syntaxique de langage, elles font partie de la syntaxe de la structure de données de la liste (expressions s). Ainsi, nous écrivons des listes et formaterons les listes. Pour formater le contenu de la liste, nous utilisons des connaissances sur le langage de programmation Lisp. Une letexpression doit être formatée différemment d'un appel de fonction. Les deux sont toujours des listes et les parenthèses doivent entourer directement les listes. Il y a quelques exemples où il est logique d'avoir une seule parenthèse sur une ligne, mais utilisez-la rarement.

Utilisez les parenthèses pour vous aider à trouver les limites de l'expression. Laissez-les vous aider à passer d'une liste à l'autre, à modifier des listes, à couper et copier des listes, à remplacer des listes, à mettre en retrait / formater des listes, à sélectionner des listes, ...

Rainer Joswig
la source
2

Pour obtenir une aide de base sur l'indentation, utilisez TAB et "CMq" ( indent-pp-sexp); la liaison "Cm" à newline-and-indentvous évitera d'avoir à appuyer sur TAB après une nouvelle ligne.

Vous pouvez naviguer par sexe avec "CM-gauche / droite / haut / bas / maison / fin", ce qui est très utile.

Si vous êtes inquiet de maintenir l'équilibre entre parenthèses, utilisez quelque chose comme les smartparens (c'est un peu plus indulgent que le paredit , qui peut initialement donner l' impression de porter une camisole de force). Il est également livré avec de nombreuses liaisons pour naviguer et éditer au niveau sexp.

Enfin, pour mettre en évidence les parens, commencez par activer l'option (menu Options-> Mettre en surbrillance les parenthèses correspondantes, ou show-paren-mode.) Vous pouvez également utiliser l'un des packages mentionnés par lawlist dans son commentaire, comme "highlight-parenthesis" ou "rainbow-delimiters ".

Davor Cubranic
la source
1

En plus de ce que les autres ont donné comme réponses, voici mes 2 cents:

  • L'indentation automatique fournie par emacs-lisp-modeest essentielle.
  • blink-matching-parenest activé (non nil) par défaut. Laissez-le.
  • J'utilise show-paren-mode, pour mettre en surbrillance la paren gauche correspondant à la paren droite devant le curseur.
  • Je supprime et retape temporairement la paren droite avant le curseur, si je veux mieux voir où se trouve la paren gauche correspondante.

Je n'utilise pas d'appairage électrique ou d'arc-en-ciel, ni aucune autre "aide". Pour moi, ce sont des ennuis, pas une aide.

En particulier, electric-pair-modeest, pour moi, une gêne gênante. Mais certaines personnes l'adorent. Et j'imagine que cela pourrait être utile dans d'autres contextes d'appariement en plus des parenthèses Lisp (j'imagine, mais je ne suis pas convaincu pour de tels cas d'utilisation non plus).

Vous trouverez ce qui vous convient le mieux. Les principales choses que je veux dire sont: (1) l'indentation automatique est votre ami, tout comme un moyen de repérer la paren gauche qui correspond à la paren droite avant le point.

En particulier, voir ce que l'indentation automatique fait pour vous vous apprend immédiatement que vous ne voulez plus jamais mettre les bonnes parenthèses en ligne par elles-mêmes. Ce style de codage, qui est omniprésent dans d'autres langues, est tout simplement bruyant.

Outre l'indentation automatique que vous obtenez avec, RETet que vous vous sentez à l' TABaise avec C-M-q. (Utilisation C-h ken emacs-lisp-modepour savoir ce que ces clés font.)

A dessiné
la source
1

J'ai remarqué que certaines personnes ont déjà mentionné les délimiteurs arc-en-ciel, c'est aussi mon mode préféré lors de l'édition de code lisp.

En fait, j'aime les parenthèses, la meilleure chose à propos de Lisp est ces parenthèses, c'est amusant de les traiter si vous savez comment:

  • installez evil-mode et son plugin evil-surround, afin que vous puissiez éditer facilement les parenthèses, par exemple, appuyez sur ci(supprimera tout ce qui se trouve à l'intérieur (), va(sélectionnera la chose enveloppée par "()" et les "()" eux-mêmes. et vous pouvez appuyer sur %pour sauter entre les parenthèses correspondantes

  • utilisez flycheck ou flymake, les parenthèses inégalées seront soulignées en temps réel

chen bin
la source
0

La difficulté ici est que vous voulez ajouter du code avant et après un certain sexp. Dans cette situation, le sexp est (concat " %" (number-to-string w) "d "). Vous souhaitez insérer l' instruction if (if (> w 1) avant et l' instruction else " %2d ") après.

Une grande partie de la difficulté est d' isoler cela sexp, personnellement j'utilise la commande ci-dessous pour isoler unsexp

(defun isolate-sexp () (interactive)
       (save-excursion (forward-sexp) (if (not (eolp-almost))
               (split-line) nil)))
(defun eolp-almost () (interactive)
(save-excursion (while (equal (char-after) ? ) (forward-char 1))
        (if (eolp) t nil )      ))

Placez simplement le curseur au début (concat " %" (number-to-string w) "d "), c'est-à-dire au premier (, puis appliquez ce qui précède isolate-sexp. Vous obtenez

(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")
                                  ))
            ad-do-it))

Ajoutez ensuite le code approprié avant et après cela sexp, c'est-à-dire

(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (if (> w 1) (concat " %" (number-to-string w) "d ") " %2d ")
                                  ))
            ad-do-it))

Et le tour est joué. Le code obtenu de cette manière n'est peut-être pas beau mais les chances de se perdre sont moindres.

Nom
la source