emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r110887: * lisp/progmodes/ruby-mode.e


From: Dmitry Gutov
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r110887: * lisp/progmodes/ruby-mode.el (ruby-move-to-block): Looks for a block
Date: Tue, 13 Nov 2012 22:57:26 +0400
User-agent: Bazaar (2.5.0)

------------------------------------------------------------
revno: 110887
committer: Dmitry Gutov <address@hidden>
branch nick: trunk
timestamp: Tue 2012-11-13 22:57:26 +0400
message:
  * lisp/progmodes/ruby-mode.el (ruby-move-to-block): Looks for a block
  start/end keyword a bit harder.  Works with different values of N.
  Add more comments.
  (ruby-end-of-block): Update accordingly.
  
  * test/automated/ruby-mode-tests.el (ruby-heredoc-font-lock)
  (ruby-singleton-class-no-heredoc-font-lock)
  (ruby-add-log-current-method-examples): New tests.
  (ruby-test-string): Extract from ruby-should-indent-buffer.
  (ruby-deftest-move-to-block): New macro.
  Add several move-to-block tests.
modified:
  lisp/ChangeLog
  lisp/progmodes/ruby-mode.el
  test/ChangeLog
  test/automated/ruby-mode-tests.el
=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2012-11-13 16:59:34 +0000
+++ b/lisp/ChangeLog    2012-11-13 18:57:26 +0000
@@ -1,3 +1,10 @@
+2012-11-13  Dmitry Gutov  <address@hidden>
+
+       * progmodes/ruby-mode.el (ruby-move-to-block): Looks for a block
+       start/end keyword a bit harder.  Works with different values of N.
+       Add more comments.
+       (ruby-end-of-block): Update accordingly.
+
 2012-11-13  Stefan Monnier  <address@hidden>
 
        * woman.el (woman-file-name): Don't mess with unread-command-events

=== modified file 'lisp/progmodes/ruby-mode.el'
--- a/lisp/progmodes/ruby-mode.el       2012-11-13 09:30:16 +0000
+++ b/lisp/progmodes/ruby-mode.el       2012-11-13 18:57:26 +0000
@@ -865,39 +865,54 @@
                 (beginning-of-line)))))
 
 (defun ruby-move-to-block (n)
-  "Move to the beginning (N < 0) or the end (N > 0) of the current block
-or blocks containing the current block."
-  ;; TODO: Make this work for n > 1,
-  ;; make it not loop for n = 0,
-  ;; document body
+  "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))
-        (down (looking-at (if (< n 0) ruby-block-end-re
-                            (concat "\\<\\(" ruby-block-beg-re "\\)\\>"))))
-        pos done)
-    (while (and (not done) (not (if (< n 0) (bobp) (eobp))))
-      (forward-line n)
-      (cond
-       ((looking-at "^\\s *$"))
-       ((looking-at "^\\s *#"))
-       ((and (> n 0) (looking-at "^=begin\\>"))
-        (re-search-forward "^=end\\>"))
-       ((and (< n 0) (looking-at "^=end\\>"))
-        (re-search-backward "^=begin\\>"))
-       (t
-        (setq pos (current-indentation))
+        (signum (if (> n 0) 1 -1))
+        (backward (< n 0))
+        down pos done)
+    (dotimes (_ (abs n))
+      (setq done nil)
+      (setq down (save-excursion
+                   (back-to-indentation)
+                   ;; There is a block start or block end keyword on this
+                   ;; line, don't need to look for another block.
+                   (and (re-search-forward
+                         (if backward ruby-block-end-re
+                           (concat "\\_<\\(" ruby-block-beg-re "\\)\\_>"))
+                         (line-end-position) t)
+                        (not (nth 8 (syntax-ppss))))))
+      (while (and (not done) (not (if backward (bobp) (eobp))))
+        (forward-line signum)
         (cond
-         ((< start pos)
-          (setq down t))
-         ((and down (= pos start))
-          (setq done t))
-         ((> start pos)
-          (setq done t)))))
-      (if done
-          (save-excursion
-            (back-to-indentation)
-            (if (looking-at (concat "\\<\\(" ruby-block-mid-re "\\)\\>"))
-                (setq done nil)))))
+         ;; Skip empty and commented out lines.
+         ((looking-at "^\\s *$"))
+         ((looking-at "^\\s *#"))
+         ;; Skip block comments;
+         ((and (not backward) (looking-at "^=begin\\>"))
+          (re-search-forward "^=end\\>"))
+         ((and backward (looking-at "^=end\\>"))
+          (re-search-backward "^=begin\\>"))
+         (t
+          (setq pos (current-indentation))
+          (cond
+           ;; Deeper intendation, we found a block.
+           ;; FIXME: We can't recognize empty blocks this way.
+           ((< start pos)
+            (setq down t))
+           ;; Block found, and same indentation as when started, stop.
+           ((and down (= pos start))
+            (setq done t))
+           ;; Shallower indentation, means outer block, can stop now.
+           ((> start pos)
+            (setq done t)))))
+        (if done
+            (save-excursion
+              (back-to-indentation)
+              ;; Not really at the first or last line of the block, move on.
+              (if (looking-at (concat "\\<\\(" ruby-block-mid-re "\\)\\>"))
+                  (setq done nil))))))
     (back-to-indentation)))
 
 (defun ruby-beginning-of-block (&optional arg)
@@ -909,8 +924,7 @@
 (defun ruby-end-of-block (&optional arg)
   "Move forward to the end of the current block.
 With ARG, move out of multiple blocks."
-  ;; Passing a value > 1 to ruby-move-to-block currently doesn't work.
-  (interactive)
+  (interactive "p")
   (ruby-move-to-block (or arg 1)))
 
 (defun ruby-forward-sexp (&optional arg)

=== modified file 'test/ChangeLog'
--- a/test/ChangeLog    2012-11-13 09:30:16 +0000
+++ b/test/ChangeLog    2012-11-13 18:57:26 +0000
@@ -4,6 +4,8 @@
        (ruby-singleton-class-no-heredoc-font-lock)
        (ruby-add-log-current-method-examples): New tests.
        (ruby-test-string): Extract from ruby-should-indent-buffer.
+       (ruby-deftest-move-to-block): New macro.
+       Add several move-to-block tests.
 
 2012-11-12  Stefan Monnier  <address@hidden>
 

=== modified file 'test/automated/ruby-mode-tests.el'
--- a/test/automated/ruby-mode-tests.el 2012-11-13 09:30:16 +0000
+++ b/test/automated/ruby-mode-tests.el 2012-11-13 18:57:26 +0000
@@ -283,6 +283,54 @@
                (should (string= (ruby-add-log-current-method)
                                 (format "M::C%s" value)))))))
 
+(defvar ruby-block-test-example
+  (ruby-test-string
+   "class C
+   |  def foo
+   |    1
+   |  end
+   |
+   |  def bar
+   |    2
+   |  end
+   |
+   |  def baz
+   |    some do
+   |    end
+   |  end
+   |end"))
+
+(defmacro ruby-deftest-move-to-block (name &rest body)
+  `(ert-deftest ,(intern (format "ruby-move-to-block-%s" name)) ()
+     (with-temp-buffer
+       (insert ruby-block-test-example)
+       (ruby-mode)
+       ,@body)))
+
+(put 'ruby-deftest-move-to-block 'lisp-indent-function 'defun)
+
+(ruby-deftest-move-to-block works-on-do
+  (goto-line 11)
+  (ruby-end-of-block)
+  (should (= 12 (line-number-at-pos)))
+  (ruby-beginning-of-block)
+  (should (= 11 (line-number-at-pos))))
+
+(ruby-deftest-move-to-block zero-is-noop
+  (goto-line 5)
+  (ruby-move-to-block 0)
+  (should (= 5 (line-number-at-pos))))
+
+(ruby-deftest-move-to-block ok-with-three
+  (goto-line 2)
+  (ruby-move-to-block 3)
+  (should (= 13 (line-number-at-pos))))
+
+(ruby-deftest-move-to-block ok-with-minus-two
+  (goto-line 10)
+  (ruby-move-to-block -2)
+  (should (= 2 (line-number-at-pos))))
+
 (provide 'ruby-mode-tests)
 
 ;;; ruby-mode-tests.el ends here


reply via email to

[Prev in Thread] Current Thread [Next in Thread]