New defun movement commands.

* lisp/progmodes/python.el (python-nav--syntactically)
(python-nav--forward-defun, python-nav-backward-defun)
(python-nav-forward-defun): New functions.

* test/automated/python-tests.el (python-nav-backward-defun-1)
(python-nav-forward-defun-1): New tests.
This commit is contained in:
Fabián Ezequiel Gallina 2013-04-17 02:08:20 -03:00
parent 619ed6e18a
commit 083850a6a1
4 changed files with 159 additions and 0 deletions

View file

@ -1,3 +1,10 @@
2013-04-17 Fabián Ezequiel Gallina <fgallina@gnu.org>
New defun movement commands.
* progmodes/python.el (python-nav--syntactically)
(python-nav--forward-defun, python-nav-backward-defun)
(python-nav-forward-defun): New functions.
2013-04-17 Fabián Ezequiel Gallina <fgallina@gnu.org>
* progmodes/python.el (python-syntax--context-compiler-macro): New defun.

View file

@ -1192,6 +1192,66 @@ Returns nil if point is not in a def or class."
;; Ensure point moves forward.
(and (> beg-pos (point)) (goto-char beg-pos)))))
(defun python-nav--syntactically (fn poscompfn &optional pos)
"Move to point using FN ignoring non-code or paren context.
FN must take no arguments and could be used to set match-data.
POSCOMPFN is a two arguments function used to compare current and
previous point after it is moved using FN, this is normally a
less-than or greater-than comparison. Optional argument POS is
internally used in recursive calls and should not be explicitly
passed."
(let* ((newpos
(and (funcall fn)
(save-match-data
(and
(not (python-syntax-context-type))
(point-marker)))))
(current-match-data (match-data)))
(cond ((or (and (not pos) newpos)
(and pos newpos (funcall poscompfn newpos pos)))
(set-match-data current-match-data)
(point-marker))
((and (not pos) (not newpos)) nil)
(t (python-nav--syntactically
fn poscompfn (point-marker))))))
(defun python-nav--forward-defun (arg)
"Internal implementation of python-nav-{backward,forward}-defun.
Uses ARG to define which function to call, and how many times
repeat it."
(let ((found))
(while (and (> arg 0)
(setq found
(python-nav--syntactically
(lambda ()
(re-search-forward
python-nav-beginning-of-defun-regexp nil t))
'>)))
(setq arg (1- arg)))
(while (and (< arg 0)
(setq found
(python-nav--syntactically
(lambda ()
(re-search-backward
python-nav-beginning-of-defun-regexp nil t))
'<)))
(setq arg (1+ arg)))
found))
(defun python-nav-backward-defun (&optional arg)
"Navigate to closer defun backward ARG times.
Unlikely `python-nav-beginning-of-defun' this doesn't care about
nested definitions."
(interactive "^p")
(python-nav--forward-defun (- (or arg 1))))
(defun python-nav-forward-defun (&optional arg)
"Navigate to closer defun forward ARG times.
Unlikely `python-nav-beginning-of-defun' this doesn't care about
nested definitions."
(interactive "^p")
(python-nav--forward-defun (or arg 1)))
(defun python-nav-beginning-of-statement ()
"Move to start of current statement."
(interactive "^")

View file

@ -1,3 +1,8 @@
2013-04-17 Fabián Ezequiel Gallina <fgallina@gnu.org>
* automated/python-tests.el (python-nav-backward-defun-1)
(python-nav-forward-defun-1): New tests.
2013-04-09 Masatake YAMATO <yamato@redhat.com>
* automated/add-log-tests.el: New file. (Bug#14112)

View file

@ -674,6 +674,93 @@ def decoratorFunctionWithArguments(arg1, arg2, arg3):
(python-tests-look-at "return wrapped_f")
(line-beginning-position))))))
(ert-deftest python-nav-backward-defun-1 ()
(python-tests-with-temp-buffer
"
class A(object): # A
def a(self): # a
pass
def b(self): # b
pass
class B(object): # B
class C(object): # C
def d(self): # d
pass
# def e(self): # e
# pass
def c(self): # c
pass
# def d(self): # d
# pass
"
(goto-char (point-max))
(should (= (save-excursion (python-nav-backward-defun))
(python-tests-look-at " def c(self): # c" -1)))
(should (= (save-excursion (python-nav-backward-defun))
(python-tests-look-at " def d(self): # d" -1)))
(should (= (save-excursion (python-nav-backward-defun))
(python-tests-look-at " class C(object): # C" -1)))
(should (= (save-excursion (python-nav-backward-defun))
(python-tests-look-at " class B(object): # B" -1)))
(should (= (save-excursion (python-nav-backward-defun))
(python-tests-look-at " def b(self): # b" -1)))
(should (= (save-excursion (python-nav-backward-defun))
(python-tests-look-at " def a(self): # a" -1)))
(should (= (save-excursion (python-nav-backward-defun))
(python-tests-look-at "class A(object): # A" -1)))
(should (not (python-nav-backward-defun)))))
(ert-deftest python-nav-forward-defun-1 ()
(python-tests-with-temp-buffer
"
class A(object): # A
def a(self): # a
pass
def b(self): # b
pass
class B(object): # B
class C(object): # C
def d(self): # d
pass
# def e(self): # e
# pass
def c(self): # c
pass
# def d(self): # d
# pass
"
(goto-char (point-min))
(should (= (save-excursion (python-nav-forward-defun))
(python-tests-look-at "(object): # A")))
(should (= (save-excursion (python-nav-forward-defun))
(python-tests-look-at "(self): # a")))
(should (= (save-excursion (python-nav-forward-defun))
(python-tests-look-at "(self): # b")))
(should (= (save-excursion (python-nav-forward-defun))
(python-tests-look-at "(object): # B")))
(should (= (save-excursion (python-nav-forward-defun))
(python-tests-look-at "(object): # C")))
(should (= (save-excursion (python-nav-forward-defun))
(python-tests-look-at "(self): # d")))
(should (= (save-excursion (python-nav-forward-defun))
(python-tests-look-at "(self): # c")))
(should (not (python-nav-forward-defun)))))
(ert-deftest python-nav-beginning-of-statement-1 ()
(python-tests-with-temp-buffer