>From 05d10742e01cc3dceb4f465695daee7cc42215d6 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Wed, 25 Apr 2012 06:55:50 +0400 Subject: [PATCH] ruby-mode: Don't propertize percent literals inside strings --- lisp/progmodes/ruby-mode.el | 58 ++++++++++++++++++++++++------------------- test/indent/ruby.rb | 3 +++ 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 5d79437..9ed3879 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -1162,7 +1162,7 @@ See `add-log-current-defun-function'." (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))))) + (1 (ruby-syntax-propertize-general-delimiters end)))) (point) end)) (defun ruby-syntax-propertize-heredoc (limit) @@ -1198,31 +1198,37 @@ See `add-log-current-defun-function'." (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 "|"))))) + (goto-char (match-beginning 1)) ; When multiline, the beginning + (let ((state (syntax-ppss)) ; may already be propertized. + (syntax-value (string-to-syntax "|"))) + ;; Move forward either way, to escape inf loop. + (goto-char (match-beginning 2)) + (unless (nth 3 state) ; not inside a string + (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 + syntax-value))) + syntax-value))) ) ;; For Emacsen where syntax-propertize-rules is not (yet) available, diff --git a/test/indent/ruby.rb b/test/indent/ruby.rb index c4a747a..fe1986a 100644 --- a/test/indent/ruby.rb +++ b/test/indent/ruby.rb @@ -7,6 +7,9 @@ c = %w(foo baz) d = %!hello! +# Don't propertize percent literals inside strings. +"(%s, %s)" % [123, 456] + # 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 -- 1.7.10.msysgit.1