summaryrefslogtreecommitdiff
path: root/lisp/progmodes/ruby-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/ruby-mode.el')
-rw-r--r--lisp/progmodes/ruby-mode.el86
1 files changed, 55 insertions, 31 deletions
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index a42a66dfa87..6e471d1aa2a 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -595,8 +595,7 @@ Can be one of `heredoc', `modifier', `expr-qstr', `expr-re'."
(not (or (eq ?_ w)
(eq ?. w)))))
(goto-char pnt)
- (setq w (char-after (point)))
- (not (eq ?! w))
+ (not (eq ?! (char-after (point))))
(skip-chars-forward " \t")
(goto-char (match-beginning 0))
(or (not (looking-at ruby-modifier-re))
@@ -877,11 +876,15 @@ calculating indentation on the lines after it."
(defun ruby-move-to-block (n)
"Move to the beginning (N < 0) or the end (N > 0) of the
current block, a sibling block, or an outer block. Do that (abs N) times."
- (let ((orig (point))
- (start (ruby-calculate-indent))
- (signum (if (> n 0) 1 -1))
+ (let ((signum (if (> n 0) 1 -1))
(backward (< n 0))
- down pos done)
+ (depth (or (nth 2 (ruby-parse-region (line-beginning-position)
+ (line-end-position)))
+ 0))
+ down done)
+ (when (< (* depth signum) 0)
+ ;; Moving end -> end or beginning -> beginning.
+ (setq depth 0))
(dotimes (_ (abs n))
(setq done nil)
(setq down (save-excursion
@@ -904,18 +907,26 @@ current block, a sibling block, or an outer block. Do that (abs N) times."
(re-search-forward "^=end\\>"))
((and backward (looking-at "^=end\\>"))
(re-search-backward "^=begin\\>"))
+ ;; Jump over a multiline literal.
+ ((ruby-in-ppss-context-p 'string)
+ (goto-char (nth 8 (syntax-ppss)))
+ (unless backward
+ (forward-sexp)
+ (when (bolp) (forward-char -1)))) ; After a heredoc.
(t
- (setq pos (current-indentation))
+ (let ((state (ruby-parse-region (point) (line-end-position))))
+ (unless (car state) ; Line ends with unfinished string.
+ (setq depth (+ (nth 2 state) depth))))
(cond
;; Deeper indentation, we found a block.
;; FIXME: We can't recognize empty blocks this way.
- ((< start pos)
+ ((> (* signum depth) 0)
(setq down t))
;; Block found, and same indentation as when started, stop.
- ((and down (= pos start))
+ ((and down (zerop depth))
(setq done t))
;; Shallower indentation, means outer block, can stop now.
- ((> start pos)
+ ((< (* signum depth) 0)
(setq done t)))))
(if done
(save-excursion
@@ -1062,29 +1073,33 @@ For example:
See `add-log-current-defun-function'."
(condition-case nil
(save-excursion
- (let ((indent 0) mname mlist
- (start (point))
- (definition-re
- (concat "^[ \t]*" ruby-defun-beg-re "[ \t]+"
- "\\("
- ;; \\. and :: for class methods
- "\\([A-Za-z_]" ruby-symbol-re "*\\|\\.\\|::" "\\)"
- "+\\)")))
+ (let* ((indent 0) mname mlist
+ (start (point))
+ (make-definition-re
+ (lambda (re)
+ (concat "^[ \t]*" re "[ \t]+"
+ "\\("
+ ;; \\. and :: for class methods
+ "\\([A-Za-z_]" ruby-symbol-re "*\\|\\.\\|::" "\\)"
+ "+\\)")))
+ (definition-re (funcall make-definition-re ruby-defun-beg-re))
+ (module-re (funcall make-definition-re "\\(class\\|module\\)")))
;; Get the current method definition (or class/module).
(when (re-search-backward definition-re nil t)
(goto-char (match-beginning 1))
- (when (ruby-block-contains-point start)
- ;; We're inside the method, class or module.
- (setq mname (match-string 2))
- (unless (string-equal "def" (match-string 1))
- (setq mlist (list mname) mname nil)))
+ (if (not (string-equal "def" (match-string 1)))
+ (setq mlist (list (match-string 2)))
+ ;; We're inside the method. For classes and modules,
+ ;; this check is skipped for performance.
+ (when (ruby-block-contains-point start)
+ (setq mname (match-string 2))))
(setq indent (current-column))
(beginning-of-line))
;; Walk up the class/module nesting.
(while (and (> indent 0)
- (re-search-backward definition-re nil t))
+ (re-search-backward module-re nil t))
(goto-char (match-beginning 1))
- (when (ruby-block-contains-point start)
+ (when (< (current-column) indent)
(setq mlist (cons (match-string 2) mlist))
(setq indent (current-column))
(beginning-of-line)))
@@ -1110,6 +1125,13 @@ See `add-log-current-defun-function'."
(let ((in-singleton-class
(when (re-search-forward ruby-singleton-class-re start t)
(goto-char (match-beginning 0))
+ ;; FIXME: Optimize it out, too?
+ ;; This can be slow in a large file, but
+ ;; unlike class/module declaration
+ ;; indentations, method definitions can be
+ ;; intermixed with these, and may or may not
+ ;; be additionally indented after visibility
+ ;; keywords.
(ruby-block-contains-point start))))
(setq mname (concat
(if in-singleton-class "." "#")
@@ -1254,8 +1276,10 @@ It will be properly highlighted even when the call omits parens."))
"\\)\\s *"
;; The regular expression itself.
"\\(/\\)[^/\n\\\\]*\\(?:\\\\.[^/\n\\\\]*\\)*\\(/\\)")
- (2 (string-to-syntax "\"/"))
- (3 (string-to-syntax "\"/")))
+ (3 (unless (nth 3 (syntax-ppss (match-beginning 2)))
+ (put-text-property (match-beginning 2) (match-end 2)
+ 'syntax-table (string-to-syntax "\"/"))
+ (string-to-syntax "\"/"))))
("^=en\\(d\\)\\_>" (1 "!"))
("^\\(=\\)begin\\_>" (1 "!"))
;; Handle here documents.
@@ -1552,7 +1576,7 @@ See `font-lock-syntax-table'.")
1 font-lock-function-name-face)
;; keywords
(cons (concat
- "\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(defined\\?\\|"
+ "\\(^\\|[^.@$]\\|\\.\\.\\)\\_<\\(defined\\?\\|"
(regexp-opt
'("alias_method"
"alias"
@@ -1602,7 +1626,7 @@ See `font-lock-syntax-table'.")
`(,ruby-here-doc-beg-re 0 (unless (ruby-singleton-class-p (match-beginning 0))
'font-lock-string-face))
;; variables
- '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\>"
+ '("\\(^\\|[^.@$]\\|\\.\\.\\)\\_<\\(nil\\|self\\|true\\|false\\)\\>"
2 font-lock-variable-name-face)
;; symbols
'("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|@?\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)"
@@ -1613,8 +1637,8 @@ See `font-lock-syntax-table'.")
'("\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+"
0 font-lock-variable-name-face)
;; constants
- '("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)"
- 2 font-lock-type-face)
+ '("\\(?:\\_<\\|::\\)\\([A-Z]+\\(\\w\\|_\\)*\\)"
+ 1 font-lock-type-face)
'("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" 2 font-lock-constant-face)
;; expression expansion
'(ruby-match-expression-expansion