Mercurial > vim
comparison runtime/indent/ruby.vim @ 10048:43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Aug 30 23:26:57 2016 +0200
Updated runtime files. Remove version checks for Vim older than 6.0.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Tue, 30 Aug 2016 23:30:09 +0200 |
parents | a5352e73dc00 |
children | 57b2b8268d3a |
comparison
equal
deleted
inserted
replaced
10047:a62862410ca1 | 10048:43efa4f5a8ea |
---|---|
11 if exists("b:did_indent") | 11 if exists("b:did_indent") |
12 finish | 12 finish |
13 endif | 13 endif |
14 let b:did_indent = 1 | 14 let b:did_indent = 1 |
15 | 15 |
16 if !exists('g:ruby_indent_access_modifier_style') | |
17 " Possible values: "normal", "indent", "outdent" | |
18 let g:ruby_indent_access_modifier_style = 'normal' | |
19 endif | |
20 | |
21 if !exists('g:ruby_indent_block_style') | |
22 " Possible values: "expression", "do" | |
23 let g:ruby_indent_block_style = 'expression' | |
24 endif | |
25 | |
16 setlocal nosmartindent | 26 setlocal nosmartindent |
17 | 27 |
18 " Now, set up our indentation expression and keys that trigger it. | 28 " Now, set up our indentation expression and keys that trigger it. |
19 setlocal indentexpr=GetRubyIndent(v:lnum) | 29 setlocal indentexpr=GetRubyIndent(v:lnum) |
20 setlocal indentkeys=0{,0},0),0],!^F,o,O,e | 30 setlocal indentkeys=0{,0},0),0],!^F,o,O,e,:,. |
21 setlocal indentkeys+==end,=else,=elsif,=when,=ensure,=rescue,==begin,==end | 31 setlocal indentkeys+==end,=else,=elsif,=when,=ensure,=rescue,==begin,==end |
32 setlocal indentkeys+==private,=protected,=public | |
22 | 33 |
23 " Only define the function once. | 34 " Only define the function once. |
24 if exists("*GetRubyIndent") | 35 if exists("*GetRubyIndent") |
25 finish | 36 finish |
26 endif | 37 endif |
32 " ============ | 43 " ============ |
33 | 44 |
34 " Regex of syntax group names that are or delimit strings/symbols or are comments. | 45 " Regex of syntax group names that are or delimit strings/symbols or are comments. |
35 let s:syng_strcom = '\<ruby\%(Regexp\|RegexpDelimiter\|RegexpEscape' . | 46 let s:syng_strcom = '\<ruby\%(Regexp\|RegexpDelimiter\|RegexpEscape' . |
36 \ '\|Symbol\|String\|StringDelimiter\|StringEscape\|ASCIICode' . | 47 \ '\|Symbol\|String\|StringDelimiter\|StringEscape\|ASCIICode' . |
37 \ '\|Interpolation\|NoInterpolation\|Comment\|Documentation\)\>' | 48 \ '\|Interpolation\|InterpolationDelimiter\|NoInterpolation\|Comment\|Documentation\)\>' |
38 | 49 |
39 " Regex of syntax group names that are strings. | 50 " Regex of syntax group names that are strings. |
40 let s:syng_string = | 51 let s:syng_string = |
41 \ '\<ruby\%(String\|Interpolation\|NoInterpolation\|StringEscape\)\>' | 52 \ '\<ruby\%(String\|Interpolation\|NoInterpolation\|StringEscape\)\>' |
42 | 53 |
47 " Expression used to check whether we should skip a match with searchpair(). | 58 " Expression used to check whether we should skip a match with searchpair(). |
48 let s:skip_expr = | 59 let s:skip_expr = |
49 \ "synIDattr(synID(line('.'),col('.'),1),'name') =~ '".s:syng_strcom."'" | 60 \ "synIDattr(synID(line('.'),col('.'),1),'name') =~ '".s:syng_strcom."'" |
50 | 61 |
51 " Regex used for words that, at the start of a line, add a level of indent. | 62 " Regex used for words that, at the start of a line, add a level of indent. |
52 let s:ruby_indent_keywords = '^\s*\zs\<\%(module\|class\|def\|if\|for' . | 63 let s:ruby_indent_keywords = |
53 \ '\|while\|until\|else\|elsif\|case\|when\|unless\|begin\|ensure' . | 64 \ '^\s*\zs\<\%(module\|class\|if\|for' . |
54 \ '\|rescue\):\@!\>' . | 65 \ '\|while\|until\|else\|elsif\|case\|when\|unless\|begin\|ensure\|rescue' . |
66 \ '\|\%(public\|protected\|private\)\=\s*def\):\@!\>' . | |
55 \ '\|\%([=,*/%+-]\|<<\|>>\|:\s\)\s*\zs' . | 67 \ '\|\%([=,*/%+-]\|<<\|>>\|:\s\)\s*\zs' . |
56 \ '\<\%(if\|for\|while\|until\|case\|unless\|begin\):\@!\>' | 68 \ '\<\%(if\|for\|while\|until\|case\|unless\|begin\):\@!\>' |
57 | 69 |
58 " Regex used for words that, at the start of a line, remove a level of indent. | 70 " Regex used for words that, at the start of a line, remove a level of indent. |
59 let s:ruby_deindent_keywords = | 71 let s:ruby_deindent_keywords = |
62 " Regex that defines the start-match for the 'end' keyword. | 74 " Regex that defines the start-match for the 'end' keyword. |
63 "let s:end_start_regex = '\%(^\|[^.]\)\<\%(module\|class\|def\|if\|for\|while\|until\|case\|unless\|begin\|do\)\>' | 75 "let s:end_start_regex = '\%(^\|[^.]\)\<\%(module\|class\|def\|if\|for\|while\|until\|case\|unless\|begin\|do\)\>' |
64 " TODO: the do here should be restricted somewhat (only at end of line)? | 76 " TODO: the do here should be restricted somewhat (only at end of line)? |
65 let s:end_start_regex = | 77 let s:end_start_regex = |
66 \ '\C\%(^\s*\|[=,*/%+\-|;{]\|<<\|>>\|:\s\)\s*\zs' . | 78 \ '\C\%(^\s*\|[=,*/%+\-|;{]\|<<\|>>\|:\s\)\s*\zs' . |
67 \ '\<\%(module\|class\|def\|if\|for\|while\|until\|case\|unless\|begin\):\@!\>' . | 79 \ '\<\%(module\|class\|if\|for\|while\|until\|case\|unless\|begin' . |
80 \ '\|\%(public\|protected\|private\)\=\s*def\):\@!\>' . | |
68 \ '\|\%(^\|[^.:@$]\)\@<=\<do:\@!\>' | 81 \ '\|\%(^\|[^.:@$]\)\@<=\<do:\@!\>' |
69 | 82 |
70 " Regex that defines the middle-match for the 'end' keyword. | 83 " Regex that defines the middle-match for the 'end' keyword. |
71 let s:end_middle_regex = '\<\%(ensure\|else\|\%(\%(^\|;\)\s*\)\@<=\<rescue:\@!\>\|when\|elsif\):\@!\>' | 84 let s:end_middle_regex = '\<\%(ensure\|else\|\%(\%(^\|;\)\s*\)\@<=\<rescue:\@!\>\|when\|elsif\):\@!\>' |
72 | 85 |
80 | 93 |
81 " Regex that defines continuation lines, not including (, {, or [. | 94 " Regex that defines continuation lines, not including (, {, or [. |
82 let s:non_bracket_continuation_regex = '\%([\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\)\s*\%(#.*\)\=$' | 95 let s:non_bracket_continuation_regex = '\%([\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\)\s*\%(#.*\)\=$' |
83 | 96 |
84 " Regex that defines continuation lines. | 97 " Regex that defines continuation lines. |
85 " TODO: this needs to deal with if ...: and so on | |
86 let s:continuation_regex = | 98 let s:continuation_regex = |
87 \ '\%(%\@<![({[\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\)\s*\%(#.*\)\=$' | 99 \ '\%(%\@<![({[\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\)\s*\%(#.*\)\=$' |
88 | 100 |
101 " Regex that defines continuable keywords | |
102 let s:continuable_regex = | |
103 \ '\C\%(^\s*\|[=,*/%+\-|;{]\|<<\|>>\|:\s\)\s*\zs' . | |
104 \ '\<\%(if\|for\|while\|until\|unless\):\@!\>' | |
105 | |
89 " Regex that defines bracket continuations | 106 " Regex that defines bracket continuations |
90 let s:bracket_continuation_regex = '%\@<!\%([({[]\)\s*\%(#.*\)\=$' | 107 let s:bracket_continuation_regex = '%\@<!\%([({[]\)\s*\%(#.*\)\=$' |
91 | 108 |
109 " Regex that defines dot continuations | |
110 let s:dot_continuation_regex = '%\@<!\.\s*\%(#.*\)\=$' | |
111 | |
112 " Regex that defines backslash continuations | |
113 let s:backslash_continuation_regex = '%\@<!\\\s*$' | |
114 | |
115 " Regex that defines end of bracket continuation followed by another continuation | |
116 let s:bracket_switch_continuation_regex = '^\([^(]\+\zs).\+\)\+'.s:continuation_regex | |
117 | |
92 " Regex that defines the first part of a splat pattern | 118 " Regex that defines the first part of a splat pattern |
93 let s:splat_regex = '[[,(]\s*\*\s*\%(#.*\)\=$' | 119 let s:splat_regex = '[[,(]\s*\*\s*\%(#.*\)\=$' |
120 | |
121 " Regex that describes all indent access modifiers | |
122 let s:access_modifier_regex = '\C^\s*\%(public\|protected\|private\)\s*\%(#.*\)\=$' | |
123 | |
124 " Regex that describes the indent access modifiers (excludes public) | |
125 let s:indent_access_modifier_regex = '\C^\s*\%(protected\|private\)\s*\%(#.*\)\=$' | |
94 | 126 |
95 " Regex that defines blocks. | 127 " Regex that defines blocks. |
96 " | 128 " |
97 " Note that there's a slight problem with this regex and s:continuation_regex. | 129 " Note that there's a slight problem with this regex and s:continuation_regex. |
98 " Code like this will be matched by both: | 130 " Code like this will be matched by both: |
100 " method_call do |(a, b)| | 132 " method_call do |(a, b)| |
101 " | 133 " |
102 " The reason is that the pipe matches a hanging "|" operator. | 134 " The reason is that the pipe matches a hanging "|" operator. |
103 " | 135 " |
104 let s:block_regex = | 136 let s:block_regex = |
105 \ '\%(\<do:\@!\>\|%\@<!{\)\s*\%(|\s*(*\s*\%([*@&]\=\h\w*,\=\s*\)\%(,\s*(*\s*[*@&]\=\h\w*\s*)*\s*\)*|\)\=\s*\%(#.*\)\=$' | 137 \ '\%(\<do:\@!\>\|%\@<!{\)\s*\%(|[^|]*|\)\=\s*\%(#.*\)\=$' |
106 | 138 |
107 let s:block_continuation_regex = '^\s*[^])}\t ].*'.s:block_regex | 139 let s:block_continuation_regex = '^\s*[^])}\t ].*'.s:block_regex |
140 | |
141 " Regex that describes a leading operator (only a method call's dot for now) | |
142 let s:leading_operator_regex = '^\s*[.]' | |
108 | 143 |
109 " 2. Auxiliary Functions {{{1 | 144 " 2. Auxiliary Functions {{{1 |
110 " ====================== | 145 " ====================== |
111 | 146 |
112 " Check if the character at lnum:col is inside a string, comment, or is ascii. | 147 " Check if the character at lnum:col is inside a string, comment, or is ascii. |
163 while lnum > 0 | 198 while lnum > 0 |
164 " If we have a continuation line, or we're in a string, use line as MSL. | 199 " If we have a continuation line, or we're in a string, use line as MSL. |
165 " Otherwise, terminate search as we have found our MSL already. | 200 " Otherwise, terminate search as we have found our MSL already. |
166 let line = getline(lnum) | 201 let line = getline(lnum) |
167 | 202 |
168 if s:Match(lnum, s:splat_regex) | 203 if !s:Match(msl, s:backslash_continuation_regex) && |
204 \ s:Match(lnum, s:backslash_continuation_regex) | |
205 " If the current line doesn't end in a backslash, but the previous one | |
206 " does, look for that line's msl | |
207 " | |
208 " Example: | |
209 " foo = "bar" \ | |
210 " "baz" | |
211 " | |
212 let msl = lnum | |
213 elseif s:Match(msl, s:leading_operator_regex) | |
214 " If the current line starts with a leading operator, keep its indent | |
215 " and keep looking for an MSL. | |
216 let msl = lnum | |
217 elseif s:Match(lnum, s:splat_regex) | |
169 " If the above line looks like the "*" of a splat, use the current one's | 218 " If the above line looks like the "*" of a splat, use the current one's |
170 " indentation. | 219 " indentation. |
171 " | 220 " |
172 " Example: | 221 " Example: |
173 " Hash[* | 222 " Hash[* |
174 " method_call do | 223 " method_call do |
175 " something | 224 " something |
176 " | 225 " |
177 return msl | 226 return msl |
178 elseif s:Match(line, s:non_bracket_continuation_regex) && | 227 elseif s:Match(lnum, s:non_bracket_continuation_regex) && |
179 \ s:Match(msl, s:non_bracket_continuation_regex) | 228 \ s:Match(msl, s:non_bracket_continuation_regex) |
180 " If the current line is a non-bracket continuation and so is the | 229 " If the current line is a non-bracket continuation and so is the |
181 " previous one, keep its indent and continue looking for an MSL. | 230 " previous one, keep its indent and continue looking for an MSL. |
182 " | 231 " |
183 " Example: | 232 " Example: |
184 " method_call one, | 233 " method_call one, |
185 " two, | 234 " two, |
235 " three | |
236 " | |
237 let msl = lnum | |
238 elseif s:Match(lnum, s:dot_continuation_regex) && | |
239 \ (s:Match(msl, s:bracket_continuation_regex) || s:Match(msl, s:block_continuation_regex)) | |
240 " If the current line is a bracket continuation or a block-starter, but | |
241 " the previous is a dot, keep going to see if the previous line is the | |
242 " start of another continuation. | |
243 " | |
244 " Example: | |
245 " parent. | |
246 " method_call { | |
186 " three | 247 " three |
187 " | 248 " |
188 let msl = lnum | 249 let msl = lnum |
189 elseif s:Match(lnum, s:non_bracket_continuation_regex) && | 250 elseif s:Match(lnum, s:non_bracket_continuation_regex) && |
190 \ (s:Match(msl, s:bracket_continuation_regex) || s:Match(msl, s:block_continuation_regex)) | 251 \ (s:Match(msl, s:bracket_continuation_regex) || s:Match(msl, s:block_continuation_regex)) |
297 | 358 |
298 return [rightmost_opening, rightmost_closing] | 359 return [rightmost_opening, rightmost_closing] |
299 endfunction | 360 endfunction |
300 | 361 |
301 function s:Match(lnum, regex) | 362 function s:Match(lnum, regex) |
302 let col = match(getline(a:lnum), '\C'.a:regex) + 1 | 363 let line = getline(a:lnum) |
303 return col > 0 && !s:IsInStringOrComment(a:lnum, col) ? col : 0 | 364 let offset = match(line, '\C'.a:regex) |
304 endfunction | 365 let col = offset + 1 |
305 | 366 |
306 function s:MatchLast(lnum, regex) | 367 while offset > -1 && s:IsInStringOrComment(a:lnum, col) |
307 let line = getline(a:lnum) | 368 let offset = match(line, '\C'.a:regex, offset + 1) |
308 let col = match(line, '.*\zs' . a:regex) | 369 let col = offset + 1 |
309 while col != -1 && s:IsInStringOrComment(a:lnum, col) | |
310 let line = strpart(line, 0, col) | |
311 let col = match(line, '.*' . a:regex) | |
312 endwhile | 370 endwhile |
313 return col + 1 | 371 |
372 if offset > -1 | |
373 return col | |
374 else | |
375 return 0 | |
376 endif | |
377 endfunction | |
378 | |
379 " Locates the containing class/module's definition line, ignoring nested classes | |
380 " along the way. | |
381 " | |
382 function! s:FindContainingClass() | |
383 let saved_position = getpos('.') | |
384 | |
385 while searchpair(s:end_start_regex, s:end_middle_regex, s:end_end_regex, 'bW', | |
386 \ s:end_skip_expr) > 0 | |
387 if expand('<cword>') =~# '\<class\|module\>' | |
388 let found_lnum = line('.') | |
389 call setpos('.', saved_position) | |
390 return found_lnum | |
391 endif | |
392 endif | |
393 | |
394 call setpos('.', saved_position) | |
395 return 0 | |
314 endfunction | 396 endfunction |
315 | 397 |
316 " 3. GetRubyIndent Function {{{1 | 398 " 3. GetRubyIndent Function {{{1 |
317 " ========================= | 399 " ========================= |
318 | 400 |
319 function GetRubyIndent(...) | 401 function GetRubyIndent(...) |
320 " 3.1. Setup {{{2 | 402 " 3.1. Setup {{{2 |
321 " ---------- | 403 " ---------- |
322 | 404 |
405 " The value of a single shift-width | |
406 if exists('*shiftwidth') | |
407 let sw = shiftwidth() | |
408 else | |
409 let sw = &sw | |
410 endif | |
411 | |
323 " For the current line, use the first argument if given, else v:lnum | 412 " For the current line, use the first argument if given, else v:lnum |
324 let clnum = a:0 ? a:1 : v:lnum | 413 let clnum = a:0 ? a:1 : v:lnum |
325 | 414 |
326 " Set up variables for restoring position in file. Could use clnum here. | 415 " Set up variables for restoring position in file. Could use clnum here. |
327 let vcol = col('.') | 416 let vcol = col('.') |
330 " ----------------------------- | 419 " ----------------------------- |
331 | 420 |
332 " Get the current line. | 421 " Get the current line. |
333 let line = getline(clnum) | 422 let line = getline(clnum) |
334 let ind = -1 | 423 let ind = -1 |
424 | |
425 " If this line is an access modifier keyword, align according to the closest | |
426 " class declaration. | |
427 if g:ruby_indent_access_modifier_style == 'indent' | |
428 if s:Match(clnum, s:access_modifier_regex) | |
429 let class_line = s:FindContainingClass() | |
430 if class_line > 0 | |
431 return indent(class_line) + sw | |
432 endif | |
433 endif | |
434 elseif g:ruby_indent_access_modifier_style == 'outdent' | |
435 if s:Match(clnum, s:access_modifier_regex) | |
436 let class_line = s:FindContainingClass() | |
437 if class_line > 0 | |
438 return indent(class_line) | |
439 endif | |
440 endif | |
441 endif | |
335 | 442 |
336 " If we got a closing bracket on an empty line, find its match and indent | 443 " If we got a closing bracket on an empty line, find its match and indent |
337 " according to it. For parentheses we indent to its column - 1, for the | 444 " according to it. For parentheses we indent to its column - 1, for the |
338 " others we indent to the containing line's MSL's level. Return -1 if fail. | 445 " others we indent to the containing line's MSL's level. Return -1 if fail. |
339 let col = matchend(line, '^\s*[]})]') | 446 let col = matchend(line, '^\s*[]})]') |
341 call cursor(clnum, col) | 448 call cursor(clnum, col) |
342 let bs = strpart('(){}[]', stridx(')}]', line[col - 1]) * 2, 2) | 449 let bs = strpart('(){}[]', stridx(')}]', line[col - 1]) * 2, 2) |
343 if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', s:skip_expr) > 0 | 450 if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', s:skip_expr) > 0 |
344 if line[col-1]==')' && col('.') != col('$') - 1 | 451 if line[col-1]==')' && col('.') != col('$') - 1 |
345 let ind = virtcol('.') - 1 | 452 let ind = virtcol('.') - 1 |
346 else | 453 elseif g:ruby_indent_block_style == 'do' |
454 let ind = indent(line('.')) | |
455 else " g:ruby_indent_block_style == 'expression' | |
347 let ind = indent(s:GetMSL(line('.'))) | 456 let ind = indent(s:GetMSL(line('.'))) |
348 endif | 457 endif |
349 endif | 458 endif |
350 return ind | 459 return ind |
351 endif | 460 endif |
364 let msl = s:GetMSL(line('.')) | 473 let msl = s:GetMSL(line('.')) |
365 let line = getline(line('.')) | 474 let line = getline(line('.')) |
366 | 475 |
367 if strpart(line, 0, col('.') - 1) =~ '=\s*$' && | 476 if strpart(line, 0, col('.') - 1) =~ '=\s*$' && |
368 \ strpart(line, col('.') - 1, 2) !~ 'do' | 477 \ strpart(line, col('.') - 1, 2) !~ 'do' |
478 " assignment to case/begin/etc, on the same line, hanging indent | |
369 let ind = virtcol('.') - 1 | 479 let ind = virtcol('.') - 1 |
480 elseif g:ruby_indent_block_style == 'do' | |
481 " align to line of the "do", not to the MSL | |
482 let ind = indent(line('.')) | |
370 elseif getline(msl) =~ '=\s*\(#.*\)\=$' | 483 elseif getline(msl) =~ '=\s*\(#.*\)\=$' |
484 " in the case of assignment to the MSL, align to the starting line, | |
485 " not to the MSL | |
371 let ind = indent(line('.')) | 486 let ind = indent(line('.')) |
372 else | 487 else |
488 " align to the MSL | |
373 let ind = indent(msl) | 489 let ind = indent(msl) |
374 endif | 490 endif |
375 endif | 491 endif |
376 return ind | 492 return ind |
377 endif | 493 endif |
387 \ && s:IsInStringDelimiter(clnum, 1) | 503 \ && s:IsInStringDelimiter(clnum, 1) |
388 \ && search('\V<<'.line, 'nbW') > 0 | 504 \ && search('\V<<'.line, 'nbW') > 0 |
389 return 0 | 505 return 0 |
390 endif | 506 endif |
391 | 507 |
508 " If the current line starts with a leading operator, add a level of indent. | |
509 if s:Match(clnum, s:leading_operator_regex) | |
510 return indent(s:GetMSL(clnum)) + sw | |
511 endif | |
512 | |
392 " 3.3. Work on the previous line. {{{2 | 513 " 3.3. Work on the previous line. {{{2 |
393 " ------------------------------- | 514 " ------------------------------- |
394 | 515 |
395 " Find a non-blank, non-multi-line string line above the current line. | 516 " Find a non-blank, non-multi-line string line above the current line. |
396 let lnum = s:PrevNonBlankNonString(clnum - 1) | 517 let lnum = s:PrevNonBlankNonString(clnum - 1) |
407 | 528 |
408 " Set up variables for the previous line. | 529 " Set up variables for the previous line. |
409 let line = getline(lnum) | 530 let line = getline(lnum) |
410 let ind = indent(lnum) | 531 let ind = indent(lnum) |
411 | 532 |
533 if g:ruby_indent_access_modifier_style == 'indent' | |
534 " If the previous line was a private/protected keyword, add a | |
535 " level of indent. | |
536 if s:Match(lnum, s:indent_access_modifier_regex) | |
537 return indent(lnum) + sw | |
538 endif | |
539 elseif g:ruby_indent_access_modifier_style == 'outdent' | |
540 " If the previous line was a private/protected/public keyword, add | |
541 " a level of indent, since the keyword has been out-dented. | |
542 if s:Match(lnum, s:access_modifier_regex) | |
543 return indent(lnum) + sw | |
544 endif | |
545 endif | |
546 | |
547 if s:Match(lnum, s:continuable_regex) && s:Match(lnum, s:continuation_regex) | |
548 return indent(s:GetMSL(lnum)) + sw + sw | |
549 endif | |
550 | |
412 " If the previous line ended with a block opening, add a level of indent. | 551 " If the previous line ended with a block opening, add a level of indent. |
413 if s:Match(lnum, s:block_regex) | 552 if s:Match(lnum, s:block_regex) |
414 return indent(s:GetMSL(lnum)) + &sw | 553 let msl = s:GetMSL(lnum) |
554 | |
555 if g:ruby_indent_block_style == 'do' | |
556 " don't align to the msl, align to the "do" | |
557 let ind = indent(lnum) + sw | |
558 elseif getline(msl) =~ '=\s*\(#.*\)\=$' | |
559 " in the case of assignment to the msl, align to the starting line, | |
560 " not to the msl | |
561 let ind = indent(lnum) + sw | |
562 else | |
563 let ind = indent(msl) + sw | |
564 endif | |
565 return ind | |
566 endif | |
567 | |
568 " If the previous line started with a leading operator, use its MSL's level | |
569 " of indent | |
570 if s:Match(lnum, s:leading_operator_regex) | |
571 return indent(s:GetMSL(lnum)) | |
415 endif | 572 endif |
416 | 573 |
417 " If the previous line ended with the "*" of a splat, add a level of indent | 574 " If the previous line ended with the "*" of a splat, add a level of indent |
418 if line =~ s:splat_regex | 575 if line =~ s:splat_regex |
419 return indent(lnum) + &sw | 576 return indent(lnum) + sw |
420 endif | 577 endif |
421 | 578 |
422 " If the previous line contained unclosed opening brackets and we are still | 579 " If the previous line contained unclosed opening brackets and we are still |
423 " in them, find the rightmost one and add indent depending on the bracket | 580 " in them, find the rightmost one and add indent depending on the bracket |
424 " type. | 581 " type. |
429 let [opening, closing] = s:ExtraBrackets(lnum) | 586 let [opening, closing] = s:ExtraBrackets(lnum) |
430 | 587 |
431 if opening.pos != -1 | 588 if opening.pos != -1 |
432 if opening.type == '(' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 | 589 if opening.type == '(' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 |
433 if col('.') + 1 == col('$') | 590 if col('.') + 1 == col('$') |
434 return ind + &sw | 591 return ind + sw |
435 else | 592 else |
436 return virtcol('.') | 593 return virtcol('.') |
437 endif | 594 endif |
438 else | 595 else |
439 let nonspace = matchend(line, '\S', opening.pos + 1) - 1 | 596 let nonspace = matchend(line, '\S', opening.pos + 1) - 1 |
440 return nonspace > 0 ? nonspace : ind + &sw | 597 return nonspace > 0 ? nonspace : ind + sw |
441 endif | 598 endif |
442 elseif closing.pos != -1 | 599 elseif closing.pos != -1 |
443 call cursor(lnum, closing.pos + 1) | 600 call cursor(lnum, closing.pos + 1) |
444 normal! % | 601 normal! % |
445 | 602 |
446 if s:Match(line('.'), s:ruby_indent_keywords) | 603 if s:Match(line('.'), s:ruby_indent_keywords) |
447 return indent('.') + &sw | 604 return indent('.') + sw |
448 else | 605 else |
449 return indent('.') | 606 return indent(s:GetMSL(line('.'))) |
450 endif | 607 endif |
451 else | 608 else |
452 call cursor(clnum, vcol) | 609 call cursor(clnum, vcol) |
453 end | 610 end |
454 endif | 611 endif |
471 end | 628 end |
472 | 629 |
473 let col = s:Match(lnum, s:ruby_indent_keywords) | 630 let col = s:Match(lnum, s:ruby_indent_keywords) |
474 if col > 0 | 631 if col > 0 |
475 call cursor(lnum, col) | 632 call cursor(lnum, col) |
476 let ind = virtcol('.') - 1 + &sw | 633 let ind = virtcol('.') - 1 + sw |
477 " TODO: make this better (we need to count them) (or, if a searchpair | 634 " TODO: make this better (we need to count them) (or, if a searchpair |
478 " fails, we know that something is lacking an end and thus we indent a | 635 " fails, we know that something is lacking an end and thus we indent a |
479 " level | 636 " level |
480 if s:Match(lnum, s:end_end_regex) | 637 if s:Match(lnum, s:end_end_regex) |
481 let ind = indent('.') | 638 let ind = indent('.') |
488 | 645 |
489 " Set up variables to use and search for MSL to the previous line. | 646 " Set up variables to use and search for MSL to the previous line. |
490 let p_lnum = lnum | 647 let p_lnum = lnum |
491 let lnum = s:GetMSL(lnum) | 648 let lnum = s:GetMSL(lnum) |
492 | 649 |
493 " If the previous line wasn't a MSL and is continuation return its indent. | 650 " If the previous line wasn't a MSL. |
494 " TODO: the || s:IsInString() thing worries me a bit. | |
495 if p_lnum != lnum | 651 if p_lnum != lnum |
496 if s:Match(p_lnum, s:non_bracket_continuation_regex) || s:IsInString(p_lnum,strlen(line)) | 652 " If previous line ends bracket and begins non-bracket continuation decrease indent by 1. |
653 if s:Match(p_lnum, s:bracket_switch_continuation_regex) | |
654 return ind - 1 | |
655 " If previous line is a continuation return its indent. | |
656 " TODO: the || s:IsInString() thing worries me a bit. | |
657 elseif s:Match(p_lnum, s:non_bracket_continuation_regex) || s:IsInString(p_lnum,strlen(line)) | |
497 return ind | 658 return ind |
498 endif | 659 endif |
499 endif | 660 endif |
500 | 661 |
501 " Set up more variables, now that we know we wasn't continuation bound. | 662 " Set up more variables, now that we know we wasn't continuation bound. |
504 | 665 |
505 " If the MSL line had an indenting keyword in it, add a level of indent. | 666 " If the MSL line had an indenting keyword in it, add a level of indent. |
506 " TODO: this does not take into account contrived things such as | 667 " TODO: this does not take into account contrived things such as |
507 " module Foo; class Bar; end | 668 " module Foo; class Bar; end |
508 if s:Match(lnum, s:ruby_indent_keywords) | 669 if s:Match(lnum, s:ruby_indent_keywords) |
509 let ind = msl_ind + &sw | 670 let ind = msl_ind + sw |
510 if s:Match(lnum, s:end_end_regex) | 671 if s:Match(lnum, s:end_end_regex) |
511 let ind = ind - &sw | 672 let ind = ind - sw |
512 endif | 673 endif |
513 return ind | 674 return ind |
514 endif | 675 endif |
515 | 676 |
516 " If the previous line ended with [*+/.,-=], but wasn't a block ending or a | 677 " If the previous line ended with [*+/.,-=], but wasn't a block ending or a |
517 " closing bracket, indent one extra level. | 678 " closing bracket, indent one extra level. |
518 if s:Match(lnum, s:non_bracket_continuation_regex) && !s:Match(lnum, '^\s*\([\])}]\|end\)') | 679 if s:Match(lnum, s:non_bracket_continuation_regex) && !s:Match(lnum, '^\s*\([\])}]\|end\)') |
519 if lnum == p_lnum | 680 if lnum == p_lnum |
520 let ind = msl_ind + &sw | 681 let ind = msl_ind + sw |
521 else | 682 else |
522 let ind = msl_ind | 683 let ind = msl_ind |
523 endif | 684 endif |
524 return ind | 685 return ind |
525 endif | 686 endif |