* lisp/progmodes/python.el (python-nav--syntactically): Fix cornercases
and do not care about match data. * test/automated/python-tests.el (python-nav-backward-defun-2) (python-nav-backward-defun-3, python-nav-forward-defun-2) (python-nav-forward-defun-3): New tests.
This commit is contained in:
parent
dd8791e96f
commit
04754d3612
4 changed files with 145 additions and 22 deletions
|
@ -1,3 +1,8 @@
|
|||
2013-04-17 Fabián Ezequiel Gallina <fgallina@gnu.org>
|
||||
|
||||
* progmodes/python.el (python-nav--syntactically): Fix cornercases
|
||||
and do not care about match data.
|
||||
|
||||
2013-04-17 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* emacs-lisp/lisp.el (lisp-completion-at-point): Provide specialized
|
||||
|
|
|
@ -1192,28 +1192,32 @@ 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--syntactically (fn poscompfn &optional contextfn)
|
||||
"Move point using FN avoiding places with specific context.
|
||||
FN must take no arguments. 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 CONTEXTFN defaults to
|
||||
`python-syntax-context-type' and is used for checking current
|
||||
point context, it must return a non-nil value if this point must
|
||||
be skipped."
|
||||
(let ((contextfn (or contextfn 'python-syntax-context-type))
|
||||
(start-pos (point-marker))
|
||||
(prev-pos))
|
||||
(catch 'found
|
||||
(while t
|
||||
(let* ((newpos
|
||||
(and (funcall fn) (point-marker)))
|
||||
(context (funcall contextfn)))
|
||||
(cond ((and (not context) newpos
|
||||
(or (and (not prev-pos) newpos)
|
||||
(and prev-pos newpos
|
||||
(funcall poscompfn newpos prev-pos))))
|
||||
(throw 'found (point-marker)))
|
||||
((and newpos context)
|
||||
(setq prev-pos (point)))
|
||||
(t (when (not newpos) (goto-char start-pos))
|
||||
(throw 'found nil))))))))
|
||||
|
||||
(defun python-nav--forward-defun (arg)
|
||||
"Internal implementation of python-nav-{backward,forward}-defun.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2013-04-17 Fabián Ezequiel Gallina <fgallina@gnu.org>
|
||||
|
||||
* automated/python-tests.el (python-nav-backward-defun-2)
|
||||
(python-nav-backward-defun-3, python-nav-forward-defun-2)
|
||||
(python-nav-forward-defun-3): New tests.
|
||||
|
||||
2013-04-17 Fabián Ezequiel Gallina <fgallina@gnu.org>
|
||||
|
||||
* automated/python-tests.el (python-nav-backward-defun-1)
|
||||
|
|
|
@ -718,6 +718,60 @@ class A(object): # A
|
|||
(python-tests-look-at "class A(object): # A" -1)))
|
||||
(should (not (python-nav-backward-defun)))))
|
||||
|
||||
(ert-deftest python-nav-backward-defun-2 ()
|
||||
(python-tests-with-temp-buffer
|
||||
"
|
||||
def decoratorFunctionWithArguments(arg1, arg2, arg3):
|
||||
'''print decorated function call data to stdout.
|
||||
|
||||
Usage:
|
||||
|
||||
@decoratorFunctionWithArguments('arg1', 'arg2')
|
||||
def func(a, b, c=True):
|
||||
pass
|
||||
'''
|
||||
|
||||
def wwrap(f):
|
||||
print 'Inside wwrap()'
|
||||
def wrapped_f(*args):
|
||||
print 'Inside wrapped_f()'
|
||||
print 'Decorator arguments:', arg1, arg2, arg3
|
||||
f(*args)
|
||||
print 'After f(*args)'
|
||||
return wrapped_f
|
||||
return wwrap
|
||||
"
|
||||
(goto-char (point-max))
|
||||
(should (= (save-excursion (python-nav-backward-defun))
|
||||
(python-tests-look-at " def wrapped_f(*args):" -1)))
|
||||
(should (= (save-excursion (python-nav-backward-defun))
|
||||
(python-tests-look-at " def wwrap(f):" -1)))
|
||||
(should (= (save-excursion (python-nav-backward-defun))
|
||||
(python-tests-look-at "def decoratorFunctionWithArguments(arg1, arg2, arg3):" -1)))
|
||||
(should (not (python-nav-backward-defun)))))
|
||||
|
||||
(ert-deftest python-nav-backward-defun-3 ()
|
||||
(python-tests-with-temp-buffer
|
||||
"
|
||||
'''
|
||||
def u(self):
|
||||
pass
|
||||
|
||||
def v(self):
|
||||
pass
|
||||
|
||||
def w(self):
|
||||
pass
|
||||
'''
|
||||
|
||||
class A(object):
|
||||
pass
|
||||
"
|
||||
(goto-char (point-min))
|
||||
(let ((point (python-tests-look-at "class A(object):")))
|
||||
(should (not (python-nav-backward-defun)))
|
||||
(should (= point (point))))))
|
||||
|
||||
(ert-deftest python-nav-forward-defun-1 ()
|
||||
(python-tests-with-temp-buffer
|
||||
"
|
||||
|
@ -762,6 +816,60 @@ class A(object): # A
|
|||
(python-tests-look-at "(self): # c")))
|
||||
(should (not (python-nav-forward-defun)))))
|
||||
|
||||
(ert-deftest python-nav-forward-defun-2 ()
|
||||
(python-tests-with-temp-buffer
|
||||
"
|
||||
def decoratorFunctionWithArguments(arg1, arg2, arg3):
|
||||
'''print decorated function call data to stdout.
|
||||
|
||||
Usage:
|
||||
|
||||
@decoratorFunctionWithArguments('arg1', 'arg2')
|
||||
def func(a, b, c=True):
|
||||
pass
|
||||
'''
|
||||
|
||||
def wwrap(f):
|
||||
print 'Inside wwrap()'
|
||||
def wrapped_f(*args):
|
||||
print 'Inside wrapped_f()'
|
||||
print 'Decorator arguments:', arg1, arg2, arg3
|
||||
f(*args)
|
||||
print 'After f(*args)'
|
||||
return wrapped_f
|
||||
return wwrap
|
||||
"
|
||||
(goto-char (point-min))
|
||||
(should (= (save-excursion (python-nav-forward-defun))
|
||||
(python-tests-look-at "(arg1, arg2, arg3):")))
|
||||
(should (= (save-excursion (python-nav-forward-defun))
|
||||
(python-tests-look-at "(f):")))
|
||||
(should (= (save-excursion (python-nav-forward-defun))
|
||||
(python-tests-look-at "(*args):")))
|
||||
(should (not (python-nav-forward-defun)))))
|
||||
|
||||
(ert-deftest python-nav-forward-defun-3 ()
|
||||
(python-tests-with-temp-buffer
|
||||
"
|
||||
class A(object):
|
||||
pass
|
||||
|
||||
'''
|
||||
def u(self):
|
||||
pass
|
||||
|
||||
def v(self):
|
||||
pass
|
||||
|
||||
def w(self):
|
||||
pass
|
||||
'''
|
||||
"
|
||||
(goto-char (point-min))
|
||||
(let ((point (python-tests-look-at "(object):")))
|
||||
(should (not (python-nav-forward-defun)))
|
||||
(should (= point (point))))))
|
||||
|
||||
(ert-deftest python-nav-beginning-of-statement-1 ()
|
||||
(python-tests-with-temp-buffer
|
||||
"
|
||||
|
|
Loading…
Add table
Reference in a new issue