diff options
Diffstat (limited to 'lisp/progmodes/ruby-mode.el')
| -rw-r--r-- | lisp/progmodes/ruby-mode.el | 86 |
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 |
