问题
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.
回答1:
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
回答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.
来源:https://stackoverflow.com/questions/20986912/llvm-ir-syntax-folding-for-vim