Няма описание

python.vim 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. "=============================================================================
  2. "
  3. " FileName: python.vim
  4. " Desc: 修改了缩进的bug
  5. "
  6. " Author: dantezhu - http://www.vimer.cn
  7. " Email: zny2008@gmail.com
  8. "
  9. " Created: 2011-02-21 23:55:50
  10. " Version: 0.1.0
  11. " History:
  12. " 0.0.1 | dantezhu | 2011-02-21 23:55:50 | initialization
  13. " 0.0.2 | dantezhu | 2011-02-22 01:15:53 | 增加了对class,if,elif
  14. " | 等的兼容
  15. " 0.0.3 | dantezhu | 2011-02-22 14:53:40 | 修正了Comment或者
  16. " | String中存在:时就会缩
  17. " | 进的问题
  18. " 0.0.4 | dantezhu | 2011-02-24 19:32:14 | 之前的fix有问题,重写
  19. " 0.0.5 | dantezhu | 2011-02-26 23:28:16 | 修正对调用函数时,多
  20. " | 行参数的)的缩进
  21. " 0.0.6 | dantezhu | 2011-02-26 23:45:18 | 只约束是字母太弱了,
  22. " | 还有数字和下划线
  23. " 0.0.7 | dantezhu | 2011-03-10 11:06:01 | 向cindent看齐,函数名
  24. " | 太短则和匹配的地方对齐
  25. " 0.0.8 | dantezhu | 2011-03-10 18:41:15 | 之前修正的有点问题
  26. " 0.0.9 | dantezhu | 2011-03-15 10:15:05 | 注释和string不缩进
  27. " 0.1.0 | dantezhu | 2011-03-16 18:18:13 | 最后某部分vim缩进bug
  28. "
  29. "=============================================================================
  30. " Python indent file
  31. " Language: Python
  32. " Maintainer: Eric Mc Sween <em@tomcom.de>
  33. " Original Author: David Bustos <bustos@caltech.edu>
  34. " Last Change: 2004 Jun 07
  35. " Only load this indent file when no other was loaded.
  36. if exists("b:did_indent")
  37. finish
  38. endif
  39. let b:did_indent = 1
  40. setlocal expandtab
  41. setlocal nolisp
  42. setlocal autoindent
  43. setlocal indentexpr=GetPythonIndent(v:lnum)
  44. setlocal indentkeys=!^F,o,O,<:>,0),0],0},=elif,=except
  45. let s:maxoff = 50
  46. " Find backwards the closest open parenthesis/bracket/brace.
  47. function! s:SearchParensPair()
  48. let line = line('.')
  49. let col = col('.')
  50. " Skip strings and comments and don't look too far
  51. let skip = "line('.') < " . (line - s:maxoff) . " ? dummy :" .
  52. \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? ' .
  53. \ '"string\\|comment"'
  54. " Search for parentheses
  55. call cursor(line, col)
  56. let parlnum = searchpair('(', '', ')', 'bW', skip)
  57. let parcol = col('.')
  58. " Search for brackets
  59. call cursor(line, col)
  60. let par2lnum = searchpair('\[', '', '\]', 'bW', skip)
  61. let par2col = col('.')
  62. " Search for braces
  63. call cursor(line, col)
  64. let par3lnum = searchpair('{', '', '}', 'bW', skip)
  65. let par3col = col('.')
  66. " Get the closest match
  67. if par2lnum > parlnum || (par2lnum == parlnum && par2col > parcol)
  68. let parlnum = par2lnum
  69. let parcol = par2col
  70. endif
  71. if par3lnum > parlnum || (par3lnum == parlnum && par3col > parcol)
  72. let parlnum = par3lnum
  73. let parcol = par3col
  74. endif
  75. " Put the cursor on the match
  76. if parlnum > 0
  77. call cursor(parlnum, parcol)
  78. endif
  79. return parlnum
  80. endfunction
  81. " Find the start of a multi-line statement
  82. function! s:StatementStart(lnum)
  83. let lnum = a:lnum
  84. while 1
  85. if getline(lnum - 1) =~ '\\$'
  86. let lnum = lnum - 1
  87. else
  88. call cursor(lnum, 1)
  89. let maybe_lnum = s:SearchParensPair()
  90. if maybe_lnum < 1
  91. return lnum
  92. else
  93. let lnum = maybe_lnum
  94. endif
  95. endif
  96. endwhile
  97. endfunction
  98. " Find the block starter that matches the current line
  99. function! s:BlockStarter(lnum, block_start_re)
  100. let lnum = a:lnum
  101. let maxindent = 10000 " whatever
  102. while lnum > 1
  103. let lnum = prevnonblank(lnum - 1)
  104. if indent(lnum) < maxindent
  105. if getline(lnum) =~ a:block_start_re
  106. return lnum
  107. else
  108. let maxindent = indent(lnum)
  109. " It's not worth going further if we reached the top level
  110. if maxindent == 0
  111. return -1
  112. endif
  113. endif
  114. endif
  115. endwhile
  116. return -1
  117. endfunction
  118. function! GetPythonIndent(lnum)
  119. " First line has indent 0
  120. if a:lnum == 1
  121. return 0
  122. endif
  123. "Add-Begin by dantezhu in 2011-03-15 10:14:01
  124. "修正注释和字符串缩进的问题
  125. " If the start of the line is in a string don't change the indent.
  126. if has('syntax_items')
  127. \ && synIDattr(synID(a:lnum, col('.')-1, 1), 'name') =~ '\(Comment\|String\)$'
  128. return -1
  129. endif
  130. "Add-End
  131. " If we can find an open parenthesis/bracket/brace, line up with it.
  132. call cursor(a:lnum, 1)
  133. let parlnum = s:SearchParensPair()
  134. if parlnum > 0
  135. let parcol = col('.')
  136. let closing_paren = match(getline(a:lnum), '^\s*[])}]') != -1
  137. if match(getline(parlnum), '[([{]\s*$', parcol - 1) != -1
  138. if closing_paren
  139. "Mod-Begin by dantezhu in 2011-02-21 23:38:24
  140. "FROM
  141. "return indent(parlnum)
  142. "TO
  143. "为了支持如下的格式:
  144. "def fun(
  145. " a,
  146. " b
  147. " ):
  148. " print a,b
  149. "又不影响如下格式:
  150. "val = {
  151. " (
  152. " 1,
  153. " 2
  154. " ):1
  155. "}
  156. if match(getline(a:lnum), ')\s*:') != -1 &&
  157. \ match(getline(parlnum), '\(def\|class\|if\|elif\|while\)\(\s\+\|(\)') != -1
  158. return indent(parlnum) + &sw
  159. else
  160. return indent(parlnum)
  161. endif
  162. "Mod-End
  163. else
  164. return indent(parlnum) + &sw
  165. endif
  166. else
  167. if closing_paren
  168. return parcol - 1
  169. else
  170. return parcol
  171. endif
  172. endif
  173. endif
  174. " Examine this line
  175. let thisline = getline(a:lnum)
  176. let thisindent = indent(a:lnum)
  177. " If the line starts with 'elif' or 'else', line up with 'if' or 'elif'
  178. if thisline =~ '^\s*\(elif\|else\)\>'
  179. let bslnum = s:BlockStarter(a:lnum, '^\s*\(if\|elif\)\>')
  180. if bslnum > 0
  181. return indent(bslnum)
  182. else
  183. return -1
  184. endif
  185. endif
  186. " If the line starts with 'except' or 'finally', line up with 'try'
  187. " or 'except'
  188. if thisline =~ '^\s*\(except\|finally\)\>'
  189. let bslnum = s:BlockStarter(a:lnum, '^\s*\(try\|except\)\>')
  190. if bslnum > 0
  191. return indent(bslnum)
  192. else
  193. return -1
  194. endif
  195. endif
  196. " Examine previous line
  197. let plnum = a:lnum - 1
  198. let pline = getline(plnum)
  199. let sslnum = s:StatementStart(plnum)
  200. " If the previous line is blank, keep the same indentation
  201. if pline =~ '^\s*$'
  202. return -1
  203. endif
  204. " If this line is explicitly joined, try to find an indentation that looks
  205. " good.
  206. if pline =~ '\\$'
  207. let compound_statement = '^\s*\(if\|while\|for\s.*\sin\|except\)\s*'
  208. let maybe_indent = matchend(getline(sslnum), compound_statement)
  209. if maybe_indent != -1
  210. return maybe_indent
  211. else
  212. return indent(sslnum) + &sw * 2
  213. endif
  214. endif
  215. " If the previous line ended with a colon, indent relative to
  216. " statement start.
  217. if pline =~ ':\s*$'
  218. "Mod-Begin by dantezhu in 2011-02-24 19:30:52
  219. "FROM
  220. "return indent(sslnum) + &sw
  221. "TO
  222. let t_col = match(pline,':\s*$')+1
  223. if synIDattr(synID(a:lnum-1, t_col, 1), 'name') !~ '\(Comment\|String\)$'
  224. return indent(sslnum) + &sw
  225. endif
  226. "Mod-End
  227. endif
  228. " If the previous line was a stop-execution statement or a pass
  229. if getline(sslnum) =~ '^\s*\(break\|continue\|raise\|return\|pass\)\>'
  230. " See if the user has already dedented
  231. if indent(a:lnum) > indent(sslnum) - &sw
  232. " If not, recommend one dedent
  233. return indent(sslnum) - &sw
  234. endif
  235. " Otherwise, trust the user
  236. return -1
  237. endif
  238. " In all other cases, line up with the start of the previous statement.
  239. return indent(sslnum)
  240. endfunction