Quick and dirty code folding

Code folding, the ability to hide code or text blocks in source or text files, is a feature present in most editors nowadays. Emacs has several modes providing this functionality with various degrees of sophistication: outline-mode, allout, hide-show or folding-mode come to mind. One can even use Emacs narrowing capabilities to cook up custom folding.

Over the years, i’ve used several of these packages (and perhaps i’ll share some tips on them in future postings). But i’ve noticed that, at the end of the day, i have usually little use for folding. I strive for short functions (whenever a function body extends a half-page, i feel a strong refactoring urge), and as a consequence i seldom need to hide their bodies, nor to mention blocks within them.

There is however one folding trick that i use all the time. I often want to hide all function bodies in a file, to get a quick summary of it contents. 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. I’ll let you read about the details in Emacs help itself, although i’m sure that by now you get the idea.

If you find yourself setting and unsetting selective-display as often as i do, next thing will be defining a handy keyboard shortcut, right?

(defun jao-toggle-selective-display ()
  (interactive)
  (set-selective-display (if selective-display nil 1)))

(global-set-key [f1] 'jao-toggle-selective-display)

or we can also use an optional numerical prefix (with 1 as default) with a little modification:

(defun jao-toggle-selective-display (column)
  (interactive "P")
  (set-selective-display 
   (if selective-display nil (or column 1))))

Happy folding!

About these ads

27 Responses to “Quick and dirty code folding”

  1. piyo Says:

    Excellent post! I don’t know how to use folding but this is one useful trick! Thanks also for listing the various “folding” modes. I keep forgetting that everybody brings their own “rock” to the “soup”.

  2. labsji Says:

    Very nifty.
    Thanks for the tip on M-1 and how it passes the value to argument. That will be very useful in several situations.
    Thanks.

  3. Paul Oliver Says:

    Where has this tip been all my life! Great blog, José! Keep it coming.

  4. Pinoy Says:

    great blog! thanks for the codes

  5. Denis Says:

    Thanks!
    This version don’t forces you to call the command twice in order to change the column:

    (defun jao-toggle-selective-display (column)
    (interactive “P”)
    (set-selective-display
    (or column ; disable toggle if column was supplied
    (unless selective-display 1))))

  6. Phil Says:

    Thanks; this is really useful! I have played with hs-minor-mode in the past, but it was pretty complicated; this is exactly what I would use.

    There is one thing that hs-minor-mode can do that this can’t though; reveal-mode. This will temporarily expand a given hidden block when the point enters the “…” markers, and it will hide it again when the point leaves the function. Do you know if this works with C-x $?

    Anyway, this blog is a gold mine; I love it. Makes me feel bad about not posting my own useful snippets.

  7. Simao Says:

    Well it does work with lisp interaction mode but in c-mode it folds all my functions.

    Any ideas?

    Thanks

  8. Thorbjørn WIlloch Says:

    One thing that I misses is a hide comment mode.
    With all these hiding modes out there it is strange that it does not exist.
    When reading code with two much comments it becomes difficult to read the code.

  9. voyager Says:

    Great tip. However, my mission in life is to get my emacs to work like CodeWright. I like emacs, but there are a few features of CodeWrite that I just can’t emulate. One of them is the ability do display all lines containing the word at point. I’ve found an “occur-at-point” which does what I want, but leaves me in the occur buffer. I never considered that CodeWright might be performing some kind of selective display or folding instead of “occur”.

    Set-selective-display works on indentation, right? Is there some way to fold on a regexp?

  10. GSIY … Ruby-Rails Portal Says:

    [...] out this site: [link] The main text deals w/ a quick and dirty way that uses a couple of commands to hide all the [...]

  11. chandan Says:

    Thanks a lot for posting such awesome tips. I surely increases my love for emacs.

  12. alex Says:

    I’ve been an emacs user for a long time and have used selective-display quite a bit. I just wish
    I could save a code-folded buffer to a file as is. Does anyone have any lisp routines to do this?

  13. anne Says:

    But i’ve noticed that, at the end of the day, i have usually little use for folding. I strive for short functions (whenever a function body extends a half-page, i feel a strong refactoring urge), and as a consequence i seldom need to hide their bodies, nor to mention blocks within them.

    well aren’t you mr. lucky ducky. i have to work with people who include 20-line function bodies WITH the declaration IN a header file. i don’t think they’ve heard of the ‘inline’ keyword.

    Seriously, thanks for the tips. it will help me and my ADD work with other people’s code.

  14. yhager Says:

    Excellent tip, I can finally “fold” the way I want to.

    Being an Emacs-Lisp newbie, I tried to modified the function so that it will fold based on the column at point, and came up with the following:

    (defun jao-selective-display ()
    "Activate selective display based on the column at point"
    (interactive)
    (set-selective-display
    (if selective-display
    nil
    (+ 1 (current-column)))))
    (global-set-key [f1] 'jao-selective-display)

  15. Andrea Gangemi Says:

    Dear Jao and yhager

    Many Many thanks for this awesome tip. :)

  16. Werelax Says:

    Great!

    Really simple and useful. An awsome little trick.

    Thanks.

  17. trashbird1240 Says:

    Bueno, just what I was looking for, and without installing any new libraries.

  18. joongoo Kang Says:

    Thank you!
    It’s Great!!!!

  19. diki Says:

    this is neat!
    @ yhager – you might find (current-indentation) even more practical than (current-column), depending on your habits :)

  20. A Nice Folding Trick for Emacs | Irreal Says:

    [...] over at Minor Emacs Wizardry has a nice post on folding in Emacs. As he points out, there are several packages to do folding but there is also a built-in method [...]

  21. Ruby code folding with Emacs | Chris Barrett Says:

    […] are a few posts kicking around about how to approach Ruby code folding in Emacs. Here’s what I have in my […]

  22. Johnny GIll Says:

    Thanks for this tip. I am finding binding this to a suitable key works really well. Just hit the key a few times until you get the folding you want.

    (defun increment-selective-display ()
    (interactive)
    (let ((column (if selective-display
    (+ selective-display 4) 4)))
    (if (> column 16)
    (set-selective-display nil)
    (set-selective-display column))))

  23. Alvaro Villegas Says:

    You’ve made my day. I was starting to consider abandoning emacs after 20 years of use (god, 20 years!, I’m getting old) and this gave me the fuel I needed to keep with it. Long live emacs :-)

  24. Ev Says:

    Thats very nice, thank you!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: