]> git.eshelyaron.com Git - emacs.git/commitdiff
* lisp/progmodes/ruby-mode.el: Handle general delimited literals.
authorDmitry Gutov <dgutov@yandex.ru>
Tue, 24 Apr 2012 15:51:14 +0000 (11:51 -0400)
committerStefan Monnier <monnier@iro.umontreal.ca>
Tue, 24 Apr 2012 15:51:14 +0000 (11:51 -0400)
(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.

Fixes: debbugs:6286
lisp/ChangeLog
lisp/progmodes/ruby-mode.el

index b1f1ad99b233cfa4e855c292d1f86691c383a03b..03fbfd83255673a225054b99d02fe86c5cbf9860 100644 (file)
@@ -1,3 +1,13 @@
+2012-04-24  Dmitry Gutov  <dgutov@yandex.ru>
+
+       * 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  Leo Liu  <sdl.web@gmail.com>
 
        * progmodes/python.el: Move hideshow setup to the end.
index 66aa256f9479d7095d707f99114ebcbfe9cfe34a..05a4042b67d32b3809f559cc1da36da32d86b0e3 100644 (file)
@@ -794,8 +794,8 @@ and `\\' when preceded by `?'."
 ;;                           (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))
@@ -1118,6 +1118,7 @@ See `add-log-current-defun-function'."
         "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, #@foo are not comments
@@ -1137,7 +1138,10 @@ See `add-log-current-defun-function'."
           ("^\\(=\\)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 +1167,41 @@ See `add-log-current-defun-function'."
               ;; 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 +1246,10 @@ This should only be called after matching against `ruby-here-doc-end-re'."
      (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 +1458,6 @@ See `font-lock-syntax-table'.")
      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)