Commit 5e9419e8 authored by Dmitry Gutov's avatar Dmitry Gutov
Browse files

* 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.
parent a77b8d5e
2012-11-13 Dmitry Gutov <dgutov@yandex.ru>
* 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 <monnier@iro.umontreal.ca>
 
* woman.el (woman-file-name): Don't mess with unread-command-events
......
......@@ -865,39 +865,54 @@ calculating indentation on the lines after it."
(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 @@ With ARG, move up multiple blocks."
(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)
......
......@@ -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 <monnier@iro.umontreal.ca>
......
......@@ -283,6 +283,54 @@ VALUES-PLIST is a list with alternating index and value elements."
(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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment