Comment obtenir des effets de pliage de code dans Emacs?


123

Quelle est la meilleure façon de réaliser quelque chose comme le pliage de code, ou le type de cyclisme utilisé par le mode org. Quelle serait la meilleure solution dans elisp pour créer ce type de comportement?

EDIT: Je suis désolé, je n'ai pas été clair. Je veux programmer quelque chose dans elisp qui fait des choses très similaires au pliage de code, ou en fait plus comme le mode org avec la hiérarchie qui peut être développée. Je me demande la meilleure façon d'atteindre cet effet. Je pense avoir entendu dire que les superpositions emacs sont une bonne solution, mais je ne sais pas.

En ce qui concerne le pliage, j'utilise simplement l'affichage sélectif intégré

MODIFIER LE NUMÉRO 2:

Merci pour les réponses, mais je pense que je pose la mauvaise question, alors laissez-moi essayer d'être plus clair sur ce que j'essaie de faire. Je souhaite créer ce qui suit

Lorsque vous mettez votre point sur une fonction et que vous appelez cette fonction elisp, elle placera la définition de la fonction où qu'elle se trouve (je pense simplement utiliser find-tag pour cela) et la dépliera dans le tampon actuel. L'idée est que si vous devez passer à un tampon différent pour lire la définition de la fonction, j'ai l'impression que c'est un changement de contexte vers un autre fichier. Je voudrais donc qu'il se comporte comme un pliage de code, mais il extrait du code externe à la mémoire tampon. Cela pose certains problèmes car il ne peut pas coller le code dans la mémoire tampon ou si quelqu'un l'enregistre, il enregistre le code extrait. Je me demande donc s'il existe un moyen de créer une zone à l'intérieur d'un tampon qui ne fait pas non plus partie du tampon. Je pense que cela a du sens.


Vous recherchez quelque chose qui, lorsque vous l'appelez avec un point dans une fonction CALL, accède à la définition de la fonction? un peu comme obtenir de l'aide sur une fonction elisp vous permettra de passer au code elisp? Je ne pense pas que vous puissiez faire cela sans un concept de "Le projet" Par exemple, comment sauriez-vous à quelle fonction "swap" vous voulez passer?
Brian Postow

1
Voir aussi: stackoverflow.com/questions/382781/… où l'affichage sélectif est un peu modifié pour certains effets de type pliage.
Michael Paulukonis

Je vous recommande de supprimer votre EDIT NB 2et de lui poser une nouvelle question.
Stefan

Réponses:


151

Le pliage est généralement inutile avec emacs, car il dispose d'outils qui implémentent explicitement les actions que les gens font manuellement lors du pliage du code.

La plupart des gens réussissent bien avec de simples recherches incrémentielles. Voir "foo" mentionné quelque part? Tapez C-sfoo, recherchez la définition, appuyez sur Entrée, lisez-la, puis appuyez sur C-x C-xpour revenir là où vous étiez. Simple et très utile.

La plupart des modes prennent en charge imenu . M-ximenuvous permettra d'accéder à une définition de fonction (etc.) par son nom. Vous pouvez également le lier à un clic de souris pour obtenir un menu de fonctions (ou l'ajouter à la barre de menus; voir la page Info pour plus de détails). Il fournit des données pour quel mode-fonction, ce qui vous permettra de voir dans quelle fonction vous vous trouvez actuellement dans la modeline. (Pourquoi vos fonctions sont-elles si longues, cependant?)

Il existe également une barre de vitesse , qui affiche graphiquement les informations du menu (et d'autres choses).

Si vous voulez avoir un aperçu de votre fichier, essayez M-xoccur". Étant donné une expression régulière, il créera un nouveau tampon avec chaque correspondance dans le tampon courant. Vous pouvez rechercher" (defun "pour avoir un aperçu des fonctions du fichier courant Cliquez sur le résultat pour vous déplacer vers cette position dans le fichier.

Alors de toute façon, pensez à ce que vous voulez vraiment réaliser, et Emacs l'implémentera probablement. Ne vous battez pas avec des outils imparfaits qui vous font plier et déplier constamment les choses.


13
Vim fournit également toutes ces fonctionnalités sous une forme ou une autre, mais je trouve toujours sa fonction de pliage de code inestimable.
intuité

115
J'ai voté à la baisse pour la première phrase ("Le pliage n'est généralement pas nécessaire avec emacs, comme ..."). J'utilise constamment un pliage simple (basé sur le niveau de retrait) pour analyser la structure du code inconnu.
Simon Michael

4
Ms o est le raccourci pour Mx se produire
Joshua Olson

3
J'ai voté à la hausse parce que de nombreux raccourcis utiles dans la réponse mais aussi un commentaire @SimonMichael voté à la hausse parce que plier / déplier pourrait encore être utile parfois!
Adrien Coquio

56
La réponse était bien pensée et très informative. Cependant, l'OP a demandé comment faire le pliage de code. L'OP n'a pas demandé quelle était la manière préférée de tout le monde d'éviter le pliage de code. Bas voté.
wkschwartz

104

mode hide-show ( hs-minor-mode) avec raccourci clavier par défaut C-c @ C-M-hpour déclencher le repliement ( hs-hide-all)


12
Cela fonctionne bien. Et avec le mal-mode, cela est déclenché par les commandes de vim normales: zR, zM, zo, zc.
Justin M. Keyes

39

Une autre façon d'écorcher le chat:

En l'occurrence, vous n'avez besoin d'aucun package ou configuration supplémentaire pour cela. Accédez simplement à n'importe quel fichier source, tapez

M-1 Cx $ et la magie opère!

Comme d'habitude, c'est de la magie blanche: Cx $ ramènera votre code.

Nous pouvons utiliser le système d'aide d'Emacs pour découvrir ce qui se passe: Ch k Cx $ nous dit que la combinaison de touches ci-dessus appelle set-selective-display , une fonction qui prend un argument numérique (le préfixe M-1 passe 1 comme valeur de cet argument) et, sans surprise, définit la variable d'affichage sélectif sur la valeur de cet argument.

du blog de sorcellerie mineur emacs

Juste pour être complet: M-3 Cx $ afficherait un code imbriqué plus profond et ainsi de suite.

FWIW J'ai fait une petite aide aujourd'hui basée sur smth. trouvé ici pour que F5 bascule le pliage du code en fonction de la position actuelle du curseur:

(global-set-key (kbd "<f5>") 'set-selective-display-dlw)

(defun set-selective-display-dlw (&optional level)
"Fold text indented same of more than the cursor.
If level is set, set the indent level to LEVEL.
If 'selective-display' is already set to LEVEL, clicking
F5 again will unset 'selective-display' by setting it to 0."
  (interactive "P")
  (if (eq selective-display (1+ (current-column)))
      (set-selective-display 0)
    (set-selective-display (or level (1+ (current-column))))))

22

J'utilise le mode mineur de contour pour plier mon code python. Au lieu de devoir placer {{{et}}} comme en mode pliage, il utilise l'endroit où le bloc est défini.

http://www.gnu.org/software/emacs/manual/html_node/emacs/Outline-Mode.html http://www.emacswiki.org/emacs/OutlineMinorMode

Je suis à peu près sûr qu'il est livré avec emacs. J'ajoute ensuite ceci à mes .emacs

;;======= Code folding =======
(add-hook 'python-mode-hook 'my-python-outline-hook)
; this gets called by outline to deteremine the level. Just use the length of the whitespace
(defun py-outline-level ()
  (let (buffer-invisibility-spec)
    (save-excursion
      (skip-chars-forward "    ")
      (current-column))))
; this get called after python mode is enabled
(defun my-python-outline-hook ()
  ; outline uses this regexp to find headers. I match lines with no indent and indented "class"
  ; and "def" lines.
  (setq outline-regexp "[^ \t]\\|[ \t]*\\(def\\|class\\) ")
  ; enable our level computation
  (setq outline-level 'py-outline-level)
  ; do not use their \C-c@ prefix, too hard to type. Note this overides some bindings.
  (setq outline-minor-mode-prefix "\C-t")
  ; turn on outline mode
  (outline-minor-mode t)
  ; initially hide all but the headers
  ;(hide-body)
  ; make paren matches visible
  (show-paren-mode 1)
)

8
ressemble à outline-modeprend en charge python prêt à l'emploi dans emacs 24 - pas besoin de outline-levelfonctions personnalisées . C'est tout ce dont j'avais besoin pour ajouter à mon user.el:(add-hook 'python-mode-hook 'outline-minor-mode)
scytale

1
oh et vous voulez vraiment remplacer outline-minor-mode-prefix- les raccourcis clavier par défaut sont horribles - j'utilise(setq outline-minor-mode-prefix (kbd "C-;"))
scytale

13

Vous pouvez également obtenir le pliage de code en utilisant CEDET avec le code suivant dans le fichier init:

(global-semantic-folding-mode t)

Après évaluation de ce code, le petit triangle apparaîtra dans la zone fringle, vous pourrez donc plier et déplier le code en l'utilisant. Cette méthode est plus précise, car elle utilise des informations syntaxiques, extraites du code source


1
si vous rencontrez un bug, jetez un œil à cette question: stackoverflow.com/questions/15307113
...

9

hs-minor-mode fonctionne à merveille.

Cela fonctionne encore plus magnifiquement lorsqu'il est associé à fold-dwim (faites ce que je veux dire). Ensuite, il y a fold-dwim-org, qui fournit des raccourcis clavier comme le mode org pour le pliage de code! Les deux peuvent être installés via la marmelade (et je pense elpa).



5

vimish-fold est également une solution simple et agréable.

https://github.com/mrkkrp/vimish-fold .

Depuis la page d'accueil:

Il s'agit d'un package pour effectuer le pliage de texte comme dans Vim. Il présente les caractéristiques suivantes:

  • pliage des régions actives;
  • bonne rétroaction visuelle: il est évident quelle partie du texte est pliée;
  • persistance par défaut: lorsque vous fermez le fichier, vos plis ne disparaissent pas;
  • la persistance s'adapte bien, vous pouvez travailler sur des centaines de fichiers avec beaucoup de plis sans effets indésirables;
  • il ne rompt pas l'indentation ou quelque chose du genre;
  • les plis peuvent être basculés de l'état plié à l'état déplié et à l'arrière très facilement;
  • navigation rapide entre les plis existants;
  • vous pouvez utiliser la souris pour déplier les plis (bon pour les débutants et pas seulement pour eux);
  • pour les fans du package avy: vous pouvez utiliser avy pour plier du texte avec un nombre minimal de touches!

En utilisant l'excellent, use-packageje l'installe et l'active en utilisant cet extrait de code dans ma configuration:

(use-package vimish-fold
  :ensure t
  :config (vimish-fold-global-mode t))

3

Je suis surpris que personne n'ait mentionné le rétrécissement-élargissement. C'est super génial, il est également livré avec emacs. Sélectionnez simplement le code sur lequel vous souhaitez vous concentrer et appuyez sur C-x n n, pour revenir au mode plein écran, faites-le C-x n w. Je préfère toujours utiliser la fonctionnalité emacs intégrée plutôt que d'encombrer mon espace utilisateur avec un autre package. Si emacs peut le faire avec des fonctionnalités intégrées, je préférerai cela à un package tiers, mais ce n'est que moi, cela ne veut pas dire ou n'implique rien d'autre que le fait que j'aime les choses simples sur des configurations longues et complexes.



2

Je pense que votre comparaison de votre "projet" au pliage n'est pas tout à fait bonne, car le pliage consiste à changer l'apparence tout en gardant le contenu du tampon intact (le texte). Votre projet impliquerait d'afficher du texte supplémentaire tout en gardant le contenu du tampon intact, AFAIU. Alors. il n'est pas implémentable en tant que composition d'insertion et de pliage de texte (alors, le contenu du tampon serait modifié).

Mais peut-être, c'est en effet possible avec le même mécanisme que le pliage est fait avec - "superpositions" ... Considérez les propriétés de superposition "before-string" et "after-string" ; peut-être que vous pourriez mettre vos définitions de fonction dans ces chaînes appartenant à une superposition de longueur nulle au point. Regardez la fonction outline-flag-region pour voir comment les superpositions sont utilisées en mode contour.


2

Si vous utilisez hs-minor-mode, cela peut être une bonne idée de définir également un raccourci plus pratique, par exemple:

(eval-after-load 'hideshow
 '(progn
   (global-set-key (kbd "C-+") 'hs-toggle-hiding)))

0

Inspiré de la réponse d' einSelbst :

(conseil-ajouter 'affichage sélectif
            : filter-args (lambda (args)
                           (si (ou (car args) affichage sélectif)
                               args
                             (liste (1+ (colonne courante)))))
            '((nom. set-selective-display-from-cursor-column)))

Voila, est C-x $soudainement devenu utile même sans aucun C-uni M-4entreprise.


0

Si vous utilisez du JavaScript et que vous utilisez js2-mode.el, vous pouvez:

C-c C-f: basculer cacher / tout afficher

C-c C-e: masquer l'élément

C-c C-s: afficher l'élément

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.