(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))
'("|" "||")))
(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 ()
"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)))
(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)))
" @ ")
(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)
((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.
((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.
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))
((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
(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
(forward-char -1)
(not (looking-at "{")))
(progn
- (forward-word-strictly -1)
+ (forward-word -1)
(not (looking-at "do\\>[^_]")))))
(t t))))
(not (eq ?, c))
(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 "\\?\\|!\\(=[~=>]\\|[^~=]\\)")
(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)
((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)
(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) '(?@ ?$))))
("^\\(=\\)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))))
(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
(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__$"
;; 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"
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