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