From 85d8205906685e4c555a0fba5be6af8f03eda572 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sat, 7 Jul 2018 12:23:08 +1200 Subject: Revert "Remove Vim Perl indent" This reverts commit f0b98feb769d9dfbbb0c1825b1291851795163db. I changed my mind again. --- vim/indent/perl.vim | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 vim/indent/perl.vim diff --git a/vim/indent/perl.vim b/vim/indent/perl.vim new file mode 100644 index 00000000..01c1259b --- /dev/null +++ b/vim/indent/perl.vim @@ -0,0 +1,114 @@ +" Custom Vim indent file for Perl5; the stock one didn't suit me. + +" Only load this indent file when no other was loaded. +if exists('b:did_indent') || &compatible + finish +endif +let b:did_indent = 1 + +" Indent settings +setlocal indentexpr=GetPerlIndent() +setlocal indentkeys=o,O,0},0),0] + +" Build patterns for heredoc indenting; note that we detect indented heredocs +" with tildes like <<~EOF, but we don't treat them any differently; note also +" a semicolon is required +let s:heredoc_word = '\I\i*' +let s:heredoc_open = '<<\~\?' + \ . '\(' + \ . '\\\?' . s:heredoc_word + \ . '\|' + \ . "'" . s:heredoc_word . "'" + \ . '\|' + \ . '"' . s:heredoc_word . '"' + \ . '\|' + \ . '`' . s:heredoc_word . '`' + \ . '\)' + \ . '.*;\s*$' + +" Define indent function +function! GetPerlIndent() + + " Get previous line, bail if none + let l:pn = prevnonblank(v:lnum - 1) + if !l:pn + return 0 + endif + + " Heredoc detection; start at top of buffer + let l:hn = 0 + while l:hn < v:lnum + let l:hl = getline(l:hn) + + " If we're not in a heredoc and not in a comment ... + if !exists('l:hw') && l:hl !~# '^\s*#' + + " Line opens with a heredoc + let l:hm = matchstr(l:hl, s:heredoc_open) + + " Store the heredoc word and make this our indent reference + if strlen(l:hm) + let l:hw = matchstr(l:hm, s:heredoc_word) + let l:pn = l:hn + endif + + " If we are in a heredoc and we found the token word, finish it + elseif exists('l:hw') && l:hl =~# '^'.l:hw.'\>' + unlet l:hw + endif + + " Bump the loop index + let l:hn = l:hn + 1 + + endwhile + + " If we ended up in a heredoc, return 0 for the indent. + if exists('l:hw') + return 0 + endif + + " Get current line properties + let l:cl = getline(v:lnum) + + " Get data of previous non-blank and non-heredoc line + let l:pl = getline(l:pn) + let l:pi = indent(l:pn) + + " Get value of 'shiftwidth' + let l:sw = exists('*shiftwidth') + \ ? shiftwidth() + \ : &shiftwidth + + " Base indent with any fractional indent removed + let l:pb = l:pi - l:pi % l:sw + + " Just follow comment indent + if l:pl =~# '^\s*#' + return l:pi + + " Move out with closing brace + elseif l:cl =~# '^\s*[])}]' + return l:pb >= l:sw ? l:pb - l:sw : 0 + + " Move in after opening brace + elseif l:pl =~# '[{([]\s*$' + return l:pb + l:sw + + " Preserve base indent after a semicolon or a hash element assignment + elseif l:pl =~# '[;,]\s*$' + \ || l:pl =~# '^\s=>.*,\s*$' + \ || l:pl =~# '^\s*sub\>.*{.*}\s+$' + return l:pb + + " Line-continuation: indent half a 'shiftwidth' + else + return l:pb + l:sw / 2 + + endif + +endfunction + +" How to undo all of that +let b:undo_indent = '|setlocal indentexpr<' + \ . '|setlocal indentkeys<' + \ . '|delfunction GetPerlIndent' -- cgit v1.2.3