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/