From: Dmitry Gutov Date: Tue, 24 Apr 2012 15:51:14 +0000 (-0400) Subject: * lisp/progmodes/ruby-mode.el: Handle general delimited literals. X-Git-Tag: emacs-24.2.90~471^2~286^2~2 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=85222d4485aaaf5b308859988ac3d06212e6bf3f;p=emacs.git * lisp/progmodes/ruby-mode.el: Handle general delimited literals. (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 --- diff --git a/lisp/ChangeLog b/lisp/ChangeLog index b1f1ad99b23..03fbfd83255 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,13 @@ +2012-04-24 Dmitry Gutov + + * 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 * progmodes/python.el: Move hideshow setup to the end. diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 66aa256f947..05a4042b67d 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -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)