6

Is there a way to emulate Vim's folding of .vimrc from Emacs?

In other words, I believe most folding and hiding packages in Emacs rely on open and closing expressions. I am not sure of the internals of these, as I have not tried to learn this much Lisp as of yet.

In Vim, folding seems to be calculated line-by-line, so the writing a function can be based on manipulating the previous fold level, as well as an absolute value.

So in a .vimrc file, we can have both

" level 1 {{{
some code
" level 2 {{{
some code 
" end of section }}}
" end of section }}}
" level 1 {{{
some code
" end of section }}}

(with pairs {{{ and }}}) or

" level 1 {{{1
some code
" level 2 {{{2
some code
" level 1 {{{1

(with {{{n) as well as mixes of these; some recommend to use the absolute values for sectioning, and the relative folding for functions.

So open and closing expressions seem to correspond with declaring relative fold levels. Is there an existing way to declare absolute fold levels in Emacs? Or can anyone point me in the right direction so I can know where to head when I tackle this on a hobby day?

(Line by line function of buffer? Overlays? What is the underlying function for folding?)

3
  • 1
    Absolute folding is exactly what you get on org-mode and on LaTeX-mode with outline-mode turned on, so it's certainly possible.
    – Malabarba
    Commented Oct 13, 2014 at 21:22
  • Oh yes, I've tried that in the past, together with code from emacswiki.org/emacs/OutlineMinorMode#toc8, but it behaved unpredictably on the fold syntax of my .vimrc. Without digging through the code (of snippet and possibly package), I imagined there might be an easier way. Commented Oct 13, 2014 at 23:59
  • My conjecture is that outline-mode is indeed the way to go, with variables outline-level and/or outline-regexp. Even it may possibly be working if I can read through the existing snippet and use it carefully, but this is deferred til I have time. I hope to write up a solution and/or my understanding when I get to this. Commented Oct 29, 2014 at 1:32

2 Answers 2

5
(add-hook '???-mode-hook
          (lambda ()
            (setq-local orgstruct-heading-prefix-regexp "\\s-*/// ")
            (turn-on-orgstruct)))

Replace ??? with the name of the mode, where you want this to happen.

This will use /// as an indication of the beginning of the sub-tree, which can be folded. The number of * characters following the /// will indicate how deep this sub-tree should be nested. Some more info here: http://orgmode.org/manual/Orgstruct-mode.html .

I'm not sure whether it's possible to use numbers rather than asterisks to tell the orgstruct mode how deep it should nest the section, but that would be most probably possible with slight modification of Org's code, if that was absolutely necessary.

2
  • Is it necessary to escape those forward-slashes?
    – Malabarba
    Commented Oct 14, 2014 at 11:49
  • @Malabarba Actually no. That's not escaping anyway (would have to be \\/\\/\\/). Just a habit with POSIX / Perl regexp I guess.
    – wvxvw
    Commented Oct 14, 2014 at 12:33
4

If you are asking about "absolute fold levels" then I can only guess that you want Org-mode like packages for the hierarchical tree-like structuring of files:

  • Outshine

    It’s an extension library for outline-minor-mode that gives buffers in different major-modes the 'look-and-feel' of Org-mode buffers and enables the use of outorg and navi-mode on them.

    An outshine file is structured like an org file, only that the headlines are outcommented with the current major-mode's comment syntax: e.g. ;; *** Third Level Header for elisp and % ** Second Level Header for LaTeX.

    With this package your can write

    " level 1 {{{1
    some code
    " level 2 {{{2
    some code
    " level 1 {{{1
    

    as

    " * level 1
    some code
    " ** level 2
    some code
    " * level 1
    

    Or if you don’t want asterisks then you can customize outline-regexp which indicates which lines are considered heading.

  • Orgstruct minor mode

    When this mode is active and the cursor is on a line that looks to Org like a headline or the first line of a list item, most structure editing commands will work, even if the same keys normally have different functionality in the major mode you are using.

    You can also use Org structure editing to fold and unfold headlines in any file by defining orgstruct-heading-prefix-regexp.

    If you set this variable to ";; " in Emacs Lisp files, you will be able to fold and unfold headlines in Emacs Lisp commented lines.

More information at: 'Org outside org' page.

Additionally packages which do not share org-mode philosophy:

  • yafolding which folds code blocks based on indentation (no special strings are needed).
  • Folding mode where you need to define folding characters:

    (folding-add-to-marks-list 'ruby-mode "#{{{" "#}}}" nil t)
    
  • Hide Show which hides balanced-expression code blocks and multi-line comment blocks. Blocks are recognized by regular expressions which match the start and end strings:

    (c-mode "{" "}" "/[*/]" nil nil)
    (java-mode "{" "}" "/[*/]" nil nil)
    (js-mode "{" "}" "/[*/]" nil)
    
  • Semantic Tag Folding which allows semantic tags to be expanded or collapsed in the style of folding mode and hideshow mode. In addition to regular semantic tag, comments preceeding tags can also be folded.

Based on your "it behaved unpredictably on the fold syntax of my .vimrc" I can assume that you really want to ask "How can I handle Vim based folding in Emacs without changing file's content?".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.