31

Code folding in Emacs

Sometimes I want to fold a block of text. In Vim you have easy folding without fuzz. Without to add any special characters like "markers" or specific regex like {{{. I would like to select a region and fold it, without messing with the structure.

When looking around, it seems there were already questions about code folding in Emacs. Someone said that there was "no perfect solution". For example, I created a clip of simple codefolding in Vim:

Vim plain folding

enter image description here

+ Fairly simple, select a region and fold it.
+ It's persistent. When you kill the buffer/close Vim. And reopen the file, the folds are still there.
+ You get a highlight bar, to easily see what's folded.

There are many other folding configurations for Vim. I'm happy with Emacs, but this is one thing that I miss. Other alternatives that I tried, for example HideShow:

HideShow

enter image description here

Evil's alternative with hide-show minor mode. I found it unusable:

- I'm not able to select a region and folding it. It folds on code blocks.

- There's no higlihgting bar or something, to attend you it's folded. You could easily miss it.

- It's not persistent. If you reopen the file, the folds are gone.

There is another package, Fold this:

Fold this

enter image description here

- It's a pretty alternative. However, it mess with the indentation, because the text under the fold gets placed next to the fold... (?).

- It's able to just visually select the region and fold it. But it breaks the indendation, so the overview gets messed up. Not very handy.

- There is no higlihgting bar or something, to attend you it's folded. You could easily miss it.

What's the issue?

I would like to replicate how Vim does folding. But when I searched around, it seems it's very hard to do that in Emacs. So I wonder if there something in emacs or its architecture that makes it difficult to replicate this? What are the limits?

wasamasa
  • 21,803
  • 1
  • 65
  • 97
ReneFroger
  • 3,855
  • 22
  • 63
  • Is your question "how can I replicate Vim's code folding?" If so, could you edit you post so that the question becomes clearer? – Dan Aug 15 '15 at 20:49
  • That would be a better question. I edited the title. – ReneFroger Aug 15 '15 at 20:50
  • Let's pretend we know sociology. Most Emacs users don't seem to care about folding at all. After all, there's tons of alternatives that make much more sense, like using imenu. A few did care about a very specific form of coding and wrote a package to implement that form only. Then Vim converts arrived and expected Emacs to be like Vim, discovered this to not be the case, tried throwing some packages together, discovered they did not solve their problem and couldn't be bothered to write a package doing all what they wanted. You're just the first one to vocalize it on this platform. Congrats. – wasamasa Aug 15 '15 at 20:58
  • Wasamasa, sorry for my tone. I'm know another alternatives, like like tags or `M-x iemenu`, etc. But that's not the case. I use folds to get a good general overview of the buffer on the first sight. I could use minimap in SublimeText, the alternative MiniMap in Emacs is not fluently. So I'm looking for an alternative for folds, to get a pretty overview of the buffer. – ReneFroger Aug 15 '15 at 21:06
  • @wasamasa If you might be wondering, I was just planning for weeks to write a package for this, but I wanted to be just sure that there is no other alternative for this, and if so, what's the limits in Emacs currently are. Hence the question. – ReneFroger Aug 15 '15 at 21:13
  • Well, do your own research, find every package implementing folding, test it, put the results into a table, read their code, write some of your own, etc. This will actually teach you about both the status quo and how well Emacs is at it. I suspect it's bad considering that implementations using overlays suffer from speed issues (like, choppy scrolling in a Org buffer with loads of hidden text) and interop problems (I've learned the other day imenu skips hidden parts of the buffer when building its index). – wasamasa Aug 15 '15 at 21:32
  • @wasamasa -- thank you for the comment about hidden text and imenu -- I just added a note to my todo-list to remove that restriction in my personal setup. – lawlist Aug 16 '15 at 00:37
  • 2
    I felt the question was too broad, so I voted to close on that basis. I would recommend that the original poster pick a couple of libraries that provide some of the features sought, and then combine/modify them as desired. If the O.P. runs into trouble implement/modifying *a particular feature*, then post a specific question limited to that one issue. The O.P. can *probably* achieve the desired visual effects, but should be prepared to make it an ongoing project to be worked on over time. – lawlist Aug 16 '15 at 01:53
  • 3
    Could you please explain what folding features you want? As a rule, you can't expect people on this site to know how Vim code folding works, and anyway you should tell us which features you want specifically. The only information you provide about what you want is an animation which only shows one example, and anyway I have no idea what it illustrates: they don't show what commands you used, why you moved the cursor to this or that spot, etc. Plus in a typical browser they play on a loop and it's impossible to tell when a repeat starts. – Gilles 'SO- stop being evil' Aug 16 '15 at 10:03
  • 4
    the hold should be removed from this question. as it currently stands it is reasonably specific. not having an answer to the question is not a good reason to close it. – Ista Aug 17 '15 at 13:12
  • 2
    ar-hide-region-atpt, ar-show-region-atpt from ‘thing-at-point-utils.el’, https://github.com/andreas-roehler/thing-at-point-utils - please un-block so that might be a regular answer. – Andreas Röhler Aug 17 '15 at 13:51
  • It seems this question is unblocked by now. So if anyone have an anser, that would be great. – ReneFroger Aug 20 '15 at 17:16
  • 2
    The question, as I understand it, is basically: "**Someone: Please write an entire library for Emacs that will provide the exact code-folding features found in Vim.**" I see from some of the comments and up-votes that there are enough people who would like to see this become a reality. However, I don't see how this could reasonably fit into answer -- the proposed new library will need to be maintained, with issues and bug-fixes. I too wouldn't mind someone writing up an entire library with cool new features for code folding. – lawlist Sep 06 '15 at 19:04
  • 1
    @lawlist, I'm playing with this, if I don't lose my interest it will be done in a day or so. It's interesting how persistent folds may change the way we edit text. There is a problem with indentation however, I don't know why it's spoiled when using overlay to make text invisible. Perhaps it's another good question to ask. – Mark Karpov Sep 07 '15 at 08:50
  • @Mark That would be great! I was trying the same with fold-this.el library. But I also struggled it with the indentation. So I'm looking for alternative ways to cope with it. – ReneFroger Sep 07 '15 at 11:15
  • (a real long-shot, here) Org-mode is built-in to emacs and has all kinds of folding. It might be possible / reasonable / desirable to make it work for code. It sort of does if you want to get into literate programming with org-babel, but that would be a cosmic change in your entire approach to programming, not a feature-set to support your current entire approach to programming. http://orgmode.org/worg/org-contrib/babel/ – Reb.Cabin Sep 07 '15 at 14:23

3 Answers3

20

Try out vimish-fold.

Features

  • batteries included: activate minor mode, bind a couple of commands and everything will just work;

  • it works on regions you select;

  • it's persistent: when you close file your folds don't disappear;

  • in addition to being persistent, it scales well, you can work on hundreds of files with lots of folds without adverse effects;

  • it's obvious which parts of text are folded;

  • it doesn't break indentation or something;

  • it can refold just unfolded folds (oh, my);

  • for fans of avy package: you can use avy to fold text with minimal number of key strokes!

Usage

Create binding for some of/all these functions:

  • vimish-fold — basic folding of selected region;

  • vimish-fold-unfold — you don't really need to bind this, just use C-g when point is placed on header representing folded text;

  • vimish-fold-unfold-all — nevertheless this may be useful;

  • vimish-fold-refold — yes, you can fold it back;

  • vimish-fold-avy — use avy to fold your text!

You can turn vimish-fold-mode selectively for modes where you want to have persistent folding, or simply activate it everywhere:

(vimish-fold-global-mode 1)
Mark Karpov
  • 4,893
  • 1
  • 24
  • 53
  • do you have any suggested key bindings? What bindings do you use when you're in C++ mode? C mode? Python mode? Lisp mode? ELisp mode? JavaScript mode? – Reb.Cabin Sep 07 '15 at 14:25
  • 1
    @Reb.Cabin, this is not mode-specific package, so global key bindings is the best choice. I'm using key bindings that don't involve key-chords and most people would consider them a bit strange, currently I have: `menu v f` → `vimish-fold`, `menu v a` → `vimish-fold-avy`, `menu v u` → `vimish-fold-unfold-all`, `menu v v` → `vimish-fold-refold`. Most my keybinds are like this, [this is my config](https://github.com/mrkkrp/dot-emacs). – Mark Karpov Sep 07 '15 at 14:33
  • Does this integrate with evil motions and textobjects? – PythonNut Sep 08 '15 at 04:14
  • @PythonNut, I don't use these packages and it currently don't integrate with them. If you have ideas or feature propositions please open an issue of GitHub page of the project and we will see if we can have them. – Mark Karpov Sep 08 '15 at 07:23
  • 1
    Hm... I'll start work on a PR. – PythonNut Sep 08 '15 at 13:44
  • Thanks for that! However, it don't work flawlessly. I have some issues with it. Will open issues on your page soon. But it's a nice improvement of fold-this.el. Thanks for it, I will validate it, it's really appreciated. – ReneFroger Sep 08 '15 at 18:01
  • [evil-vimish-fold](https://github.com/alexmurray/evil-vimish-fold) automatically integrates `vimish-fold` with `evil` so you can use the standard `vim` keybindings to fold / unfold etc. – alexmurray Nov 03 '15 at 03:12
  • 2
    I, for one, find vimish-fold completely unusable. Maybe it's intuitive to those already familiar with code-folding in vim... I don't know. Also, I don't understand why folding in org-mode works so well, but Emacs does not yet have good code-folding... – kjo Jul 23 '16 at 12:47
  • Does not support nested folding and (less important) moving/deleting folded text. – tejasvi88 Mar 29 '21 at 14:48
2

I like and use vimish-fold with evil-vimish-fold (and avy):

  ;; Optional use of avy
  (use-package avy
    :bind ("C-c J" . avy-goto-line)
    :commands avy-goto-line
    :init
    (setq-default
     ;; the unpredictability of this (when enabled) makes it a poor default
     avy-single-candidate-jump nil
     avy-background nil 
     avy-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)
     avy-style 'at-full))

  ;; This does the heavy lifting
  (use-package vimish-fold
    :after evil)

  ;; This gives us evil integration, i.e., key bindings
  (use-package evil-vimish-fold
    :after evil vimish-fold
    :init
    (setq evil-vimish-fold-target-modes '(prog-mode markdown-mode conf-mode text-mode))
    :config
    (evil-vimish-fold-mode 1))

If you use package.el to get your packages then you can add an

:ensure

form to the use-package form.

Adjust the evil-vimish-fold-target-modes to include any that you wish to use folding in. Note that prog-mode is the parent mode of most programming modes, so it is sort of a catch all.

Note that this will give you many of the usual vim folding key bindings. Here are some that I use often:

z f Create a fold after first highlighting a region (or use a prefix count like vim).

z o Open existing fold at point.

z d Delete an existing fold.

z R Open all folds in the buffer.

z c Close existing fold at point.

z j Next fold.

z k Previous fold.

Etc.

As Mark Karpov, the creator of vimish-fold, mentioned in his answer, you can use M-x vimish-fold-avy which will fold everything between point and the location you choose via the avy interface that it presents.

An example of using a count prefix would be:

4 z f f

to create a fold from point to 4 lines down.

Joe
  • 541
  • 3
  • 14
1

I wrote foldout.el years ago, so if your file can be “outlined” then it can be folded without needing additional markers.

kbro
  • 181
  • 5
  • Could you please give a few more details on this? How does one "outline" code? Are you speaking of the foldout.el that is included in GNU Emacs? – hackerb9 Sep 13 '21 at 03:55
  • 1
    If you study outline.el you'll see you can define a function `outline-level' that returns the level for the current line. I wrote some elisp for a c-mode buffer that basically returned the indentation level of the current line. This allowed outline-minor-mode to treat pretty much every line as a heading, and foldout.el used this to hide indented blocks of code. Sadly I appear to have lost my c-outline.el file! – kbro Sep 17 '21 at 10:29
  • 1
    And, yes, the "foldout.el" in the Emacs distribution is mine! – kbro Sep 17 '21 at 10:31
  • If you find or recreate c-outline.el, please update your answer as I'd be very interested in seeing that solution – hackerb9 Sep 19 '21 at 19:33