perl.vim 5.8 KB

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