perl.vim (6083B)
1 " Vim indent file 2 " Language: Perl 3 " Maintainer: vim-perl <vim-perl@googlegroups.com> (need to be subscribed to post) 4 " Homepage: https://github.com/vim-perl/vim-perl 5 " Bugs/requests: https://github.com/vim-perl/vim-perl/issues 6 " License: Vim License (see :help license) 7 " Last Change: 2022 Jun 14 8 9 " Suggestions and improvements by : 10 " Aaron J. Sherman (use syntax for hints) 11 " Artem Chuprina (play nice with folding) 12 13 " TODO things that are not or not properly indented (yet) : 14 " - Continued statements 15 " print "foo", 16 " "bar"; 17 " print "foo" 18 " if bar(); 19 " - Multiline regular expressions (m//x) 20 " (The following probably needs modifying the perl syntax file) 21 " - qw() lists 22 " - Heredocs with terminators that don't match \I\i* 23 24 " Only load this indent file when no other was loaded. 25 if exists("b:did_indent") 26 finish 27 endif 28 let b:did_indent = 1 29 30 " Is syntax highlighting active ? 31 let b:indent_use_syntax = has("syntax") 32 33 setlocal indentexpr=GetPerlIndent() 34 setlocal indentkeys+=0=,0),0],0=or,0=and 35 if !b:indent_use_syntax 36 setlocal indentkeys+=0=EO 37 endif 38 39 let b:undo_indent = "setl inde< indk<" 40 41 let s:cpo_save = &cpo 42 set cpo-=C 43 44 function! GetPerlIndent() 45 46 " Get the line to be indented 47 let cline = getline(v:lnum) 48 49 " Indent POD markers to column 0 50 if cline =~ '^\s*=\L\@!' 51 return 0 52 endif 53 54 " Get current syntax item at the line's first char 55 let csynid = '' 56 if b:indent_use_syntax 57 let csynid = synIDattr(synID(v:lnum,1,0),"name") 58 endif 59 60 " Don't reindent POD and heredocs 61 if csynid == "perlPOD" || csynid == "perlHereDoc" || csynid =~ "^pod" 62 return indent(v:lnum) 63 endif 64 65 " Indent end-of-heredocs markers to column 0 66 if b:indent_use_syntax 67 " Assumes that an end-of-heredoc marker matches \I\i* to avoid 68 " confusion with other types of strings 69 if csynid == "perlStringStartEnd" && cline =~ '^\I\i*$' 70 return 0 71 endif 72 else 73 " Without syntax hints, assume that end-of-heredocs markers begin with EO 74 if cline =~ '^\s*EO' 75 return 0 76 endif 77 endif 78 79 " Now get the indent of the previous perl line. 80 81 " Find a non-blank line above the current line. 82 let lnum = prevnonblank(v:lnum - 1) 83 " Hit the start of the file, use zero indent. 84 if lnum == 0 85 return 0 86 endif 87 let line = getline(lnum) 88 let ind = indent(lnum) 89 " Skip heredocs, POD, and comments on 1st column 90 if b:indent_use_syntax 91 let skippin = 2 92 while skippin 93 let synid = synIDattr(synID(lnum,1,0),"name") 94 if (synid == "perlStringStartEnd" && line =~ '^\I\i*$') 95 \ || (skippin != 2 && synid == "perlPOD") 96 \ || (skippin != 2 && synid == "perlHereDoc") 97 \ || synid == "perlComment" 98 \ || synid =~ "^pod" 99 let lnum = prevnonblank(lnum - 1) 100 if lnum == 0 101 return 0 102 endif 103 let line = getline(lnum) 104 let ind = indent(lnum) 105 let skippin = 1 106 else 107 let skippin = 0 108 endif 109 endwhile 110 else 111 if line =~ "^EO" 112 let lnum = search("<<[\"']\\=EO", "bW") 113 let line = getline(lnum) 114 let ind = indent(lnum) 115 endif 116 endif 117 118 " Indent blocks enclosed by {}, (), or [] 119 if b:indent_use_syntax 120 " Find a real opening brace 121 " NOTE: Unlike Perl character classes, we do NOT need to escape the 122 " closing brackets with a backslash. Doing so just puts a backslash 123 " in the character class and causes sorrow. Instead, put the closing 124 " bracket as the first character in the class. 125 let braceclass = '[][(){}]' 126 let bracepos = match(line, braceclass, matchend(line, '^\s*[])}]')) 127 while bracepos != -1 128 let synid = synIDattr(synID(lnum, bracepos + 1, 0), "name") 129 " If the brace is highlighted in one of those groups, indent it. 130 " 'perlHereDoc' is here only to handle the case '&foo(<<EOF)'. 131 if synid == "" 132 \ || synid == "perlMatchStartEnd" 133 \ || synid == "perlHereDoc" 134 \ || synid == "perlBraces" 135 \ || synid == "perlStatementIndirObj" 136 \ || synid == "perlSubDeclaration" 137 \ || synid =~ "^perlFiledescStatement" 138 \ || synid =~ '^perl\(Sub\|Block\|Package\)Fold' 139 let brace = strpart(line, bracepos, 1) 140 if brace == '(' || brace == '{' || brace == '[' 141 let ind = ind + shiftwidth() 142 else 143 let ind = ind - shiftwidth() 144 endif 145 endif 146 let bracepos = match(line, braceclass, bracepos + 1) 147 endwhile 148 let bracepos = matchend(cline, '^\s*[])}]') 149 if bracepos != -1 150 let synid = synIDattr(synID(v:lnum, bracepos, 0), "name") 151 if synid == "" 152 \ || synid == "perlMatchStartEnd" 153 \ || synid == "perlBraces" 154 \ || synid == "perlStatementIndirObj" 155 \ || synid =~ '^perl\(Sub\|Block\|Package\)Fold' 156 let ind = ind - shiftwidth() 157 endif 158 endif 159 else 160 if line =~ '[{[(]\s*\(#[^])}]*\)\=$' 161 let ind = ind + shiftwidth() 162 endif 163 if cline =~ '^\s*[])}]' 164 let ind = ind - shiftwidth() 165 endif 166 endif 167 168 " Indent lines that begin with 'or' or 'and' 169 if cline =~ '^\s*\(or\|and\)\>' 170 if line !~ '^\s*\(or\|and\)\>' 171 let ind = ind + shiftwidth() 172 endif 173 elseif line =~ '^\s*\(or\|and\)\>' 174 let ind = ind - shiftwidth() 175 endif 176 177 return ind 178 179 endfunction 180 181 let &cpo = s:cpo_save 182 unlet s:cpo_save 183 184 " vim:ts=8:sts=4:sw=4:expandtab:ft=vim