aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabián Ezequiel Gallina2014-07-09 00:55:53 -0300
committerFabián Ezequiel Gallina2014-07-09 00:55:53 -0300
commitfded0b4a15d4ec7f92a64f03e9aa78f19a9b6031 (patch)
tree5c88e13a1348c09d6c641ac53f970eadb2819d97
parentd8899d09b992d733dc1cc6ec93b11cb75ce84f5d (diff)
downloademacs-fded0b4a15d4ec7f92a64f03e9aa78f19a9b6031.tar.gz
emacs-fded0b4a15d4ec7f92a64f03e9aa78f19a9b6031.zip
Fix dedenters and electric colon handling.
* lisp/progmodes/python.el (python-rx-constituents): Add dedenter and block-ender. (python-indent-dedenters, python-indent-block-enders): Delete. (python-indent-context): Return new case for dedenter-statement. (python-indent-calculate-indentation): Handle new case. (python-indent-calculate-levels): Fix levels calculation for dedenter statements. (python-indent-post-self-insert-function): Fix colon handling. (python-info-dedenter-opening-block-message): New function. (python-indent-line): Use it. (python-info-closing-block) (python-info-closing-block-message): Remove. (python-info-dedenter-opening-block-position) (python-info-dedenter-opening-block-positions) (python-info-dedenter-statement-p): New functions. * test/automated/python-tests.el (python-indent-block-enders-1) (python-indent-block-enders-2): Fix tests. (python-indent-block-enders-3) (python-indent-block-enders-4) (python-indent-block-enders-5) (python-indent-dedenters-1) (python-indent-dedenters-2): Remove tests. (python-indent-dedenters-1) (python-indent-dedenters-2) (python-indent-dedenters-3) (python-indent-dedenters-4) (python-indent-dedenters-5) (python-indent-dedenters-6) (python-indent-dedenters-7) (python-info-dedenter-opening-block-position-1) (python-info-dedenter-opening-block-position-2) (python-info-dedenter-opening-block-position-3) (python-info-dedenter-opening-block-positions-1) (python-info-dedenter-opening-block-positions-2) (python-info-dedenter-opening-block-positions-3) (python-info-dedenter-opening-block-positions-4) (python-info-dedenter-opening-block-positions-5) (python-info-dedenter-opening-block-message-1) (python-info-dedenter-opening-block-message-2) (python-info-dedenter-opening-block-message-3) (python-info-dedenter-opening-block-message-4) (python-info-dedenter-opening-block-message-5) (python-info-dedenter-statement-p-1) (python-info-dedenter-statement-p-2) (python-info-dedenter-statement-p-3) (python-info-dedenter-statement-p-4) (python-info-dedenter-statement-p-5): New tests. Fixes: debbugs:15163
-rw-r--r--lisp/ChangeLog20
-rw-r--r--lisp/progmodes/python.el204
-rw-r--r--test/ChangeLog37
-rw-r--r--test/automated/python-tests.el750
4 files changed, 816 insertions, 195 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 0333e366beb..5bf133af77a 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,23 @@
12014-07-09 Fabián Ezequiel Gallina <fgallina@gnu.org>
2
3 Fix dedenters and electric colon handling. (Bug#15163)
4
5 * progmodes/python.el
6 (python-rx-constituents): Add dedenter and block-ender.
7 (python-indent-dedenters, python-indent-block-enders): Delete.
8 (python-indent-context): Return new case for dedenter-statement.
9 (python-indent-calculate-indentation): Handle new case.
10 (python-indent-calculate-levels): Fix levels calculation for
11 dedenter statements.
12 (python-indent-post-self-insert-function): Fix colon handling.
13 (python-info-dedenter-opening-block-message): New function.
14 (python-indent-line): Use it.
15 (python-info-closing-block)
16 (python-info-closing-block-message): Remove.
17 (python-info-dedenter-opening-block-position)
18 (python-info-dedenter-opening-block-positions)
19 (python-info-dedenter-statement-p): New functions.
20
12014-07-08 Stefan Monnier <monnier@iro.umontreal.ca> 212014-07-08 Stefan Monnier <monnier@iro.umontreal.ca>
2 22
3 * progmodes/sh-script.el (sh-smie-sh-rules): Don't align with a && in 23 * progmodes/sh-script.el (sh-smie-sh-rules): Don't align with a && in
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 2301db8ecf6..237302f0530 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -322,6 +322,13 @@
322 (or "def" "class" "if" "elif" "else" "try" 322 (or "def" "class" "if" "elif" "else" "try"
323 "except" "finally" "for" "while" "with") 323 "except" "finally" "for" "while" "with")
324 symbol-end)) 324 symbol-end))
325 (dedenter . ,(rx symbol-start
326 (or "elif" "else" "except" "finally")
327 symbol-end))
328 (block-ender . ,(rx symbol-start
329 (or
330 "break" "continue" "pass" "raise" "return")
331 symbol-end))
325 (decorator . ,(rx line-start (* space) ?@ (any letter ?_) 332 (decorator . ,(rx line-start (* space) ?@ (any letter ?_)
326 (* (any word ?_)))) 333 (* (any word ?_))))
327 (defun . ,(rx symbol-start (or "def" "class") symbol-end)) 334 (defun . ,(rx symbol-start (or "def" "class") symbol-end))
@@ -631,18 +638,6 @@ It makes underscores and dots word constituent chars.")
631(defvar python-indent-levels '(0) 638(defvar python-indent-levels '(0)
632 "Levels of indentation available for `python-indent-line-function'.") 639 "Levels of indentation available for `python-indent-line-function'.")
633 640
634(defvar python-indent-dedenters '("else" "elif" "except" "finally")
635 "List of words that should be dedented.
636These make `python-indent-calculate-indentation' subtract the value of
637`python-indent-offset'.")
638
639(defvar python-indent-block-enders
640 '("break" "continue" "pass" "raise" "return")
641 "List of words that mark the end of a block.
642These make `python-indent-calculate-indentation' subtract the
643value of `python-indent-offset' when `python-indent-context' is
644AFTER-LINE.")
645
646(defun python-indent-guess-indent-offset () 641(defun python-indent-guess-indent-offset ()
647 "Guess and set `python-indent-offset' for the current buffer." 642 "Guess and set `python-indent-offset' for the current buffer."
648 (interactive) 643 (interactive)
@@ -693,6 +688,7 @@ Where status can be any of the following symbols:
693 * after-backslash: Previous line ends in a backslash 688 * after-backslash: Previous line ends in a backslash
694 * after-beginning-of-block: Point is after beginning of block 689 * after-beginning-of-block: Point is after beginning of block
695 * after-line: Point is after normal line 690 * after-line: Point is after normal line
691 * dedenter-statement: Point is on a dedenter statement.
696 * no-indent: Point is at beginning of buffer or other special case 692 * no-indent: Point is at beginning of buffer or other special case
697START is the buffer position where the sexp starts." 693START is the buffer position where the sexp starts."
698 (save-restriction 694 (save-restriction
@@ -747,6 +743,8 @@ START is the buffer position where the sexp starts."
747 (when (looking-at (python-rx block-start)) 743 (when (looking-at (python-rx block-start))
748 (point-marker))))) 744 (point-marker)))))
749 'after-beginning-of-block) 745 'after-beginning-of-block)
746 ((when (setq start (python-info-dedenter-statement-p))
747 'dedenter-statement))
750 ;; After normal line 748 ;; After normal line
751 ((setq start (save-excursion 749 ((setq start (save-excursion
752 (back-to-indentation) 750 (back-to-indentation)
@@ -777,8 +775,7 @@ START is the buffer position where the sexp starts."
777 (goto-char context-start) 775 (goto-char context-start)
778 (+ (current-indentation) python-indent-offset)) 776 (+ (current-indentation) python-indent-offset))
779 ;; When after a simple line just use previous line 777 ;; When after a simple line just use previous line
780 ;; indentation, in the case current line starts with a 778 ;; indentation.
781 ;; `python-indent-dedenters' de-indent one level.
782 (`after-line 779 (`after-line
783 (let* ((pair (save-excursion 780 (let* ((pair (save-excursion
784 (goto-char context-start) 781 (goto-char context-start)
@@ -786,25 +783,27 @@ START is the buffer position where the sexp starts."
786 (current-indentation) 783 (current-indentation)
787 (python-info-beginning-of-block-p)))) 784 (python-info-beginning-of-block-p))))
788 (context-indentation (car pair)) 785 (context-indentation (car pair))
789 (after-block-start-p (cdr pair)) 786 ;; TODO: Separate block enders into its own case.
790 (adjustment 787 (adjustment
791 (if (or (save-excursion 788 (if (save-excursion
792 (back-to-indentation) 789 (python-util-forward-comment -1)
793 (and 790 (python-nav-beginning-of-statement)
794 ;; De-indent only when dedenters are not 791 (looking-at (python-rx block-ender)))
795 ;; next to a block start. This allows
796 ;; one-liner constructs such as:
797 ;; if condition: print "yay"
798 ;; else: print "wry"
799 (not after-block-start-p)
800 (looking-at (regexp-opt python-indent-dedenters))))
801 (save-excursion
802 (python-util-forward-comment -1)
803 (python-nav-beginning-of-statement)
804 (looking-at (regexp-opt python-indent-block-enders))))
805 python-indent-offset 792 python-indent-offset
806 0))) 793 0)))
807 (- context-indentation adjustment))) 794 (- context-indentation adjustment)))
795 ;; When point is on a dedenter statement, search for the
796 ;; opening block that corresponds to it and use its
797 ;; indentation. If no opening block is found just remove
798 ;; indentation as this is an invalid python file.
799 (`dedenter-statement
800 (let ((block-start-point
801 (python-info-dedenter-opening-block-position)))
802 (save-excursion
803 (if (not block-start-point)
804 0
805 (goto-char block-start-point)
806 (current-indentation)))))
808 ;; When inside of a string, do nothing. just use the current 807 ;; When inside of a string, do nothing. just use the current
809 ;; indentation. XXX: perhaps it would be a good idea to 808 ;; indentation. XXX: perhaps it would be a good idea to
810 ;; invoke standard text indentation here 809 ;; invoke standard text indentation here
@@ -931,16 +930,25 @@ START is the buffer position where the sexp starts."
931 930
932(defun python-indent-calculate-levels () 931(defun python-indent-calculate-levels ()
933 "Calculate `python-indent-levels' and reset `python-indent-current-level'." 932 "Calculate `python-indent-levels' and reset `python-indent-current-level'."
934 (let* ((indentation (python-indent-calculate-indentation)) 933 (if (not (python-info-dedenter-statement-p))
935 (remainder (% indentation python-indent-offset)) 934 (let* ((indentation (python-indent-calculate-indentation))
936 (steps (/ (- indentation remainder) python-indent-offset))) 935 (remainder (% indentation python-indent-offset))
937 (setq python-indent-levels (list 0)) 936 (steps (/ (- indentation remainder) python-indent-offset)))
938 (dotimes (step steps) 937 (setq python-indent-levels (list 0))
939 (push (* python-indent-offset (1+ step)) python-indent-levels)) 938 (dotimes (step steps)
940 (when (not (eq 0 remainder)) 939 (push (* python-indent-offset (1+ step)) python-indent-levels))
941 (push (+ (* python-indent-offset steps) remainder) python-indent-levels)) 940 (when (not (eq 0 remainder))
942 (setq python-indent-levels (nreverse python-indent-levels)) 941 (push (+ (* python-indent-offset steps) remainder) python-indent-levels)))
943 (setq python-indent-current-level (1- (length python-indent-levels))))) 942 (setq python-indent-levels
943 (or
944 (mapcar (lambda (pos)
945 (save-excursion
946 (goto-char pos)
947 (current-indentation)))
948 (python-info-dedenter-opening-block-positions))
949 (list 0))))
950 (setq python-indent-current-level (1- (length python-indent-levels))
951 python-indent-levels (nreverse python-indent-levels)))
944 952
945(defun python-indent-toggle-levels () 953(defun python-indent-toggle-levels ()
946 "Toggle `python-indent-current-level' over `python-indent-levels'." 954 "Toggle `python-indent-current-level' over `python-indent-levels'."
@@ -989,7 +997,7 @@ equal to
989 (indent-to next-indent) 997 (indent-to next-indent)
990 (goto-char starting-pos)) 998 (goto-char starting-pos))
991 (and follow-indentation-p (back-to-indentation))) 999 (and follow-indentation-p (back-to-indentation)))
992 (python-info-closing-block-message)) 1000 (python-info-dedenter-opening-block-message))
993 1001
994(defun python-indent-line-function () 1002(defun python-indent-line-function ()
995 "`indent-line-function' for Python mode. 1003 "`indent-line-function' for Python mode.
@@ -1125,14 +1133,7 @@ the line will be re-indented automatically if needed."
1125 (eolp) 1133 (eolp)
1126 (not (equal ?: (char-before (1- (point))))) 1134 (not (equal ?: (char-before (1- (point)))))
1127 (not (python-syntax-comment-or-string-p))) 1135 (not (python-syntax-comment-or-string-p)))
1128 (let ((indentation (current-indentation)) 1136 (python-indent-line)))))
1129 (calculated-indentation (python-indent-calculate-indentation)))
1130 (python-info-closing-block-message)
1131 (when (> indentation calculated-indentation)
1132 (save-excursion
1133 (indent-line-to calculated-indentation)
1134 (when (not (python-info-closing-block-message))
1135 (indent-line-to indentation)))))))))
1136 1137
1137 1138
1138;;; Navigation 1139;;; Navigation
@@ -3450,49 +3451,88 @@ parent defun name."
3450 (and (python-info-end-of-statement-p) 3451 (and (python-info-end-of-statement-p)
3451 (python-info-statement-ends-block-p))) 3452 (python-info-statement-ends-block-p)))
3452 3453
3453(defun python-info-closing-block () 3454(define-obsolete-function-alias
3454 "Return the point of the block the current line closes." 3455 'python-info-closing-block
3455 (let ((closing-word (save-excursion 3456 'python-info-dedenter-opening-block-position "24.4")
3456 (back-to-indentation) 3457
3457 (current-word))) 3458(defun python-info-dedenter-opening-block-position ()
3458 (indentation (current-indentation))) 3459 "Return the point of the closest block the current line closes.
3459 (when (member closing-word python-indent-dedenters) 3460Returns nil if point is not on a dedenter statement or no opening
3461block can be detected. The latter case meaning current file is
3462likely an invalid python file."
3463 (let ((positions (python-info-dedenter-opening-block-positions))
3464 (indentation (current-indentation))
3465 (position))
3466 (while (and (not position)
3467 positions)
3460 (save-excursion 3468 (save-excursion
3461 (forward-line -1) 3469 (goto-char (car positions))
3462 (while (and (> (current-indentation) indentation) 3470 (if (<= (current-indentation) indentation)
3463 (not (bobp)) 3471 (setq position (car positions))
3464 (not (back-to-indentation)) 3472 (setq positions (cdr positions)))))
3465 (forward-line -1))) 3473 position))
3466 (back-to-indentation) 3474
3467 (cond 3475(defun python-info-dedenter-opening-block-positions ()
3468 ((not (equal indentation (current-indentation))) nil) 3476 "Return points of blocks the current line may close sorted by closer.
3469 ((string= closing-word "elif") 3477Returns nil if point is not on a dedenter statement or no opening
3470 (when (member (current-word) '("if" "elif")) 3478block can be detected. The latter case meaning current file is
3471 (point-marker))) 3479likely an invalid python file."
3472 ((string= closing-word "else") 3480 (save-excursion
3473 (when (member (current-word) '("if" "elif" "except" "for" "while")) 3481 (let ((dedenter-pos (python-info-dedenter-statement-p)))
3474 (point-marker))) 3482 (when dedenter-pos
3475 ((string= closing-word "except") 3483 (goto-char dedenter-pos)
3476 (when (member (current-word) '("try")) 3484 (let* ((pairs '(("elif" "elif" "if")
3477 (point-marker))) 3485 ("else" "if" "elif" "except" "for" "while")
3478 ((string= closing-word "finally") 3486 ("except" "except" "try")
3479 (when (member (current-word) '("except" "else")) 3487 ("finally" "else" "except" "try")))
3480 (point-marker)))))))) 3488 (dedenter (match-string-no-properties 0))
3481 3489 (possible-opening-blocks (cdr (assoc-string dedenter pairs)))
3482(defun python-info-closing-block-message (&optional closing-block-point) 3490 (collected-indentations)
3483 "Message the contents of the block the current line closes. 3491 (opening-blocks))
3484With optional argument CLOSING-BLOCK-POINT use that instead of 3492 (catch 'exit
3485recalculating it calling `python-info-closing-block'." 3493 (while (python-nav--syntactically
3486 (let ((point (or closing-block-point (python-info-closing-block)))) 3494 (lambda ()
3495 (re-search-backward (python-rx block-start) nil t))
3496 #'<)
3497 (let ((indentation (current-indentation)))
3498 (when (and (not (memq indentation collected-indentations))
3499 (or (not collected-indentations)
3500 (< indentation (apply #'min collected-indentations))))
3501 (setq collected-indentations
3502 (cons indentation collected-indentations))
3503 (when (member (match-string-no-properties 0)
3504 possible-opening-blocks)
3505 (setq opening-blocks (cons (point) opening-blocks))))
3506 (when (zerop indentation)
3507 (throw 'exit nil)))))
3508 ;; sort by closer
3509 (nreverse opening-blocks))))))
3510
3511(define-obsolete-function-alias
3512 'python-info-closing-block-message
3513 'python-info-dedenter-opening-block-message "24.4")
3514
3515(defun python-info-dedenter-opening-block-message ()
3516 "Message the first line of the block the current statement closes."
3517 (let ((point (python-info-dedenter-opening-block-position)))
3487 (when point 3518 (when point
3488 (save-restriction 3519 (save-restriction
3489 (widen) 3520 (widen)
3490 (message "Closes %s" (save-excursion 3521 (message "Closes %s" (save-excursion
3491 (goto-char point) 3522 (goto-char point)
3492 (back-to-indentation)
3493 (buffer-substring 3523 (buffer-substring
3494 (point) (line-end-position)))))))) 3524 (point) (line-end-position))))))))
3495 3525
3526(defun python-info-dedenter-statement-p ()
3527 "Return point if current statement is a dedenter.
3528Sets `match-data' to the keyword that starts the dedenter
3529statement."
3530 (save-excursion
3531 (python-nav-beginning-of-statement)
3532 (when (and (not (python-syntax-context-type))
3533 (looking-at (python-rx dedenter)))
3534 (point))))
3535
3496(defun python-info-line-ends-backslash-p (&optional line-number) 3536(defun python-info-line-ends-backslash-p (&optional line-number)
3497 "Return non-nil if current line ends with backslash. 3537 "Return non-nil if current line ends with backslash.
3498With optional argument LINE-NUMBER, check that line instead." 3538With optional argument LINE-NUMBER, check that line instead."
diff --git a/test/ChangeLog b/test/ChangeLog
index f93b553f341..cf4ddc83544 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,40 @@
12014-07-09 Fabián Ezequiel Gallina <fgallina@gnu.org>
2
3 * automated/python-tests.el
4 (python-indent-block-enders-1)
5 (python-indent-block-enders-2): Fix tests.
6 (python-indent-block-enders-3)
7 (python-indent-block-enders-4)
8 (python-indent-block-enders-5)
9 (python-indent-dedenters-1)
10 (python-indent-dedenters-2): Remove tests.
11 (python-indent-dedenters-1)
12 (python-indent-dedenters-2)
13 (python-indent-dedenters-3)
14 (python-indent-dedenters-4)
15 (python-indent-dedenters-5)
16 (python-indent-dedenters-6)
17 (python-indent-dedenters-7)
18 (python-info-dedenter-opening-block-position-1)
19 (python-info-dedenter-opening-block-position-2)
20 (python-info-dedenter-opening-block-position-3)
21 (python-info-dedenter-opening-block-positions-1)
22 (python-info-dedenter-opening-block-positions-2)
23 (python-info-dedenter-opening-block-positions-3)
24 (python-info-dedenter-opening-block-positions-4)
25 (python-info-dedenter-opening-block-positions-5)
26 (python-info-dedenter-opening-block-message-1)
27 (python-info-dedenter-opening-block-message-2)
28 (python-info-dedenter-opening-block-message-3)
29 (python-info-dedenter-opening-block-message-4)
30 (python-info-dedenter-opening-block-message-5)
31 (python-info-dedenter-statement-p-1)
32 (python-info-dedenter-statement-p-2)
33 (python-info-dedenter-statement-p-3)
34 (python-info-dedenter-statement-p-4)
35 (python-info-dedenter-statement-p-5): New tests.
36
37
12014-07-01 Fabián Ezequiel Gallina <fgallina@gnu.org> 382014-07-01 Fabián Ezequiel Gallina <fgallina@gnu.org>
2 39
3 * automated/python-tests.el 40 * automated/python-tests.el
diff --git a/test/automated/python-tests.el b/test/automated/python-tests.el
index a35242fe882..3a4eda36bfe 100644
--- a/test/automated/python-tests.el
+++ b/test/automated/python-tests.el
@@ -435,79 +435,6 @@ def foo(a, b, c={
435 (should (eq (car (python-indent-context)) 'after-beginning-of-block)) 435 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
436 (should (= (python-indent-calculate-indentation) 4)))) 436 (should (= (python-indent-calculate-indentation) 4))))
437 437
438(ert-deftest python-indent-dedenters-1 ()
439 "Check all dedenters."
440 (python-tests-with-temp-buffer
441 "
442def foo(a, b, c):
443 if a:
444 print (a)
445 elif b:
446 print (b)
447 else:
448 try:
449 print (c.pop())
450 except (IndexError, AttributeError):
451 print (c)
452 finally:
453 print ('nor a, nor b are true')
454"
455 (python-tests-look-at "if a:")
456 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
457 (should (= (python-indent-calculate-indentation) 4))
458 (python-tests-look-at "print (a)")
459 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
460 (should (= (python-indent-calculate-indentation) 8))
461 (python-tests-look-at "elif b:")
462 (should (eq (car (python-indent-context)) 'after-line))
463 (should (= (python-indent-calculate-indentation) 4))
464 (python-tests-look-at "print (b)")
465 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
466 (should (= (python-indent-calculate-indentation) 8))
467 (python-tests-look-at "else:")
468 (should (eq (car (python-indent-context)) 'after-line))
469 (should (= (python-indent-calculate-indentation) 4))
470 (python-tests-look-at "try:")
471 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
472 (should (= (python-indent-calculate-indentation) 8))
473 (python-tests-look-at "print (c.pop())")
474 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
475 (should (= (python-indent-calculate-indentation) 12))
476 (python-tests-look-at "except (IndexError, AttributeError):")
477 (should (eq (car (python-indent-context)) 'after-line))
478 (should (= (python-indent-calculate-indentation) 8))
479 (python-tests-look-at "print (c)")
480 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
481 (should (= (python-indent-calculate-indentation) 12))
482 (python-tests-look-at "finally:")
483 (should (eq (car (python-indent-context)) 'after-line))
484 (should (= (python-indent-calculate-indentation) 8))
485 (python-tests-look-at "print ('nor a, nor b are true')")
486 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
487 (should (= (python-indent-calculate-indentation) 12))))
488
489(ert-deftest python-indent-dedenters-2 ()
490 "Check one-liner block special case.."
491 (python-tests-with-temp-buffer
492 "
493cond = True
494if cond:
495
496 if cond: print 'True'
497else: print 'False'
498
499else:
500 return
501"
502 (python-tests-look-at "else: print 'False'")
503 ;; When a block has code after ":" it's just considered a simple
504 ;; line as that's a common thing to happen in one-liners.
505 (should (eq (car (python-indent-context)) 'after-line))
506 (should (= (python-indent-calculate-indentation) 4))
507 (python-tests-look-at "else:")
508 (should (eq (car (python-indent-context)) 'after-line))
509 (should (= (python-indent-calculate-indentation) 0))))
510
511(ert-deftest python-indent-after-backslash-1 () 438(ert-deftest python-indent-after-backslash-1 ()
512 "The most common case." 439 "The most common case."
513 (python-tests-with-temp-buffer 440 (python-tests-with-temp-buffer
@@ -575,9 +502,9 @@ objects = Thing.objects.all() \\\\
575 (should (= (python-indent-calculate-indentation) 0)))) 502 (should (= (python-indent-calculate-indentation) 0))))
576 503
577(ert-deftest python-indent-block-enders-1 () 504(ert-deftest python-indent-block-enders-1 ()
578 "Test `python-indent-block-enders' value honoring." 505 "Test de-indentation for pass keyword."
579 (python-tests-with-temp-buffer 506 (python-tests-with-temp-buffer
580 " 507 "
581Class foo(object): 508Class foo(object):
582 509
583 def bar(self): 510 def bar(self):
@@ -589,17 +516,17 @@ Class foo(object):
589 else: 516 else:
590 pass 517 pass
591" 518"
592 (python-tests-look-at "3)") 519 (python-tests-look-at "3)")
593 (forward-line 1) 520 (forward-line 1)
594 (should (= (python-indent-calculate-indentation) 8)) 521 (should (= (python-indent-calculate-indentation) 8))
595 (python-tests-look-at "pass") 522 (python-tests-look-at "pass")
596 (forward-line 1) 523 (forward-line 1)
597 (should (= (python-indent-calculate-indentation) 8)))) 524 (should (= (python-indent-calculate-indentation) 8))))
598 525
599(ert-deftest python-indent-block-enders-2 () 526(ert-deftest python-indent-block-enders-2 ()
600 "Test `python-indent-block-enders' value honoring." 527 "Test de-indentation for return keyword."
601 (python-tests-with-temp-buffer 528 (python-tests-with-temp-buffer
602 " 529 "
603Class foo(object): 530Class foo(object):
604 '''raise lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do 531 '''raise lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
605 532
@@ -612,10 +539,177 @@ Class foo(object):
612 2, 539 2,
613 3) 540 3)
614" 541"
615 (python-tests-look-at "def") 542 (python-tests-look-at "def")
616 (should (= (python-indent-calculate-indentation) 4)) 543 (should (= (python-indent-calculate-indentation) 4))
617 (python-tests-look-at "if") 544 (python-tests-look-at "if")
618 (should (= (python-indent-calculate-indentation) 8)))) 545 (should (= (python-indent-calculate-indentation) 8))
546 (python-tests-look-at "return")
547 (should (= (python-indent-calculate-indentation) 12))
548 (goto-char (point-max))
549 (should (= (python-indent-calculate-indentation) 8))))
550
551(ert-deftest python-indent-block-enders-3 ()
552 "Test de-indentation for continue keyword."
553 (python-tests-with-temp-buffer
554 "
555for element in lst:
556 if element is None:
557 continue
558"
559 (python-tests-look-at "if")
560 (should (= (python-indent-calculate-indentation) 4))
561 (python-tests-look-at "continue")
562 (should (= (python-indent-calculate-indentation) 8))
563 (forward-line 1)
564 (should (= (python-indent-calculate-indentation) 4))))
565
566(ert-deftest python-indent-block-enders-4 ()
567 "Test de-indentation for break keyword."
568 (python-tests-with-temp-buffer
569 "
570for element in lst:
571 if element is None:
572 break
573"
574 (python-tests-look-at "if")
575 (should (= (python-indent-calculate-indentation) 4))
576 (python-tests-look-at "break")
577 (should (= (python-indent-calculate-indentation) 8))
578 (forward-line 1)
579 (should (= (python-indent-calculate-indentation) 4))))
580
581(ert-deftest python-indent-block-enders-5 ()
582 "Test de-indentation for raise keyword."
583 (python-tests-with-temp-buffer
584 "
585for element in lst:
586 if element is None:
587 raise ValueError('Element cannot be None')
588"
589 (python-tests-look-at "if")
590 (should (= (python-indent-calculate-indentation) 4))
591 (python-tests-look-at "raise")
592 (should (= (python-indent-calculate-indentation) 8))
593 (forward-line 1)
594 (should (= (python-indent-calculate-indentation) 4))))
595
596(ert-deftest python-indent-dedenters-1 ()
597 "Test de-indentation for the elif keyword."
598 (python-tests-with-temp-buffer
599 "
600if save:
601 try:
602 write_to_disk(data)
603 finally:
604 cleanup()
605 elif
606"
607 (python-tests-look-at "elif\n")
608 (should (eq (car (python-indent-context)) 'dedenter-statement))
609 (should (= (python-indent-calculate-indentation) 0))
610 (should (equal (python-indent-calculate-levels) '(0)))))
611
612(ert-deftest python-indent-dedenters-2 ()
613 "Test de-indentation for the else keyword."
614 (python-tests-with-temp-buffer
615 "
616if save:
617 try:
618 write_to_disk(data)
619 except IOError:
620 msg = 'Error saving to disk'
621 message(msg)
622 logger.exception(msg)
623 except Exception:
624 if hide_details:
625 logger.exception('Unhandled exception')
626 else
627 finally:
628 data.free()
629"
630 (python-tests-look-at "else\n")
631 (should (eq (car (python-indent-context)) 'dedenter-statement))
632 (should (= (python-indent-calculate-indentation) 8))
633 (should (equal (python-indent-calculate-levels) '(0 4 8)))))
634
635(ert-deftest python-indent-dedenters-3 ()
636 "Test de-indentation for the except keyword."
637 (python-tests-with-temp-buffer
638 "
639if save:
640 try:
641 write_to_disk(data)
642 except
643"
644 (python-tests-look-at "except\n")
645 (should (eq (car (python-indent-context)) 'dedenter-statement))
646 (should (= (python-indent-calculate-indentation) 4))
647 (should (equal (python-indent-calculate-levels) '(4)))))
648
649(ert-deftest python-indent-dedenters-4 ()
650 "Test de-indentation for the finally keyword."
651 (python-tests-with-temp-buffer
652 "
653if save:
654 try:
655 write_to_disk(data)
656 finally
657"
658 (python-tests-look-at "finally\n")
659 (should (eq (car (python-indent-context)) 'dedenter-statement))
660 (should (= (python-indent-calculate-indentation) 4))
661 (should (equal (python-indent-calculate-levels) '(4)))))
662
663(ert-deftest python-indent-dedenters-5 ()
664 "Test invalid levels are skipped in a complex example."
665 (python-tests-with-temp-buffer
666 "
667if save:
668 try:
669 write_to_disk(data)
670 except IOError:
671 msg = 'Error saving to disk'
672 message(msg)
673 logger.exception(msg)
674 finally:
675 if cleanup:
676 do_cleanup()
677 else
678"
679 (python-tests-look-at "else\n")
680 (should (eq (car (python-indent-context)) 'dedenter-statement))
681 (should (= (python-indent-calculate-indentation) 8))
682 (should (equal (python-indent-calculate-levels) '(0 8)))))
683
684(ert-deftest python-indent-dedenters-6 ()
685 "Test indentation is zero when no opening block for dedenter."
686 (python-tests-with-temp-buffer
687 "
688try:
689 # if save:
690 write_to_disk(data)
691 else
692"
693 (python-tests-look-at "else\n")
694 (should (eq (car (python-indent-context)) 'dedenter-statement))
695 (should (= (python-indent-calculate-indentation) 0))
696 (should (equal (python-indent-calculate-levels) '(0)))))
697
698(ert-deftest python-indent-dedenters-7 ()
699 "Test indentation case from Bug#15163."
700 (python-tests-with-temp-buffer
701 "
702if a:
703 if b:
704 pass
705 else:
706 pass
707 else:
708"
709 (python-tests-look-at "else:" 2)
710 (should (eq (car (python-indent-context)) 'dedenter-statement))
711 (should (= (python-indent-calculate-indentation) 0))
712 (should (equal (python-indent-calculate-levels) '(0)))))
619 713
620 714
621;;; Navigation 715;;; Navigation
@@ -2428,9 +2522,9 @@ if width == 0 and height == 0 and \\\\
2428 (python-util-forward-comment -1) 2522 (python-util-forward-comment -1)
2429 (should (python-info-end-of-block-p)))) 2523 (should (python-info-end-of-block-p))))
2430 2524
2431(ert-deftest python-info-closing-block-1 () 2525(ert-deftest python-info-dedenter-opening-block-position-1 ()
2432 (python-tests-with-temp-buffer 2526 (python-tests-with-temp-buffer
2433 " 2527 "
2434if request.user.is_authenticated(): 2528if request.user.is_authenticated():
2435 try: 2529 try:
2436 profile = request.user.get_profile() 2530 profile = request.user.get_profile()
@@ -2445,26 +2539,26 @@ if request.user.is_authenticated():
2445 profile.views += 1 2539 profile.views += 1
2446 profile.save() 2540 profile.save()
2447" 2541"
2448 (python-tests-look-at "try:") 2542 (python-tests-look-at "try:")
2449 (should (not (python-info-closing-block))) 2543 (should (not (python-info-dedenter-opening-block-position)))
2450 (python-tests-look-at "except Profile.DoesNotExist:") 2544 (python-tests-look-at "except Profile.DoesNotExist:")
2451 (should (= (python-tests-look-at "try:" -1 t) 2545 (should (= (python-tests-look-at "try:" -1 t)
2452 (python-info-closing-block))) 2546 (python-info-dedenter-opening-block-position)))
2453 (python-tests-look-at "else:") 2547 (python-tests-look-at "else:")
2454 (should (= (python-tests-look-at "except Profile.DoesNotExist:" -1 t) 2548 (should (= (python-tests-look-at "except Profile.DoesNotExist:" -1 t)
2455 (python-info-closing-block))) 2549 (python-info-dedenter-opening-block-position)))
2456 (python-tests-look-at "if profile.stats:") 2550 (python-tests-look-at "if profile.stats:")
2457 (should (not (python-info-closing-block))) 2551 (should (not (python-info-dedenter-opening-block-position)))
2458 (python-tests-look-at "else:") 2552 (python-tests-look-at "else:")
2459 (should (= (python-tests-look-at "if profile.stats:" -1 t) 2553 (should (= (python-tests-look-at "if profile.stats:" -1 t)
2460 (python-info-closing-block))) 2554 (python-info-dedenter-opening-block-position)))
2461 (python-tests-look-at "finally:") 2555 (python-tests-look-at "finally:")
2462 (should (= (python-tests-look-at "else:" -2 t) 2556 (should (= (python-tests-look-at "else:" -2 t)
2463 (python-info-closing-block))))) 2557 (python-info-dedenter-opening-block-position)))))
2464 2558
2465(ert-deftest python-info-closing-block-2 () 2559(ert-deftest python-info-dedenter-opening-block-position-2 ()
2466 (python-tests-with-temp-buffer 2560 (python-tests-with-temp-buffer
2467 " 2561 "
2468if request.user.is_authenticated(): 2562if request.user.is_authenticated():
2469 profile = Profile.objects.get_or_create(user=request.user) 2563 profile = Profile.objects.get_or_create(user=request.user)
2470 if profile.stats: 2564 if profile.stats:
@@ -2475,10 +2569,440 @@ data = {
2475} 2569}
2476 'else' 2570 'else'
2477" 2571"
2478 (python-tests-look-at "'else': 'do it'") 2572 (python-tests-look-at "'else': 'do it'")
2479 (should (not (python-info-closing-block))) 2573 (should (not (python-info-dedenter-opening-block-position)))
2480 (python-tests-look-at "'else'") 2574 (python-tests-look-at "'else'")
2481 (should (not (python-info-closing-block))))) 2575 (should (not (python-info-dedenter-opening-block-position)))))
2576
2577(ert-deftest python-info-dedenter-opening-block-position-3 ()
2578 (python-tests-with-temp-buffer
2579 "
2580if save:
2581 try:
2582 write_to_disk(data)
2583 except IOError:
2584 msg = 'Error saving to disk'
2585 message(msg)
2586 logger.exception(msg)
2587 except Exception:
2588 if hide_details:
2589 logger.exception('Unhandled exception')
2590 else
2591 finally:
2592 data.free()
2593"
2594 (python-tests-look-at "try:")
2595 (should (not (python-info-dedenter-opening-block-position)))
2596
2597 (python-tests-look-at "except IOError:")
2598 (should (= (python-tests-look-at "try:" -1 t)
2599 (python-info-dedenter-opening-block-position)))
2600
2601 (python-tests-look-at "except Exception:")
2602 (should (= (python-tests-look-at "except IOError:" -1 t)
2603 (python-info-dedenter-opening-block-position)))
2604
2605 (python-tests-look-at "if hide_details:")
2606 (should (not (python-info-dedenter-opening-block-position)))
2607
2608 ;; check indentation modifies the detected opening block
2609 (python-tests-look-at "else")
2610 (should (= (python-tests-look-at "if hide_details:" -1 t)
2611 (python-info-dedenter-opening-block-position)))
2612
2613 (indent-line-to 8)
2614 (should (= (python-tests-look-at "if hide_details:" -1 t)
2615 (python-info-dedenter-opening-block-position)))
2616
2617 (indent-line-to 4)
2618 (should (= (python-tests-look-at "except Exception:" -1 t)
2619 (python-info-dedenter-opening-block-position)))
2620
2621 (indent-line-to 0)
2622 (should (= (python-tests-look-at "if save:" -1 t)
2623 (python-info-dedenter-opening-block-position)))))
2624
2625(ert-deftest python-info-dedenter-opening-block-positions-1 ()
2626 (python-tests-with-temp-buffer
2627 "
2628if save:
2629 try:
2630 write_to_disk(data)
2631 except IOError:
2632 msg = 'Error saving to disk'
2633 message(msg)
2634 logger.exception(msg)
2635 except Exception:
2636 if hide_details:
2637 logger.exception('Unhandled exception')
2638 else
2639 finally:
2640 data.free()
2641"
2642 (python-tests-look-at "try:")
2643 (should (not (python-info-dedenter-opening-block-positions)))
2644
2645 (python-tests-look-at "except IOError:")
2646 (should
2647 (equal (list
2648 (python-tests-look-at "try:" -1 t))
2649 (python-info-dedenter-opening-block-positions)))
2650
2651 (python-tests-look-at "except Exception:")
2652 (should
2653 (equal (list
2654 (python-tests-look-at "except IOError:" -1 t))
2655 (python-info-dedenter-opening-block-positions)))
2656
2657 (python-tests-look-at "if hide_details:")
2658 (should (not (python-info-dedenter-opening-block-positions)))
2659
2660 ;; check indentation does not modify the detected opening blocks
2661 (python-tests-look-at "else")
2662 (should
2663 (equal (list
2664 (python-tests-look-at "if hide_details:" -1 t)
2665 (python-tests-look-at "except Exception:" -1 t)
2666 (python-tests-look-at "if save:" -1 t))
2667 (python-info-dedenter-opening-block-positions)))
2668
2669 (indent-line-to 8)
2670 (should
2671 (equal (list
2672 (python-tests-look-at "if hide_details:" -1 t)
2673 (python-tests-look-at "except Exception:" -1 t)
2674 (python-tests-look-at "if save:" -1 t))
2675 (python-info-dedenter-opening-block-positions)))
2676
2677 (indent-line-to 4)
2678 (should
2679 (equal (list
2680 (python-tests-look-at "if hide_details:" -1 t)
2681 (python-tests-look-at "except Exception:" -1 t)
2682 (python-tests-look-at "if save:" -1 t))
2683 (python-info-dedenter-opening-block-positions)))
2684
2685 (indent-line-to 0)
2686 (should
2687 (equal (list
2688 (python-tests-look-at "if hide_details:" -1 t)
2689 (python-tests-look-at "except Exception:" -1 t)
2690 (python-tests-look-at "if save:" -1 t))
2691 (python-info-dedenter-opening-block-positions)))))
2692
2693(ert-deftest python-info-dedenter-opening-block-positions-2 ()
2694 "Test detection of opening blocks for elif."
2695 (python-tests-with-temp-buffer
2696 "
2697if var:
2698 if var2:
2699 something()
2700 elif var3:
2701 something_else()
2702 elif
2703"
2704 (python-tests-look-at "elif var3:")
2705 (should
2706 (equal (list
2707 (python-tests-look-at "if var2:" -1 t)
2708 (python-tests-look-at "if var:" -1 t))
2709 (python-info-dedenter-opening-block-positions)))
2710
2711 (python-tests-look-at "elif\n")
2712 (should
2713 (equal (list
2714 (python-tests-look-at "elif var3:" -1 t)
2715 (python-tests-look-at "if var:" -1 t))
2716 (python-info-dedenter-opening-block-positions)))))
2717
2718(ert-deftest python-info-dedenter-opening-block-positions-3 ()
2719 "Test detection of opening blocks for else."
2720 (python-tests-with-temp-buffer
2721 "
2722try:
2723 something()
2724except:
2725 if var:
2726 if var2:
2727 something()
2728 elif var3:
2729 something_else()
2730 else
2731
2732if var4:
2733 while var5:
2734 var4.pop()
2735 else
2736
2737 for value in var6:
2738 if value > 0:
2739 print value
2740 else
2741"
2742 (python-tests-look-at "else\n")
2743 (should
2744 (equal (list
2745 (python-tests-look-at "elif var3:" -1 t)
2746 (python-tests-look-at "if var:" -1 t)
2747 (python-tests-look-at "except:" -1 t))
2748 (python-info-dedenter-opening-block-positions)))
2749
2750 (python-tests-look-at "else\n")
2751 (should
2752 (equal (list
2753 (python-tests-look-at "while var5:" -1 t)
2754 (python-tests-look-at "if var4:" -1 t))
2755 (python-info-dedenter-opening-block-positions)))
2756
2757 (python-tests-look-at "else\n")
2758 (should
2759 (equal (list
2760 (python-tests-look-at "if value > 0:" -1 t)
2761 (python-tests-look-at "for value in var6:" -1 t)
2762 (python-tests-look-at "if var4:" -1 t))
2763 (python-info-dedenter-opening-block-positions)))))
2764
2765(ert-deftest python-info-dedenter-opening-block-positions-4 ()
2766 "Test detection of opening blocks for except."
2767 (python-tests-with-temp-buffer
2768 "
2769try:
2770 something()
2771except ValueError:
2772 something_else()
2773 except
2774"
2775 (python-tests-look-at "except ValueError:")
2776 (should
2777 (equal (list (python-tests-look-at "try:" -1 t))
2778 (python-info-dedenter-opening-block-positions)))
2779
2780 (python-tests-look-at "except\n")
2781 (should
2782 (equal (list (python-tests-look-at "except ValueError:" -1 t))
2783 (python-info-dedenter-opening-block-positions)))))
2784
2785(ert-deftest python-info-dedenter-opening-block-positions-5 ()
2786 "Test detection of opening blocks for finally."
2787 (python-tests-with-temp-buffer
2788 "
2789try:
2790 something()
2791 finally
2792
2793try:
2794 something_else()
2795except:
2796 logger.exception('something went wrong')
2797 finally
2798
2799try:
2800 something_else_else()
2801except Exception:
2802 logger.exception('something else went wrong')
2803else:
2804 print ('all good')
2805 finally
2806"
2807 (python-tests-look-at "finally\n")
2808 (should
2809 (equal (list (python-tests-look-at "try:" -1 t))
2810 (python-info-dedenter-opening-block-positions)))
2811
2812 (python-tests-look-at "finally\n")
2813 (should
2814 (equal (list (python-tests-look-at "except:" -1 t))
2815 (python-info-dedenter-opening-block-positions)))
2816
2817 (python-tests-look-at "finally\n")
2818 (should
2819 (equal (list (python-tests-look-at "else:" -1 t))
2820 (python-info-dedenter-opening-block-positions)))))
2821
2822(ert-deftest python-info-dedenter-opening-block-message-1 ()
2823 "Test dedenters inside strings are ignored."
2824 (python-tests-with-temp-buffer
2825 "'''
2826try:
2827 something()
2828except:
2829 logger.exception('something went wrong')
2830'''
2831"
2832 (python-tests-look-at "except\n")
2833 (should (not (python-info-dedenter-opening-block-message)))))
2834
2835(ert-deftest python-info-dedenter-opening-block-message-2 ()
2836 "Test except keyword."
2837 (python-tests-with-temp-buffer
2838 "
2839try:
2840 something()
2841except:
2842 logger.exception('something went wrong')
2843"
2844 (python-tests-look-at "except:")
2845 (should (string=
2846 "Closes try:"
2847 (substring-no-properties
2848 (python-info-dedenter-opening-block-message))))
2849 (end-of-line)
2850 (should (string=
2851 "Closes try:"
2852 (substring-no-properties
2853 (python-info-dedenter-opening-block-message))))))
2854
2855(ert-deftest python-info-dedenter-opening-block-message-3 ()
2856 "Test else keyword."
2857 (python-tests-with-temp-buffer
2858 "
2859try:
2860 something()
2861except:
2862 logger.exception('something went wrong')
2863else:
2864 logger.debug('all good')
2865"
2866 (python-tests-look-at "else:")
2867 (should (string=
2868 "Closes except:"
2869 (substring-no-properties
2870 (python-info-dedenter-opening-block-message))))
2871 (end-of-line)
2872 (should (string=
2873 "Closes except:"
2874 (substring-no-properties
2875 (python-info-dedenter-opening-block-message))))))
2876
2877(ert-deftest python-info-dedenter-opening-block-message-4 ()
2878 "Test finally keyword."
2879 (python-tests-with-temp-buffer
2880 "
2881try:
2882 something()
2883except:
2884 logger.exception('something went wrong')
2885else:
2886 logger.debug('all good')
2887finally:
2888 clean()
2889"
2890 (python-tests-look-at "finally:")
2891 (should (string=
2892 "Closes else:"
2893 (substring-no-properties
2894 (python-info-dedenter-opening-block-message))))
2895 (end-of-line)
2896 (should (string=
2897 "Closes else:"
2898 (substring-no-properties
2899 (python-info-dedenter-opening-block-message))))))
2900
2901(ert-deftest python-info-dedenter-opening-block-message-5 ()
2902 "Test elif keyword."
2903 (python-tests-with-temp-buffer
2904 "
2905if a:
2906 something()
2907elif b:
2908"
2909 (python-tests-look-at "elif b:")
2910 (should (string=
2911 "Closes if a:"
2912 (substring-no-properties
2913 (python-info-dedenter-opening-block-message))))
2914 (end-of-line)
2915 (should (string=
2916 "Closes if a:"
2917 (substring-no-properties
2918 (python-info-dedenter-opening-block-message))))))
2919
2920
2921(ert-deftest python-info-dedenter-statement-p-1 ()
2922 "Test dedenters inside strings are ignored."
2923 (python-tests-with-temp-buffer
2924 "'''
2925try:
2926 something()
2927except:
2928 logger.exception('something went wrong')
2929'''
2930"
2931 (python-tests-look-at "except\n")
2932 (should (not (python-info-dedenter-statement-p)))))
2933
2934(ert-deftest python-info-dedenter-statement-p-2 ()
2935 "Test except keyword."
2936 (python-tests-with-temp-buffer
2937 "
2938try:
2939 something()
2940except:
2941 logger.exception('something went wrong')
2942"
2943 (python-tests-look-at "except:")
2944 (should (= (point) (python-info-dedenter-statement-p)))
2945 (end-of-line)
2946 (should (= (save-excursion
2947 (back-to-indentation)
2948 (point))
2949 (python-info-dedenter-statement-p)))))
2950
2951(ert-deftest python-info-dedenter-statement-p-3 ()
2952 "Test else keyword."
2953 (python-tests-with-temp-buffer
2954 "
2955try:
2956 something()
2957except:
2958 logger.exception('something went wrong')
2959else:
2960 logger.debug('all good')
2961"
2962 (python-tests-look-at "else:")
2963 (should (= (point) (python-info-dedenter-statement-p)))
2964 (end-of-line)
2965 (should (= (save-excursion
2966 (back-to-indentation)
2967 (point))
2968 (python-info-dedenter-statement-p)))))
2969
2970(ert-deftest python-info-dedenter-statement-p-4 ()
2971 "Test finally keyword."
2972 (python-tests-with-temp-buffer
2973 "
2974try:
2975 something()
2976except:
2977 logger.exception('something went wrong')
2978else:
2979 logger.debug('all good')
2980finally:
2981 clean()
2982"
2983 (python-tests-look-at "finally:")
2984 (should (= (point) (python-info-dedenter-statement-p)))
2985 (end-of-line)
2986 (should (= (save-excursion
2987 (back-to-indentation)
2988 (point))
2989 (python-info-dedenter-statement-p)))))
2990
2991(ert-deftest python-info-dedenter-statement-p-5 ()
2992 "Test elif keyword."
2993 (python-tests-with-temp-buffer
2994 "
2995if a:
2996 something()
2997elif b:
2998"
2999 (python-tests-look-at "elif b:")
3000 (should (= (point) (python-info-dedenter-statement-p)))
3001 (end-of-line)
3002 (should (= (save-excursion
3003 (back-to-indentation)
3004 (point))
3005 (python-info-dedenter-statement-p)))))
2482 3006
2483(ert-deftest python-info-line-ends-backslash-p-1 () 3007(ert-deftest python-info-line-ends-backslash-p-1 ()
2484 (python-tests-with-temp-buffer 3008 (python-tests-with-temp-buffer