Sunday, April 22, 2012

Re: foldmethod=syntax

On Sun, 22 Apr 2012, Chris Jones wrote:

> On Sun, Apr 22, 2012 at 07:47:19AM EDT, Christian Brabandt wrote:
>
>> On So, 22 Apr 2012, Chris Jones wrote:
>
>>> I have a few hundred text files, mostly documentation, and all of
>>> them basically have the following structure:
>
>>>
>>> | 1. first section
>>> | ...
>>> | 2. second section
>>> | ...
>>> | etc..
>
>>> I would like to have Vim automatically create folds [...]
>
>> set fdm=expr fde=getline(v:lnum)=~'^\\d\\+.*section$'?'>1':'='
>
> Initially, I was planning on using fdm=syntax rather than fdm=expr for
> the sake of scalability, in case I needed to add stuff later: the
> sample above is a slightly simplified version as there are for
> instance nested levels in some of the actual files: 1.1 subsection..
> 1.2.. etc. as well as some lists where items are prepended with a
> dash/asterisk/dot..
>
> The difficulty with fdm=syntax is that there is no explicit 'end of
> section marker' in my free-form, but nonetheless fairly 'standard'
> files and as often with Vim, it looks like folding was mostly designed
> to work with stuff like C code in mind.. Here, unfortunagely, the end
> of the current section is also the start of the next one.

I'm not positive, but this might be a case for keepend.

See: :help :syn-keepend


> I tried playing with the rs=/re= feature (:h syn-pattern) to no avail.
>
> But I think I have already spent a lot more time with this than I
> intended without getting anywhere.. and so a simple fde that only
> handles top-level folds would be absolutely fine.
>
> Now, as to the fold expression you suggest:
>
> . I'm not sure I understand why I need a getline(), since ':h fde'
> states that the expression 'is evaluated for each line to obtain its
> fold level'. I thought this meant that Vim would take care of the
> matching against the entire file?

'fde' is only set up with the v:lnum variable (which tells the function
what line it's being evaluated for). getline() gets the content of the
line.


> . Just for the record, the 'section' literal was only meant for
> clarification (?) but I shouldn't have any problem changing that bit
> to match just the leading digit(s) followed by a dot - '^\s\+\.', e.g.
> and hopefully, it won't match elsewhere in the files.
>
> I won't have the time to take the regex apart & test it until later
> tonight and find out why it's not matching anything against my sample
> file, even when I use it as a search pattern from the command line,
> magic or nomagic.. Could the double backslashes have something to do
> with it..?

The doubled backslashes are a side-effect of the way ':set' is
evaluated. For anything where the quoting gets messy, I always tend to
use ':let-&' instead. Or, better yet, a function.

So, in this case, Christian's example might become:

fun! FoldSimpleText()
return getline(v:lnum) =~ '^\d\+.*section$' ? '>1' : '='
endf
setl fdm=expr fde=FoldSimpleText()

If you have subsections, this can be improved to:

fun! FoldSimpleText()
" extract the section header
let section_match = matchlist(getline(v:lnum), '^\s*\(\%(\d\+\.\)\+\)')
if !len(section_match)
return '='
end
" start a fold with the count of the '.'s in the section header
return '>'.len(filter(split(section_match[1], '\zs'), 'v:val == "."'))
endf
setl fdm=expr fde=FoldSimpleText()

--
Best,
Ben

--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

No comments: