emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/emacs-24 r108021: * ruby-mode.el: Handle ge


From: Stefan Monnier
Subject: [Emacs-diffs] /srv/bzr/emacs/emacs-24 r108021: * ruby-mode.el: Handle general delimited literals.
Date: Fri, 02 Nov 2012 02:32:08 -0000
User-agent: Bazaar (2.5.0)

------------------------------------------------------------
revno: 108021 [merge]
fixes bug: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=6286
committer: Stefan Monnier <address@hidden>
branch nick: trunk
timestamp: Tue 2012-04-24 13:08:55 -0400
message:
  * ruby-mode.el: Handle general delimited literals.
added:
  test/indent/ruby.rb
modified:
  lisp/ChangeLog
  lisp/progmodes/ruby-mode.el
  test/ChangeLog
=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2012-04-24 15:19:07 +0000
+++ b/lisp/ChangeLog    2012-04-24 17:08:55 +0000
@@ -1,3 +1,25 @@
+2012-04-24  Stefan Monnier  <address@hidden>
+
+       * progmodes/ruby-mode.el: Simplify last change, and cleanup code.
+       (ruby-syntax-propertize-regexp): Remove.
+       (ruby-syntax-propertize-function): Split regexp into chunks.
+       Match following code directly.
+
+2012-04-24  Dmitry Gutov  <address@hidden>
+
+       * progmodes/ruby-mode.el: Handle Cucumber defs (bug#6286).
+       (ruby-syntax-propertize-regexp): New function.
+       (ruby-syntax-propertize-function): Use it to handle regexp not preceded
+       by a special keyword.
+
+       * progmodes/ruby-mode.el: Handle general delimited literals (bug#6286).
+       (ruby-syntax-general-delimiters-goto-beg)
+       (ruby-syntax-propertize-general-delimiters): New functions.
+       (ruby-syntax-propertize-function): Use them to handle GDL.
+       (ruby-font-lock-keywords): Move old handling of GDL...
+       (ruby-font-lock-syntactic-keywords): .. to here.
+       (ruby-calculate-indent): Adjust indentation for GDL.
+
 2012-04-24  Michael Albinus  <address@hidden>
 
        * notifications.el (notifications-interface)

=== modified file 'lisp/progmodes/ruby-mode.el'
--- a/lisp/progmodes/ruby-mode.el       2012-03-21 18:33:07 +0000
+++ b/lisp/progmodes/ruby-mode.el       2012-04-24 17:02:46 +0000
@@ -784,7 +784,7 @@
                       (not (looking-at "[a-z_]"))))
                (and (looking-at ruby-operator-re)
                     (not (ruby-special-char-p))
-                    ;; operator at the end of line
+                    ;; Operator at the end of line.
                     (let ((c (char-after (point))))
                       (and
 ;;                     (or (null begin)
@@ -794,8 +794,9 @@
 ;;                           (not (or (eolp) (looking-at "#")
 ;;                                    (and (eq (car (nth 1 state)) ?{)
 ;;                                         (looking-at "|"))))))
-                       (or (not (eq ?/ c))
-                           (null (nth 0 (ruby-parse-region (or begin 
parse-start) (point)))))
+                       ;; Not a regexp or general delimited literal.
+                       (null (nth 0 (ruby-parse-region (or begin parse-start)
+                                                       (point))))
                        (or (not (eq ?| (char-after (point))))
                            (save-excursion
                              (or (eolp) (forward-char -1))
@@ -1110,6 +1111,8 @@
             mlist)))))
 
 (declare-function ruby-syntax-propertize-heredoc "ruby-mode" (limit))
+(declare-function ruby-syntax-general-delimiters-goto-beg "ruby-mode" ())
+(declare-function ruby-syntax-propertize-general-delimiters "ruby-mode" 
(limit))
 
 (if (eval-when-compile (fboundp #'syntax-propertize-rules))
     ;; New code that works independently from font-lock.
@@ -1118,26 +1121,48 @@
         "Syntactic keywords for Ruby mode.  See `syntax-propertize-function'."
         (goto-char start)
         (ruby-syntax-propertize-heredoc end)
+        (ruby-syntax-general-delimiters-goto-beg)
         (funcall
          (syntax-propertize-rules
-          ;; #{ }, #$hoge, address@hidden are not comments
+          ;; #{ }, #$hoge, address@hidden are not comments.
           ("\\(#\\)address@hidden" (1 "."))
-          ;; $' $" $` .... are variables
-          ;; ?' ?" ?` are ascii codes
+          ;; $' $" $` .... are variables.
+          ;; ?' ?" ?` are ascii codes.
           ("\\([?$]\\)[#\"'`]"
            (1 (unless (save-excursion
                         ;; Not within a string.
                         (nth 3 (syntax-ppss (match-beginning 0))))
                 (string-to-syntax "\\"))))
-          ;; regexps
-          ("\\(^\\|[[=(,~?:;<>]\\|\\(^\\|\\s 
\\)\\(if\\|elsif\\|unless\\|while\\|until\\|when\\|and\\|or\\|&&\\|||\\)\\|g?sub!?\\|scan\\|split!?\\)\\s
 *\\(/\\)[^/\n\\\\]*\\(\\\\.[^/\n\\\\]*\\)*\\(/\\)"
-           (4 "\"/")
-           (6 "\"/"))
+          ;; Regexps: regexps are distinguished from division either because
+          ;; of the keyword/symbol before them, or because of the code
+          ;; following them.
+          ((concat
+            ;; Special tokens that can't be followed by a division operator.
+            "\\(?:\\(^\\|[[=(,~?:;<>]\\|\\(?:^\\|\\s \\)"
+            (regexp-opt '("if" "elsif" "unless" "while" "until" "when" "and"
+                          "or" "&&" "||"
+                          "gsub" "gsub!" "sub" "sub!" "scan" "split" "split!"))
+            "\\)\\s *\\)?"
+            ;; The regular expression itself.
+            "\\(/\\)[^/\n\\\\]*\\(?:\\\\.[^/\n\\\\]*\\)*\\(/\\)"
+            ;; Special code that cannot follow a division operator.
+            ;; FIXME: Just because the second slash of "/foo/ do bar" can't
+            ;; be a division, doesn't mean it can't *start* a regexp, as in
+            ;; "x = toto/foo; if /do bar/".
+            "\\([imxo]*\\s *\\(?:,\\|\\_<do\\_>\\)\\)?")
+           (2 (when (or (match-beginning 1) (match-beginning 4))
+                (string-to-syntax "\"/")))
+           (3 (if (or (match-beginning 1) (match-beginning 4))
+                  (string-to-syntax "\"/")
+                (goto-char (match-end 2)))))
           ("^=en\\(d\\)\\_>" (1 "!"))
           ("^\\(=\\)begin\\_>" (1 "!"))
           ;; Handle here documents.
           ((concat ruby-here-doc-beg-re ".*\\(\n\\)")
-           (7 (prog1 "\"" (ruby-syntax-propertize-heredoc end)))))
+           (7 (prog1 "\"" (ruby-syntax-propertize-heredoc end))))
+          ;; Handle percent literals: %w(), %q{}, etc.
+          ("\\(?:^\\|[[ \t\n<+(,=]\\)\\(%\\)[qQrswWx]?\\([[:punct:]]\\)"
+           (1 (prog1 "|" (ruby-syntax-propertize-general-delimiters end)))))
          (point) end))
 
       (defun ruby-syntax-propertize-heredoc (limit)
@@ -1163,6 +1188,41 @@
               ;; Make extra sure we don't move back, lest we could fall into an
               ;; inf-loop.
               (if (< (point) start) (goto-char start))))))
+
+      (defun ruby-syntax-general-delimiters-goto-beg ()
+        (let ((state (syntax-ppss)))
+          ;; Move to the start of the literal, in case it's multiline.
+          ;; TODO: determine the literal type more reliably here?
+          (when (eq t (nth 3 state))
+            (goto-char (nth 8 state))
+            (beginning-of-line))))
+
+      (defun ruby-syntax-propertize-general-delimiters (limit)
+        (goto-char (match-beginning 2))
+        (let* ((op (char-after))
+               (ops (char-to-string op))
+               (cl (or (cdr (aref (syntax-table) op))
+                       (cdr (assoc op '((?< . ?>))))))
+               parse-sexp-lookup-properties)
+          (ignore-errors
+            (if cl
+                (progn  ; Paired delimiters.
+                  ;; Delimiter pairs of the same kind can be nested
+                  ;; inside the literal, as long as they are balanced.
+                  ;; Create syntax table that ignores other characters.
+                  (with-syntax-table (make-char-table 'syntax-table nil)
+                    (modify-syntax-entry op (concat "(" (char-to-string cl)))
+                    (modify-syntax-entry cl (concat ")" ops))
+                    (modify-syntax-entry ?\\ "\\")
+                    (save-restriction
+                      (narrow-to-region (point) limit)
+                      (forward-list))))  ; skip to the paired character
+              ;; Single character delimiter.
+              (re-search-forward (concat "[^\\]\\(?:\\\\\\\\\\)*"
+                                         (regexp-quote ops)) limit nil))
+            ;; If we reached here, the closing delimiter was found.
+            (put-text-property (1- (point)) (point)
+                               'syntax-table (string-to-syntax "|")))))
       )
 
   ;; For Emacsen where syntax-propertize-rules is not (yet) available,
@@ -1207,6 +1267,10 @@
      (4 (7 . ?/))
      (6 (7 . ?/)))
     ("^=en\\(d\\)\\_>" 1 "!")
+    ;; General delimited string.
+    ("\\(^\\|[[ \t\n<+(,=]\\)\\(%[xrqQwW]?\\([^<[{(a-zA-Z0-9 
\n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\3\\)\\)"
+     (3 "\"")
+     (5 "\""))
     ("^\\(=\\)begin\\_>" 1 (ruby-comment-beg-syntax))
     ;; Currently, the following case is highlighted incorrectly:
     ;;
@@ -1415,9 +1479,6 @@
      1 font-lock-variable-name-face)
    '("\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+"
      0 font-lock-variable-name-face)
-   ;; general delimited string
-   '("\\(^\\|[[ \t\n<+(,=]\\)\\(%[xrqQwW]?\\([^<[{(a-zA-Z0-9 
\n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\3\\)\\)"
-     (2 font-lock-string-face))
    ;; constants
    '("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)"
      2 font-lock-type-face)

=== modified file 'test/ChangeLog'
--- a/test/ChangeLog    2012-04-11 03:24:26 +0000
+++ b/test/ChangeLog    2012-04-24 17:06:12 +0000
@@ -1,3 +1,7 @@
+2012-04-24  Stefan Monnier  <address@hidden>
+
+       * indent/ruby.rb: New file, to test new syntax-propertize code.
+
 2012-04-11  Glenn Morris  <address@hidden>
 
        * automated/vc-bzr.el (vc-bzr-test-faulty-bzr-autoloads): New test.

=== added file 'test/indent/ruby.rb'
--- a/test/indent/ruby.rb       1970-01-01 00:00:00 +0000
+++ b/test/indent/ruby.rb       2012-04-24 17:02:46 +0000
@@ -0,0 +1,19 @@
+# Don't mis-match "sub" at the end of words.
+a = asub / aslb + bsub / bslb;
+
+b = %Q{This is a "string"}
+c = %w(foo
+ bar
+ baz)
+d = %!hello!
+
+# A "do" after a slash means that slash is not a division, but it doesn't imply
+# it's a regexp-ender, since it can be a regexp-starter instead!
+x = toto / foo; if /do bar/ then
+                  toto = 1
+                end
+
+# Some Cucumber code:
+Given /toto/ do
+  print "hello"
+end


reply via email to

[Prev in Thread] Current Thread [Next in Thread]