]> git.eshelyaron.com Git - emacs.git/commitdiff
Get Ruby's SMIE code to pass the test suite.
authorStefan Monnier <monnier@iro.umontreal.ca>
Sat, 5 Oct 2013 18:37:08 +0000 (14:37 -0400)
committerStefan Monnier <monnier@iro.umontreal.ca>
Sat, 5 Oct 2013 18:37:08 +0000 (14:37 -0400)
* lisp/progmodes/ruby-mode.el (ruby-use-smie): Change default.
(ruby-comment-column): Follow the global default, by default.
(ruby-smie-grammar): Add assignment syntax.
(ruby-smie--implicit-semi-p): No implicit semi-colon after an
open-paren, a comma, or a \.
(ruby-smie--forward-token, ruby-smie--backward-token): Handle heredocs,
and line continuations.
(ruby-smie-rules): Adjust handling of open-paren, now that it's never
followed by implicit semi-colons.  Add rule for string concatenation
and for indentation at BOB.
(ruby-forward-sexp, ruby-backward-sexp): Adjust for when smie is in use.

* lisp/emacs-lisp/smie.el (smie-next-sexp): Don't go back to pos before
calling next-sexp, since next-token may have skipped chars which
next-sexp doesn't know should be skipped!

* test/indent/ruby.rb: Port a few cases from automated/ruby-mode-tests.el.
Adjust indentation of continued line to the new SMIE behavior.

lisp/ChangeLog
lisp/emacs-lisp/smie.el
lisp/progmodes/ruby-mode.el
test/ChangeLog
test/indent/ruby.rb

index e3ca87515356f5bd4ff85c090c06f7fc6a6a896c..a7fbec849b5b1ef65aa4078ac36693d8c7b769bd 100644 (file)
@@ -1,7 +1,25 @@
+2013-10-05  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       * progmodes/ruby-mode.el (ruby-use-smie): Change default.
+       (ruby-comment-column): Follow the global default, by default.
+       (ruby-smie-grammar): Add assignment syntax.
+       (ruby-smie--implicit-semi-p): No implicit semi-colon after an
+       open-paren, a comma, or a \.
+       (ruby-smie--forward-token, ruby-smie--backward-token): Handle heredocs,
+       and line continuations.
+       (ruby-smie-rules): Adjust handling of open-paren, now that it's never
+       followed by implicit semi-colons.  Add rule for string concatenation
+       and for indentation at BOB.
+       (ruby-forward-sexp, ruby-backward-sexp): Adjust for when smie is in use.
+
+       * emacs-lisp/smie.el (smie-next-sexp): Don't go back to pos before
+       calling next-sexp, since next-token may have skipped chars which
+       next-sexp doesn't know should be skipped!
+
 2013-10-05  Leo Liu  <sdl.web@gmail.com>
 
-       * progmodes/octave.el (octave-send-region): Call
-       compilation-forget-errors.
+       * progmodes/octave.el (octave-send-region):
+       Call compilation-forget-errors.
 
 2013-10-04  Xue Fuqiao  <xfq.free@gmail.com>
 
index f9d0fd9366b0e878807d0451c601165f70f42023..e35cb4a8fc2ff4f8bb8b0d195448a129733835fc 100644 (file)
@@ -707,7 +707,7 @@ Possible return values:
              ((null toklevels)
               (when (zerop (length token))
                 (condition-case err
-                    (progn (goto-char pos) (funcall next-sexp 1) nil)
+                    (progn (funcall next-sexp 1) nil)
                   (scan-error
                    (let ((pos (nth 2 err)))
                      (throw 'return
index 95206c153901f8fe9867be2162ea83a02c3f120c..662cef82259b3c72cf535dd40badbbaeaf280f1f 100644 (file)
@@ -144,7 +144,7 @@ This should only be called after matching against `ruby-here-doc-beg-re'."
 (define-abbrev-table 'ruby-mode-abbrev-table ()
   "Abbrev table in use in Ruby mode buffers.")
 
-(defvar ruby-use-smie nil)
+(defvar ruby-use-smie t)
 
 (defvar ruby-mode-map
   (let ((map (make-sparse-keymap)))
@@ -198,7 +198,7 @@ This should only be called after matching against `ruby-here-doc-beg-re'."
   "Indentation of Ruby statements."
   :type 'integer :group 'ruby)
 
-(defcustom ruby-comment-column 32
+(defcustom ruby-comment-column (default-value 'comment-column)
   "Indentation column of comments."
   :type 'integer :group 'ruby)
 
@@ -246,7 +246,7 @@ Also ignores spaces after parenthesis when 'space."
     '((id)
       (insts (inst) (insts ";" insts))
       (inst (exp) (inst "iuwu-mod" exp))
-      (exp  (exp1) (exp "," exp))
+      (exp  (exp1) (exp "," exp) (exp "=" exp))
       (exp1 (exp2) (exp2 "?" exp1 ":" exp1))
       (exp2 ("def" insts "end")
             ("begin" insts-rescue-insts "end")
@@ -265,7 +265,7 @@ Also ignores spaces after parenthesis when 'space."
       (for-body (for-head ";" insts))
       (for-head (id "in" exp))
       (cases (exp "then" insts) ;; FIXME: Ruby also allows (exp ":" insts).
-             (cases "when" cases) (insts "else" insts))
+             (cases "when" cases) (insts "else" insts))
       (expseq (exp) );;(expseq "," expseq)
       (hashvals (id "=>" exp1) (hashvals "," hashvals))
       (insts-rescue-insts (insts)
@@ -274,7 +274,7 @@ Also ignores spaces after parenthesis when 'space."
       (itheni (insts) (exp "then" insts))
       (ielsei (itheni) (itheni "else" insts))
       (if-body (ielsei) (if-body "elsif" if-body)))
-    '((nonassoc "in") (assoc ";") (assoc ","))
+    '((nonassoc "in") (assoc ";") (assoc ",") (right "="))
     '((assoc "when"))
     '((assoc "elsif"))
     '((assoc "rescue" "ensure"))
@@ -288,7 +288,8 @@ Also ignores spaces after parenthesis when 'space."
   (save-excursion
     (skip-chars-backward " \t")
     (not (or (bolp)
-             (and (memq (char-before) '(?\; ?- ?+ ?* ?/ ?: ?.))
+             (and (memq (char-before)
+                        '(?\; ?- ?+ ?* ?/ ?: ?. ?, ?\[ ?\( ?\{ ?\\))
                   ;; Make sure it's not the end of a regexp.
                   (not (eq (car (syntax-after (1- (point)))) 7)))
              (and (memq (char-before) '(?\? ?=))
@@ -305,12 +306,13 @@ Also ignores spaces after parenthesis when 'space."
 
 (defun ruby-smie--forward-token ()
   (skip-chars-forward " \t")
-  (if (and (looking-at "[\n#]")
-           ;; Only add implicit ; when needed.
-           (ruby-smie--implicit-semi-p))
-      (progn
-        (if (eolp) (forward-char 1) (forward-comment 1))
-        ";")
+  (cond
+   ((looking-at "\\s\"") "")            ;A heredoc or a string.
+   ((and (looking-at "[\n#]")
+         (ruby-smie--implicit-semi-p))  ;Only add implicit ; when needed.
+    (if (eolp) (forward-char 1) (forward-comment 1))
+    ";")
+   (t
     (forward-comment (point-max))
     (if (looking-at ":\\s.+")
         (progn (goto-char (match-end 0)) (match-string 0)) ;; bug#15208.
@@ -321,15 +323,18 @@ Also ignores spaces after parenthesis when 'space."
             tok "iuwu-mod"))
          ((equal tok "|")
           (if (ruby-smie--opening-pipe-p) "opening-|" tok))
-         (t tok))))))
+         ((and (equal tok "") (looking-at "\\\\\n"))
+          (goto-char (match-end 0)) (ruby-smie--forward-token))
+         (t tok)))))))
 
 (defun ruby-smie--backward-token ()
   (let ((pos (point)))
     (forward-comment (- (point)))
-    (if (and (> pos (line-end-position))
-             (ruby-smie--implicit-semi-p))
-        (progn (skip-chars-forward " \t")
-               ";")
+    (cond
+     ((and (> pos (line-end-position)) (ruby-smie--implicit-semi-p))
+      (skip-chars-forward " \t") ";")
+     ((and (bolp) (not (bobp))) "")         ;Presumably a heredoc.
+     (t
       (let ((tok (smie-default-backward-token)))
         (when (and (eq ?: (char-before)) (string-match "\\`\\s." tok))
           (forward-char -1) (setq tok (concat ":" tok))) ;; bug#15208.
@@ -339,20 +344,31 @@ Also ignores spaces after parenthesis when 'space."
               tok "iuwu-mod"))
          ((equal tok "|")
           (if (ruby-smie--opening-pipe-p) "opening-|" tok))
-         (t tok))))))
+         ((and (equal tok "") (eq ?\\ (char-before)) (looking-at "\n"))
+          (forward-char -1) (ruby-smie--backward-token))
+         (t tok)))))))
 
 (defun ruby-smie-rules (kind token)
   (pcase (cons kind token)
     (`(:elem . basic) ruby-indent-level)
+    ;; "foo" "bar" is the concatenation of the two strings, so the second
+    ;; should be aligned with the first.
+    (`(:elem . args) (if (looking-at "\\s\"") 0))
+    ;; (`(:after . ",") (smie-rule-separator kind))
     (`(:after . ";")
      (if (smie-rule-parent-p "def" "begin" "do" "class" "module" "for"
-                             "[" "{" "while" "until" "unless"
+                             "while" "until" "unless"
                              "if" "then" "elsif" "else" "when"
                              "rescue" "ensure")
          (smie-rule-parent ruby-indent-level)
        ;; For (invalid) code between switch and case.
        ;; (if (smie-parent-p "switch") 4)
        0))
+    (`(:before . ,(or `"(" `"[" `"{"))
+     ;; Treat purely syntactic block-constructs as being part of their parent,
+     ;; when the opening statement is hanging.
+     (if (smie-rule-hanging-p) (smie-rule-parent)))
+    (`(:after . "=") 2)
     (`(:before . "do")
      (when
          (save-excursion
@@ -369,8 +385,9 @@ Also ignores spaces after parenthesis when 'space."
     (`(:before . ,(or `"when"))
      (if (not (smie-rule-sibling-p)) 0)) ;; ruby-indent-level
     ;; Hack attack: Since newlines are separators, don't try to align args that
-    ;; appear on a separate line.
-    (`(:list-intro . ";") t)))
+    ;; appear on a separate line.  "" is for the case where the "previous
+    ;; separator" was not an implicit ";" but the BOB.
+    (`(:list-intro . ,(or `";" `"")) t)))
 
 (defun ruby-imenu-create-index-in-block (prefix beg end)
   "Create an imenu index of methods inside a block."
@@ -1095,8 +1112,10 @@ With ARG, move out of multiple blocks."
 With ARG, do it many times.  Negative ARG means move backward."
   ;; TODO: Document body
   (interactive "p")
-  (if (and (numberp arg) (< arg 0))
-      (ruby-backward-sexp (- arg))
+  (cond
+   (ruby-use-smie (forward-sexp arg))
+   ((and (numberp arg) (< arg 0)) (ruby-backward-sexp (- arg)))
+   (t
     (let ((i (or arg 1)))
       (condition-case nil
           (while (> i 0)
@@ -1131,15 +1150,17 @@ With ARG, do it many times.  Negative ARG means move backward."
                      (not expr))))
             (setq i (1- i)))
         ((error) (forward-word 1)))
-      i)))
+      i))))
 
 (defun ruby-backward-sexp (&optional arg)
   "Move backward across one balanced expression (sexp).
 With ARG, do it many times.  Negative ARG means move forward."
   ;; TODO: Document body
   (interactive "p")
-  (if (and (numberp arg) (< arg 0))
-      (ruby-forward-sexp (- arg))
+  (cond
+   (ruby-use-smie (backward-sexp arg))
+   ((and (numberp arg) (< arg 0)) (ruby-forward-sexp (- arg)))
+   (t
     (let ((i (or arg 1)))
       (condition-case nil
           (while (> i 0)
@@ -1178,7 +1199,7 @@ With ARG, do it many times.  Negative ARG means move forward."
                    nil))
             (setq i (1- i)))
         ((error)))
-      i)))
+      i))))
 
 (defun ruby-indent-exp (&optional ignored)
   "Indent each line in the balanced expression following the point."
index b3bcdd9a5bde563ddfd4ada5e6e80082a9258c59..ac98b1c304065ec9851448c6dd5d623a27896364 100644 (file)
@@ -1,3 +1,8 @@
+2013-10-05  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       * indent/ruby.rb: Port a few cases from automated/ruby-mode-tests.el.
+       Adjust indentation of continued line to the new SMIE behavior.
+
 2013-10-04  Stefan Monnier  <monnier@iro.umontreal.ca>
 
        * automated/completion-tests.el:
index 6c9b9775b4822a6e99c65515488308cc204a4d13..15315bcf65383735c6d638625ce935bba5688000 100644 (file)
@@ -1,3 +1,10 @@
+if something_wrong?             # ruby-move-to-block-skips-heredoc
+  ActiveSupport::Deprecation.warn(<<-eowarn)
+  boo hoo
+  end
+  eowarn
+end
+
 # Percent literals.
 b = %Q{This is a "string"}
 c = %w!foo
@@ -21,6 +28,26 @@ a = asub / aslb + bsub / bslb;
 # Highlight the regexp after "if".
 x = toto / foo if /do bar/ =~ "dobar"
 
+bar(class: XXX) do              # ruby-indent-keyword-label
+  foo
+end
+bar
+
+foo = [1,                       # ruby-deep-indent
+       2]
+
+foo = {                         # ruby-deep-indent-disabled
+  a : b
+}
+
+foo = [                         # ruby-deep-indent-disabled
+  1
+]
+
+foo(                            # ruby-deep-indent-disabled
+  a
+)
+
 # Multiline regexp.
 /bars
  tees # toots
@@ -74,4 +101,4 @@ end
 
 # Bug#15369
 MSG = 'Separate every 3 digits in the integer portion of a number' \
-  'with underscores(_).'
+      'with underscores(_).'