BUG: ruby-mode.el : '/=' operator breaks following indentation

Using emacs 21.4, ruby-mode.el from Ruby 1.8.5 (byte-compiled), if I
open a file with the following code ...

def foo
  x /= y
   bar
end

...move the cursor to the word "bar" and press Tab, nothing happens!
If I replace "/=" with "*=" then Tab fixes the indentation as I'd
expect.

Any suggestions for debugging this? I've hacked elisp a few times but
major mode definitions are beyond my experience.

Regards,

Jeremy Henty

The issue is probably that it's treating the "/=" as the beginning of
a multiline regexp. A common fix for these sorts of "mistaken
delimiters" is to put a comment at the end of the line containing a
closing delimiter:

def foo
  x /= y #/
  bar
end

Not ideal, but it might get you by.

BTW, there's a newer ruby-mode.el in the ruby CVS repository. It
still doesn't fix this, although the behavior is slightly different
(it doesn't indent the "bar" at all, as if in a multiline string).

G.

···

On 11/30/06, Jeremy Henty <jeremy@chaos.org.uk> wrote:

Using emacs 21.4, ruby-mode.el from Ruby 1.8.5 (byte-compiled), if I
open a file with the following code ...

def foo
  x /= y
   bar
end

...move the cursor to the word "bar" and press Tab, nothing happens!
If I replace "/=" with "*=" then Tab fixes the indentation as I'd
expect.

Any suggestions for debugging this? I've hacked elisp a few times but
major mode definitions are beyond my experience.

Hi,

Using emacs 21.4, ruby-mode.el from Ruby 1.8.5 (byte-compiled), if I
open a file with the following code ...

def foo
x /= y
  bar
end

Does this patch work for you?

              matz.

diff --git a/misc/ruby-mode.el b/misc/ruby-mode.el
index 38d5b71..33c5901 100755
--- a/misc/ruby-mode.el
+++ b/misc/ruby-mode.el
@@ -383,6 +383,8 @@ The variable ruby-indent-level controls the amount of indentation.
    (t
     (setq in-string (point))
     (goto-char end))))
+ ((looking-at "/=")
+ (goto-char pnt))
        ((looking-at "/")
   (cond
    ((and (not (eobp)) (ruby-expr-beg 'expr-re))

···

In message "Re: BUG: ruby-mode.el : '/=' operator breaks following indentation" on Thu, 30 Nov 2006 08:35:06 +0900, Jeremy Henty <jeremy@chaos.org.uk> writes:

Oops, I misread. It sounds like it is the same behavior. Still, it
might be a newer version.

···

11/30/06, George Ogata <george.ogata@gmail.com> wrote:

BTW, there's a newer ruby-mode.el in the ruby CVS repository. It
still doesn't fix this, although the behavior is slightly different
(it doesn't indent the "bar" at all, as if in a multiline string).

Thanks, that works. A slightly better fix is to add a ';' as well to
convince the major mode that the statement has ended, otherwise it
adds extra indentation to the next line.

def foo
  x /= y # / ;
  bar
end

I wonder how the Ruby parser decides that /= is an operator and not
the start of a regexp?

Regards,

Jeremy Henty

···

On 2006-11-30, George Ogata <george.ogata@gmail.com> wrote:

The issue is probably that it's treating the "/=" as the beginning
of a multiline regexp. A common fix for these sorts of "mistaken
delimiters" is to put a comment at the end of the line containing a
closing delimiter:

def foo
  x /= y #/
  bar
end

Yes. Thank you!

Jeremy Henty

···

On 2006-12-04, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

In message "Re: BUG: ruby-mode.el : '/=' operator breaks following indentation" > on Thu, 30 Nov 2006 08:35:06 +0900, Jeremy Henty <jeremy@chaos.org.uk> writes:

Using emacs 21.4, ruby-mode.el from Ruby 1.8.5 (byte-compiled), if I
open a file with the following code ...

def foo
x /= y
  bar
end

Does this patch work for you?

Thanks, that works. A slightly better fix is to add a ';' as well to
convince the major mode that the statement has ended, otherwise it
adds extra indentation to the next line.

def foo
  x /= y # / ;
  bar
end

Hmm, my ruby-mode doesn't seem to need the ';'. I'm using the CVS
HEAD version with XEmacs 21.4.19.

I wonder how the Ruby parser decides that /= is an operator and not
the start of a regexp?

It's just the way the grammar is defined. For it to be a regexp,
you'd need parens on the call to #x.

g@crash:~$ cat test.rb
x /=/
g@crash:~$ ruby test.rb
test.rb:1: unterminated string meets end of file
test.rb:1: parse error, unexpected tSTRING_END, expecting
tSTRING_CONTENT or tREGEXP_END or tSTRING_DBEG or tSTRING_DVAR
g@crash:~$ cat test2.rb
x(/=/)
g@crash:~$ ruby test2.rb
test2.rb:1: undefined method `x' for main:Object (NoMethodError)
g@crash:~$ ruby -v
ruby 1.8.4 (2005-12-24) [i686-linux]

The ruby-mode parser is much simpler than the one the ruby interpreter
uses. For a start, it's not based on a proper grammar. I don't
suppose someone's tried to use semantic [1] or something to produce
something a little more robust?

[1] http://www.xemacs.org/Documentation/packages/html/semantic.html

···

On 11/30/06, Jeremy Henty <jeremy@chaos.org.uk> wrote:

A slightly better fix is to add a ';' as well to convince the major
mode that the statement has ended, otherwise it adds extra
indentation to the next line.

def foo
  x /= y # / ;
  bar
end

Hmm, my ruby-mode doesn't seem to need the ';'. I'm using the CVS
HEAD version with XEmacs 21.4.19.

Mine definitely does need it. I'm using stock Ruby 1.8.5 and GNU
Emacs 21.4 .

I wonder how the Ruby parser decides that /= is an operator and not
the start of a regexp?

It's just the way the grammar is defined.

"Mommy, why is the sky blue?" "Hush child, it's just the way the
physics is defined." :slight_smile:

For it to be a regexp, you'd need parens on the call to #x.

Hmm, so after an identifier the parser tries to parse an infix
operator trying to parse an expression, whereas after an open paren
there can't be an infix operator so it parses "/=" as the start of a
regexp? If so, I wonder how easy it would be to fix the emacs major
mode to do the same thing?

Thanks for your help.

Regards,

Jeremy Henty

···

On 2006-12-01, George Ogata <george.ogata@gmail.com> wrote:

On 11/30/06, Jeremy Henty <jeremy@chaos.org.uk> wrote: