How to achieve code folding effects in Emacs?
Asked Answered
S

14

150

What's the best way to achieve something like code folding, or the type of cycling that org-mode uses. What would be the best solution in elisp to create this type of behavior?

EDIT: I'm sorry I was not clear. I want to program something in elisp that does things very similar to code folding, or actually most like org-mode with the hierarchy that can be expanded. I am wondering the best way to achieve this effect. I think I have heard emacs overlays are a good solution, but I don't know.

As far as folding I just use the builtin set-selective-display

EDIT NUMBER 2:

Thanks for the answers but I think I am asking the wrong question so let me try to be more clear on what I am trying to do. I would like to create the following

When you put your point on a function and call this elisp function it will put the function definition from wherever it is (I am thinking of just using find-tag for this) and unfold it in the current buffer. The idea is if you have to jump to a different buffer to read the function definition I feel like it's a context switch to another file. So I would like it to behave like code folding only it pulls in code external from the buffer. This presents some problems as it can not actually paste the code into the buffer or if someone saves it will save the pulled in code. So I am wondering if there is a way to create an area inside a buffer that is also not part of the buffer. I think that makes sense.

Settling answered 6/7, 2009 at 2:29 Comment(3)
You're looking for something that when you call it with point in a function CALL it jumps to the function definition? sort of like getting help about an elisp function will let you jump to the elisp code? I don't think you can do this without some concept of "The project" For example, how would you know which "swap" function you want to jump to?Romanticism
See also: #383281 where selective-display is tweaked a bit for some folding-like effects.Forbade
I recommend you remove your EDIT NB 2 and make a new question for it.Winch
F
152

Folding is generally unnecessary with emacs, as it has tools that explicitly implement the actions people do manually when folding code.

Most people have good success with simple incremental searches. See "foo" mentioned somewhere? Type C-sfoo, find the definition, press enter, read it, and then press C-x C-x to go back to where you were. Simple and very useful.

Most modes support imenu. M-ximenu will let you jump to a function definition (etc.) by name. You can also bind it to a mouse click to get a menu of functions (or add it to the menubar; see the Info page for more detail). It provides data for which-function-mode, which will let you see which function you are currently inside in the modeline. (Why are your functions this long, though?)

There is also speedbar, which displays the imenu information (and other things) graphically.

If you want to get an overview of your file, try M-xoccur". Given a regex, it will create a new buffer with each match in the current buffer. You can search for "(defun" to get an overview of the functions the current file implements. Clicking on the result will move you to that position in the file.

So anyway, think about what you really want to achieve, and Emacs probably implements that. Don't fight with imperfect tools that make you fold and unfold things constantly.

Falsity answered 31/7, 2009 at 8:35 Comment(8)
Vim also provides all of these features in one form or another but I still find its code folding facility invaluable.Erma
M-x occur just saved me a bunch of headache. Excellent post!Wipe
I down-voted for the first sentence ("Folding is generally unnecessary with emacs, as..."). I use simple folding (based on indent level) constantly to scan the structure of unfamiliar code.Mitzimitzie
M-s o is the shortcut for M-x occurBloater
I up-voted because many useful shortcut in the answer but also up-voted @SimonMichael comment because fold / unfold could still be useful sometimes !Twophase
The answer was well thought out and very informative. However, the OP asked how to do code folding. The OP did not ask what everyone's favorite way of avoiding code folding was. Down voted.Cheston
It is true that the question was about folding. But what @Falsity wants to say is that folding is way of using, to people that aren't aware of all that emacs can offer. he gives the extra mile, and i don't think anyone needs to down vote him for that, on contrary.Kep
Folding is useful when looking at how the code before a block relates to the code after the block, for example when checking to see that elements that must be paired are paired properly. All the techniques listed above have a place, and so does folding.Ultramontanism
S
157

You can use the hide-show mode (hs-minor-mode). To activate this mode on the fly for the current buffer only, type M-x hs-minor-mode RET

Assuming you have the default keybinding:

  • C-c @ C-M-h To fold it all (hs-hide-all).
  • C-c @ C-h Hides the current block (hs-hide-block). The point (cursor) has to be inside the block.
  • C-c @ C-s Show current block (hs-show-block). The point has to be in the {...} marker that is hiding the code.
Statampere answered 30/7, 2009 at 19:18 Comment(3)
This works well. And with evil-mode, this is triggered by the normal vim commands: zR, zM, zo, zc.Underbodice
Should be the accepted answer, this is THE way to code folding in emacs. Works very well everywhere and built-in.Fabliau
For me this really fails with Python. I had a class that was about 80 lines and then below that I had another 100 lines of code that all got folded when trying to fold the class so this was a bit more aggressive then I would have liked.Related
F
152

Folding is generally unnecessary with emacs, as it has tools that explicitly implement the actions people do manually when folding code.

Most people have good success with simple incremental searches. See "foo" mentioned somewhere? Type C-sfoo, find the definition, press enter, read it, and then press C-x C-x to go back to where you were. Simple and very useful.

Most modes support imenu. M-ximenu will let you jump to a function definition (etc.) by name. You can also bind it to a mouse click to get a menu of functions (or add it to the menubar; see the Info page for more detail). It provides data for which-function-mode, which will let you see which function you are currently inside in the modeline. (Why are your functions this long, though?)

There is also speedbar, which displays the imenu information (and other things) graphically.

If you want to get an overview of your file, try M-xoccur". Given a regex, it will create a new buffer with each match in the current buffer. You can search for "(defun" to get an overview of the functions the current file implements. Clicking on the result will move you to that position in the file.

So anyway, think about what you really want to achieve, and Emacs probably implements that. Don't fight with imperfect tools that make you fold and unfold things constantly.

Falsity answered 31/7, 2009 at 8:35 Comment(8)
Vim also provides all of these features in one form or another but I still find its code folding facility invaluable.Erma
M-x occur just saved me a bunch of headache. Excellent post!Wipe
I down-voted for the first sentence ("Folding is generally unnecessary with emacs, as..."). I use simple folding (based on indent level) constantly to scan the structure of unfamiliar code.Mitzimitzie
M-s o is the shortcut for M-x occurBloater
I up-voted because many useful shortcut in the answer but also up-voted @SimonMichael comment because fold / unfold could still be useful sometimes !Twophase
The answer was well thought out and very informative. However, the OP asked how to do code folding. The OP did not ask what everyone's favorite way of avoiding code folding was. Down voted.Cheston
It is true that the question was about folding. But what @Falsity wants to say is that folding is way of using, to people that aren't aware of all that emacs can offer. he gives the extra mile, and i don't think anyone needs to down vote him for that, on contrary.Kep
Folding is useful when looking at how the code before a block relates to the code after the block, for example when checking to see that elements that must be paired are paired properly. All the techniques listed above have a place, and so does folding.Ultramontanism
H
52

Another way to skin the cat:

As it happens, you don’t need any package or extra configuration for that. Just go to any source file, type

M-1 C-x $ and magic happens!

As usual, it’s white magic: C-x $ will bring your code back.

We can use Emacs’ help system to discover what’s going on: C-h k C-x $ tells us that the above key combination is calling set-selective-display, a function that takes one numerical argument (the M-1 prefix passes 1 as the value of that argument) and, unsurprisingly, sets the variable selective-display to the value of that argument.

from minor emacs wizardry blog

Just for completeness: M-3 C-x $ would show deeper nested code and so on.

FWIW I made a tiny helper today based on smth. found here so that F5 toggles code folding based on the current cursor position:

(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))))))
Hokanson answered 2/1, 2015 at 21:50 Comment(1)
This is perfect, and set-selective-display-dlw is very good. ThanksEnfold
P
24

I use the outline minor mode to fold my python code. Instead of needing to place {{{ and }}} as in folding mode, it uses where the block is defined.

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

I am pretty sure that it comes with emacs. I then add this to my .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)
)
Perdomo answered 6/7, 2009 at 5:29 Comment(3)
looks like outline-mode supports python out-of-the-box in emacs 24 - no need for custom outline-level functions. This is all I needed to add to my user.el: (add-hook 'python-mode-hook 'outline-minor-mode)Taboret
oh and you definitely want to override outline-minor-mode-prefix - the default keybindings are awful - I use (setq outline-minor-mode-prefix (kbd "C-;"))Taboret
@Taboret Yes outline-mode supports the python-mode in emacs out of the box - but the code above uses py- and so is for the python python-mode and is still needed if you use that python-mode.Coronado
C
13

You can also get code folding by using CEDET with following code in init file:

(global-semantic-folding-mode t)

After evaluation of this code, the small triangle will appear in fringle area, so you will able to fold & unfold code using it. This method is more precise, as it uses syntactic information, extracted from source code

Capsular answered 6/7, 2009 at 5:46 Comment(2)
if facing some bug, have a look on this question: #15307613Means
Is this deprecated?Verbalism
J
11

hs-minor-mode works beautifully.

It works even more beautifully when paired with fold-dwim (do what I mean). Then there's fold-dwim-org, which provides org-mode like key-bindings for code folding! Both can be installed via marmalade (and I think elpa).

Jere answered 24/7, 2012 at 23:1 Comment(0)
A
9

I am surprised that noone mentioned narrowing-widening. It's super awesome, it comes bundled with emacs as well. Simply select code you want to focus on and press C-x n n, to go back to full view mode just do C-x n w. I always prefer to use built-in emacs functionality than clutter my user space with another package. If emacs can do it with built-in functionality then I'll prefer that over some third party package, but that's just me, doesn't mean or imply anything else besides that I like simple stuff over complex long configs.

Automate answered 30/9, 2019 at 10:1 Comment(1)
Narrowing is different from folding. Folding is more about hiding stuff. Narrowing comes in handy when focusing on a specific part of code.Anjelicaanjou
T
7

vimish-fold is also a nice and easy solution.

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

From the homepage:

This is a package to perform text folding like in Vim. It has the following features:

  • folding of active regions;
  • good visual feedback: it's obvious which part of text is folded;
  • persistence by default: when you close file your folds don't disappear;
  • persistence scales well, you can work on hundreds of files with lots of folds without adverse effects;
  • it doesn't break indentation or something;
  • folds can be toggled from folded state to unfolded and back very easily;
  • quick navigation between existing folds;
  • you can use mouse to unfold folds (good for beginners and not only for them);
  • for fans of avy package: you can use avy to fold text with minimal number of key strokes!

Using the excellent use-package I install and activate it using this snippet in my config:

(use-package vimish-fold
  :ensure t
  :config (vimish-fold-global-mode t))
Tact answered 18/1, 2017 at 9:25 Comment(0)
U
6

Apparently there is no perfect solution, but I think the best one is this:

http://www.emacswiki.org/emacs/FoldingMode

Untitled answered 6/7, 2009 at 2:37 Comment(0)
L
3

I believe that your comparison of your "project" to folding is not quite good, because folding is about changing the appearance while keeping the buffer contents intact (the text). Your project would involve showing extra text while keeping the buffer contents intact, AFAIU. So. it's not implementable as a composition of text-insertion and folding (then, the buffer contents would be changed).

But perhaps, it's indeed possible with the same mechanism as folding is done with -- "overlays"... Consider the "before-string" and "after-string" overlay properties; perhaps, you could put your function definitions into these strings belonging to a zero-length overlay at the point. Look at outline-flag-region function to see how overlays are used in the outline mode.

Londalondon answered 25/7, 2010 at 14:41 Comment(0)
M
2

emacs comes with hs-minor-mode which fascilitates code folding between balanced expressions http://www.emacswiki.org/emacs/HideShow

Modestamodeste answered 25/6, 2010 at 3:12 Comment(0)
M
2

If you use hs-minor-mode, it might be a good idea to also set a more convenient shortcut, e.g.:

(eval-after-load 'hideshow
 '(progn
   (global-set-key (kbd "C-+") 'hs-toggle-hiding)))
Morningglory answered 30/5, 2017 at 12:49 Comment(0)
A
1

With inspiration from einSelbst's answer:

(advice-add 'set-selective-display
            :filter-args (lambda (args)
                           (if (or (car args) selective-display)
                               args
                             (list (1+ (current-column)))))
            '((name . set-selective-display-from-cursor-column)))

Voila, C-x $ suddenly became useful even without any C-u nor M-4 business.

Atomic answered 29/9, 2018 at 11:36 Comment(0)
B
0

If you are doing some JavaScript and using js2-mode.el, you can:

C-c C-f: toggle hide/show all

C-c C-e: hide element

C-c C-s: show element

Brink answered 23/4, 2020 at 12:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.