Comment mettre en forme un code assez joli (insertion de nouvelles lignes, retrait, etc.)?

24

J'utilise spacemacsmais je suppose que ce sont les connaissances emacs qui sont requises ici.

J'ai un fichier JSON avec une seule longue ligne, disons ce JSON de json.org/example:

{"menu": {"id": "file", "value": "File", "popup": {"menuitem": [{"value": "New", "onclick": "CreateNewDoc()"}, {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"}]}}}

J'aimerais qu'emacs réindente cela, ce qui signifie pour moi de ne pas changer le caractère le plus à gauche de la ligne au niveau d'indentation approprié, mais de casser la ligne en plusieurs lignes.

Si j'utilise spacemacs/indent-region-or-buffer( SPC j =) alors le texte n'est pas changé du tout.

Comment pourrais-je demander à emacs de briser cette longue file d'attente et de se réindenter pour obtenir quelque chose comme ceci:

{"menu": {
  "id": "file",
  "value": "File",
  "popup": {
    "menuitem": [
      {"value": "New", "onclick": "CreateNewDoc()"},
      {"value": "Open", "onclick": "OpenDoc()"},
      {"value": "Close", "onclick": "CloseDoc()"}
    ]
  }
}}

Je ne suis pas intéressé par une réponse spécifique à JSON, par exemple je crois qu'intelliJ le fait pour n'importe quelle langue qu'il supporte (java, json ...). Je pense que c'est réalisable pour n'importe quel langage emacs a un mode majeur pour, ou disons les plus populaires.

EDIT J'ai découvert M-x json-reformat-regionque spacemacslivré avec et fonctionne, mais oui, j'aimerais ça pour n'importe quelle langue et avec toujours le même raccourci, basé sur le mode majeur ...

EDIT2 Ok donc ma conclusion est qu'il est implémenté pour différentes langues, JSON & lisp au moins, probablement d'autres, et il serait facile pour encore plus (XML / XHTML, go qui a go-fmt et utilise également clang). Cependant, il n'y a pas de nom de fonction générique qui le ferait pour tous les langages. Il y a de la place ici pour l'implémenter en spacemacscouches pour les différents langages ... Je n'ai cependant pas trouvé d'implémentation X / HTML, ce qui m'étonne un peu.

Emmanuel Touzery
la source
3
Pour HTML / JS / CSS: web-beautiful.el. C'est le meilleur que j'ai trouvé, mais cela dépend de node.js.
nounou

Réponses:

10

Il semble que vous ayez plus besoin de la fill-regionfonction que de l'indentation.

  • Sélectionnez cette ligne et faites M-x fill-region.
  • Sélectionnez le même, maintenant divisé en plusieurs lignes, et faites M-x indent-region.

Cependant, cela n'insérera pas de nouvelles lignes aux points exacts comme indiqué dans votre exemple. Cela rendra simplement la ligne ajustée dans les colonnes de remplissage.

Kaushal Modi
la source
1
c'est quelque chose. Peut-être que ce que je voulais n'était pas réalisable de toute façon. Peut-être que j'attendrai un peu plus longtemps au cas où quelqu'un aurait une solution magique pour une indentation agressive plus intelligente ... Si rien d'autre ne se présente, je marquerai cela comme la réponse.
Emmanuel Touzery
@EmmanuelTouzery Ce que vous voulez est réalisable avec peu d'élisp tant que les règles d'insertion de la nouvelle ligne sont cohérentes. Dans votre exemple de résultat mis en forme, je vois que vous ne disposez pas d' un saut de ligne après {dans {"menu":mais vous n'avez un après {dans {"id":. Je ne connais pas JSON et donc votre réponse formatée a probablement un modèle qui me manque. Mais si vous pouvez mettre à jour votre question avec un ensemble de règles pour insérer cette nouvelle ligne, alors quelqu'un peut trouver la réponse que vous voulez.
Kaushal Modi
Je pensais que cela aurait existé pour n'importe quelle langue, y compris les règles spécifiques à la langue. Par exemple {sur la première ligne pour java, sur la ligne suivante pour C # disons, et ainsi de suite.
Emmanuel Touzery
(en d'autres termes, quelque chose comme gofmtmais pour n'importe quelle langue) - gofmt.com
Emmanuel Touzery
19

json.elpackage fournit json-pretty-print-buffer. C'est ce qu'il produit pour votre exemple:

{
  "menu": {
    "popup": {
      "menuitem": [
        {
          "onclick": "CreateNewDoc()",
          "value": "New"
        },
        {
          "onclick": "OpenDoc()",
          "value": "Open"
        },
        {
          "onclick": "CloseDoc()",
          "value": "Close"
        }
      ]
    },
    "value": "File",
    "id": "file"
  }
}

Semble assez décent pour moi.

wvxvw
la source
2
Oui, en fait, j'ai vu sur github.com/gongo/json-reformat que "De emacs 24.4, json-pretty-printet json-pretty-print-buffer(spécifications similaires à json-reformat-region) était fourni". Mais je pensais qu'emacs pourrait avoir une fonction qui fonctionnerait pour toutes les langues (spécifique à chaque langue en mode majeur populaire), ce qui n'est pas le cas.
Emmanuel Touzery
c'est la bonne réponse
Joe Heyming
6

Selon l'astuce ici , vous pouvez utiliser une commande externe pour formater une région dans votre fichier Json:

(defun json-format ()
  (interactive)
  (save-excursion
    (shell-command-on-region (region-beginning)
                             (region-end)
                             "python -m json.tool"
                             (buffer-name)
                             t)))

Vous pouvez facilement l'étendre pour formater l'ensemble du tampon:

(defun json-format ()
  (interactive)
  (save-excursion
    (shell-command-on-region (point-min)
                             (point-max)
                             "python -m json.tool"
                             (buffer-name) t))) 

Emacs n'a pas d'outil de formatage pour les langages de programmation ( sauf pour Lisp ), seulement des commandes d'indentation.

Tu Do
la source
1
J'ai découvert M-x json-reformat-regionque ça spacemacsmarche avec et ça marche, mais oui, j'aimerais ça pour n'importe quelle langue et avec toujours le même raccourci, basé sur le mode majeur ... Il semble que ce ne soit pas supporté, dommage ...
Emmanuel Touzery
1
Pour formater correctement une langue, vous avez besoin d'un analyseur de langue réel. Emacs a des analyseurs de langage intégrés pour certaines langues, mais seul l'analyseur Lisp intégré est récemment utilisé pour le reformatage du code, comme lien vers la démo ci-dessus. S'il existe des formateurs externes, il est facile de les intégrer à Emacs, c'est-à-dire clang-format.
Tu Do
2

Pour ce scénario spécifique, json-pretty-printcela embellira le morceau de json en surbrillance.

Fergie
la source
1

BTW, pour les principaux modes utilisant SMIE comme moteur d'indentation, il y a une partie de ce dont vous avez besoin pour cela sous la forme d'un auto-fill-modesupport. Je pense fill-paragraphou fill-regionne ferai pas un bon travail, mais si vous mettez votre code sur une seule ligne, allez à la fin de cette ligne et M-: (smie-auto-fill)cela devrait donner des résultats sensés (probablement pas parfait par une longue période, cependant).

Stefan
la source