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))
la source
%2d
parce qu'une fois que la largeur passe à 3 caractères ou plus, elle passe de justifié à droite à justifié à gauche.highlight-parentheses
;rainbow-delimiters
; etc. Voici ma propre version simplifiéehighlight-parentheses
qui 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.Réponses:
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-b
pour avancer / reculer de sexpC-M-n
/C-M-p
pour avancer / reculer par listeC-M-u
/C-M-d
pour monter / descendre d'un niveauC-M-t
pour échanger les deux sexps autour du pointC-M-k
tuer un sexpC-M-SPC
pour marquer un sexpC-M-q
pour ré-indenter un sexpL'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 surC-M-q
pour ré-indenter l'expression entière. Pour remplacer le(concat...
je commencerais par mettre un point au début de ce sexp et frapperC-M-o
pour 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-mode
cette 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 personnalisershow-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.
la source
C-M-q
peut ê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 toujoursC-x u
annuler).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.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 danslispy
est 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
()
, appuyez sur (.if
.()
.> w 10
.Étape 4
Pour cloner la chaîne:
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:
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
2
pour obtenir le code de fin: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.
la source
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:
Supposons que ce
1
soit vraiment une grande expression et que vous souhaitiez l'indenter sur sa propre ligne.C'est trompeur.
1
est 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.Si nous utilisons ce schéma sur votre propre code, nous obtenons ceci:
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*
).la source
newline-and-indent
pour emacs-lisp-mode et lisp-interaction-mode résout votre premier exemple, PythonNut. Et TAB fera le travail le reste du temps.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
: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-delimiters
mettra 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:
Mais lorsque vous mettez le point sur une paren, il frappe les parens afin que vous puissiez voir les niveaux d'imbrication:
Et voici le code pour le faire:
la source
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.
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:
Je m'attendrais à ce que les
let
variables liées commencent sur la même colonne verticale. Je m'attendrais également à ce que le corps dulet
soit moins échancré. Nous apprenons comment unlet
doit ê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. Ledef
dans 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
Le
let*
serait:,let*
une liste de fixations et un corps.Ainsi j'aime voir:
Plus détaillé:
Pour un appel de fonction, j'aime voir:
ou
ou
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.
Évitez les exemples d'espaces:
ou
ou
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
let
expression 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, ...
la source
Pour obtenir une aide de base sur l'indentation, utilisez TAB et "CMq" (
indent-pp-sexp
); la liaison "Cm" ànewline-and-indent
vous é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 ".la source
En plus de ce que les autres ont donné comme réponses, voici mes 2 cents:
emacs-lisp-mode
est essentielle.blink-matching-paren
est activé (nonnil
) par défaut. Laissez-le.show-paren-mode
, pour mettre en surbrillance la paren gauche correspondant à la paren droite devant le curseur.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-mode
est, 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,
RET
et que vous vous sentez à l'TAB
aise avecC-M-q
. (UtilisationC-h k
enemacs-lisp-mode
pour savoir ce que ces clés font.)la source
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 correspondantesutilisez flycheck ou flymake, les parenthèses inégalées seront soulignées en temps réel
la source
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
Placez simplement le curseur au début
(concat " %" (number-to-string w) "d ")
, c'est-à-dire au premier(
, puis appliquez ce qui précèdeisolate-sexp
. Vous obtenezAjoutez ensuite le code approprié avant et après cela
sexp
, c'est-à-direEt 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.
la source