I have a type of data file (ENDF, if your interested) for which I'd like to create a custom ViM folding file. The folds would be dependent on (defined by) the contents of columns 66-80 of the file.
Columns 66-80 of the file(s) look something like this:
-columns 1--65 -125 0 0 0
-columns 1--65 -125 3 1 1
-columns 1--65 -125 3 1 2
-columns 1--65 -125 3 1 3
...
-columns 1--65 -125 3 1 35
-columns 1--65 -125 3 099999
-columns 1--65 -125 3 2 1
...
-columns 1--65 -125 3 2 35
-columns 1--65 -125 3 099999
...
-columns 1--65 -125 3 099999
-columns 1--65 -125 0 0 0
-columns 1--65 -125 4 2 1
...
-columns 1--65 -125 4 2 195
I'd like the first indent level to be where columns 71–72 have the same number. In the example above those numbers are 3
,4
.
The second fold level are where columns 73–76 have the same number. In the above example those numbers are 1
and 2
, but could have any number—up to three digits.
Here is my first attempt at a script.
" ENDF folding functions
setlocal foldmethod=expr
setlocal foldexpr=ENDFFolds(v:lnum)
let MF = '0'
let MT = '0'
" This function is executed
function! ENDFFolds(lnum)
" Get the current line
let line = getline(v:lnum)
let mf = strpart(line, 71, 72)
echom mf
" Check to see if we have moved into a new file (MF)
if mf == MF
" Check to see if we have moved into a new section (MT)
let mt = strpart(line, 73, 75)
if mt == MT
return "="
else
MT = mt
return ">2"
endif
else
MF = mf
return ">1"
endif
endfunction
I've put this script in ~/.vim/ftplugin/endf/folding.vim
. I know the file is being found because I see the result of echo mf
.
Unfortunately, this doesn't work. No folds are found. Please advise.
With painstaking trial and error, I came up with this solution:
setlocal foldmethod=expr
setlocal foldexpr=ENDFFolds()
setlocal foldtext=ENDFFoldText()
let g:current_line = ''
let g:current_mf = 0
let g:current_mt = 0
" This function is executed for every line to determine the fold level
function! ENDFFolds()
" Get the current line
let line = getline(v:lnum)
let g:previous_mf = g:current_mf
let g:current_mf = str2nr(strpart(line, 70, 2))
let g:previous_mt = g:current_mt
let g:current_mt = str2nr(strpart(line, 72, 3))
if g:previous_mf == 0
let g:current_mt = 0
return '>1'
else
if g:previous_mt == 0
return ">2"
else
return "="
endif
endif
endfunction
function! ENDFFoldText()
let foldsize = (v:foldend-v:foldstart)
let line = getline(v:foldstart)
let MAT = strpart(line, 66, 4)
let MF = strpart(line, 70, 2)
let MT = strpart(line, 72, 3)
return 'MAT='.MAT.' MF='.MF.' MT='.MT.' '.' ('.foldsize.' lines)'
endfunction