summaryrefslogtreecommitdiffstats
path: root/runtime/indent/ruby.vim
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/indent/ruby.vim')
-rw-r--r--runtime/indent/ruby.vim48
1 files changed, 37 insertions, 11 deletions
diff --git a/runtime/indent/ruby.vim b/runtime/indent/ruby.vim
index 559d8652a6..6ce8529fd1 100644
--- a/runtime/indent/ruby.vim
+++ b/runtime/indent/ruby.vim
@@ -4,7 +4,7 @@
" Previous Maintainer: Nikolai Weibull <now at bitwi.se>
" URL: https://github.com/vim-ruby/vim-ruby
" Release Coordinator: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2021 Feb 03
+" Last Change: 2022 Mar 22
" 0. Initialization {{{1
" =================
@@ -40,9 +40,11 @@ setlocal nosmartindent
" Now, set up our indentation expression and keys that trigger it.
setlocal indentexpr=GetRubyIndent(v:lnum)
setlocal indentkeys=0{,0},0),0],!^F,o,O,e,:,.
-setlocal indentkeys+==end,=else,=elsif,=when,=ensure,=rescue,==begin,==end
+setlocal indentkeys+==end,=else,=elsif,=when,=in\ ,=ensure,=rescue,==begin,==end
setlocal indentkeys+==private,=protected,=public
+let b:undo_indent = "setlocal indentexpr< indentkeys< smartindent<"
+
" Only define the function once.
if exists("*GetRubyIndent")
finish
@@ -85,14 +87,17 @@ let s:skip_expr =
" Regex used for words that, at the start of a line, add a level of indent.
let s:ruby_indent_keywords =
\ '^\s*\zs\<\%(module\|class\|if\|for' .
- \ '\|while\|until\|else\|elsif\|case\|when\|unless\|begin\|ensure\|rescue' .
+ \ '\|while\|until\|else\|elsif\|case\|when\|in\|unless\|begin\|ensure\|rescue' .
\ '\|\%(\K\k*[!?]\?\s\+\)\=def\):\@!\>' .
\ '\|\%([=,*/%+-]\|<<\|>>\|:\s\)\s*\zs' .
\ '\<\%(if\|for\|while\|until\|case\|unless\|begin\):\@!\>'
+" Def without an end clause: def method_call(...) = <expression>
+let s:ruby_endless_def = '\<def\s\+\k\+[!?]\=\%((.*)\|\s\)\s*='
+
" Regex used for words that, at the start of a line, remove a level of indent.
let s:ruby_deindent_keywords =
- \ '^\s*\zs\<\%(ensure\|else\|rescue\|elsif\|when\|end\):\@!\>'
+ \ '^\s*\zs\<\%(ensure\|else\|rescue\|elsif\|when\|in\|end\):\@!\>'
" Regex that defines the start-match for the 'end' keyword.
"let s:end_start_regex = '\%(^\|[^.]\)\<\%(module\|class\|def\|if\|for\|while\|until\|case\|unless\|begin\|do\)\>'
@@ -104,15 +109,31 @@ let s:end_start_regex =
\ '\|\%(^\|[^.:@$]\)\@<=\<do:\@!\>'
" Regex that defines the middle-match for the 'end' keyword.
-let s:end_middle_regex = '\<\%(ensure\|else\|\%(\%(^\|;\)\s*\)\@<=\<rescue:\@!\>\|when\|elsif\):\@!\>'
+let s:end_middle_regex = '\<\%(ensure\|else\|\%(\%(^\|;\)\s*\)\@<=\<rescue:\@!\>\|when\|\%(\%(^\|;\)\s*\)\@<=\<in\|elsif\):\@!\>'
" Regex that defines the end-match for the 'end' keyword.
let s:end_end_regex = '\%(^\|[^.:@$]\)\@<=\<end:\@!\>'
-" Expression used for searchpair() call for finding match for 'end' keyword.
-let s:end_skip_expr = s:skip_expr .
- \ ' || (expand("<cword>") == "do"' .
- \ ' && getline(".") =~ "^\\s*\\<\\(while\\|until\\|for\\):\\@!\\>")'
+" Expression used for searchpair() call for finding a match for an 'end' keyword.
+function! s:EndSkipExpr()
+ if eval(s:skip_expr)
+ return 1
+ elseif expand('<cword>') == 'do'
+ \ && getline(".") =~ '^\s*\<\(while\|until\|for\):\@!\>'
+ return 1
+ elseif getline('.') =~ s:ruby_endless_def
+ return 1
+ elseif getline('.') =~ '\<def\s\+\k\+[!?]\=([^)]*$'
+ " Then it's a `def method(` with a possible `) =` later
+ call search('\<def\s\+\k\+\zs(', 'W', line('.'))
+ normal! %
+ return getline('.') =~ ')\s*='
+ else
+ return 0
+ endif
+endfunction
+
+let s:end_skip_expr = function('s:EndSkipExpr')
" Regex that defines continuation lines, not including (, {, or [.
let s:non_bracket_continuation_regex =
@@ -572,6 +593,11 @@ function! s:AfterUnbalancedBracket(pline_info) abort
call cursor(info.plnum, closing.pos + 1)
normal! %
+ if strpart(info.pline, closing.pos) =~ '^)\s*='
+ " special case: the closing `) =` of an endless def
+ return indent(s:GetMSL(line('.')))
+ endif
+
if s:Match(line('.'), s:ruby_indent_keywords)
return indent('.') + info.sw
else
@@ -610,7 +636,7 @@ function! s:AfterIndentKeyword(pline_info) abort
let info = a:pline_info
let col = s:Match(info.plnum, s:ruby_indent_keywords)
- if col > 0
+ if col > 0 && s:Match(info.plnum, s:ruby_endless_def) <= 0
call cursor(info.plnum, col)
let ind = virtcol('.') - 1 + info.sw
" TODO: make this better (we need to count them) (or, if a searchpair
@@ -657,7 +683,7 @@ function! s:IndentingKeywordInMSL(msl_info) abort
" TODO: this does not take into account contrived things such as
" module Foo; class Bar; end
let col = s:Match(info.plnum_msl, s:ruby_indent_keywords)
- if col > 0
+ if col > 0 && s:Match(info.plnum_msl, s:ruby_endless_def) <= 0
let ind = indent(info.plnum_msl) + info.sw
if s:Match(info.plnum_msl, s:end_end_regex)
let ind = ind - info.sw