[前][次][番号順一覧][スレッド一覧]

ruby-changes:6635

From: nobu <ko1@a...>
Date: Tue, 22 Jul 2008 09:51:59 +0900 (JST)
Subject: [ruby-changes:6635] Ruby:r18150 (trunk, ruby_1_8): * misc/ruby-mode.el: fix here-doc strings with inner quotes. patches

nobu	2008-07-22 09:51:35 +0900 (Tue, 22 Jul 2008)

  New Revision: 18150

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=18150

  Log:
    * misc/ruby-mode.el: fix here-doc strings with inner quotes.  patches
      by Nathan Weizenbaum <nex342 AT gmail.com> from [ruby-core:17615]
      through [ruby-core:17910].

  Modified files:
    branches/ruby_1_8/ChangeLog
    branches/ruby_1_8/misc/ruby-mode.el
    trunk/ChangeLog
    trunk/misc/ruby-mode.el

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 18149)
+++ ChangeLog	(revision 18150)
@@ -1,3 +1,9 @@
+Tue Jul 22 09:51:32 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* misc/ruby-mode.el: fix here-doc strings with inner quotes.  patches
+	  by Nathan Weizenbaum <nex342 AT gmail.com> from [ruby-core:17615]
+	  through [ruby-core:17910].
+
 Tue Jul 22 04:26:16 2008  Nobuyoshi Nakada  <nobu@r...>
 
 	* include/ruby/intern.h (rb_str_buf_new2): optimization for literals.
Index: misc/ruby-mode.el
===================================================================
--- misc/ruby-mode.el	(revision 18149)
+++ misc/ruby-mode.el	(revision 18150)
@@ -49,16 +49,28 @@
 (defconst ruby-block-end-re "\\<end\\>")
 
 (defconst ruby-here-doc-beg-re
-  "<<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)")
+  "\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)")
 
+(defconst ruby-here-doc-end-re
+  "^\\([ \t]+\\)?\\(.*\\)\\(.\\)$")
+
 (defun ruby-here-doc-end-match ()
   (concat "^"
-	  (if (match-string 1) "[ \t]*" nil)
+	  (if (match-string 2) "[ \t]*" nil)
 	  (regexp-quote
-	   (or (match-string 3)
-	       (match-string 4)
-	       (match-string 5)))))
+	   (or (match-string 4)
+	       (match-string 5)
+	       (match-string 6)))))
 
+(defun ruby-here-doc-beg-match ()
+  (let ((contents (regexp-quote (concat (match-string 2) (match-string 3)))))
+    (concat "<<"
+            (let ((match (match-string 1)))
+              (if (and match (> (length match) 0))
+                  (concat "\\(?:-\\([\"']?\\)\\|\\([\"']\\)" (match-string 1) "\\)"
+                          contents "\\(\\1\\|\\2\\)")
+                (concat "-?\\([\"']\\|\\)" contents "\\1"))))))
+
 (defconst ruby-delimiter
   (concat "[?$/%(){}#\"'`.:]\\|<<\\|\\[\\|\\]\\|\\<\\("
 	  ruby-block-beg-re
@@ -172,8 +184,8 @@
 
 (eval-when-compile (require 'cl))
 (defun ruby-imenu-create-index-in-block (prefix beg end)
-  (let ((index-alist '()) (case-fold-search nil)
-	name next pos decl sing)
+  (let ((index-alist '())
+        name next pos decl sing)
     (goto-char beg)
     (while (re-search-forward "^\\s *\\(\\(class\\>\\(\\s *<<\\)?\\|module\\>\\)\\s *\\([^\(<\n ]+\\)\\|\\(def\\|alias\\)\\>\\s *\\([^\(\n ]+\\)\\)" end t)
       (setq sing (match-beginning 3))
@@ -220,6 +232,7 @@
 (defun ruby-mode-variables ()
   (set-syntax-table ruby-mode-syntax-table)
   (setq local-abbrev-table ruby-mode-abbrev-table)
+  (setq case-fold-search nil)
   (make-local-variable 'indent-line-function)
   (setq indent-line-function 'ruby-indent-line)
   (make-local-variable 'require-final-newline)
@@ -235,6 +248,8 @@
   (setq indent-tabs-mode ruby-indent-tabs-mode)
   (make-local-variable 'parse-sexp-ignore-comments)
   (setq parse-sexp-ignore-comments t)
+  (make-local-variable 'parse-sexp-lookup-properties)
+  (setq parse-sexp-lookup-properties t)
   (make-local-variable 'paragraph-start)
   (setq paragraph-start (concat "$\\|" page-delimiter))
   (make-local-variable 'paragraph-separate)
@@ -645,7 +660,6 @@
   (save-excursion
     (beginning-of-line)
     (let ((indent-point (point))
-	  (case-fold-search nil)
 	  state bol eol begin op-end
 	  (paren (progn (skip-syntax-forward " ")
 			(and (char-after) (matching-paren (char-after)))))
@@ -1090,7 +1104,7 @@
       (setq font-lock-variable-name-face font-lock-type-face))
 
   (setq ruby-font-lock-syntactic-keywords
-	'(
+	`(
 	  ;; #{ }, #$hoge, #@foo are not comments
 	  ("\\(#\\)[{$@]" 1 (1 . nil))
 	  ;; the last $', $", $` in the respective string is not variable
@@ -1106,8 +1120,77 @@
 	   (4 (7 . ?/))
 	   (6 (7 . ?/)))
 	  ("^\\(=\\)begin\\(\\s \\|$\\)" 1 (7 . nil))
-	  ("^\\(=\\)end\\(\\s \\|$\\)" 1 (7 . nil))))
+	  ("^\\(=\\)end\\(\\s \\|$\\)" 1 (7 . nil))
+	  (,(concat ruby-here-doc-beg-re ".*\\(\n\\)")
+	   ,(+ 1 (regexp-opt-depth ruby-here-doc-beg-re))
+           (ruby-here-doc-beg-syntax))
+	  (,ruby-here-doc-end-re 3 (ruby-here-doc-end-syntax))))
 
+  (defun ruby-in-non-here-doc-string-p ()
+    (let ((syntax (syntax-ppss)))
+      (or (nth 4 syntax)
+          ;; In a string *without* a generic delimiter
+          ;; If it's generic, it's a heredoc and we don't care
+          ;; See `parse-partial-sexp'
+          (numberp (nth 3 syntax)))))
+
+  (defun ruby-in-here-doc-p ()
+    (save-excursion
+      (let ((old-point (point)))
+        (beginning-of-line)
+        (catch 'found-beg
+          (while (re-search-backward ruby-here-doc-beg-re nil t)
+            (if (not (or (syntax-ppss-context (syntax-ppss))
+                         (ruby-here-doc-find-end old-point)))
+                (throw 'found-beg t)))))))
+
+  (defun ruby-here-doc-find-end (&optional limit)
+    "Expects the point to be on a line with one or more heredoc
+openers. Returns the buffer position at which all heredocs on the
+line are terminated, or nil if they aren't terminated before the
+buffer position `limit' or the end of the buffer."
+    (save-excursion
+      (beginning-of-line)
+      (catch 'done
+        (let ((eol (save-excursion (end-of-line) (point)))
+              ;; Fake match data such that (match-end 0) is at eol
+              (end-match-data (progn (looking-at ".*$") (match-data)))
+              beg-match-data end-re)
+          (while (re-search-forward ruby-here-doc-beg-re eol t)
+            (setq beg-match-data (match-data))
+            (setq end-re (ruby-here-doc-end-match))
+
+            (set-match-data end-match-data)
+            (goto-char (match-end 0))
+            (unless (re-search-forward end-re limit t) (throw 'done nil))
+            (setq end-match-data (match-data))
+
+            (set-match-data beg-match-data)
+            (goto-char (match-end 0)))
+          (set-match-data end-match-data)
+          (goto-char (match-end 0))
+          (point)))))
+
+  (defun ruby-here-doc-beg-syntax ()
+    (save-excursion
+      (goto-char (match-beginning 0))
+      (unless (or (ruby-in-non-here-doc-string-p)
+                  (ruby-in-here-doc-p))
+        (string-to-syntax "|"))))
+
+  (defun ruby-here-doc-end-syntax ()
+    (save-excursion
+      (goto-char (match-end 0))
+      (let ((old-point (point))
+            (beg-exists (re-search-backward (ruby-here-doc-beg-match) nil t))
+            (eol (save-excursion (end-of-line) (point))))
+        (if (and beg-exists ; If there is a heredoc that matches this line...
+                 (null (syntax-ppss-context (syntax-ppss))) ; And that's not inside a heredoc/string/comment...
+                 (progn (goto-char (match-end 0)) ; And it's the last heredoc on its line...
+                        (not (re-search-forward ruby-here-doc-beg-re eol t)))
+                 (eq old-point (ruby-here-doc-find-end old-point))) ; And it ends at this point...
+            (string-to-syntax "|")))))
+
   (if (featurep 'xemacs)
       (put 'ruby-mode 'font-lock-defaults
 	   '((ruby-font-lock-keywords)
@@ -1147,35 +1230,7 @@
       (modify-syntax-entry ?_ "w" tbl)
       tbl))
 
-  (defun ruby-font-lock-here-docs (limit)
-    (if (re-search-forward ruby-here-doc-beg-re limit t)
-	(let (beg)
-	  (beginning-of-line)
-          (forward-line)
-	  (setq beg (point))
-	  (if (re-search-forward (ruby-here-doc-end-match) nil t)
-	      (progn
-		(set-match-data (list beg (point)))
-		t)))))
-
-  (defun ruby-font-lock-maybe-here-docs (limit)
-    (let (beg)
-      (save-excursion
-	(if (re-search-backward ruby-here-doc-beg-re nil t)
-	    (progn
-	      (beginning-of-line)
-              (forward-line)
-	      (setq beg (point)))))
-      (if (and beg
-	       (let ((end-match (ruby-here-doc-end-match)))
-                 (and (not (re-search-backward end-match beg t))
-		      (re-search-forward end-match nil t))))
-	  (progn
-	    (set-match-data (list beg (point)))
-	    t)
-          nil)))
-
-  (defvar ruby-font-lock-keywords
+  (defconst ruby-font-lock-keywords
     (list
      ;; functions
      '("^\\s *def\\s +\\([^( \t\n]+\\)"
@@ -1224,6 +1279,8 @@
 	     "\\|")
 	    "\\)\\>\\)")
 	   2)
+     ;; here-doc beginnings
+     (list ruby-here-doc-beg-re 0 'font-lock-string-face)
      ;; variables
      '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\>"
        2 font-lock-variable-name-face)
@@ -1237,13 +1294,6 @@
        0 font-lock-comment-face t)
      '(ruby-font-lock-maybe-docs
        0 font-lock-comment-face t)
-     ;; "here" document
-     '(ruby-font-lock-here-docs
-       0 font-lock-string-face t)
-     '(ruby-font-lock-maybe-here-docs
-       0 font-lock-string-face t)
-     `(,ruby-here-doc-beg-re
-       0 font-lock-string-face t)
      ;; general delimited string
      '("\\(^\\|[[ \t\n<+(,=]\\)\\(%[xrqQwW]?\\([^<[{(a-zA-Z0-9 \n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\3\\)\\)"
        (2 font-lock-string-face))
Index: ruby_1_8/ChangeLog
===================================================================
--- ruby_1_8/ChangeLog	(revision 18149)
+++ ruby_1_8/ChangeLog	(revision 18150)
@@ -1,3 +1,9 @@
+Tue Jul 22 09:51:32 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* misc/ruby-mode.el: fix here-doc strings with inner quotes.  patches
+	  by Nathan Weizenbaum <nex342 AT gmail.com> from [ruby-core:17615]
+	  through [ruby-core:17910].
+
 Sat Jul 19 00:27:58 2008  NAKAMURA Usaku  <usa@r...>
 
 	* numeric.c (check_uint, rb_num2uint, rb_fix2uint): fixed wrong check
Index: ruby_1_8/misc/ruby-mode.el
===================================================================
--- ruby_1_8/misc/ruby-mode.el	(revision 18149)
+++ ruby_1_8/misc/ruby-mode.el	(revision 18150)
@@ -48,16 +48,28 @@
 (defconst ruby-block-end-re "\\<end\\>")
 
 (defconst ruby-here-doc-beg-re
-  "<<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)")
+  "\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)")
 
+(defconst ruby-here-doc-end-re
+  "^\\([ \t]+\\)?\\(.*\\)\\(.\\)$")
+
 (defun ruby-here-doc-end-match ()
   (concat "^"
-	  (if (match-string 1) "[ \t]*" nil)
+	  (if (match-string 2) "[ \t]*" nil)
 	  (regexp-quote
-	   (or (match-string 3)
-	       (match-string 4)
-	       (match-string 5)))))
+	   (or (match-string 4)
+	       (match-string 5)
+	       (match-string 6)))))
 
+(defun ruby-here-doc-beg-match ()
+  (let ((contents (regexp-quote (concat (match-string 2) (match-string 3)))))
+    (concat "<<"
+            (let ((match (match-string 1)))
+              (if (and match (> (length match) 0))
+                  (concat "\\(?:-\\([\"']?\\)\\|\\([\"']\\)" (match-string 1) "\\)"
+                          contents "\\(\\1\\|\\2\\)")
+                (concat "-?\\([\"']\\|\\)" contents "\\1"))))))
+
 (defconst ruby-delimiter
   (concat "[?$/%(){}#\"'`.:]\\|<<\\|\\[\\|\\]\\|\\<\\("
 	  ruby-block-beg-re
@@ -163,8 +175,8 @@
 
 (eval-when-compile (require 'cl))
 (defun ruby-imenu-create-index-in-block (prefix beg end)
-  (let ((index-alist '()) (case-fold-search nil)
-	name next pos decl sing)
+  (let ((index-alist '())
+        name next pos decl sing)
     (goto-char beg)
     (while (re-search-forward "^\\s *\\(\\(class\\>\\(\\s *<<\\)?\\|module\\>\\)\\s *\\([^\(<\n ]+\\)\\|\\(def\\|alias\\)\\>\\s *\\([^\(\n ]+\\)\\)" end t)
       (setq sing (match-beginning 3))
@@ -211,6 +223,7 @@
 (defun ruby-mode-variables ()
   (set-syntax-table ruby-mode-syntax-table)
   (setq local-abbrev-table ruby-mode-abbrev-table)
+  (setq case-fold-search nil)
   (make-local-variable 'indent-line-function)
   (setq indent-line-function 'ruby-indent-line)
   (make-local-variable 'require-final-newline)
@@ -226,6 +239,8 @@
   (setq indent-tabs-mode ruby-indent-tabs-mode)
   (make-local-variable 'parse-sexp-ignore-comments)
   (setq parse-sexp-ignore-comments t)
+  (make-local-variable 'parse-sexp-lookup-properties)
+  (setq parse-sexp-lookup-properties t)
   (make-local-variable 'paragraph-start)
   (setq paragraph-start (concat "$\\|" page-delimiter))
   (make-local-variable 'paragraph-separate)
@@ -591,7 +606,6 @@
   (save-excursion
     (beginning-of-line)
     (let ((indent-point (point))
-	  (case-fold-search nil)
 	  state bol eol begin op-end
 	  (paren (progn (skip-syntax-forward " ")
 			(and (char-after) (matching-paren (char-after)))))
@@ -1007,7 +1021,7 @@
       (setq font-lock-variable-name-face font-lock-type-face))
 
   (setq ruby-font-lock-syntactic-keywords
-	'(
+	`(
 	  ;; #{ }, #$hoge, #@foo are not comments
 	  ("\\(#\\)[{$@]" 1 (1 . nil))
 	  ;; the last $', $", $` in the respective string is not variable
@@ -1023,8 +1037,77 @@
 	   (4 (7 . ?/))
 	   (6 (7 . ?/)))
 	  ("^\\(=\\)begin\\(\\s \\|$\\)" 1 (7 . nil))
-	  ("^\\(=\\)end\\(\\s \\|$\\)" 1 (7 . nil))))
+	  ("^\\(=\\)end\\(\\s \\|$\\)" 1 (7 . nil))
+	  (,(concat ruby-here-doc-beg-re ".*\\(\n\\)")
+	   ,(+ 1 (regexp-opt-depth ruby-here-doc-beg-re))
+           (ruby-here-doc-beg-syntax))
+	  (,ruby-here-doc-end-re 3 (ruby-here-doc-end-syntax))))
 
+  (defun ruby-in-non-here-doc-string-p ()
+    (let ((syntax (syntax-ppss)))
+      (or (nth 4 syntax)
+          ;; In a string *without* a generic delimiter
+          ;; If it's generic, it's a heredoc and we don't care
+          ;; See `parse-partial-sexp'
+          (numberp (nth 3 syntax)))))
+
+  (defun ruby-in-here-doc-p ()
+    (save-excursion
+      (let ((old-point (point)))
+        (beginning-of-line)
+        (catch 'found-beg
+          (while (re-search-backward ruby-here-doc-beg-re nil t)
+            (if (not (or (syntax-ppss-context (syntax-ppss))
+                         (ruby-here-doc-find-end old-point)))
+                (throw 'found-beg t)))))))
+
+  (defun ruby-here-doc-find-end (&optional limit)
+    "Expects the point to be on a line with one or more heredoc
+openers. Returns the buffer position at which all heredocs on the
+line are terminated, or nil if they aren't terminated before the
+buffer position `limit' or the end of the buffer."
+    (save-excursion
+      (beginning-of-line)
+      (catch 'done
+        (let ((eol (save-excursion (end-of-line) (point)))
+              ;; Fake match data such that (match-end 0) is at eol
+              (end-match-data (progn (looking-at ".*$") (match-data)))
+              beg-match-data end-re)
+          (while (re-search-forward ruby-here-doc-beg-re eol t)
+            (setq beg-match-data (match-data))
+            (setq end-re (ruby-here-doc-end-match))
+
+            (set-match-data end-match-data)
+            (goto-char (match-end 0))
+            (unless (re-search-forward end-re limit t) (throw 'done nil))
+            (setq end-match-data (match-data))
+
+            (set-match-data beg-match-data)
+            (goto-char (match-end 0)))
+          (set-match-data end-match-data)
+          (goto-char (match-end 0))
+          (point)))))
+
+  (defun ruby-here-doc-beg-syntax ()
+    (save-excursion
+      (goto-char (match-beginning 0))
+      (unless (or (ruby-in-non-here-doc-string-p)
+                  (ruby-in-here-doc-p))
+        (string-to-syntax "|"))))
+
+  (defun ruby-here-doc-end-syntax ()
+    (save-excursion
+      (goto-char (match-end 0))
+      (let ((old-point (point))
+            (beg-exists (re-search-backward (ruby-here-doc-beg-match) nil t))
+            (eol (save-excursion (end-of-line) (point))))
+        (if (and beg-exists ; If there is a heredoc that matches this line...
+                 (null (syntax-ppss-context (syntax-ppss))) ; And that's not inside a heredoc/string/comment...
+                 (progn (goto-char (match-end 0)) ; And it's the last heredoc on its line...
+                        (not (re-search-forward ruby-here-doc-beg-re eol t)))
+                 (eq old-point (ruby-here-doc-find-end old-point))) ; And it ends at this point...
+            (string-to-syntax "|")))))
+
   (if (featurep 'xemacs)
       (put 'ruby-mode 'font-lock-defaults
 	   '((ruby-font-lock-keywords)
@@ -1064,35 +1147,7 @@
       (modify-syntax-entry ?_ "w" tbl)
       tbl))
 
-  (defun ruby-font-lock-here-docs (limit)
-    (if (re-search-forward ruby-here-doc-beg-re limit t)
-	(let (beg)
-	  (beginning-of-line)
-          (forward-line)
-	  (setq beg (point))
-	  (if (re-search-forward (ruby-here-doc-end-match) nil t)
-	      (progn
-		(set-match-data (list beg (point)))
-		t)))))
-
-  (defun ruby-font-lock-maybe-here-docs (limit)
-    (let (beg)
-      (save-excursion
-	(if (re-search-backward ruby-here-doc-beg-re nil t)
-	    (progn
-	      (beginning-of-line)
-              (forward-line)
-	      (setq beg (point)))))
-      (if (and beg
-	       (let ((end-match (ruby-here-doc-end-match)))
-                 (and (not (re-search-backward end-match beg t))
-		      (re-search-forward end-match nil t))))
-	  (progn
-	    (set-match-data (list beg (point)))
-	    t)
-          nil)))
-
-  (defvar ruby-font-lock-keywords
+  (defconst ruby-font-lock-keywords
     (list
      ;; functions
      '("^\\s *def\\s +\\([^( \t\n]+\\)"
@@ -1141,6 +1196,8 @@
 	     "\\|")
 	    "\\)\\>\\)")
 	   2)
+     ;; here-doc beginnings
+     (list ruby-here-doc-beg-re 0 'font-lock-string-face)
      ;; variables
      '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\>"
        2 font-lock-variable-name-face)
@@ -1154,13 +1211,6 @@
        0 font-lock-comment-face t)
      '(ruby-font-lock-maybe-docs
        0 font-lock-comment-face t)
-     ;; "here" document
-     '(ruby-font-lock-here-docs
-       0 font-lock-string-face t)
-     '(ruby-font-lock-maybe-here-docs
-       0 font-lock-string-face t)
-     `(,ruby-here-doc-beg-re
-       0 font-lock-string-face t)
      ;; general delimited string
      '("\\(^\\|[[ \t\n<+(,=]\\)\\(%[xrqQwW]?\\([^<[{(a-zA-Z0-9 \n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\3\\)\\)"
        (2 font-lock-string-face))

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]