From 7132e457ad3d5c6eec1c1eb78e1b7409d1fd5631 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Wed, 13 Feb 2013 12:15:05 +0400 Subject: [PATCH] * lisp/progmodes/ruby-mode.el (ruby-move-to-block): Improve performance. Instead of recalculating indentation fully for each line, sum up indentation depth based only on visited lines. (ruby-parse-partial): Increase the depth after "do" even when END is right after it. (ruby-parse-partial): When END is in the middle of a percent literal, increase the depth if the delimiter chars belong to the paren syntax class. * test/automated/ruby-mode-tests.el (ruby-move-to-block-skips-percent-literal): New test. --- lisp/ChangeLog | 11 +++++++++++ lisp/progmodes/ruby-mode.el | 31 +++++++++++++++++++++---------- test/ChangeLog | 5 +++++ test/automated/ruby-mode-tests.el | 18 ++++++++++++++++++ 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 34bc1aaf024..dbf380d72c8 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,14 @@ +2013-02-13 Dmitry Gutov + + * progmodes/ruby-mode.el (ruby-move-to-block): Improve + performance. Instead of recalculating indentation fully for each + line, sum up indentation depth based only on visited lines. + (ruby-parse-partial): Increase the depth after "do" even when END + is right after it. + (ruby-parse-partial): When END is in the middle of a percent + literal, increase the depth if the delimiter chars belong to the + paren syntax class. + 2013-02-13 Kirill A. Korinskiy * play/fortune.el (fortune-compile): Also make the compiled file diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 19d1ffe0a3b..b1017bb6302 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -519,6 +519,12 @@ Can be one of `heredoc', `modifier', `expr-qstr', `expr-re'." (concat "[^\\]\\(\\\\\\\\\\)*" w)) end t))) (setq in-string (point)) + (when (eq (char-syntax (string-to-char w)) ?\() + ;; The rest of the literal, when parsed separately, will + ;; have the depth of -1. So in the rare case when this + ;; number is used despite the in-string status, the + ;; depths will balance. + (setq depth (1+ depth))) (goto-char end))) (t (goto-char pnt)))) @@ -595,8 +601,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 +882,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 @@ -905,17 +914,19 @@ current block, a sibling block, or an outer block. Do that (abs N) times." ((and backward (looking-at "^=end\\>")) (re-search-backward "^=begin\\>")) (t - (setq pos (ruby-calculate-indent)) + (incf depth (or (nth 2 (ruby-parse-region (point) + (line-end-position))) + 0)) (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 diff --git a/test/ChangeLog b/test/ChangeLog index 41bb1be190e..f508209008e 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,8 @@ +2013-02-13 Dmitry Gutov + + * automated/ruby-mode-tests.el + (ruby-move-to-block-skips-percent-literal): New test. + 2013-02-04 Chong Yidong * automated/thingatpt.el: New file. diff --git a/test/automated/ruby-mode-tests.el b/test/automated/ruby-mode-tests.el index 2028c6fad00..6798a49d53c 100644 --- a/test/automated/ruby-mode-tests.el +++ b/test/automated/ruby-mode-tests.el @@ -445,6 +445,24 @@ VALUES-PLIST is a list with alternating index and value elements." (ruby-move-to-block -2) (should (= 2 (line-number-at-pos)))) +(ert-deftest ruby-move-to-block-skips-percent-literal () + (dolist (s (list (ruby-test-string + "foo do + | a = %%w( + | ) + |end") + (ruby-test-string + "foo do + | a = %%w| + | | + |end"))) + (ruby-with-temp-buffer s + (goto-line 1) + (ruby-end-of-block) + (should (= 4 (line-number-at-pos))) + (ruby-beginning-of-block) + (should (= 1 (line-number-at-pos)))))) + (provide 'ruby-mode-tests) ;;; ruby-mode-tests.el ends here -- 2.39.5