* lisp/progmodes/python.el:

(python-nav--lisp-forward-sexp): New function.
(python-nav--lisp-forward-sexp-safe): Use it.  Rename from
python-nav-lisp-forward-sexp-safe.
(python-nav--forward-sexp): New argument SAFE allows switching
forward sexp movement behavior for parens.
(python-nav-forward-sexp): Throw errors on unterminated parens.
(python-nav-backward-sexp, python-nav-forward-sexp-safe)
(python-nav-backward-sexp-safe): New functions.
(python-shell-buffer-substring): Use
`python-nav-forward-sexp-safe'.

* test/automated/python-tests.el
(python-nav-lisp-forward-sexp-safe-1): Remove test.
(python-nav-forward-sexp-safe-1): New test.

Fixes: debbugs:16191
This commit is contained in:
Fabián Ezequiel Gallina 2013-12-25 15:07:31 -03:00
parent 99e4926fcb
commit 0137922173
4 changed files with 108 additions and 46 deletions

View file

@ -1,3 +1,18 @@
2013-12-25 Fabián Ezequiel Gallina <fgallina@gnu.org>
* progmodes/python.el:
(python-nav--lisp-forward-sexp): New function.
(python-nav--lisp-forward-sexp-safe): Use it. Rename from
python-nav-lisp-forward-sexp-safe.
(python-nav--forward-sexp): New argument SAFE allows switching
forward sexp movement behavior for parens.
(python-nav-forward-sexp): Throw errors on unterminated parens
(Bug#16191).
(python-nav-backward-sexp, python-nav-forward-sexp-safe)
(python-nav-backward-sexp-safe): New functions.
(python-shell-buffer-substring): Use
`python-nav-forward-sexp-safe'.
2013-12-25 Lars Ingebrigtsen <larsi@gnus.org>
* net/shr.el (shr-find-fill-point): Don't break lines before a

View file

@ -1424,25 +1424,36 @@ backward to previous block."
(and (goto-char starting-pos) nil)
(and (not (= (point) starting-pos)) (point-marker)))))
(defun python-nav-lisp-forward-sexp-safe (&optional arg)
"Safe version of standard `forward-sexp'.
When ARG > 0 move forward, else if ARG is < 0."
(or arg (setq arg 1))
(defun python-nav--lisp-forward-sexp (&optional arg)
"Standard version `forward-sexp'.
It ignores completely the value of `forward-sexp-function' by
setting it to nil before calling `forward-sexp'. With positive
ARG move forward only one sexp, else move backwards."
(let ((forward-sexp-function)
(paren-regexp
(if (> arg 0) (python-rx close-paren) (python-rx open-paren)))
(search-fn
(if (> arg 0) #'re-search-forward #'re-search-backward)))
(arg (if (or (not arg) (> arg 0)) 1 -1)))
(forward-sexp arg)))
(defun python-nav--lisp-forward-sexp-safe (&optional arg)
"Safe version of standard `forward-sexp'.
When at end of sexp (i.e. looking at a opening/closing paren)
skips it instead of throwing an error. With positive ARG move
forward only one sexp, else move backwards."
(let* ((arg (if (or (not arg) (> arg 0)) 1 -1))
(paren-regexp
(if (> arg 0) (python-rx close-paren) (python-rx open-paren)))
(search-fn
(if (> arg 0) #'re-search-forward #'re-search-backward)))
(condition-case nil
(forward-sexp arg)
(python-nav--lisp-forward-sexp arg)
(error
(while (and (funcall search-fn paren-regexp nil t)
(python-syntax-context 'paren)))))))
(defun python-nav--forward-sexp (&optional dir)
(defun python-nav--forward-sexp (&optional dir safe)
"Move to forward sexp.
With positive Optional argument DIR direction move forward, else
backwards."
With positive optional argument DIR direction move forward, else
backwards. When optional argument SAFE is non-nil do not throw
errors when at end of sexp, skip it instead."
(setq dir (or dir 1))
(unless (= dir 0)
(let* ((forward-p (if (> dir 0)
@ -1460,7 +1471,9 @@ backwards."
(eq (syntax-class (syntax-after (1- (point))))
(car (string-to-syntax ")")))))
;; Inside a paren or looking at it, lisp knows what to do.
(python-nav-lisp-forward-sexp-safe dir))
(if safe
(python-nav--lisp-forward-sexp-safe dir)
(python-nav--lisp-forward-sexp dir)))
(t
;; This part handles the lispy feel of
;; `python-nav-forward-sexp'. Knowing everything about the
@ -1474,7 +1487,9 @@ backwards."
((python-info-end-of-statement-p) 'statement-end)))
(next-sexp-pos
(save-excursion
(python-nav-lisp-forward-sexp-safe dir)
(if safe
(python-nav--lisp-forward-sexp-safe dir)
(python-nav--lisp-forward-sexp dir))
(point)))
(next-sexp-context
(save-excursion
@ -1528,23 +1543,48 @@ backwards."
(python-nav-beginning-of-statement))
(t (goto-char next-sexp-pos))))))))))
(defun python-nav--backward-sexp ()
"Move to backward sexp."
(python-nav--forward-sexp -1))
(defun python-nav-forward-sexp (&optional arg)
"Move forward across one block of code.
With ARG, do it that many times. Negative arg -N means
move backward N times."
"Move forward across expressions.
With ARG, do it that many times. Negative arg -N means move
backward N times."
(interactive "^p")
(or arg (setq arg 1))
(while (> arg 0)
(python-nav--forward-sexp)
(python-nav--forward-sexp 1)
(setq arg (1- arg)))
(while (< arg 0)
(python-nav--backward-sexp)
(python-nav--forward-sexp -1)
(setq arg (1+ arg))))
(defun python-nav-backward-sexp (&optional arg)
"Move backward across expressions.
With ARG, do it that many times. Negative arg -N means move
backward N times."
(interactive "^p")
(or arg (setq arg 1))
(python-nav-forward-sexp (- arg)))
(defun python-nav-forward-sexp-safe (&optional arg)
"Move forward safely across expressions.
With ARG, do it that many times. Negative arg -N means move
backward N times."
(interactive "^p")
(or arg (setq arg 1))
(while (> arg 0)
(python-nav--forward-sexp 1 t)
(setq arg (1- arg)))
(while (< arg 0)
(python-nav--forward-sexp -1 t)
(setq arg (1+ arg))))
(defun python-nav-backward-sexp-safe (&optional arg)
"Move backward safely across expressions.
With ARG, do it that many times. Negative arg -N means move
backward N times."
(interactive "^p")
(or arg (setq arg 1))
(python-nav-forward-sexp-safe (- arg)))
(defun python-nav--up-list (&optional dir)
"Internal implementation of `python-nav-up-list'.
DIR is always 1 or -1 and comes sanitized from
@ -2212,7 +2252,7 @@ the python shell:
(save-excursion
(when (python-nav-if-name-main)
(cons (point)
(progn (python-nav-forward-sexp)
(progn (python-nav-forward-sexp-safe)
(point)))))))
;; Oh destructuring bind, how I miss you.
(if-name-main-start (car if-name-main-start-end))

View file

@ -1,3 +1,9 @@
2013-12-25 Fabián Ezequiel Gallina <fgallina@gnu.org>
* automated/python-tests.el
(python-nav-lisp-forward-sexp-safe-1): Remove test.
(python-nav-forward-sexp-safe-1): New test.
2013-12-20 Dmitry Gutov <dgutov@yandex.ru>
* automated/ruby-mode-tests.el: Add tests for

View file

@ -1339,28 +1339,6 @@ if request.user.is_authenticated():
(python-tests-look-at
"if request.user.is_authenticated():" -1)))))
(ert-deftest python-nav-lisp-forward-sexp-safe-1 ()
(python-tests-with-temp-buffer
"
profile = Profile.objects.create(user=request.user)
profile.notify()
"
(python-tests-look-at "profile =")
(python-nav-lisp-forward-sexp-safe 4)
(should (looking-at "(user=request.user)"))
(python-tests-look-at "user=request.user")
(python-nav-lisp-forward-sexp-safe -1)
(should (looking-at "(user=request.user)"))
(python-nav-lisp-forward-sexp-safe -4)
(should (looking-at "profile ="))
(python-tests-look-at "user=request.user")
(python-nav-lisp-forward-sexp-safe 3)
(should (looking-at ")"))
(python-nav-lisp-forward-sexp-safe 1)
(should (looking-at "$"))
(python-nav-lisp-forward-sexp-safe 1)
(should (looking-at ".notify()"))))
(ert-deftest python-nav-forward-sexp-1 ()
(python-tests-with-temp-buffer
"
@ -1477,6 +1455,29 @@ def another_statement():
(python-nav-forward-sexp -1)
(should (looking-at "from some_module import some_sub_module"))))
(ert-deftest python-nav-forward-sexp-safe-1 ()
(python-tests-with-temp-buffer
"
profile = Profile.objects.create(user=request.user)
profile.notify()
"
(python-tests-look-at "profile =")
(python-nav-forward-sexp-safe 1)
(should (looking-at "$"))
(beginning-of-line 1)
(python-tests-look-at "user=request.user")
(python-nav-forward-sexp-safe -1)
(should (looking-at "(user=request.user)"))
(python-nav-forward-sexp-safe -4)
(should (looking-at "profile ="))
(python-tests-look-at "user=request.user")
(python-nav-forward-sexp-safe 3)
(should (looking-at ")"))
(python-nav-forward-sexp-safe 1)
(should (looking-at "$"))
(python-nav-forward-sexp-safe 1)
(should (looking-at "$"))))
(ert-deftest python-nav-up-list-1 ()
(python-tests-with-temp-buffer
"