# Wild ideas: Finding a missing 'end'

**URL:** <https://www.ruby-forum.com/t/wild-ideas-finding-a-missing-end/100463>\
**Category:** Ruby\
**Created:** [July 29, 2006, 3:11am UTC](https://www.ruby-forum.com/t/wild-ideas-finding-a-missing-end/100463 "2006-07-29T03:11:01Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mat\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ce7236/32.png) [@Mat\_S](https://www.ruby-forum.com/u/Mat_S)\
**Post date:** [July 29, 2006, 3:11am UTC](https://www.ruby-forum.com/t/wild-ideas-finding-a-missing-end/100463/1 "2006-07-29T03:11:01Z")

</div>

I was just reading a nuby question from the rails list and I had this  
thought:

class MyClass  
def foo  
if true  
end  
end

This code generates a parse error at the last line. Now most  
languages do this, so it’s not a big deal. But how frickin cool  
would it be if a future version of ruby looked at the indenting and  
made a guess as to where the missing end/} might be.

Like:  
test.rb:5: parse error, unexpected $, expecting kEND. Did you miss  
an “end” on line 4?

Maybe people have thought about this already. I’m just thinking out  
loud here, really.  
-Mat

---

<div class="post-metadata">

**Author:** ![Mat\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ce7236/32.png) [@Mat\_S](https://www.ruby-forum.com/u/Mat_S)\
**Post date:** [July 29, 2006, 8:19am UTC](https://www.ruby-forum.com/t/wild-ideas-finding-a-missing-end/100463/2 "2006-07-29T08:19:26Z")

</div>

Yes, it has been considered. Unfortunately allowing the  
interpreter/compiler figure this out only works in the extremely  
simple case

Consider:

a=[1,2,3]  
for i in a  
begin  
if i \> 1  
x = 3\*i  
end  
end  
puts x

Obviously there is a missing end statement. However, where we put it  
makes a big difference. If we put it before the puts x, we get a very  
different output then if we put it after puts x. This is a simple  
example as well, even more complex examples will show that it gets  
very dangerous to let the interpreter figure out what you meant.

Using indentation is dangerous, because indentation doesn’t mean  
anything in ruby normally, and trying to figure out the right thing  
would mean that we start having to be careful with indentation levels,  
and code works in strange ways because we don’t know ruby is ‘helping’  
us out. It can make for very hard to find bugs.

---

<div class="post-metadata">

**Author:** ![Mat\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ce7236/32.png) [@Mat\_S](https://www.ruby-forum.com/u/Mat_S)\
**Post date:** [July 29, 2006, 1:55pm UTC](https://www.ruby-forum.com/t/wild-ideas-finding-a-missing-end/100463/3 "2006-07-29T13:55:21Z")

</div>

Hi –

On Sat, 29 Jul 2006, N Okia wrote:

> x = 3\*i  
> Using indentation is dangerous, because indentation doesn’t mean  
> anything in ruby normally, and trying to figure out the right thing  
> would mean that we start having to be careful with indentation levels,  
> and code works in strange ways because we don’t know ruby is ‘helping’  
> us out. It can make for very hard to find bugs.

But surely just a warning can’t be harmful, even if it mentions what  
turns out to be the wrong line – ?

David

---

<div class="post-metadata">

**Author:** ![Mat\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ce7236/32.png) [@Mat\_S](https://www.ruby-forum.com/u/Mat_S)\
**Post date:** [July 29, 2006, 2:18pm UTC](https://www.ruby-forum.com/t/wild-ideas-finding-a-missing-end/100463/4 "2006-07-29T14:18:10Z")

</div>

unknown wrote:

> Hi –
> 
> On Sat, 29 Jul 2006, N Okia wrote:
> 
> > x = 3\*i  
> > Using indentation is dangerous, because indentation doesn’t mean  
> > anything in ruby normally, and trying to figure out the right thing  
> > would mean that we start having to be careful with indentation levels,  
> > and code works in strange ways because we don’t know ruby is ‘helping’  
> > us out. It can make for very hard to find bugs.
> 
> But surely just a warning can’t be harmful, even if it mentions what  
> turns out to be the wrong line – ?
> 
> David

I agree as far as giving the coder the exact error line in a better way  
than currently, yes. That would help more than scanning the code for the  
missing end. 🙂

---

<div class="post-metadata">

**Author:** ![Mat\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ce7236/32.png) [@Mat\_S](https://www.ruby-forum.com/u/Mat_S)\
**Post date:** [July 29, 2006, 2:31pm UTC](https://www.ruby-forum.com/t/wild-ideas-finding-a-missing-end/100463/5 "2006-07-29T14:31:42Z")

</div>

> > Using indentation is dangerous, because indentation doesn’t mean  
> > anything in ruby normally, and trying to figure out the right thing  
> > would mean that we start having to be careful with indentation levels,  
> > and code works in strange ways because we don’t know ruby is ‘helping’  
> > us out. It can make for very hard to find bugs.

I think its better for it to guess than to just return the last line of  
the file each time. Perhaps return multiple guesses.

Cheers  
Nic

---

<div class="post-metadata">

**Author:** ![Mat\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ce7236/32.png) [@Mat\_S](https://www.ruby-forum.com/u/Mat_S)\
**Post date:** [July 29, 2006, 6:55pm UTC](https://www.ruby-forum.com/t/wild-ideas-finding-a-missing-end/100463/6 "2006-07-29T18:55:48Z")

</div>

Hi –

On Sun, 30 Jul 2006, kate rhodes wrote:

> You could go on and on and on and on with screwed up cases like this? Either  
> you write something complex enough to figure out what the hell us crazy  
> humans meant or you get misleading results which in my opinion is worse than  
> no results.
> 
> Remember, a solution in the Ruby core has to work for all users not just the  
> users who happen to have good and consistent indentation habits.

The solution could be to give a specific hint if it’s a simple case,  
and not if it isn’t 🙂

David

---

<div class="post-metadata">

**Author:** ![Mat\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ce7236/32.png) [@Mat\_S](https://www.ruby-forum.com/u/Mat_S)\
**Post date:** [July 29, 2006, 6:49pm UTC](https://www.ruby-forum.com/t/wild-ideas-finding-a-missing-end/100463/7 "2006-07-29T18:49:26Z")

</div>

The problem with using indentation to even guess at an area in pretty  
much  
any language other than python is that it would require a huge amount of  
logic to account for the myriad possible edge cases.

What happens when a user mixes tabs and spaces?  
If one line is indented 3 spaces and the next is 4 is that a typo or is  
it  
an intentional indication of a subsection?  
What happens when there’s a long method call that the developer has  
decided  
to indent a portion of on a second line instead of having the thing  
stretch  
way off to the right of the typical viewing area?

You could go on and on and on and on with screwed up cases like this?  
Either  
you write something complex enough to figure out what the hell us crazy  
humans meant or you get misleading results which in my opinion is worse  
than  
no results.

Remember, a solution in the Ruby core has to work for all users not just  
the  
users who happen to have good and consistent indentation habits.

- kate = masukomi

---

<div class="post-metadata">

**Author:** ![Mat\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ce7236/32.png) [@Mat\_S](https://www.ruby-forum.com/u/Mat_S)\
**Post date:** [July 29, 2006, 7:48pm UTC](https://www.ruby-forum.com/t/wild-ideas-finding-a-missing-end/100463/8 "2006-07-29T19:48:58Z")

</div>

On 29/07/06, Mat S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> This code generates a parse error at the last line. Now most  
> languages do this, so it’s not a big deal. But how frickin cool  
> would it be if a future version of ruby looked at the indenting and  
> made a guess as to where the missing end/} might be.

Like this?

* * *

def error\_line(code)  
File.open(‘tmp.rb’, ‘w’) do |io|  
io \<\< code  
end  
s = `ruby -c tmp.rb 2>&1`  
if (s =~ /parse error/)  
return s[/\d+/].to\_i  
else  
return false  
end  
end

code = File.read(ARGV[0])

exit unless error\_line(code)

lines = code.split(/\n/)

x = lines.length / 2  
xmin = 0  
xmax = lines.length

while l = error\_line(code)  
if l \< x  
xmax = x  
elsif l \> x  
xmin = x  
else  
break  
end  
x = xmin + (xmax - xmin)/2  
code = (lines[0,x] + [‘end’] + lines[x…-1]).join(“\n”)  
end

puts(“Error around line #{x+1}”)

* * *

This is pretty rough code that I just threw together without much  
thought, but it seems to work. Its temporary file handling leaves a  
lot to be desired.

Paul.
