From 6e2f9dd3dd8b3c65608366039ce69666905d80cb Mon Sep 17 00:00:00 2001 From: kobarity Date: Sun, 3 Jul 2022 14:22:13 +0200 Subject: [PATCH] Fix `python-nav-beginning-of-defun' line continuation using backslash * lisp/progmodes/python.el (python-nav--beginning-of-defun): Allow line continuation using backslash in defuns (bug#55702). (python-info-looking-at-beginning-of-defun): Add CHECK-STATEMENT argument. --- lisp/progmodes/python.el | 25 ++++++--- test/lisp/progmodes/python-tests.el | 81 ++++++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 9 deletions(-) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 16cdf58611a..7a626ae35ee 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -1472,15 +1472,17 @@ With positive ARG search backwards, else search forwards." 0)))) (found (progn - (when (and (python-info-looking-at-beginning-of-defun) + (when (and (python-info-looking-at-beginning-of-defun nil t) (or (< arg 0) ;; If looking at beginning of defun, and if ;; pos is > line-content-start, ensure a ;; backward re search match this defun by ;; going to end of line before calling ;; re-search-fn bug#40563 - (and (> arg 0) (> pos line-content-start)))) - (end-of-line 1)) + (and (> arg 0) + (or (python-info-continuation-line-p) + (> pos line-content-start))))) + (python-nav-end-of-statement)) (while (and (funcall re-search-fn python-nav-beginning-of-defun-regexp nil t) @@ -1490,14 +1492,18 @@ With positive ARG search backwards, else search forwards." (and (> arg 0) (not (= (current-indentation) 0)) (>= (current-indentation) body-indentation))))) - (and (python-info-looking-at-beginning-of-defun) + (and (python-info-looking-at-beginning-of-defun nil t) (or (not (= (line-number-at-pos pos) (line-number-at-pos))) (and (>= (point) line-beg-pos) (<= (point) line-content-start) (> pos line-content-start))))))) (if found - (or (beginning-of-line 1) t) + (progn + (when (< arg 0) + (python-nav-beginning-of-statement)) + (beginning-of-line 1) + t) (and (goto-char pos) nil)))) (defun python-nav-beginning-of-defun (&optional arg) @@ -5299,10 +5305,15 @@ operator." (forward-line -1) (python-info-assignment-statement-p t)))) -(defun python-info-looking-at-beginning-of-defun (&optional syntax-ppss) - "Check if point is at `beginning-of-defun' using SYNTAX-PPSS." +(defun python-info-looking-at-beginning-of-defun (&optional syntax-ppss + check-statement) + "Check if point is at `beginning-of-defun' using SYNTAX-PPSS. +When CHECK-STATEMENT is non-nil, the current statement is checked +instead of the current physical line." (and (not (python-syntax-context-type (or syntax-ppss (syntax-ppss)))) (save-excursion + (when check-statement + (python-nav-beginning-of-statement)) (beginning-of-line 1) (looking-at python-nav-beginning-of-defun-regexp)))) diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index c59a2e79533..d7b3c102f2d 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -1757,6 +1757,36 @@ def foo(x): (should (= (marker-position (mark-marker)) expected-mark-end-position))))) +(ert-deftest python-mark-defun-5 () + "Test `python-mark-defun' with point inside backslash escaped defun." + (python-tests-with-temp-buffer + " +def \\ + foo(x): + return x +" + (let ((transient-mark-mode t) + (expected-mark-beginning-position + (progn + (python-tests-look-at "def ") + (1- (line-beginning-position)))) + (expected-mark-end-position + (save-excursion + (python-tests-look-at "return x") + (forward-line) + (point)))) + (python-tests-look-at "def ") + (python-mark-defun 1) + (should (= (point) expected-mark-beginning-position)) + (should (= (marker-position (mark-marker)) + expected-mark-end-position)) + (deactivate-mark) + (python-tests-look-at "foo(x)") + (python-mark-defun 1) + (should (= (point) expected-mark-beginning-position)) + (should (= (marker-position (mark-marker)) + expected-mark-end-position))))) + ;;; Navigation @@ -1905,17 +1935,47 @@ class C(object): (ert-deftest python-nav-beginning-of-defun-4 () (python-tests-with-temp-buffer " +def a(): + pass + def \\ - a(): + b(): return 0 + +def c(): + pass " - (python-tests-look-at "return 0") + (python-tests-look-at "def c():") + (should (= (save-excursion + (python-nav-beginning-of-defun) + (point)) + (save-excursion + (python-tests-look-at "def \\" -1) + (beginning-of-line) + (point)))) + (python-tests-look-at "return 0" -1) (should (= (save-excursion (python-nav-beginning-of-defun) (point)) (save-excursion (python-tests-look-at "def \\" -1) (beginning-of-line) + (point)))) + (python-tests-look-at "b():" -1) + (should (= (save-excursion + (python-nav-beginning-of-defun) + (point)) + (save-excursion + (python-tests-look-at "def \\" -1) + (beginning-of-line) + (point)))) + (python-tests-look-at "def a():" -1) + (should (= (save-excursion + (python-nav-beginning-of-defun -1) + (point)) + (save-excursion + (python-tests-look-at "def \\") + (beginning-of-line) (point)))))) (ert-deftest python-nav-end-of-defun-1 () @@ -5242,6 +5302,23 @@ def decorat0r(deff): (python-tests-look-at "deff()") (should (not (python-info-looking-at-beginning-of-defun))))) +(ert-deftest python-info-looking-at-beginning-of-defun-2 () + (python-tests-with-temp-buffer + " +def \\ + foo(arg): + pass +" + (python-tests-look-at "def \\") + (should (python-info-looking-at-beginning-of-defun)) + (should (python-info-looking-at-beginning-of-defun nil t)) + (python-tests-look-at "foo(arg):") + (should (not (python-info-looking-at-beginning-of-defun))) + (should (python-info-looking-at-beginning-of-defun nil t)) + (python-tests-look-at "pass") + (should (not (python-info-looking-at-beginning-of-defun))) + (should (not (python-info-looking-at-beginning-of-defun nil t))))) + (ert-deftest python-info-current-line-comment-p-1 () (python-tests-with-temp-buffer " -- 2.39.2