1

In Emacs org-mode, folds use * at the start of the lines, and any * added consecutively, will add a level of indentation to the header.

Furthermore, the header text placed after * or any number of it, will be the only thing shown when folded/folding (in contrast, Vim's fold show part of the text that was folded, instead of only showing the header's text).

Here a gif (roughly 2 seconds) with one fold level.

example

And here another one (roughly 5 seconds) with more than one fold level (three levels).

another

Any way/or existing plugin to do this?

Nordine Lotfi
  • 683
  • 4
  • 16
  • 1
    You could try foldmarker=*,*, though you'll almost certainly have to use numbers, and it might not work. – D. Ben Knoble Sep 17 '20 at 00:43
  • yeah, and beside the marker itself, I would prefer if the fold won't show the text it fold, and instead just show the actual header (when folded). If it's too confusing i can show a picture :) @D.BenKnoble – Nordine Lotfi Sep 17 '20 at 00:46
  • 1
    There’s an option which controls the foldtext shown – D. Ben Knoble Sep 17 '20 at 01:38
  • 1
    I'm not sure I got your case 100% right... But take a look at my answer and see if that does it. Otherwise, maybe post an example? Either a picture of what you get in Emacs, or just post some sample text and explain where it should fold and where it should not... Thanks! – filbranden Sep 17 '20 at 02:34
  • Thanks! just added two examples gif (short, the first one is 2 second, second one is roughly 5 second). @filbranden – Nordine Lotfi Sep 17 '20 at 03:02
  • 1
    Yeah thanks! That's what I had in mind. So that should be exactly what the snippet in my answer does. Take it for a spin, let me know if you find any corner case where it doesn't do what you expect... You might want to drop the optional leading whitespace if you expect the *s to always start on the first column. – filbranden Sep 17 '20 at 03:11
  • Tried it, and i have to say it work great! The only minor problem is that it still show the number of lines at the start (when folded) instead of just the header text (what is after the *). But that's only a minor problem and still work great :D Thanks a lot! @filbranden – Nordine Lotfi Sep 17 '20 at 03:17
  • 1
    Just updated the answer to include a 'foldtext' that does exactly what's on your animations. (Well, except for the highlighting, but I think a lot of that should be doable in Vim as well, though I'm not totally sure whether you can have different styles for different closed folds... Ask a question about that part if you like!) – filbranden Sep 17 '20 at 03:49
  • 1
    Yeah, didn't really need the highlighting but might as well do that on another post :D Thanks a lot again! @filbranden – Nordine Lotfi Sep 17 '20 at 04:02

1 Answers1

2

You can accomplish this kind of folding fairly easily by using a file expression, using a function to calculate the fold level of the current line.

You can start a new fold of level n on a line that starts with n *s (possibly followed by whitespace.) For a line that doesn't start with *, simply use the fold level of the most recent * line above it.

That's easily implemented with:

 function OrgFold(lnum)
  let level = strlen(matchstr(getline(a:lnum), '\v^\s*\zs\*+'))
  if level > 0
    return '>'.level
  else
    return '='
  endif
endfunction

The folding function can return something like >2 to start a level 2 fold on the current line. Returning = means use the fold level of the preceding line which had the fold level explicitly set.

Enable this folding with:

set foldmethod=expr foldexpr=OrgFold(v:lnum)

You can customize the text displayed when the block is folded. For example, to simply display the first line followed by three dots, you can use:

set foldtext=getline(v:foldstart).'...'.repeat('\ ',999)

This expression also suppresses the dashes to the right of the fold text, by padding the string with enough spaces to fully hide them.

filbranden
  • 28,785
  • 3
  • 26
  • 71