1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-25 07:28:20 +00:00

Add a new user option in Python mode to improve the indentation

* lisp/progmodes/python.el (python-indent-block-paren-deeper): New
user option.
(python-indent-context): Add a new context :inside-paren-from-block.
(python-indent--calculate-indentation): Modify according to
`python-indent-block-paren-deeper' and :inside-paren-from-block.
* test/lisp/progmodes/python-tests.el
(python-indent-inside-paren-block-1)
(python-indent-inside-paren-block-2)
(python-indent-inside-paren-block-3)
(python-indent-inside-paren-block-4): New tests.
(python-indent-inside-paren-5, python-indent-dedenters-8): Modify
according to the new context.
* etc/NEWS: Document the new user option.  (Bug#62696)
This commit is contained in:
kobarity 2023-04-16 22:18:39 +09:00 committed by Eli Zaretskii
parent 2f013c46f7
commit 711e8bc717
3 changed files with 181 additions and 9 deletions

View File

@ -280,6 +280,23 @@ distracting and easily confused with actual code, or a significant
early aid that relieves you from moving the buffer or reaching for the
mouse to consult an error message.
** Python mode
*** New user option 'python-indent-block-paren-deeper'.
If non-nil, increase the indentation of the lines inside parens in a
header of a block when they are indented to the same level as the body
of the block:
if (some_expression
and another_expression):
do_something()
instead of:
if (some_expression
and another_expression):
do_something()
* New Modes and Packages in Emacs 30.1

View File

@ -1270,6 +1270,31 @@ For NODE, OVERRIDE, START, END, and ARGS, see
:type 'integer
:safe 'natnump)
(defcustom python-indent-block-paren-deeper nil
"Increase indentation inside parens of a block.
If non-nil, increase the indentation of the lines inside parens
in a header of a block when they are indented to the same level
as the body of the block:
if (some_expression
and another_expression):
do_something()
instead of:
if (some_expression
and another_expression):
do_something()
This variable only works if the opening paren is followed by
non-whitespace characters on the same line. Modify
`python-indent-def-block-scale' to customize the case where
non-whitespace character does not follow the opening paren on the
same line."
:version "30.1"
:type 'boolean
:safe 'booleanp)
(defvar python-indent-current-level 0
"Deprecated var available for compatibility.")
@ -1367,6 +1392,10 @@ keyword
- Point is inside a paren with items starting in their own line
from a block start.
- START is the position of the open paren.
:inside-paren-from-block
- Point is inside a paren from a block start followed by some
items on the same line.
- START is the first non space char position *after* the open paren.
:after-backslash
- Fallback case when point is after backslash.
@ -1450,12 +1479,16 @@ keyword
(starts-in-newline
(cons :inside-paren-newline-start start))
;; General case.
(t (cons :inside-paren
(save-excursion
(goto-char (1+ start))
(skip-syntax-forward "(" 1)
(skip-syntax-forward " ")
(point))))))))
(t (let ((after-start (save-excursion
(goto-char (1+ start))
(skip-syntax-forward "(" 1)
(skip-syntax-forward " ")
(point))))
(if (save-excursion
(python-nav-beginning-of-statement)
(python-info-looking-at-beginning-of-block))
(cons :inside-paren-from-block after-start)
(cons :inside-paren after-start))))))))
;; After backslash.
((let ((start (when (not (python-syntax-comment-or-string-p ppss))
(python-info-line-ends-backslash-p
@ -1603,7 +1636,17 @@ possibilities can be narrowed to specific indentation points."
(`(,(or :inside-paren-newline-start-from-block) . ,start)
(goto-char start)
(+ (current-indentation)
(* python-indent-offset python-indent-def-block-scale))))))
(* python-indent-offset python-indent-def-block-scale)))
(`(,:inside-paren-from-block . ,start)
(goto-char start)
(let ((column (current-column)))
(if (and python-indent-block-paren-deeper
(= column (+ (save-excursion
(python-nav-beginning-of-statement)
(current-indentation))
python-indent-offset)))
(+ column python-indent-offset)
column))))))
(defun python-indent--calculate-levels (indentation)
"Calculate levels list given INDENTATION.

View File

@ -1139,7 +1139,7 @@ while ((not some_condition) and
(should (eq (car (python-indent-context)) :no-indent))
(should (= (python-indent-calculate-indentation) 0))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-from-block))
(should (= (python-indent-calculate-indentation) 7))
(forward-line 1)
(should (eq (car (python-indent-context)) :after-block-start))
@ -1174,6 +1174,118 @@ CHOICES = (('some', 'choice'),
;; This signals an error if the test fails
(should (eq (car (python-indent-context)) :inside-paren-newline-start))))
(ert-deftest python-indent-inside-paren-block-1 ()
"`python-indent-block-paren-deeper' set to nil (default).
See Bug#62696."
(python-tests-with-temp-buffer
"
if ('VALUE' in my_unnecessarily_long_dictionary and
some_other_long_condition_case):
do_something()
elif (some_case or
another_case):
do_another()
"
(python-tests-look-at "if")
(should (eq (car (python-indent-context)) :no-indent))
(should (= (python-indent-calculate-indentation) 0))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren-from-block))
(should (= (python-indent-calculate-indentation) 4))
(forward-line 1)
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))
(forward-line 1)
(should (eq (car (python-indent-context)) :at-dedenter-block-start))
(should (= (python-indent-calculate-indentation) 0))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren-from-block))
(should (= (python-indent-calculate-indentation) 6))
(forward-line 1)
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))))
(ert-deftest python-indent-inside-paren-block-2 ()
"`python-indent-block-paren-deeper' set to t.
See Bug#62696."
(python-tests-with-temp-buffer
"
if ('VALUE' in my_unnecessarily_long_dictionary and
some_other_long_condition_case):
do_something()
elif (some_case or
another_case):
do_another()
"
(let ((python-indent-block-paren-deeper t))
(python-tests-look-at "if")
(should (eq (car (python-indent-context)) :no-indent))
(should (= (python-indent-calculate-indentation) 0))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren-from-block))
(should (= (python-indent-calculate-indentation) 8))
(forward-line 1)
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))
(forward-line 1)
(should (eq (car (python-indent-context)) :at-dedenter-block-start))
(should (= (python-indent-calculate-indentation) 0))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren-from-block))
(should (= (python-indent-calculate-indentation) 6))
(forward-line 1)
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4)))))
(ert-deftest python-indent-inside-paren-block-3 ()
"With backslash. `python-indent-block-paren-deeper' set to nil (default).
See Bug#62696."
(python-tests-with-temp-buffer
"
if 'VALUE' in my_uncessarily_long_dictionary and\\
(some_other_long_condition_case or
another_case):
do_something()
"
(python-tests-look-at "if")
(should (eq (car (python-indent-context)) :no-indent))
(should (= (python-indent-calculate-indentation) 0))
(forward-line 1)
(should (eq (car (python-indent-context))
:after-backslash-block-continuation))
(should (= (python-indent-calculate-indentation) 3))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren-from-block))
(should (= (python-indent-calculate-indentation) 4))
(forward-line 1)
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4))))
(ert-deftest python-indent-inside-paren-block-4 ()
"With backslash. `python-indent-block-paren-deeper' set to t.
See Bug#62696."
(python-tests-with-temp-buffer
"
if 'VALUE' in my_uncessarily_long_dictionary and\\
(some_other_long_condition_case or
another_case):
do_something()
"
(let ((python-indent-block-paren-deeper t))
(python-tests-look-at "if")
(should (eq (car (python-indent-context)) :no-indent))
(should (= (python-indent-calculate-indentation) 0))
(forward-line 1)
(should (eq (car (python-indent-context))
:after-backslash-block-continuation))
(should (= (python-indent-calculate-indentation) 3))
(forward-line 1)
(should (eq (car (python-indent-context)) :inside-paren-from-block))
(should (= (python-indent-calculate-indentation) 8))
(forward-line 1)
(should (eq (car (python-indent-context)) :after-block-start))
(should (= (python-indent-calculate-indentation) 4)))))
(ert-deftest python-indent-after-block-1 ()
"The most simple after-block case that shouldn't fail."
(python-tests-with-temp-buffer
@ -1670,7 +1782,7 @@ a == 4):
(should (= (python-indent-calculate-indentation) 0))
(should (= (python-indent-calculate-indentation t) 0))
(python-tests-look-at "a == 4):\n")
(should (eq (car (python-indent-context)) :inside-paren))
(should (eq (car (python-indent-context)) :inside-paren-from-block))
(should (= (python-indent-calculate-indentation) 6))
(python-indent-line)
(should (= (python-indent-calculate-indentation t) 4))