Subject: 24.1.50; (Contains ERT test) ruby-indent-line doesn't indent line after symbol creation using string interpolation
From: Rolando Pereira <[email-masked]>
To: [email-masked]
Date: Thu, 12 Jul 2012 15:53:26 +0100
List-Id: <debbugs-submit.debbugs.gnu.org>

When writing ruby code, if you type something like
:"foo#{variable_name}" emacs can no longer indent lines following it
because it gives the following error:

ruby-forward-string: Search failed: "[^\\]\\(\\\\\\\\\\)*[\"]"

However, ruby-mode has no problem indenting lines that only contain
:"foo" (ie. without the string interpolation).

Here's an ERT that shows the problem. In it, I don't activate ruby-mode
because `ruby-indent-line' can be called after the call to (require
'ruby-mode) and I believe it makes the test simpler (eg. no need to
worry about stuff in ruby-mode-hook):

(ert-deftest indent-line-after-symbol-made-from-string-interpolation ()
  "Ensure that `ruby-mode' can indent lines after seeing a symbol made using string interpolation

The syntax for creating a symbol using string interpolation is the following:
:\"bar#{variable_name}\"

For example, if `variable_name' is the number 10, then this
creates the symbol :bar10 and if `variable_name' is the string
\"bar\", then this creates the symbol :barbar."
  (let ((initial-content "def foo(suffix)
  :\"bar#{suffix}\"
")
	(expected-content "def foo(suffix)
  :\"bar#{suffix}\"
  "))

    (require 'ruby-mode)
    (with-temp-buffer
      ;; No need to call `ruby-mode', since `ruby-indent-line' can be
      ;; used after the (require 'ruby-mode)
      ;(ruby-mode)
      (insert initial-content)
      (ruby-indent-line)
      (let ((buffer-content (buffer-substring-no-properties (point-min) (point-max))))
	(ert-should (string= buffer-content expected-content))))))

To experience the problem from emacs -Q you can do the following steps
(which are similar to the steps that the ERT test performs):

1. Open emacs -Q
2. Require 'ruby-mode with M-: (require 'ruby-mode)
2. Create a "ruby-temp" buffer with C-x b ruby-temp RET
3. Write the following:
"def foo(suffix)
  :"bar#{suffix}"
" <-- cursor is here
4. Call M-x ruby-indent-line

The final result should be:
"def foo(suffix)
  :"bar#{suffix}
  " <-- cursor is here

But ruby-indent-line crashes instead with the following error:

ruby-forward-string: Search failed: "[^\\]\\(\\\\\\\\\\)*[\"]"

In GNU Emacs 24.1.50.1 (i686-pc-linux-gnu, GTK+ Version 2.20.1)
 of 2012-06-17 on rolando-desktop
Bzr revision: 108644 [email-masked]
Windowing system distributor `The X.Org Foundation', version 11.0.10706000
Important settings:
  value of $LANG: pt_PT.utf8
  locale-coding-system: utf-8-unix
  default enable-multibyte-characters: t

Major mode: Lisp Interaction

Minor modes in effect:
  tooltip-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  transient-mark-mode: t

Recent input:
<down> <down> <down> M-x r u b y - i n d e n t - l 
i n e <return> C-x b * n m e <backspace> <backspace> 
<backspace> m e s <tab> <backspace> <backspace> <backspace> 
M e s s <tab> <return> <help-echo> <help-echo> <down-mouse-1> 
<mouse-1> <double-down-mouse-1> <double-mouse-1> <triple-down-mouse-1> 
<triple-mouse-1> C-x b * s c r <tab> <return> C-y <up> 
<up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> 
<up> <up> <up> <up> <up> <up> <up> <up> <up> <left> 
<left> <left> <left> <left> <left> <left> <left> <left> 
<left> <left> <left> <left> <left> <left> <left> <left> 
<left> <left> <left> <left> <left> <left> <left> <left> 
<left> <right> <right> <right> <right> <right> <right> 
<right> <right> <right> <right> <right> <right> <right> 
<right> <right> <right> <right> <right> <right> <right> 
<right> <right> <right> - i n t e r p o l a t i o n 
<down> <end> <C-backspace> <C-backspace> <C-backspace> 
<left> <left> <left> <left> <left> <left> <left> <left> 
<left> <left> <left> <left> <left> <left> <left> <left> 
<end> u s i n g SPC s t r i n g SPC i n r t e <backspace> 
<backspace> <backspace> t e r p o l a t i o n <down> 
<down> <left> <left> <left> <left> <left> <left> <left> 
<left> <left> <left> <left> <left> <left> <left> <left> 
<left> <left> <left> <left> <left> <left> <left> <left> 
<left> <left> <left> <left> <left> <left> <left> <left> 
<left> <right> u s i n g SPC s t r i n g SPC i n t 
e r p o l a t i o n SPC i s M-d M-d M-d M-d <down> 
<down> <down> <down> <down> <down> <down> <down> <down> 
<down> <down> <down> <down> <down> <down> <down> <down> 
<down> <right> <right> <right> <right> M-x r e p o 
r t - e m <tab> <return>

Recent messages:
For information about GNU Emacs and the GNU system, type C-h C-a.
byte-code: End of buffer
ruby-forward-string: Search failed: #("[^\\]\\(\\\\\\\\\\)*[\"]" 14 15 (face font-lock-string-face fontified t))
Mark set

Load-path shadows:
None found.

Features:
(shadow sort gnus-util mail-extr emacsbug message format-spec rfc822 mml
easymenu mml-sec mm-decode mm-bodies mm-encode mail-parse rfc2231
mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums
mm-util mail-prsvr mail-utils ruby-mode time-date tooltip ediff-hook
vc-hooks lisp-float-type mwheel x-win x-dnd tool-bar dnd fontset image
regexp-opt fringe tabulated-list newcomment lisp-mode register page
menu-bar rfn-eshadow timer select scroll-bar mouse jit-lock font-lock
syntax facemenu font-core frame cham georgian utf-8-lang misc-lang
vietnamese tibetan thai tai-viet lao korean japanese hebrew greek
romanian slovak czech european ethiopic indian cyrillic chinese
case-table epa-hook jka-cmpr-hook help simple abbrev minibuffer loaddefs
button faces cus-face files text-properties overlay sha1 md5 base64
format env code-pages mule custom widget hashtable-print-readable
backquote make-network-process dbusbind dynamic-setting
system-font-setting font-render-setting move-toolbar gtk x-toolkit x
multi-tty emacs)