Question

I am working with LLVM-IR code, generated by clang -emit-llvm and want to get code folding working.

So far I am using foldmethod=expr and foldexpr=LLVMFold(). I would like to use syntax based folding (i.e. foldmethod=syntax) using the syntax file from the llvm repository. Available here.

Note that the first regex is from the syntax file for the label.

function! LLVMFolds()
    let thisline = getline(v:lnum)
    if match(thisline, '^[-a-zA-Z$._][-a-zA-Z$._0-9]*:') >= 0
        return ">2"
    elseif match(thisline, '^\}$') >= 0
        return "<1"
    elseif match(thisline, '{$') >= 0
        return ">1"
    else
        return "="
    endif
endfunction

Which gobbles the closing braces into the level 2 folds.

Also tried have been foldmethod=indent which didn't fold enough and foldmethod=marker with foldmark="{,}" Ideally for this sample incomplete LLVM-IR code:

define i32 @main() nounwind {
entry:
  %retval = alloca i32, align 4

for.cond:                                         ; preds = %entry
  %4 = load i32* %i, align 4
  %cmp1 = icmp slt i32 %4, 10
  br i1 %cmp1, label %for.body, label %for.end
}

I would like folds to be from the { of the define to the } and in each labelled section, i.e. from the entry: to the clear line.

Was it helpful?

Solution 2

I have used this function now

function! LLVMFolds()
    let thisline = getline(v:lnum)
    let nextline = getline(v:lnum + 1)
    " match start of global var block
    if match(thisline, '^@') == 0 && foldlevel(v:lnum - 1) <= 0
        return ">1"
    " match start of global struct block
    elseif match(thisline, '^%') == 0 && foldlevel(v:lnum - 1) <= 0
        return ">1"
    " matches lables
    elseif match(thisline, '^[-a-zA-Z$._][-a-zA-Z$._0-9]*:') >= 0
        return ">2"
    " keep closing brace outside  l2 fold
    elseif match(nextline, '^\}$') >= 0
        return "<2"
    " keep closing brace in l1 fold
    elseif match(thisline, '^\}$') >= 0
        return "<1"
    " open new l1 fold for open brace
    elseif match(thisline, '{$') >= 0
        return ">1"
    " for the next line being empty, close the fold for the var and struct blocks
    elseif match(nextline, '^$') >= 0
        if match(thisline, '^@') == 0 && foldlevel(v:lnum - 1) == 1
            return "<1"
        elseif match(thisline, '^%') >= 0 && foldlevel(v:lnum - 1) == 1
            return "<1"
        else
            return "="
        endif
    else
        return "="
    endif
endfunction

Which excludes the closing brace from the level 2 fold, and folds the initial lists of global structs and variables.

OTHER TIPS

I do not think that

:set foldmethod=syntax

is going to help with the syntax file in your link, since that file does not define any fold arguments.

Your LLVMFolds() function seems to do almost what you want, but (if I understand correctly) you do not want the fold to include the } line. Maybe what you want is to make the previous line end the fold, like this:

function! Foo(lnum)
    let thisline = getline(v:lnum)
    let nextline = getline(v:lnum + 1)
    if match(thisline, '^[-a-zA-Z$._][-a-zA-Z$._0-9]*:') >= 0
        return ">2"
    elseif match(nextline, '^\}$') >= 0
        return "<1"
    elseif match(thisline, '{$') >= 0
        return ">1"
    else
        return "="
    endif
endfunction

This may or may not do what you want if there are no lines between { and }. For testing purposes, try

:set fdm=expr foldexpr=LLVMFolds() fdc=5

References:

:help fold-syntax
:help :syn-fold
:help fold-expr
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top