aboutsummaryrefslogtreecommitdiff
path: root/vim/indent
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2018-07-07 12:23:08 +1200
committerTom Ryder <tom@sanctum.geek.nz>2018-07-07 12:23:08 +1200
commit85d8205906685e4c555a0fba5be6af8f03eda572 (patch)
tree70b6ed615d334e8cf11b80789a27fcdeb206963e /vim/indent
parentRemove Vim Perl indent (diff)
downloaddotfiles-85d8205906685e4c555a0fba5be6af8f03eda572.tar.gz
dotfiles-85d8205906685e4c555a0fba5be6af8f03eda572.zip
Revert "Remove Vim Perl indent"
This reverts commit f0b98feb769d9dfbbb0c1825b1291851795163db. I changed my mind again.
Diffstat (limited to 'vim/indent')
-rw-r--r--vim/indent/perl.vim114
1 files changed, 114 insertions, 0 deletions
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'