X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/991c801cd6b6b323fb4510de9e295b3fea2fb12f..63efcc268635dea78c6bd80749eae4ee2c72d717:/lisp/progmodes/ruby-mode.el diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index c1001450bd..d237074197 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -431,17 +431,11 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'." (not (or (bolp) (memq (char-before) '(?\[ ?\()) (and (memq (char-before) - '(?\; ?- ?+ ?* ?/ ?: ?. ?, ?\\ ?& ?> ?< ?% ?~ ?^)) - ;; Not a binary operator symbol. - (not (eq (char-before (1- (point))) ?:)) - ;; Not the end of a regexp or a percent literal. - (not (memq (car (syntax-after (1- (point)))) '(7 15)))) - (and (eq (char-before) ?\?) - (equal (save-excursion (ruby-smie--backward-token)) "?")) - (and (eq (char-before) ?=) - ;; Not a symbol :==, :!=, or a foo= method. - (string-match "\\`\\s." (save-excursion - (ruby-smie--backward-token)))) + '(?\; ?- ?+ ?* ?/ ?: ?. ?, ?\\ ?& ?> ?< ?% ?~ ?^ ?= ??)) + ;; Not a binary operator symbol like :+ or :[]=. + ;; Or a (method or symbol) name ending with ?. + ;; Or the end of a regexp or a percent literal. + (not (memq (car (syntax-after (1- (point)))) '(3 7 15)))) (and (eq (char-before) ?|) (member (save-excursion (ruby-smie--backward-token)) '("|" "||"))) @@ -454,7 +448,7 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'." (defun ruby-smie--redundant-do-p (&optional skip) (save-excursion - (if skip (backward-word-strictly 1)) + (if skip (backward-word 1)) (member (nth 2 (smie-backward-sexp ";")) '("while" "until" "for")))) (defun ruby-smie--opening-pipe-p () @@ -485,12 +479,16 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'." "else" "elsif" "do" "end" "and") 'symbols)))) (memq (car (syntax-after pos)) '(7 15)) - (looking-at "[([]\\|[-+!~]\\sw\\|:\\(?:\\sw\\|\\s.\\)"))))) + (looking-at "[([]\\|[-+!~:]\\(?:\\sw\\|\\s_\\)"))))) -(defun ruby-smie--at-dot-call () +(defun ruby-smie--before-method-name () + ;; Only need to be accurate when method has keyword name. (and (eq ?w (char-syntax (following-char))) - (eq (char-before) ?.) - (not (eq (char-before (1- (point))) ?.)))) + (or + (and + (eq (char-before) ?.) + (not (eq (char-before (1- (point))) ?.))) + (looking-back "^\\s *def\\s +\\=" (line-beginning-position))))) (defun ruby-smie--forward-token () (let ((pos (point))) @@ -511,17 +509,15 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'." (save-excursion (ruby-smie--args-separator-p (prog1 (point) (goto-char pos))))) " @ ") - ((looking-at ":\\s.+") - (goto-char (match-end 0)) (match-string 0)) ;bug#15208. ((looking-at "\\s\"") "") ;A string. (t - (let ((dot (ruby-smie--at-dot-call)) + (let ((dot (ruby-smie--before-method-name)) (tok (smie-default-forward-token))) (when dot (setq tok (concat "." tok))) (cond ((member tok '("unless" "if" "while" "until")) - (if (save-excursion (forward-word-strictly -1) (ruby-smie--bosp)) + (if (save-excursion (forward-word -1) (ruby-smie--bosp)) tok "iuwu-mod")) ((string-match-p "\\`|[*&]?\\'" tok) (forward-char (- 1 (length tok))) @@ -559,11 +555,9 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'." " @ ") (t (let ((tok (smie-default-backward-token)) - (dot (ruby-smie--at-dot-call))) + (dot (ruby-smie--before-method-name))) (when dot (setq tok (concat "." tok))) - (when (and (eq ?: (char-before)) (string-match "\\`\\s." tok)) - (forward-char -1) (setq tok (concat ":" tok))) ;; bug#15208. (cond ((member tok '("unless" "if" "while" "until")) (if (ruby-smie--bosp) @@ -581,7 +575,7 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'." ((equal tok "do") (cond ((not (ruby-smie--redundant-do-p)) tok) - ((> (save-excursion (forward-word-strictly 1) + ((> (save-excursion (forward-word 1) (forward-comment (point-max)) (point)) (line-end-position)) (ruby-smie--backward-token)) ;Fully redundant. @@ -894,12 +888,18 @@ and `\\' when preceded by `?'." ((and (eq c ?:) (or (not b) (eq (char-syntax b) ? )))) ((eq c ?\\) (eq b ??))))) -(defun ruby-singleton-class-p (&optional pos) +(defun ruby-verify-heredoc (&optional pos) (save-excursion (when pos (goto-char pos)) - (forward-word-strictly -1) - (and (or (bolp) (not (eq (char-before (point)) ?_))) - (looking-at ruby-singleton-class-re)))) + ;; Not right after a symbol or prefix character. + ;; Method names are only allowed when separated by + ;; whitespace. Not a limitation in Ruby, but it's hard for + ;; us to do better. + (when (not (memq (car (syntax-after (1- (point)))) '(2 3 6 10))) + (or (not (memq (char-before) '(?\s ?\t))) + (ignore (forward-word -1)) + (eq (char-before) ?_) + (not (looking-at ruby-singleton-class-re)))))) (defun ruby-expr-beg (&optional option) "Check if point is possibly at the beginning of an expression. @@ -919,7 +919,7 @@ Can be one of `heredoc', `modifier', `expr-qstr', `expr-re'." nil) ((looking-at ruby-operator-re)) ((eq option 'heredoc) - (and (< space 0) (not (ruby-singleton-class-p start)))) + (and (< space 0) (ruby-verify-heredoc start))) ((or (looking-at "[\\[({,;]") (and (looking-at "[!?]") (or (not (eq option 'modifier)) @@ -1240,7 +1240,7 @@ delimiter." ((let ((s (ruby-parse-region (point) ruby-indent-point))) (and (nth 2 s) (> (nth 2 s) 0) (or (goto-char (cdr (nth 1 s))) t))) - (forward-word-strictly -1) + (forward-word -1) (setq indent (ruby-indent-size (current-column) (nth 2 state)))) (t @@ -1259,7 +1259,7 @@ delimiter." (if (null (cdr (nth 1 state))) (error "Invalid nesting")) (goto-char (cdr (nth 1 state))) - (forward-word-strictly -1) ; skip back a keyword + (forward-word -1) ; skip back a keyword (setq begin (point)) (cond ((looking-at "do\\>[^_]") ; iter block is a special case @@ -1352,7 +1352,7 @@ delimiter." (forward-char -1) (not (looking-at "{"))) (progn - (forward-word-strictly -1) + (forward-word -1) (not (looking-at "do\\>[^_]"))))) (t t)))) (not (eq ?, c)) @@ -1505,11 +1505,10 @@ With ARG, do it many times. Negative ARG means move backward." (not (eq (char-before (point)) ?.)) (not (eq (char-before (point)) ?:))) (ruby-end-of-block) - (forward-word-strictly 1)) + (forward-word 1)) ((looking-at "\\(\\$\\|@@?\\)?\\sw") (while (progn - (while (progn (forward-word-strictly 1) - (looking-at "_"))) + (while (progn (forward-word 1) (looking-at "_"))) (cond ((looking-at "::") (forward-char 2) t) ((> (skip-chars-forward ".") 0)) ((looking-at "\\?\\|!\\(=[~=>]\\|[^~=]\\)") @@ -1525,7 +1524,7 @@ With ARG, do it many times. Negative ARG means move backward." (skip-chars-forward "<")) (not expr)))) (setq i (1- i))) - ((error) (forward-word-strictly 1))) + ((error) (forward-word 1))) i)))) (defun ruby-backward-sexp (&optional arg) @@ -1561,7 +1560,7 @@ With ARG, do it many times. Negative ARG means move forward." ((looking-at "\\s(") nil) (t (forward-char 1) - (while (progn (forward-word-strictly -1) + (while (progn (forward-word -1) (pcase (char-before) (`?_ t) (`?. (forward-char -1) t) @@ -1848,18 +1847,22 @@ It will be properly highlighted even when the call omits parens.") (syntax-propertize-rules ;; $' $" $` .... are variables. ;; ?' ?" ?` are character literals (one-char strings in 1.9+). - ("\\([?$]\\)[#\"'`]" + ("\\([?$]\\)[#\"'`:?]" (1 (if (save-excursion (nth 3 (syntax-ppss (match-beginning 0)))) ;; Within a string, skip. (ignore (goto-char (match-end 1))) - (string-to-syntax "\\")))) - ;; Part of symbol when at the end of a method name. + (put-text-property (match-end 1) (match-end 0) + 'syntax-table (string-to-syntax "_")) + (string-to-syntax "'")))) + ;; Symbols with special characters. + ("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\)\\)" + (3 (string-to-syntax "_"))) + ;; Part of method name when at the end of it. ("[!?]" (0 (unless (save-excursion (or (nth 8 (syntax-ppss (match-beginning 0))) - (eq (char-before) ?:) (let (parse-sexp-lookup-properties) (zerop (skip-syntax-backward "w_"))) (memq (preceding-char) '(?@ ?$)))) @@ -1894,14 +1897,14 @@ It will be properly highlighted even when the call omits parens.") ("^\\(=\\)begin\\_>" (1 "!")) ;; Handle here documents. ((concat ruby-here-doc-beg-re ".*\\(\n\\)") - (7 (unless (or (nth 8 (save-excursion - (syntax-ppss (match-beginning 0)))) - (ruby-singleton-class-p (match-beginning 0))) + (7 (when (and (not (nth 8 (save-excursion + (syntax-ppss (match-beginning 0))))) + (ruby-verify-heredoc (match-beginning 0))) (put-text-property (match-beginning 7) (match-end 7) 'syntax-table (string-to-syntax "\"")) (ruby-syntax-propertize-heredoc end)))) ;; Handle percent literals: %w(), %q{}, etc. - ((concat "\\(?:^\\|[[ \t\n<+(,=]\\)" ruby-percent-literal-beg-re) + ((concat "\\(?:^\\|[[ \t\n<+(,=*]\\)" ruby-percent-literal-beg-re) (1 (unless (nth 8 (save-excursion (syntax-ppss (match-beginning 1)))) ;; Not inside a string, a comment, or a percent literal. (ruby-syntax-propertize-percent-literal end) @@ -1920,7 +1923,7 @@ It will be properly highlighted even when the call omits parens.") (beginning-of-line) (while (re-search-forward ruby-here-doc-beg-re (line-end-position) t) - (unless (ruby-singleton-class-p (match-beginning 0)) + (when (ruby-verify-heredoc (match-beginning 0)) (push (concat (ruby-here-doc-end-match) "\n") res)))) (save-excursion ;; With multiple openers on the same line, we don't know in which @@ -2166,7 +2169,7 @@ See `font-lock-syntax-table'.") (1 font-lock-builtin-face)) ;; Here-doc beginnings. (,ruby-here-doc-beg-re - (0 (unless (ruby-singleton-class-p (match-beginning 0)) + (0 (when (ruby-verify-heredoc (match-beginning 0)) 'font-lock-string-face))) ;; Perl-ish keywords. "\\_<\\(?:BEGIN\\|END\\)\\_>\\|^__END__$" @@ -2177,17 +2180,14 @@ See `font-lock-syntax-table'.") ;; Keywords that evaluate to certain values. ("\\_<__\\(?:LINE\\|ENCODING\\|FILE\\)__\\_>" (0 font-lock-builtin-face)) - ;; Symbols with symbol characters. + ;; Symbols. ("\\(^\\|[^:]\\)\\(:@?\\(?:\\w\\|_\\)+\\)\\([!?=]\\)?" (2 font-lock-constant-face) (3 (unless (and (eq (char-before (match-end 3)) ?=) (eq (char-after (match-end 3)) ?>)) - ;; bug#18466 + ;; bug#18644 font-lock-constant-face) nil t)) - ;; Symbols with special characters. - ("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)" - 2 font-lock-constant-face) ;; Special globals. (,(concat "\\$\\(?:[:\"!@;,/\\._><\\$?~=*&`'+0-9]\\|-[0adFiIlpvw]\\|" (regexp-opt '("LOAD_PATH" "LOADED_FEATURES" "PROGRAM_NAME" @@ -2227,7 +2227,7 @@ See `font-lock-syntax-table'.") 1 font-lock-negation-char-face) ;; Character literals. ;; FIXME: Support longer escape sequences. - ("\\_<\\?\\\\?\\S " 0 font-lock-string-face) + ("\\?\\\\?\\_<.\\_>" 0 font-lock-string-face) ;; Regexp options. ("\\(?:\\s|\\|/\\)\\([imxo]+\\)" 1 (when (save-excursion