meson.vim 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. " Vim indent file
  2. " Language: Meson
  3. " Maintainer: Nirbheek Chauhan <nirbheek.chauhan@gmail.com>
  4. " Original Authors: David Bustos <bustos@caltech.edu>
  5. " Bram Moolenaar <Bram@vim.org>
  6. " Last Change: 2015 Feb 23
  7. " Only load this indent file when no other was loaded.
  8. if exists("b:did_indent")
  9. finish
  10. endif
  11. let b:did_indent = 1
  12. " Some preliminary settings
  13. setlocal nolisp " Make sure lisp indenting doesn't supersede us
  14. setlocal autoindent " indentexpr isn't much help otherwise
  15. setlocal indentexpr=GetMesonIndent(v:lnum)
  16. setlocal indentkeys+==elif,=else,=endforeach,=endif,0)
  17. " Only define the function once.
  18. if exists("*GetMesonIndent")
  19. finish
  20. endif
  21. let s:keepcpo= &cpo
  22. setlocal cpo&vim
  23. " Come here when loading the script the first time.
  24. let s:maxoff = 50 " maximum number of lines to look backwards for ()
  25. " Force sw=2 sts=2 because that's required by convention
  26. setlocal shiftwidth=2
  27. setlocal softtabstop=2
  28. function GetMesonIndent(lnum)
  29. echom getline(line("."))
  30. " If this line is explicitly joined: If the previous line was also joined,
  31. " line it up with that one, otherwise add two 'shiftwidth'
  32. if getline(a:lnum - 1) =~ '\\$'
  33. if a:lnum > 1 && getline(a:lnum - 2) =~ '\\$'
  34. return indent(a:lnum - 1)
  35. endif
  36. return indent(a:lnum - 1) + (exists("g:mesonindent_continue") ? eval(g:mesonindent_continue) : (shiftwidth() * 2))
  37. endif
  38. " If the start of the line is in a string don't change the indent.
  39. if has('syntax_items')
  40. \ && synIDattr(synID(a:lnum, 1, 1), "name") =~ "String$"
  41. return -1
  42. endif
  43. " Search backwards for the previous non-empty line.
  44. let plnum = prevnonblank(v:lnum - 1)
  45. if plnum == 0
  46. " This is the first non-empty line, use zero indent.
  47. return 0
  48. endif
  49. " If the previous line is inside parenthesis, use the indent of the starting
  50. " line.
  51. " Trick: use the non-existing "dummy" variable to break out of the loop when
  52. " going too far back.
  53. call cursor(plnum, 1)
  54. let parlnum = searchpair('(\|{\|\[', '', ')\|}\|\]', 'nbW',
  55. \ "line('.') < " . (plnum - s:maxoff) . " ? dummy :"
  56. \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')"
  57. \ . " =~ '\\(Comment\\|Todo\\|String\\)$'")
  58. if parlnum > 0
  59. let plindent = indent(parlnum)
  60. let plnumstart = parlnum
  61. else
  62. let plindent = indent(plnum)
  63. let plnumstart = plnum
  64. endif
  65. " When inside parenthesis: If at the first line below the parenthesis add
  66. " two 'shiftwidth', otherwise same as previous line.
  67. " i = (a
  68. " + b
  69. " + c)
  70. call cursor(a:lnum, 1)
  71. let p = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW',
  72. \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :"
  73. \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')"
  74. \ . " =~ '\\(Comment\\|Todo\\|String\\)$'")
  75. if p > 0
  76. if p == plnum
  77. " When the start is inside parenthesis, only indent one 'shiftwidth'.
  78. let pp = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW',
  79. \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :"
  80. \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')"
  81. \ . " =~ '\\(Comment\\|Todo\\|String\\)$'")
  82. if pp > 0
  83. return indent(plnum) + (exists("g:pyindent_nested_paren") ? eval(g:pyindent_nested_paren) : shiftwidth())
  84. endif
  85. return indent(plnum) + (exists("g:pyindent_open_paren") ? eval(g:pyindent_open_paren) : (shiftwidth() * 2))
  86. endif
  87. if plnumstart == p
  88. return indent(plnum)
  89. endif
  90. return plindent
  91. endif
  92. " Get the line and remove a trailing comment.
  93. " Use syntax highlighting attributes when possible.
  94. let pline = getline(plnum)
  95. let pline_len = strlen(pline)
  96. if has('syntax_items')
  97. " If the last character in the line is a comment, do a binary search for
  98. " the start of the comment. synID() is slow, a linear search would take
  99. " too long on a long line.
  100. if synIDattr(synID(plnum, pline_len, 1), "name") =~ "\\(Comment\\|Todo\\)$"
  101. let min = 1
  102. let max = pline_len
  103. while min < max
  104. let col = (min + max) / 2
  105. if synIDattr(synID(plnum, col, 1), "name") =~ "\\(Comment\\|Todo\\)$"
  106. let max = col
  107. else
  108. let min = col + 1
  109. endif
  110. endwhile
  111. let pline = strpart(pline, 0, min - 1)
  112. endif
  113. else
  114. let col = 0
  115. while col < pline_len
  116. if pline[col] == '#'
  117. let pline = strpart(pline, 0, col)
  118. break
  119. endif
  120. let col = col + 1
  121. endwhile
  122. endif
  123. " If the previous line ended the conditional/loop
  124. if getline(plnum) =~ '^\s*\(endif\|endforeach\)\>\s*'
  125. " Maintain indent
  126. return -1
  127. endif
  128. " If the previous line ended with a builtin, indent this line
  129. if pline =~ '^\s*\(foreach\|if\|else\|elif\)\>\s*'
  130. return plindent + shiftwidth()
  131. endif
  132. " If the current line begins with a header keyword, deindent
  133. if getline(a:lnum) =~ '^\s*\(else\|elif\|endif\|endforeach\)'
  134. " Unless the previous line was a one-liner
  135. if getline(plnumstart) =~ '^\s*\(foreach\|if\)\>\s*'
  136. return plindent
  137. endif
  138. " Or the user has already dedented
  139. if indent(a:lnum) <= plindent - shiftwidth()
  140. return -1
  141. endif
  142. return plindent - shiftwidth()
  143. endif
  144. " When after a () construct we probably want to go back to the start line.
  145. " a = (b
  146. " + c)
  147. " here
  148. if parlnum > 0
  149. return plindent
  150. endif
  151. return -1
  152. endfunction
  153. let &cpo = s:keepcpo
  154. unlet s:keepcpo
  155. " vim:sw=2