Skip to content

Commit 482e2ce

Browse files
authored
Merge pull request #433 from vim-ruby/endless-def
"Endless" def support for ruby 3
2 parents 0f603a1 + 910bc7e commit 482e2ce

File tree

3 files changed

+76
-6
lines changed

3 files changed

+76
-6
lines changed

indent/ruby.vim

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ let s:ruby_indent_keywords =
8989
\ '\|\%([=,*/%+-]\|<<\|>>\|:\s\)\s*\zs' .
9090
\ '\<\%(if\|for\|while\|until\|case\|unless\|begin\):\@!\>'
9191

92+
" Def without an end clause: def method_call(...) = <expression>
93+
let s:ruby_endless_def = '\<def\s\+\k\+[!?]\=\%((.*)\|\s\)\s*='
94+
9295
" Regex used for words that, at the start of a line, remove a level of indent.
9396
let s:ruby_deindent_keywords =
9497
\ '^\s*\zs\<\%(ensure\|else\|rescue\|elsif\|when\|end\):\@!\>'
@@ -108,10 +111,26 @@ let s:end_middle_regex = '\<\%(ensure\|else\|\%(\%(^\|;\)\s*\)\@<=\<rescue:\@!\>
108111
" Regex that defines the end-match for the 'end' keyword.
109112
let s:end_end_regex = '\%(^\|[^.:@$]\)\@<=\<end:\@!\>'
110113

111-
" Expression used for searchpair() call for finding match for 'end' keyword.
112-
let s:end_skip_expr = s:skip_expr .
113-
\ ' || (expand("<cword>") == "do"' .
114-
\ ' && getline(".") =~ "^\\s*\\<\\(while\\|until\\|for\\):\\@!\\>")'
114+
" Expression used for searchpair() call for finding a match for an 'end' keyword.
115+
function! s:EndSkipExpr()
116+
if eval(s:skip_expr)
117+
return 1
118+
elseif expand('<cword>') == 'do'
119+
\ && getline(".") =~ '^\s*\<\(while\|until\|for\):\@!\>'
120+
return 1
121+
elseif getline('.') =~ s:ruby_endless_def
122+
return 1
123+
elseif getline('.') =~ '\<def\s\+\k\+[!?]\=([^)]*$'
124+
" Then it's a `def method(` with a possible `) =` later
125+
call search('\<def\s\+\k\+\zs(', 'W', line('.'))
126+
normal! %
127+
return getline('.') =~ ')\s*='
128+
else
129+
return 0
130+
endif
131+
endfunction
132+
133+
let s:end_skip_expr = function('s:EndSkipExpr')
115134

116135
" Regex that defines continuation lines, not including (, {, or [.
117136
let s:non_bracket_continuation_regex =
@@ -571,6 +590,11 @@ function! s:AfterUnbalancedBracket(pline_info) abort
571590
call cursor(info.plnum, closing.pos + 1)
572591
normal! %
573592

593+
if strpart(info.pline, closing.pos) =~ '^)\s*='
594+
" special case: the closing `) =` of an endless def
595+
return indent(s:GetMSL(line('.')))
596+
endif
597+
574598
if s:Match(line('.'), s:ruby_indent_keywords)
575599
return indent('.') + info.sw
576600
else
@@ -609,7 +633,7 @@ function! s:AfterIndentKeyword(pline_info) abort
609633
let info = a:pline_info
610634
let col = s:Match(info.plnum, s:ruby_indent_keywords)
611635

612-
if col > 0
636+
if col > 0 && s:Match(info.plnum, s:ruby_endless_def) <= 0
613637
call cursor(info.plnum, col)
614638
let ind = virtcol('.') - 1 + info.sw
615639
" TODO: make this better (we need to count them) (or, if a searchpair
@@ -656,7 +680,7 @@ function! s:IndentingKeywordInMSL(msl_info) abort
656680
" TODO: this does not take into account contrived things such as
657681
" module Foo; class Bar; end
658682
let col = s:Match(info.plnum_msl, s:ruby_indent_keywords)
659-
if col > 0
683+
if col > 0 && s:Match(info.plnum_msl, s:ruby_endless_def) <= 0
660684
let ind = indent(info.plnum_msl) + info.sw
661685
if s:Match(info.plnum_msl, s:end_end_regex)
662686
let ind = ind - info.sw

spec/indent/end_constructs_spec.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,20 @@
2727
foo = bar; class One; end
2828
end
2929
EOF
30+
31+
assert_correct_indenting <<~EOF
32+
nested do
33+
while true do
34+
def foo
35+
if bar
36+
for i in collection
37+
def baz
38+
end
39+
end
40+
end
41+
end
42+
end
43+
end
44+
EOF
3045
end
3146
end

spec/indent/method_definitions_spec.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,35 @@ def one(x)
3737
end
3838
EOF
3939
end
40+
41+
specify "endless methods" do
42+
assert_correct_indenting <<~EOF
43+
indented_block do
44+
def foo(bar) = puts(bar)
45+
def foo!(bar) = puts(bar)
46+
def foo?(bar) = puts(bar)
47+
48+
def foo(bar)=puts(bar)
49+
50+
def foo(bar) = bar + 1
51+
52+
def foo() = 1 + 1
53+
def foo = 1 + 1
54+
55+
private def foo(bar) = bar + 1
56+
57+
def foo(bar) =
58+
bar + 1
59+
60+
def foo(bar = default_function()) = puts(bar)
61+
62+
def foo(bar = default_function()) =
63+
puts(bar)
64+
65+
def foo(
66+
bar
67+
) = puts(bar)
68+
end
69+
EOF
70+
end
4071
end

0 commit comments

Comments
 (0)