Mercurial > vim
comparison runtime/indent/r.vim @ 3082:3502a7f991fc
Updated runtime files.
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Wed, 14 Sep 2011 17:55:08 +0200 |
parents | |
children | 37ecb8ff4560 |
comparison
equal
deleted
inserted
replaced
3081:1e50bdaa24f8 | 3082:3502a7f991fc |
---|---|
1 " Vim indent file | |
2 " Language: R | |
3 " Author: Jakson Alves de Aquino <jalvesaq@gmail.com> | |
4 " Last Change: Wed Aug 31, 2011 12:24AM | |
5 | |
6 | |
7 " Only load this indent file when no other was loaded. | |
8 if exists("b:did_r_indent") | |
9 finish | |
10 endif | |
11 let b:did_r_indent = 1 | |
12 | |
13 setlocal indentkeys=0{,0},:,!^F,o,O,e | |
14 setlocal indentexpr=GetRIndent() | |
15 | |
16 " Only define the function once. | |
17 if exists("*GetRIndent") | |
18 finish | |
19 endif | |
20 | |
21 " Options to make the indentation more similar to Emacs/ESS: | |
22 if !exists("g:r_indent_align_args") | |
23 let g:r_indent_align_args = 1 | |
24 endif | |
25 if !exists("g:r_indent_ess_comments") | |
26 let g:r_indent_ess_comments = 0 | |
27 endif | |
28 if !exists("g:r_indent_comment_column") | |
29 let g:r_indent_comment_column = 40 | |
30 endif | |
31 if ! exists("g:r_indent_ess_compatible") | |
32 let g:r_indent_ess_compatible = 0 | |
33 endif | |
34 | |
35 function s:RDelete_quotes(line) | |
36 let i = 0 | |
37 let j = 0 | |
38 let line1 = "" | |
39 let llen = strlen(a:line) | |
40 while i < llen | |
41 if a:line[i] == '"' | |
42 let i += 1 | |
43 let line1 = line1 . 's' | |
44 while !(a:line[i] == '"' && ((i > 1 && a:line[i-1] == '\' && a:line[i-2] == '\') || a:line[i-1] != '\')) && i < llen | |
45 let i += 1 | |
46 endwhile | |
47 if a:line[i] == '"' | |
48 let i += 1 | |
49 endif | |
50 else | |
51 if a:line[i] == "'" | |
52 let i += 1 | |
53 let line1 = line1 . 's' | |
54 while !(a:line[i] == "'" && ((i > 1 && a:line[i-1] == '\' && a:line[i-2] == '\') || a:line[i-1] != '\')) && i < llen | |
55 let i += 1 | |
56 endwhile | |
57 if a:line[i] == "'" | |
58 let i += 1 | |
59 endif | |
60 else | |
61 if a:line[i] == "`" | |
62 let i += 1 | |
63 let line1 = line1 . 's' | |
64 while a:line[i] != "`" && i < llen | |
65 let i += 1 | |
66 endwhile | |
67 if a:line[i] == "`" | |
68 let i += 1 | |
69 endif | |
70 endif | |
71 endif | |
72 endif | |
73 if i == llen | |
74 break | |
75 endif | |
76 let line1 = line1 . a:line[i] | |
77 let j += 1 | |
78 let i += 1 | |
79 endwhile | |
80 return line1 | |
81 endfunction | |
82 | |
83 " Convert foo(bar()) int foo() | |
84 function s:RDelete_parens(line) | |
85 if s:Get_paren_balance(a:line, "(", ")") != 0 | |
86 return a:line | |
87 endif | |
88 let i = 0 | |
89 let j = 0 | |
90 let line1 = "" | |
91 let llen = strlen(a:line) | |
92 while i < llen | |
93 let line1 = line1 . a:line[i] | |
94 if a:line[i] == '(' | |
95 let nop = 1 | |
96 while nop > 0 && i < llen | |
97 let i += 1 | |
98 if a:line[i] == ')' | |
99 let nop -= 1 | |
100 else | |
101 if a:line[i] == '(' | |
102 let nop += 1 | |
103 endif | |
104 endif | |
105 endwhile | |
106 let line1 = line1 . a:line[i] | |
107 endif | |
108 let i += 1 | |
109 endwhile | |
110 return line1 | |
111 endfunction | |
112 | |
113 function! s:Get_paren_balance(line, o, c) | |
114 let line2 = substitute(a:line, a:o, "", "g") | |
115 let openp = strlen(a:line) - strlen(line2) | |
116 let line3 = substitute(line2, a:c, "", "g") | |
117 let closep = strlen(line2) - strlen(line3) | |
118 return openp - closep | |
119 endfunction | |
120 | |
121 function! s:Get_matching_brace(linenr, o, c, delbrace) | |
122 let line = SanitizeRLine(getline(a:linenr)) | |
123 if a:delbrace == 1 | |
124 let line = substitute(line, '{$', "", "") | |
125 endif | |
126 let pb = s:Get_paren_balance(line, a:o, a:c) | |
127 let i = a:linenr | |
128 while pb != 0 && i > 1 | |
129 let i -= 1 | |
130 let pb += s:Get_paren_balance(SanitizeRLine(getline(i)), a:o, a:c) | |
131 endwhile | |
132 return i | |
133 endfunction | |
134 | |
135 " This function is buggy because there 'if's without 'else' | |
136 " It must be rewritten relying more on indentation | |
137 function! s:Get_matching_if(linenr, delif) | |
138 " let filenm = expand("%") | |
139 " call writefile([filenm], "/tmp/matching_if_" . a:linenr) | |
140 let line = SanitizeRLine(getline(a:linenr)) | |
141 if a:delif | |
142 let line = substitute(line, "if", "", "g") | |
143 endif | |
144 let elsenr = 0 | |
145 let i = a:linenr | |
146 let ifhere = 0 | |
147 while i > 0 | |
148 let line2 = substitute(line, '\<else\>', "xxx", "g") | |
149 let elsenr += strlen(line) - strlen(line2) | |
150 if line =~ '.*\s*if\s*()' || line =~ '.*\s*if\s*()' | |
151 let elsenr -= 1 | |
152 if elsenr == 0 | |
153 let ifhere = i | |
154 break | |
155 endif | |
156 endif | |
157 let i -= 1 | |
158 let line = SanitizeRLine(getline(i)) | |
159 endwhile | |
160 if ifhere | |
161 return ifhere | |
162 else | |
163 return a:linenr | |
164 endif | |
165 endfunction | |
166 | |
167 function! s:Get_last_paren_idx(line, o, c, pb) | |
168 let blc = a:pb | |
169 let line = substitute(a:line, '\t', s:curtabstop, "g") | |
170 let theidx = -1 | |
171 let llen = strlen(line) | |
172 let idx = 0 | |
173 while idx < llen | |
174 if line[idx] == a:o | |
175 let blc -= 1 | |
176 if blc == 0 | |
177 let theidx = idx | |
178 endif | |
179 else | |
180 if line[idx] == a:c | |
181 let blc += 1 | |
182 endif | |
183 endif | |
184 let idx += 1 | |
185 endwhile | |
186 return theidx + 1 | |
187 endfunction | |
188 | |
189 " Get previous relevant line. Search back until getting a line that isn't | |
190 " comment or blank | |
191 function s:Get_prev_line(lineno) | |
192 let lnum = a:lineno - 1 | |
193 let data = getline( lnum ) | |
194 while lnum > 0 && (data =~ '^\s*#' || data =~ '^\s*$') | |
195 let lnum = lnum - 1 | |
196 let data = getline( lnum ) | |
197 endwhile | |
198 return lnum | |
199 endfunction | |
200 | |
201 " This function is also used by r-plugin/common_global.vim | |
202 " Delete from '#' to the end of the line, unless the '#' is inside a string. | |
203 function SanitizeRLine(line) | |
204 let newline = s:RDelete_quotes(a:line) | |
205 let newline = s:RDelete_parens(newline) | |
206 let newline = substitute(newline, '#.*', "", "") | |
207 let newline = substitute(newline, '\s*$', "", "") | |
208 return newline | |
209 endfunction | |
210 | |
211 function GetRIndent() | |
212 | |
213 let clnum = line(".") " current line | |
214 | |
215 let cline = getline(clnum) | |
216 if cline =~ '^\s*#' | |
217 if g:r_indent_ess_comments == 1 | |
218 if cline =~ '^\s*###' | |
219 return 0 | |
220 endif | |
221 if cline !~ '^\s*##' | |
222 return g:r_indent_comment_column | |
223 endif | |
224 endif | |
225 endif | |
226 | |
227 let cline = SanitizeRLine(cline) | |
228 | |
229 if cline =~ '^\s*}' || cline =~ '^\s*}\s*)$' | |
230 let indline = s:Get_matching_brace(clnum, '{', '}', 1) | |
231 if indline > 0 && indline != clnum | |
232 let iline = SanitizeRLine(getline(indline)) | |
233 if s:Get_paren_balance(iline, "(", ")") == 0 || iline =~ '(\s*{$' | |
234 return indent(indline) | |
235 else | |
236 let indline = s:Get_matching_brace(indline, '(', ')', 1) | |
237 return indent(indline) | |
238 endif | |
239 endif | |
240 endif | |
241 | |
242 " Find the first non blank line above the current line | |
243 let lnum = s:Get_prev_line(clnum) | |
244 " Hit the start of the file, use zero indent. | |
245 if lnum == 0 | |
246 return 0 | |
247 endif | |
248 | |
249 let line = SanitizeRLine(getline(lnum)) | |
250 | |
251 if &filetype == "rhelp" | |
252 if cline =~ '^\\dontshow{' || cline =~ '^\\dontrun{' || cline =~ '^\\donttest{' || cline =~ '^\\testonly{' | |
253 return 0 | |
254 endif | |
255 if line =~ '^\\examples{' || line =~ '^\\usage{' || line =~ '^\\dontshow{' || line =~ '^\\dontrun{' || line =~ '^\\donttest{' || line =~ '^\\testonly{' | |
256 return 0 | |
257 endif | |
258 if line =~ '^\\method{.*}{.*}(.*' | |
259 let line = substitute(line, '^\\method{\(.*\)}{.*}', '\1', "") | |
260 endif | |
261 endif | |
262 | |
263 if cline =~ '^\s*{' | |
264 if g:r_indent_ess_compatible && line =~ ')$' | |
265 let nlnum = lnum | |
266 let nline = line | |
267 while s:Get_paren_balance(nline, '(', ')') < 0 | |
268 let nlnum = s:Get_prev_line(nlnum) | |
269 let nline = SanitizeRLine(getline(nlnum)) . nline | |
270 endwhile | |
271 if nline =~ '^\s*function\s*(' && indent(nlnum) == &sw | |
272 return 0 | |
273 endif | |
274 endif | |
275 if s:Get_paren_balance(line, "(", ")") == 0 | |
276 return indent(lnum) | |
277 endif | |
278 endif | |
279 | |
280 " line is an incomplete command: | |
281 if line =~ '\<\(if\|while\|for\|function\)\s*()$' || line =~ '\<else$' || line =~ '<-$' | |
282 return indent(lnum) + &sw | |
283 endif | |
284 | |
285 " Deal with () and [] | |
286 | |
287 let pb = s:Get_paren_balance(line, '(', ')') | |
288 | |
289 if line =~ '^\s*{$' || line =~ '(\s*{' || (pb == 0 && (line =~ '{$' || line =~ '(\s*{$')) | |
290 return indent(lnum) + &sw | |
291 endif | |
292 | |
293 let bb = s:Get_paren_balance(line, '[', ']') | |
294 | |
295 let s:curtabstop = repeat(' ', &tabstop) | |
296 if g:r_indent_align_args == 1 | |
297 | |
298 if pb == 0 && bb == 0 && (line =~ '.*[,&|\-\*+<>]$' || cline =~ '^\s*[,&|\-\*+<>]') | |
299 return indent(lnum) | |
300 endif | |
301 | |
302 if pb > 0 | |
303 if &filetype == "rhelp" | |
304 let ind = s:Get_last_paren_idx(line, '(', ')', pb) | |
305 else | |
306 let ind = s:Get_last_paren_idx(getline(lnum), '(', ')', pb) | |
307 endif | |
308 return ind | |
309 endif | |
310 | |
311 if pb < 0 && line =~ '.*[,&|\-\*+<>]$' | |
312 let lnum = s:Get_prev_line(lnum) | |
313 while pb < 1 && lnum > 0 | |
314 let line = SanitizeRLine(getline(lnum)) | |
315 let line = substitute(line, '\t', s:curtabstop, "g") | |
316 let ind = strlen(line) | |
317 while ind > 0 | |
318 if line[ind] == ')' | |
319 let pb -= 1 | |
320 else | |
321 if line[ind] == '(' | |
322 let pb += 1 | |
323 endif | |
324 endif | |
325 if pb == 1 | |
326 return ind + 1 | |
327 endif | |
328 let ind -= 1 | |
329 endwhile | |
330 let lnum -= 1 | |
331 endwhile | |
332 return 0 | |
333 endif | |
334 | |
335 if bb > 0 | |
336 let ind = s:Get_last_paren_idx(getline(lnum), '[', ']', bb) | |
337 return ind | |
338 endif | |
339 endif | |
340 | |
341 let post_block = 0 | |
342 if line =~ '}$' | |
343 let lnum = s:Get_matching_brace(lnum, '{', '}', 0) | |
344 let line = SanitizeRLine(getline(lnum)) | |
345 if lnum > 0 && line =~ '^\s*{' | |
346 let lnum = s:Get_prev_line(lnum) | |
347 let line = SanitizeRLine(getline(lnum)) | |
348 endif | |
349 let pb = s:Get_paren_balance(line, '(', ')') | |
350 let post_block = 1 | |
351 endif | |
352 | |
353 let post_fun = 0 | |
354 if pb < 0 && line !~ ')\s*[,&|\-\*+<>]$' | |
355 let post_fun = 1 | |
356 while pb < 0 && lnum > 0 | |
357 let lnum -= 1 | |
358 let linepiece = SanitizeRLine(getline(lnum)) | |
359 let pb += s:Get_paren_balance(linepiece, "(", ")") | |
360 let line = linepiece . line | |
361 endwhile | |
362 if line =~ '{$' && post_block == 0 | |
363 return indent(lnum) + &sw | |
364 endif | |
365 | |
366 " Now we can do some tests again | |
367 if cline =~ '^\s*{' | |
368 return indent(lnum) | |
369 endif | |
370 if post_block == 0 | |
371 let newl = SanitizeRLine(line) | |
372 if newl =~ '\<\(if\|while\|for\|function\)\s*()$' || newl =~ '\<else$' || newl =~ '<-$' | |
373 return indent(lnum) + &sw | |
374 endif | |
375 endif | |
376 endif | |
377 | |
378 if cline =~ '^\s*else' | |
379 if line =~ '<-\s*if\s*()' | |
380 return indent(lnum) + &sw | |
381 else | |
382 if line =~ '\<if\s*()' | |
383 return indent(lnum) | |
384 else | |
385 return indent(lnum) - &sw | |
386 endif | |
387 endif | |
388 endif | |
389 | |
390 if bb < 0 && line =~ '.*]' | |
391 while bb < 0 && lnum > 0 | |
392 let lnum -= 1 | |
393 let linepiece = SanitizeRLine(getline(lnum)) | |
394 let bb += s:Get_paren_balance(linepiece, "[", "]") | |
395 let line = linepiece . line | |
396 endwhile | |
397 let line = s:RDelete_parens(line) | |
398 endif | |
399 | |
400 let plnum = s:Get_prev_line(lnum) | |
401 let ppost_else = 0 | |
402 if plnum > 0 | |
403 let pline = SanitizeRLine(getline(plnum)) | |
404 let ppost_block = 0 | |
405 if pline =~ '}$' | |
406 let ppost_block = 1 | |
407 let plnum = s:Get_matching_brace(plnum, '{', '}', 0) | |
408 let pline = SanitizeRLine(getline(plnum)) | |
409 if pline =~ '^\s*{$' && plnum > 0 | |
410 let plnum = s:Get_prev_line(plnum) | |
411 let pline = SanitizeRLine(getline(plnum)) | |
412 endif | |
413 endif | |
414 | |
415 if pline =~ 'else$' | |
416 let ppost_else = 1 | |
417 let plnum = s:Get_matching_if(plnum, 0) | |
418 let pline = SanitizeRLine(getline(plnum)) | |
419 endif | |
420 | |
421 if pline =~ '^\s*else\s*if\s*(' | |
422 let pplnum = s:Get_prev_line(plnum) | |
423 let ppline = SanitizeRLine(getline(pplnum)) | |
424 while ppline =~ '^\s*else\s*if\s*(' || ppline =~ '^\s*if\s*()\s*\S$' | |
425 let plnum = pplnum | |
426 let pline = ppline | |
427 let pplnum = s:Get_prev_line(plnum) | |
428 let ppline = SanitizeRLine(getline(pplnum)) | |
429 endwhile | |
430 while ppline =~ '\<\(if\|while\|for\|function\)\s*()$' || ppline =~ '\<else$' || ppline =~ '<-$' | |
431 let plnum = pplnum | |
432 let pline = ppline | |
433 let pplnum = s:Get_prev_line(plnum) | |
434 let ppline = SanitizeRLine(getline(pplnum)) | |
435 endwhile | |
436 endif | |
437 | |
438 let ppb = s:Get_paren_balance(pline, '(', ')') | |
439 if ppb < 0 && (pline =~ ')\s*{$' || pline =~ ')$') | |
440 while ppb < 0 && plnum > 0 | |
441 let plnum -= 1 | |
442 let linepiece = SanitizeRLine(getline(plnum)) | |
443 let ppb += s:Get_paren_balance(linepiece, "(", ")") | |
444 let pline = linepiece . pline | |
445 endwhile | |
446 let pline = s:RDelete_parens(pline) | |
447 endif | |
448 endif | |
449 | |
450 let ind = indent(lnum) | |
451 let pind = indent(plnum) | |
452 | |
453 if g:r_indent_align_args == 0 && pb != 0 | |
454 let ind += pb * &sw | |
455 return ind | |
456 endif | |
457 | |
458 if ind == pind || (ind == (pind + &sw) && pline =~ '{$' && ppost_else == 0) | |
459 return ind | |
460 endif | |
461 | |
462 while pind < ind && plnum > 0 && ppb == 0 | |
463 let ind = pind | |
464 let plnum = s:Get_prev_line(plnum) | |
465 let pline = getline(plnum) | |
466 let ppb = s:Get_paren_balance(pline, '(', ')') | |
467 while pline =~ '^\s*else' | |
468 let plnum = s:Get_matching_if(plnum, 1) | |
469 let pline = getline(plnum) | |
470 let ppb = s:Get_paren_balance(pline, '(', ')') | |
471 endwhile | |
472 let pind = indent(plnum) | |
473 if ind == (pind + &sw) && pline =~ '{$' | |
474 return ind | |
475 endif | |
476 endwhile | |
477 | |
478 return ind | |
479 | |
480 endfunction | |
481 | |
482 " vim: sw=4 |