perl.vim 5.9 KB

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