Last active
December 11, 2015 15:55
-
-
Save bpj/0727f00b5c566bdd8fb0 to your computer and use it in GitHub Desktop.
A foldexpr function to fold both Pod and Perl code sensibly in the same file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
" vim: set ft=vim et tw=80: | |
" A foldexpr function to fold both Pod and Perl code sensibly in the same | |
" file. It folds Pod according to its logical structure and code by | |
" indentation. | |
" | |
" Author: Benct Philip Jonsson <[email protected]> | |
" Version: 2015-12-11-14 (YYYY-MM-DD-HH) | |
" | |
" It requires that the Pod blocks are well-behaved and start with `=pod` or | |
" `=encoding`. | |
" | |
" * The first line of the file starts a level 1 fold | |
" * Each `=pod`/`=encoding` line starts a level 1 fold. | |
" * Each `=cut` line ends a level 1 fold. | |
" * Each `=headN` line starts a level N+1 fold | |
" * Each `=begin` or `=over` line increases the current fold level by one | |
" * Each `=end` or `=back` line decreases the current fold level by one | |
" * FIXME: If there is a variable `b:fold_items` and it has a non-empty value: | |
" * FIXME: Each `=item` line increases the current fold level by one | |
" * FIXME: Each `=for enditem` line decreases the current fold level by one | |
" * The line *after* each `=cut` line starts a level 1 fold | |
" * If a line has *more or less* indentation than the previous line | |
" we do our best to 'fake' folding by indent: | |
" * If the difference is positive the fold level is increased by | |
" the_difference/&softtabstop | |
" * If the difference is negative the fold level is decreased by | |
" abs the_difference/&softtabstop | |
" * Vim modeline(s) are start a level 1 fold | |
" * All other lines inherit the nearest lower foldlevel | |
" | |
" FIXME: Find a way to fold `=items`, preferably without closing pseudo-markup. | |
setlocal foldmethod=expr | |
setlocal foldexpr=GetPerlFold(v:lnum) | |
if empty(&l:foldcolumn) | |
setlocal foldcolumn=4 | |
endif | |
" let s:pod_re='\v^\=%((encoding|pod)|(cut)|head(\d)|(begin)|(end)|(over)|(back)|(item)|(for enditem))>' | |
let s:pod_re='\v^\=%((encoding|pod)|(cut)|head(\d)|(begin)|(end)|(over)|(back))>' | |
" 1 pod 2 cut 3 head 4 begin 5 end 6 over 7 back 8 item 9 for enditem | |
function! GetPerlFold(lnum) | |
if a:lnum==1 | |
return '>1' | |
else | |
let thisline=getline(a:lnum) | |
if thisline =~ '\v\c^\#\s+vim\:' " modeline | |
return '>1' | |
endif | |
let matches = matchlist(thisline, s:pod_re) | |
if !empty(matches) | |
if !empty(matches[1]) " pod/encoding | |
return '>1' | |
elseif !empty(matches[2]) " cut | |
return '<1' | |
elseif !empty(matches[3]) " head(\d) | |
return '>' . (matches[3]+1) | |
elseif !empty(matches[4]) " begin | |
return 'a1' | |
elseif !empty(matches[5]) " end | |
return 's1' | |
elseif !empty(matches[6]) " over | |
return 'a1' | |
elseif !empty(matches[7]) " back | |
return 's1' | |
" FIXME: find a way to do =item folding which works! | |
" elseif exists('b:fold_items') and !empty(b:fold_items) | |
" if !empty(matches[8]) " item | |
" return 'a1' | |
" elseif !empty(matches[9]) " for enditem | |
" return 's1' | |
" else | |
" return '=' | |
" endif | |
else | |
return '=' | |
endif | |
elseif empty(matches) | |
let prevline = getline(a:lnum-1) | |
if prevline =~ '\v^\=cut>' | |
return '>1' | |
" elseif thisline =~ '\v^\s*$' | |
" return '=' | |
else " 'fake' indent folding | |
let thisindent = indent(a:lnum) | |
let previndent = indent(a:lnum-1) | |
if thisindent != previndent | |
let diffindent = float2nr(round(abs(thisindent-previndent)/&softtabstop)) | |
return thisindent > previndent ? 'a' . diffindent : 's' . diffindent | |
else | |
return '=' | |
endif | |
endif | |
endif | |
endif | |
return '0' | |
endfunction | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment