vim/ftplugin/snakemake/folding.vim @ 417f91fae3c2

More
author Steve Losh <steve@stevelosh.com>
date Thu, 28 Mar 2024 16:06:55 -0400
parents c4bb62cd1c7f
children (none)
setlocal foldmethod=expr
setlocal foldexpr=GetSnakemakeFold(v:lnum)

function! GetSnakemakeFold(lnum)
    " fold preamble
    if a:lnum == 1
        return '>1'
    endif

    let thisline = getline(a:lnum)

    " two blank lines end folds
    if thisline =~? '\v^\s*$'
        if ActualPreviousLineNonblank(a:lnum)
            return "="
        endif
        return '-1'
    " start fold on top level rules or python objects
    elseif thisline =~? '\v^(rule|def|checkpoint|class)'
        return ">1"
    elseif thisline =~? '\v^\S'
        if IsEmpty(a:lnum+1)
            if IsEmpty(a:lnum+2)
                return ">1"
            endif
        endif
        return "0"
        " if PreviousLineIndented(a:lnum) && NextRuleIndented(a:lnum)
        "     return ">1"
        " endif
    endif

    return "="

endfunction

function! NextRuleIndented(lnum)
    let numlines = line('$')
    let current = a:lnum + 1

    while current <= numlines
        let thisline = getline(current)
        if thisline =~? '\v^(rule|def|checkpoint|class)'
            return 0
        elseif thisline =~? '\v^\s+(rule|checkpoint)'
            return 1
        endif

        let current += 1
    endwhile

    return 0
endfunction

function! PreviousLineIndented(lnum)
    let current = a:lnum - 1

    while current >= 1
        let thisline = getline(current)
        if thisline =~? '\v^\S'
            return 0
        elseif thisline =~? '\v^\s+\S'
            return 1
        endif

        let current -= 1
    endwhile

    return 0
endfunction

function! ActualPreviousLineNonblank(lnum)
    let current = a:lnum - 1

    if current >= 1
        let thisline = getline(current)
        if thisline =~? '\v^\s*\S'
            return 1
        else
            return 0
        endif
    endwhile

    return 0
endfunction

function! IsEmpty(lnum)
    let numlines = line('$')
    if a:lnum > numlines
        return 0
    elseif a:lnum < 1
        return 0
    else
        let thisline = getline(a:lnum)
        if thisline =~? '\v^$'
            return 1
        else
            return 0
        endif
    endif
endfunction