PageRenderTime 28ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/indent/javascript.vim

https://github.com/qsorix/vim
Vim Script | 423 lines | 316 code | 62 blank | 45 comment | 106 complexity | 6c828296bb2306b8b5de8aae02a4783b MD5 | raw file
  1. " Vim indent file
  2. " Language: JavaScript
  3. " Maintainer: JiangMiao <jiangfriend@gmail.com>
  4. " Last Change: 2011-10-19
  5. " Version: 1.4.6
  6. " Homepage: http://www.vim.org/scripts/script.php?script_id=3227
  7. " Repository: https://github.com/jiangmiao/simple-javascript-indenter
  8. if exists('b:did_indent')
  9. finish
  10. endif
  11. " Disable Assginment let script will not indent assignment.
  12. if(!exists('g:SimpleJsIndenter_DisableAssignment'))
  13. let g:SimpleJsIndenter_DisableAssignment = 0
  14. endif
  15. " Brief Mode will indent no more than one level.
  16. if(!exists('g:SimpleJsIndenter_BriefMode'))
  17. let g:SimpleJsIndenter_BriefMode = 0
  18. endif
  19. " The value should be float, -1/2 should be written in -0.5
  20. if(!exists('g:SimpleJsIndenter_CaseIndentLevel'))
  21. let g:SimpleJsIndenter_CaseIndentLevel = 0
  22. endif
  23. if(!exists('g:SimpleJsIndenter_GreedyIndent'))
  24. let g:SimpleJsIndenter_GreedyIndent = 1
  25. endif
  26. let b:did_indent = 1
  27. let b:indented = 0
  28. let b:in_comment = 0
  29. setlocal indentexpr=GetJsIndent()
  30. setlocal indentkeys+==},=),=],0=*/,0=/*,0=\,,0=;,*<Return>
  31. if exists("*GetJsIndent")
  32. finish
  33. endif
  34. let s:expr_left = '[[{(]'
  35. let s:expr_right = '[)}\]]'
  36. let s:expr_all = '[[{()}\]]'
  37. let s:expr_case = '\s\+\(case\s\+[^\:]*\|default\)\s*:\s*'
  38. let s:expr_comment_start = '/\*c'
  39. let s:expr_comment_end = 'c\*/'
  40. let s:expr_comma_start = '^\s*,'
  41. let s:expr_var = '^\s*var\s'
  42. let s:expr_var_stop = ';'
  43. " add $ to Fix
  44. " ;(function() {
  45. " something;
  46. " })
  47. let s:expr_semic_start = '^\s*;\s*$'
  48. " Check prev line
  49. function! DoIndentPrev(ind,str)
  50. let ind = a:ind
  51. let pline = a:str
  52. let first = 1
  53. let last = 0
  54. if g:SimpleJsIndenter_GreedyIndent || pline !~ s:expr_left || s:IsOneLineIndentLoose(pline)
  55. let mstr = matchstr(pline, '^'.s:expr_right.'*')
  56. let last = strlen(mstr)
  57. let start_with_expr_right = last
  58. else
  59. let start_with_expr_right = 0
  60. endif
  61. let ind_add = 0
  62. let ind_dec = 0
  63. while 1
  64. let last=match(pline, s:expr_all, last)
  65. if last == -1
  66. break
  67. endif
  68. let str = pline[last]
  69. let last = last + 1
  70. if match(str, s:expr_left) != -1
  71. let ind_add += 1
  72. else
  73. if start_with_expr_right == 0
  74. let ind_dec += 1
  75. endif
  76. endif
  77. endwhile
  78. "BriefMode
  79. if(g:SimpleJsIndenter_BriefMode)
  80. if ind_add > 1
  81. let ind_add = 1
  82. endif
  83. if ind_dec > 1
  84. let ind_dec = 1
  85. endif
  86. endif
  87. let ind = a:ind + (ind_add - ind_dec) * &sw
  88. if (match(' '.pline, s:expr_case)!=-1)
  89. let ind = float2nr(ind - &sw * g:SimpleJsIndenter_CaseIndentLevel)
  90. endif
  91. if match(pline, s:expr_comment_start) != -1
  92. let ind = ind + 1
  93. endif
  94. if match(pline, s:expr_comment_end) != -1
  95. let ind = ind - 1
  96. endif
  97. if match(pline, s:expr_comma_start) != -1
  98. let ind = ind + 2
  99. if match(pline, s:expr_var_stop) != -1
  100. let ind = ind - 4
  101. endif
  102. endif
  103. " buggy
  104. if match(pline, s:expr_semic_start) != -1
  105. let ind = ind - 2
  106. endif
  107. return ind
  108. endfunction
  109. " Check current line
  110. function! DoIndent(ind, str, pline)
  111. let ind = a:ind
  112. let line = a:str
  113. let pline = a:pline
  114. let last = 0
  115. let first = 1
  116. if g:SimpleJsIndenter_GreedyIndent || line !~ s:expr_left || s:IsOneLineIndentLoose(line)
  117. let mstr = matchstr(line, '^'.s:expr_right.'*')
  118. let num = strlen(mstr)
  119. let start_with_expr_right = num
  120. " If start with expr right, then indent as more as possible.
  121. if start_with_expr_right
  122. let num = len(split(line, s:expr_right, 1)) - 1
  123. endif
  124. let ind = ind - &sw * num
  125. endif
  126. "BriefMode
  127. if(g:SimpleJsIndenter_BriefMode)
  128. if(ind<a:ind)
  129. let ind = a:ind - &sw
  130. endif
  131. if(ind>a:ind)
  132. let ind = a:ind + &sw
  133. endif
  134. endif
  135. if (match(' '.line, s:expr_case)!=-1)
  136. let ind = float2nr(ind + &sw * g:SimpleJsIndenter_CaseIndentLevel)
  137. endif
  138. if (match(line, s:expr_comma_start) != -1)
  139. let ind = ind - 2
  140. if (match(pline, s:expr_var) != -1)
  141. let ind = ind + 4
  142. endif
  143. endif
  144. if (match(line, s:expr_semic_start) != -1 && match(pline, s:expr_comma_start) != -1)
  145. let ind = ind - 2
  146. endif
  147. if ind<0
  148. let ind=0
  149. endif
  150. return ind
  151. endfunction
  152. " Remove strings and comments
  153. function! TrimLine(pline)
  154. let line = substitute(a:pline, '\\\\', '_','g')
  155. let line = substitute(line, '\\.', '_','g')
  156. " One line comment
  157. let line = substitute(line, '^\s*/\*.*\*/\s*$', '//c', 'g')
  158. let line = substitute(line, '^\s*//.*$', '//c', 'g')
  159. " remove all non ascii character
  160. let line = substitute(line, '[^\x00-\x7f]', '', 'g')
  161. " Strings
  162. let new_line = ''
  163. let sub_line = ''
  164. let min_pos = 0
  165. while 1
  166. let c = ''
  167. let base_pos = min_pos
  168. let min_pos = match(line, '[''"/]', base_pos)
  169. if min_pos == -1
  170. let new_line .= strpart(line, base_pos)
  171. break
  172. endif
  173. let c = line[min_pos]
  174. let new_line .= strpart(line, base_pos, min_pos - base_pos)
  175. let sub_line = ''
  176. if c == ''''
  177. let sub_line = matchstr(line, "^'.\\{-}'", min_pos)
  178. if sub_line != ''
  179. let new_line .= '_'
  180. endif
  181. elseif c == '"'
  182. let sub_line = matchstr(line, '^".\{-}"', min_pos)
  183. if sub_line != ''
  184. let new_line .= '_'
  185. endif
  186. elseif c == '/'
  187. " Skip all if match a comment
  188. if line[min_pos+1] == '/'
  189. let sub_line = matchstr(line, '^/.*', min_pos)
  190. if min_pos == 0 && sub_line != ''
  191. let new_line = '//c'
  192. break
  193. endif
  194. elseif line[min_pos+1] == '*'
  195. let sub_line = matchstr(line, '^/\*.\{-}\*/', min_pos)
  196. else
  197. " /.../ sometimes is not a regexp, (a / b); // c
  198. let m = matchlist(line, '^\(/[^/]\+/\)\([^/]\|$\)', min_pos)
  199. if len(m)
  200. let new_line .= '_'
  201. let sub_line = m[1]
  202. endif
  203. endif
  204. endif
  205. if sub_line != ''
  206. let min_pos = min_pos + strlen(sub_line)
  207. else
  208. let new_line .= c
  209. let min_pos = min_pos + 1
  210. endif
  211. endwhile
  212. let line = new_line
  213. " Comment
  214. let line = substitute(line, '/\*.*$','/*c','')
  215. let line = substitute(line, '^.\{-}\*/','c*/','')
  216. let line = substitute(line, '^\s*\*.*','','')
  217. " Brackets
  218. let new_line = ''
  219. while new_line != line
  220. let new_line = line
  221. let line = substitute(line,'\(([^)(]*)\|\[[^\][]*\]\|{[^}{]*}\)','_','g')
  222. endwhile
  223. " Trim Blank
  224. let line = matchlist(line, '\s*\(.\{-}\)\s*$')[1]
  225. return line
  226. endfunction
  227. function! s:GetLine(num)
  228. return TrimLine(getline(a:num))
  229. endfunction
  230. let s:expr_partial = '[+\-*/|&,]$'
  231. let s:expr_partial2 = '[+\-*/|&]$'
  232. function! s:IsPartial(line)
  233. " Add IndentLoose for
  234. " function a() {
  235. " test(["hello",
  236. " "world",
  237. " "a",
  238. " "b"
  239. " ]) // Failed
  240. " }
  241. return match(a:line, '\*/$') == -1 && match(a:line, s:expr_partial)!=-1 && ( match(a:line, s:expr_all)==-1 || s:IsOneLineIndentLoose(a:line) )
  242. endfunction
  243. function! s:IsComment(line)
  244. return a:line =~ '^\s*//' || a:line =~ '^\s*/\*.*\*/\s*$'
  245. endfunction
  246. function! s:SearchBack(num)
  247. let num = a:num
  248. let new_num = num
  249. let partial = 0
  250. while 1
  251. if new_num == 0
  252. break
  253. endif
  254. let line = getline(new_num)
  255. if !s:IsComment(line)
  256. let line = TrimLine(line)
  257. if !s:IsPartial(line)
  258. if partial > 0
  259. " Store line number to last partial
  260. let num = partial
  261. endif
  262. break
  263. endif
  264. " Save the partial postion
  265. let partial = new_num
  266. if match(line, s:expr_all)!=-1
  267. let num = new_num
  268. break
  269. endif
  270. endif
  271. let num = new_num
  272. let new_num = num - 1
  273. endwhile
  274. return num
  275. endfunction
  276. function! s:AssignIndent(line)
  277. let ind = 0
  278. let line = a:line
  279. let line = matchlist(line, '^\s*\(.\{-}\)\s*$')[1]
  280. if(match(line,'.*=.*'.s:expr_partial2) != -1)
  281. return ind + strlen(matchstr(line, '.*=\s*'))
  282. elseif(match(line,'\(var\|return\)\s\+.*=\s*') != -1)
  283. return ind + strlen(matchstr(line, '\(var\|return\)\s\+'))
  284. elseif(match(line,'\(var\|return\)\s\+') != -1)
  285. return ind + strlen(matchstr(line, '\(var\|return\)\s\+'))
  286. elseif(match(line,'^\w\s\+=\s*.*[^,]$') != -1)
  287. return ind + strlen(matchstr(line, '^\w\s\+=\s*'))
  288. endif
  289. return ind
  290. endfunction
  291. function! s:IsAssign(line)
  292. return match(a:line, s:expr_all) == -1 && s:AssignIndent(a:line)>0
  293. endfunction
  294. function DoIndentAssign(ind, line)
  295. return a:ind + s:AssignIndent(a:line)
  296. endfunction
  297. function! s:IsOneLineIndent(line)
  298. return match(a:line, '^[})\]]*\s*\(if\|else\|while\|try\|catch\|finally\|for\|else\s\+if\)\s*_\=$') != -1
  299. endfunction
  300. function! s:IsOneLineIndentLoose(line)
  301. " _\= equal _? in PCRE
  302. return match(a:line, '^[})\]]*\s*\(if\|else\|while\|try\|catch\|finally\|for\|else\s\+if\)') != -1
  303. endfunction
  304. function! GetJsIndent()
  305. if v:lnum == 1
  306. return 0
  307. endif
  308. let pnum = prevnonblank(v:lnum-1)
  309. let pline = s:GetLine(pnum)
  310. let ppnum = prevnonblank(pnum - 1)
  311. let ppline = s:GetLine(ppnum)
  312. if ((s:IsPartial(pline)||s:IsComment(pline)) && pnum == v:lnum-1)||match(pline, s:expr_left)!=-1
  313. let pnum = s:SearchBack(pnum)
  314. let ind = indent(pnum)
  315. let pline = s:GetLine(pnum)
  316. let ind = DoIndentPrev(ind, pline)
  317. if(!g:SimpleJsIndenter_DisableAssignment)
  318. if s:IsAssign(pline) && match(s:GetLine(v:lnum), s:expr_all)==-1
  319. let ind = DoIndentAssign(ind, pline)
  320. endif
  321. endif
  322. else
  323. let fix = 1
  324. " Ignore the comments
  325. while s:IsComment(ppline)
  326. let ppnum = prevnonblank(ppnum-1)
  327. let ppline = s:GetLine(ppnum)
  328. let fix += 1
  329. endwhile
  330. if s:IsPartial(ppline) && ppnum == pnum- fix
  331. let pnum = s:SearchBack(ppnum)
  332. endif
  333. let ind = indent(pnum)
  334. let pline = s:GetLine(pnum)
  335. let ind = DoIndentPrev(ind, pline)
  336. let ppnum = prevnonblank(pnum-1)
  337. let ppline = s:GetLine(ppnum)
  338. if s:IsOneLineIndent(pline) && match(s:GetLine(v:lnum), s:expr_all)==-1
  339. let ind = ind + &sw
  340. endif
  341. if s:IsOneLineIndent(ppline)
  342. let ind = ind - &sw
  343. endif
  344. endif
  345. " If pline is indented, and ppline is partial then indent
  346. " Fix for
  347. " function() {
  348. " b( this,
  349. " a(),
  350. " d() );
  351. " },
  352. let real_pnum = prevnonblank(v:lnum-1)
  353. if(real_pnum!=pnum)
  354. let pline = s:GetLine(real_pnum)
  355. let ind = DoIndentPrev(ind, pline)
  356. endif
  357. let line = s:GetLine(v:lnum)
  358. let ind = DoIndent(ind, line, pline)
  359. return ind
  360. endfunction