diff options
| author | Fabián Ezequiel Gallina | 2012-05-17 00:03:34 -0300 |
|---|---|---|
| committer | Fabián Ezequiel Gallina | 2012-05-17 00:03:34 -0300 |
| commit | 0674d3fadbd4c5755598dc2791a179dbbe1d018e (patch) | |
| tree | 348d356abe1a98f2867988b7996a6b59a2862822 /lisp/progmodes/python.el | |
| parent | bbd27e0710f2885448949880e5b3e48c6a7b97a5 (diff) | |
| download | emacs-0674d3fadbd4c5755598dc2791a179dbbe1d018e.tar.gz emacs-0674d3fadbd4c5755598dc2791a179dbbe1d018e.zip | |
Enhancements on indentation code and related functions.
This commit includes:
* A more robust implementation of `python-indent-calculate-indentation'.
* enhancements on `python-indent-context' when dealing with backslashes
and blocks.
* Many changes, comments and enhancements to
`python-indent-calculate-indentation'. Many of them especially focused
to match pep8 guidelines, being this one the most important new one:
http://mail.python.org/pipermail/python-dev/2011-June/111760.html
* Better `python-info-line-ends-backslash-p' that would work as intended
on narrowed buffers.
* `python-info-continuation-line-p' now does what's supposed to do.
* Enhanced implementation of `python-info-continuation-line-p',
`python-info-block-continuation-line-p' and
`python-info-assignment-continuation-line-p'
New Functions:
* `python-util-forward-comment' a simple replacement `forward-comment'
with some necessary enhancements.
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 418 |
1 files changed, 238 insertions, 180 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 2f886a5b803..3244f299778 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -535,30 +535,35 @@ These make `python-indent-calculate-indentation' subtract the value of | |||
| 535 | (save-restriction | 535 | (save-restriction |
| 536 | (widen) | 536 | (widen) |
| 537 | (goto-char (point-min)) | 537 | (goto-char (point-min)) |
| 538 | (let ((found-block)) | 538 | (let ((block-end)) |
| 539 | (while (and (not found-block) | 539 | (while (and (not block-end) |
| 540 | (re-search-forward | 540 | (re-search-forward |
| 541 | (python-rx line-start block-start) nil t)) | 541 | (python-rx line-start block-start) nil t)) |
| 542 | (when (and (not (python-info-ppss-context 'string)) | 542 | (when (and |
| 543 | (not (python-info-ppss-context 'comment)) | 543 | (not (python-info-ppss-context-type)) |
| 544 | (progn | 544 | (progn |
| 545 | (goto-char (line-end-position)) | 545 | (goto-char (line-end-position)) |
| 546 | (forward-comment -9999) | 546 | (python-util-forward-comment -1) |
| 547 | (eq ?: (char-before)))) | 547 | (if (equal (char-before) ?:) |
| 548 | (setq found-block t))) | 548 | t |
| 549 | (if (not found-block) | 549 | (forward-line 1) |
| 550 | (when (python-info-block-continuation-line-p) | ||
| 551 | (while (and (python-info-continuation-line-p) | ||
| 552 | (not (eobp))) | ||
| 553 | (forward-line 1)) | ||
| 554 | (python-util-forward-comment -1) | ||
| 555 | (when (equal (char-before) ?:) | ||
| 556 | t))))) | ||
| 557 | (setq block-end (point-marker)))) | ||
| 558 | (let ((indentation | ||
| 559 | (when block-end | ||
| 560 | (goto-char block-end) | ||
| 561 | (python-util-forward-comment) | ||
| 562 | (current-indentation)))) | ||
| 563 | (if indentation | ||
| 564 | (setq python-indent-offset indentation) | ||
| 550 | (message "Can't guess python-indent-offset, using defaults: %s" | 565 | (message "Can't guess python-indent-offset, using defaults: %s" |
| 551 | python-indent-offset) | 566 | python-indent-offset))))))) |
| 552 | (while (and (progn | ||
| 553 | (goto-char (line-end-position)) | ||
| 554 | (python-info-continuation-line-p)) | ||
| 555 | (not (eobp))) | ||
| 556 | (forward-line 1)) | ||
| 557 | (forward-line 1) | ||
| 558 | (forward-comment 9999) | ||
| 559 | (let ((indent-offset (current-indentation))) | ||
| 560 | (when (> indent-offset 0) | ||
| 561 | (setq python-indent-offset indent-offset)))))))) | ||
| 562 | 567 | ||
| 563 | (defun python-indent-context () | 568 | (defun python-indent-context () |
| 564 | "Get information on indentation context. | 569 | "Get information on indentation context. |
| @@ -594,42 +599,32 @@ START is the buffer position where the sexp starts." | |||
| 594 | ((setq start (when (not (or (python-info-ppss-context 'string ppss) | 599 | ((setq start (when (not (or (python-info-ppss-context 'string ppss) |
| 595 | (python-info-ppss-context 'comment ppss))) | 600 | (python-info-ppss-context 'comment ppss))) |
| 596 | (let ((line-beg-pos (line-beginning-position))) | 601 | (let ((line-beg-pos (line-beginning-position))) |
| 597 | (when (eq ?\\ (char-before (1- line-beg-pos))) | 602 | (when (python-info-line-ends-backslash-p (1- line-beg-pos)) |
| 598 | (- line-beg-pos 2))))) | 603 | (- line-beg-pos 2))))) |
| 599 | 'after-backslash) | 604 | 'after-backslash) |
| 600 | ;; After beginning of block | 605 | ;; After beginning of block |
| 601 | ((setq start (save-excursion | 606 | ((setq start (save-excursion |
| 602 | (let ((block-regexp (python-rx block-start)) | 607 | (when (progn |
| 603 | (block-start-line-end ":[[:space:]]*$")) | 608 | (back-to-indentation) |
| 604 | (back-to-indentation) | 609 | (python-util-forward-comment -1) |
| 605 | (forward-comment -9999) | 610 | (equal (char-before) ?:)) |
| 606 | (back-to-indentation) | 611 | ;; Move to the first block start that's not in within |
| 607 | (when (or (python-info-continuation-line-p) | 612 | ;; a string, comment or paren and that's not a |
| 608 | (and (not (looking-at block-regexp)) | 613 | ;; continuation line. |
| 609 | (save-excursion | 614 | (while (and (re-search-backward |
| 610 | (re-search-forward | 615 | (python-rx block-start) nil t) |
| 611 | block-start-line-end | 616 | (or |
| 612 | (line-end-position) t)))) | 617 | (python-info-ppss-context 'string) |
| 613 | (while (and (forward-line -1) | 618 | (python-info-ppss-context 'comment) |
| 614 | (python-info-continuation-line-p) | 619 | (python-info-ppss-context 'paren) |
| 615 | (not (bobp)))) | 620 | (python-info-continuation-line-p)))) |
| 616 | (back-to-indentation) | 621 | (when (looking-at (python-rx block-start)) |
| 617 | (when (not (looking-at block-regexp)) | ||
| 618 | (forward-line 1))) | ||
| 619 | (back-to-indentation) | ||
| 620 | (when (and (looking-at block-regexp) | ||
| 621 | (or (re-search-forward | ||
| 622 | block-start-line-end | ||
| 623 | (line-end-position) t) | ||
| 624 | (save-excursion | ||
| 625 | (goto-char (line-end-position)) | ||
| 626 | (python-info-continuation-line-p)))) | ||
| 627 | (point-marker))))) | 622 | (point-marker))))) |
| 628 | 'after-beginning-of-block) | 623 | 'after-beginning-of-block) |
| 629 | ;; After normal line | 624 | ;; After normal line |
| 630 | ((setq start (save-excursion | 625 | ((setq start (save-excursion |
| 631 | (back-to-indentation) | 626 | (back-to-indentation) |
| 632 | (forward-comment -9999) | 627 | (python-util-forward-comment -1) |
| 633 | (python-nav-sentence-start) | 628 | (python-nav-sentence-start) |
| 634 | (point-marker))) | 629 | (point-marker))) |
| 635 | 'after-line) | 630 | 'after-line) |
| @@ -647,9 +642,14 @@ START is the buffer position where the sexp starts." | |||
| 647 | (save-excursion | 642 | (save-excursion |
| 648 | (case context-status | 643 | (case context-status |
| 649 | ('no-indent 0) | 644 | ('no-indent 0) |
| 645 | ;; When point is after beginning of block just add one level | ||
| 646 | ;; of indentation relative to the context-start | ||
| 650 | ('after-beginning-of-block | 647 | ('after-beginning-of-block |
| 651 | (goto-char context-start) | 648 | (goto-char context-start) |
| 652 | (+ (current-indentation) python-indent-offset)) | 649 | (+ (current-indentation) python-indent-offset)) |
| 650 | ;; When after a simple line just use previous line | ||
| 651 | ;; indentation, in the case current line starts with a | ||
| 652 | ;; `python-indent-dedenters' de-indent one level. | ||
| 653 | ('after-line | 653 | ('after-line |
| 654 | (- | 654 | (- |
| 655 | (save-excursion | 655 | (save-excursion |
| @@ -660,92 +660,125 @@ START is the buffer position where the sexp starts." | |||
| 660 | (looking-at (regexp-opt python-indent-dedenters))) | 660 | (looking-at (regexp-opt python-indent-dedenters))) |
| 661 | python-indent-offset | 661 | python-indent-offset |
| 662 | 0))) | 662 | 0))) |
| 663 | ;; When inside of a string, do nothing. just use the current | ||
| 664 | ;; indentation. XXX: perhaps it would be a good idea to | ||
| 665 | ;; invoke standard text indentation here | ||
| 663 | ('inside-string | 666 | ('inside-string |
| 664 | (goto-char context-start) | 667 | (goto-char context-start) |
| 665 | (current-indentation)) | 668 | (current-indentation)) |
| 669 | ;; After backslash we have several posibilities | ||
| 666 | ('after-backslash | 670 | ('after-backslash |
| 667 | (let* ((block-continuation | 671 | (cond |
| 668 | (save-excursion | 672 | ;; Check if current line is a dot continuation. For this |
| 669 | (forward-line -1) | 673 | ;; the current line must start with a dot and previous |
| 670 | (python-info-block-continuation-line-p))) | 674 | ;; line must contain a dot too. |
| 671 | (assignment-continuation | 675 | ((save-excursion |
| 672 | (save-excursion | 676 | (back-to-indentation) |
| 673 | (forward-line -1) | 677 | (when (looking-at "\\.") |
| 674 | (python-info-assignment-continuation-line-p))) | 678 | (forward-line -1) |
| 675 | (dot-continuation | 679 | (goto-char (line-end-position)) |
| 676 | (save-excursion | 680 | (while (and (re-search-backward "\\." (line-beginning-position) t) |
| 677 | (back-to-indentation) | 681 | (or (python-info-ppss-context 'comment) |
| 678 | (when (looking-at "\\.") | 682 | (python-info-ppss-context 'string) |
| 679 | (forward-line -1) | 683 | (python-info-ppss-context 'paren)))) |
| 680 | (goto-char (line-end-position)) | 684 | (if (and (looking-at "\\.") |
| 681 | (while (and (re-search-backward "\\." (line-beginning-position) t) | 685 | (not (or (python-info-ppss-context 'comment) |
| 682 | (or (python-info-ppss-context 'comment) | 686 | (python-info-ppss-context 'string) |
| 683 | (python-info-ppss-context 'string) | 687 | (python-info-ppss-context 'paren)))) |
| 684 | (python-info-ppss-context 'paren)))) | 688 | ;; The indentation is the same column of the |
| 685 | (if (and (looking-at "\\.") | 689 | ;; first matching dot that's not inside a |
| 686 | (not (or (python-info-ppss-context 'comment) | 690 | ;; comment, a string or a paren |
| 687 | (python-info-ppss-context 'string) | 691 | (current-column) |
| 688 | (python-info-ppss-context 'paren)))) | 692 | ;; No dot found on previous line, just add another |
| 689 | (current-column) | 693 | ;; indentation level. |
| 690 | (+ (current-indentation) python-indent-offset))))) | 694 | (+ (current-indentation) python-indent-offset))))) |
| 691 | (indentation (cond | 695 | ;; Check if prev line is a block continuation |
| 692 | (dot-continuation | 696 | ((let ((block-continuation-start |
| 693 | dot-continuation) | 697 | (python-info-block-continuation-line-p))) |
| 694 | (block-continuation | 698 | (when block-continuation-start |
| 695 | (goto-char block-continuation) | 699 | ;; If block-continuation-start is set jump to that |
| 696 | (re-search-forward | 700 | ;; marker and use first column after the block start |
| 697 | (python-rx block-start (* space)) | 701 | ;; as indentation value. |
| 698 | (line-end-position) t) | 702 | (goto-char block-continuation-start) |
| 699 | (current-column)) | 703 | (re-search-forward |
| 700 | (assignment-continuation | 704 | (python-rx block-start (* space)) |
| 701 | (goto-char assignment-continuation) | 705 | (line-end-position) t) |
| 702 | (re-search-forward | 706 | (current-column)))) |
| 703 | (python-rx simple-operator) | 707 | ;; Check if current line is an assignment continuation |
| 704 | (line-end-position) t) | 708 | ((let ((assignment-continuation-start |
| 705 | (forward-char 1) | 709 | (python-info-assignment-continuation-line-p))) |
| 706 | (re-search-forward | 710 | (when assignment-continuation-start |
| 707 | (python-rx (* space)) | 711 | ;; If assignment-continuation is set jump to that |
| 708 | (line-end-position) t) | 712 | ;; marker and use first column after the assignment |
| 709 | (current-column)) | 713 | ;; operator as indentation value. |
| 710 | (t | 714 | (goto-char assignment-continuation-start) |
| 711 | (goto-char context-start) | 715 | (current-column)))) |
| 712 | (if (not | 716 | (t |
| 713 | (save-excursion | 717 | (forward-line -1) |
| 714 | (back-to-indentation) | 718 | (if (save-excursion |
| 715 | (looking-at | 719 | (and |
| 716 | "\\(?:return\\|from\\|import\\)\s+"))) | 720 | (python-info-line-ends-backslash-p) |
| 717 | (current-indentation) | 721 | (forward-line -1) |
| 718 | (+ (current-indentation) | 722 | (python-info-line-ends-backslash-p))) |
| 719 | (length | 723 | ;; The two previous lines ended in a backslash so we must |
| 720 | (match-string-no-properties 0)))))))) | 724 | ;; respect previous line indentation. |
| 721 | indentation)) | 725 | (current-indentation) |
| 726 | ;; What happens here is that we are dealing with the second | ||
| 727 | ;; line of a backslash continuation, in that case we just going | ||
| 728 | ;; to add one indentation level. | ||
| 729 | (+ (current-indentation) python-indent-offset))))) | ||
| 730 | ;; When inside a paren there's a need to handle nesting | ||
| 731 | ;; correctly | ||
| 722 | ('inside-paren | 732 | ('inside-paren |
| 723 | (or (save-excursion | 733 | (cond |
| 724 | (skip-syntax-forward "\s" (line-end-position)) | 734 | ;; If current line closes the outtermost open paren use the |
| 725 | (when (and (looking-at (regexp-opt '(")" "]" "}"))) | 735 | ;; current indentation of the context-start line. |
| 726 | (not (forward-char 1)) | 736 | ((save-excursion |
| 727 | (not (python-info-ppss-context 'paren))) | 737 | (skip-syntax-forward "\s" (line-end-position)) |
| 728 | (goto-char context-start) | 738 | (when (and (looking-at (regexp-opt '(")" "]" "}"))) |
| 739 | (progn | ||
| 740 | (forward-char 1) | ||
| 741 | (not (python-info-ppss-context 'paren)))) | ||
| 742 | (goto-char context-start) | ||
| 743 | (current-indentation)))) | ||
| 744 | ;; If open paren is contained on a line by itself add another | ||
| 745 | ;; indentation level, else look for the first word after the | ||
| 746 | ;; opening paren and use it's column position as indentation | ||
| 747 | ;; level. | ||
| 748 | ((let* ((content-starts-in-newline) | ||
| 749 | (indent | ||
| 750 | (save-excursion | ||
| 751 | (if (setq content-starts-in-newline | ||
| 752 | (progn | ||
| 753 | (goto-char context-start) | ||
| 754 | (forward-char) | ||
| 755 | (save-restriction | ||
| 756 | (narrow-to-region | ||
| 757 | (line-beginning-position) | ||
| 758 | (line-end-position)) | ||
| 759 | (python-util-forward-comment)) | ||
| 760 | (looking-at "$"))) | ||
| 761 | (+ (current-indentation) python-indent-offset) | ||
| 762 | (current-column))))) | ||
| 763 | ;; Adjustments | ||
| 764 | (cond | ||
| 765 | ;; If current line closes a nested open paren de-indent one | ||
| 766 | ;; level. | ||
| 767 | ((progn | ||
| 729 | (back-to-indentation) | 768 | (back-to-indentation) |
| 730 | (current-column))) | 769 | (looking-at (regexp-opt '(")" "]" "}")))) |
| 731 | (- | 770 | (- indent python-indent-offset)) |
| 732 | (save-excursion | 771 | ;; If the line of the opening paren that wraps the current |
| 733 | (goto-char context-start) | 772 | ;; line starts a block add another level of indentation to |
| 734 | (forward-char) | 773 | ;; follow new pep8 recommendation. See: http://ur1.ca/5rojx |
| 735 | (save-restriction | 774 | ((save-excursion |
| 736 | (narrow-to-region | 775 | (when (and content-starts-in-newline |
| 737 | (line-beginning-position) | 776 | (progn |
| 738 | (line-end-position)) | 777 | (goto-char context-start) |
| 739 | (forward-comment 9999)) | 778 | (back-to-indentation) |
| 740 | (if (looking-at "$") | 779 | (looking-at (python-rx block-start)))) |
| 741 | (+ (current-indentation) python-indent-offset) | 780 | (+ indent python-indent-offset)))) |
| 742 | (forward-comment 9999) | 781 | (t indent))))))))))) |
| 743 | (current-column))) | ||
| 744 | (if (progn | ||
| 745 | (back-to-indentation) | ||
| 746 | (looking-at (regexp-opt '(")" "]" "}")))) | ||
| 747 | python-indent-offset | ||
| 748 | 0))))))))) | ||
| 749 | 782 | ||
| 750 | (defun python-indent-calculate-levels () | 783 | (defun python-indent-calculate-levels () |
| 751 | "Calculate `python-indent-levels' and reset `python-indent-current-level'." | 784 | "Calculate `python-indent-levels' and reset `python-indent-current-level'." |
| @@ -972,7 +1005,7 @@ decorators are not included. Return non-nil if point is moved to the | |||
| 972 | (let ((found)) | 1005 | (let ((found)) |
| 973 | (dotimes (i (- arg) found) | 1006 | (dotimes (i (- arg) found) |
| 974 | (python-end-of-defun-function) | 1007 | (python-end-of-defun-function) |
| 975 | (forward-comment 9999) | 1008 | (python-util-forward-comment) |
| 976 | (goto-char (line-end-position)) | 1009 | (goto-char (line-end-position)) |
| 977 | (when (not (eobp)) | 1010 | (when (not (eobp)) |
| 978 | (setq found | 1011 | (setq found |
| @@ -996,7 +1029,7 @@ Returns nil if point is not in a def or class." | |||
| 996 | (not (eobp)) | 1029 | (not (eobp)) |
| 997 | (or (not (current-word)) | 1030 | (or (not (current-word)) |
| 998 | (> (current-indentation) beg-defun-indent)))) | 1031 | (> (current-indentation) beg-defun-indent)))) |
| 999 | (forward-comment 9999) | 1032 | (python-util-forward-comment) |
| 1000 | (goto-char (line-beginning-position)))) | 1033 | (goto-char (line-beginning-position)))) |
| 1001 | 1034 | ||
| 1002 | (defun python-nav-sentence-start () | 1035 | (defun python-nav-sentence-start () |
| @@ -1036,13 +1069,13 @@ With negative argument, move backward repeatedly to start of sentence." | |||
| 1036 | (interactive "^p") | 1069 | (interactive "^p") |
| 1037 | (or arg (setq arg 1)) | 1070 | (or arg (setq arg 1)) |
| 1038 | (while (> arg 0) | 1071 | (while (> arg 0) |
| 1039 | (forward-comment 9999) | 1072 | (python-util-forward-comment) |
| 1040 | (python-nav-sentence-end) | 1073 | (python-nav-sentence-end) |
| 1041 | (forward-line 1) | 1074 | (forward-line 1) |
| 1042 | (setq arg (1- arg))) | 1075 | (setq arg (1- arg))) |
| 1043 | (while (< arg 0) | 1076 | (while (< arg 0) |
| 1044 | (python-nav-sentence-end) | 1077 | (python-nav-sentence-end) |
| 1045 | (forward-comment -9999) | 1078 | (python-util-forward-comment -1) |
| 1046 | (python-nav-sentence-start) | 1079 | (python-nav-sentence-start) |
| 1047 | (forward-line -1) | 1080 | (forward-line -1) |
| 1048 | (setq arg (1+ arg)))) | 1081 | (setq arg (1+ arg)))) |
| @@ -2415,7 +2448,7 @@ not inside a defun." | |||
| 2415 | (widen) | 2448 | (widen) |
| 2416 | (save-excursion | 2449 | (save-excursion |
| 2417 | (goto-char (line-end-position)) | 2450 | (goto-char (line-end-position)) |
| 2418 | (forward-comment -9999) | 2451 | (python-util-forward-comment -1) |
| 2419 | (setq min-indent (current-indentation)) | 2452 | (setq min-indent (current-indentation)) |
| 2420 | (while (python-beginning-of-defun-function 1 t) | 2453 | (while (python-beginning-of-defun-function 1 t) |
| 2421 | (when (or (< (current-indentation) min-indent) | 2454 | (when (or (< (current-indentation) min-indent) |
| @@ -2462,68 +2495,83 @@ not inside a defun." | |||
| 2462 | (when (member (current-word) '("except" "else")) | 2495 | (when (member (current-word) '("except" "else")) |
| 2463 | (point-marker)))))))) | 2496 | (point-marker)))))))) |
| 2464 | 2497 | ||
| 2465 | (defun python-info-line-ends-backslash-p () | 2498 | (defun python-info-line-ends-backslash-p (&optional line-number) |
| 2466 | "Return non-nil if current line ends with backslash." | 2499 | "Return non-nil if current line ends with backslash. |
| 2467 | (string= (or (ignore-errors | 2500 | With optional argument LINE-NUMBER, check that line instead." |
| 2468 | (buffer-substring | 2501 | (save-excursion |
| 2469 | (line-end-position) | 2502 | (save-restriction |
| 2470 | (- (line-end-position) 1))) "") "\\")) | 2503 | (when line-number |
| 2504 | (goto-char line-number)) | ||
| 2505 | (widen) | ||
| 2506 | (goto-char (line-end-position)) | ||
| 2507 | (equal (char-after (1- (point))) ?\\)))) | ||
| 2471 | 2508 | ||
| 2472 | (defun python-info-continuation-line-p () | 2509 | (defun python-info-continuation-line-p () |
| 2473 | "Return non-nil if current line is continuation of another." | 2510 | "Check if current line is continuation of another. |
| 2474 | (let ((current-ppss-context-type (python-info-ppss-context-type))) | 2511 | When current line is continuation of another return the point |
| 2475 | (and | 2512 | where the continued line ends." |
| 2476 | (equal (save-excursion | 2513 | (save-excursion |
| 2477 | (goto-char (line-end-position)) | 2514 | (save-restriction |
| 2478 | (forward-comment 9999) | 2515 | (widen) |
| 2479 | (python-info-ppss-context-type)) | 2516 | (let* ((context-type (progn |
| 2480 | current-ppss-context-type) | 2517 | (back-to-indentation) |
| 2481 | (or (python-info-line-ends-backslash-p) | 2518 | (python-info-ppss-context-type))) |
| 2482 | (string-match ",[[:space:]]*$" (buffer-substring | 2519 | (line-start (line-number-at-pos)) |
| 2483 | (line-beginning-position) | 2520 | (context-start (when context-type |
| 2484 | (line-end-position))) | 2521 | (python-info-ppss-context context-type)))) |
| 2485 | (save-excursion | 2522 | (cond ((equal context-type 'paren) |
| 2486 | (let ((innermost-paren (progn | 2523 | ;; Lines inside a paren are always a continuation line |
| 2487 | (goto-char (line-end-position)) | 2524 | ;; (except the first one). |
| 2488 | (python-info-ppss-context 'paren)))) | 2525 | (when (equal (python-info-ppss-context-type) 'paren) |
| 2489 | (when (and innermost-paren | 2526 | (python-util-forward-comment -1) |
| 2490 | (and (<= (line-beginning-position) innermost-paren) | 2527 | (python-util-forward-comment -1) |
| 2491 | (>= (line-end-position) innermost-paren))) | 2528 | (point-marker))) |
| 2492 | (goto-char innermost-paren) | 2529 | ((or (equal context-type 'comment) |
| 2493 | (looking-at (python-rx open-paren (* space) line-end))))) | 2530 | (equal context-type 'string)) |
| 2494 | (save-excursion | 2531 | ;; move forward an roll again |
| 2495 | (back-to-indentation) | 2532 | (goto-char context-start) |
| 2496 | (python-info-ppss-context 'paren)))))) | 2533 | (python-util-forward-comment) |
| 2534 | (python-info-continuation-line-p)) | ||
| 2535 | (t | ||
| 2536 | ;; Not within a paren, string or comment, the only way we are | ||
| 2537 | ;; dealing with a continuation line is that previous line | ||
| 2538 | ;; contains a backslash, and this can only be the previous line | ||
| 2539 | ;; from current | ||
| 2540 | (back-to-indentation) | ||
| 2541 | (python-util-forward-comment -1) | ||
| 2542 | (python-util-forward-comment -1) | ||
| 2543 | (when (and (equal (1- line-start) (line-number-at-pos)) | ||
| 2544 | (python-info-line-ends-backslash-p)) | ||
| 2545 | (point-marker)))))))) | ||
| 2497 | 2546 | ||
| 2498 | (defun python-info-block-continuation-line-p () | 2547 | (defun python-info-block-continuation-line-p () |
| 2499 | "Return non-nil if current line is a continuation of a block." | 2548 | "Return non-nil if current line is a continuation of a block." |
| 2500 | (save-excursion | 2549 | (save-excursion |
| 2501 | (while (and (not (bobp)) | 2550 | (when (python-info-continuation-line-p) |
| 2502 | (python-info-continuation-line-p)) | 2551 | (forward-line -1) |
| 2503 | (forward-line -1)) | 2552 | (back-to-indentation) |
| 2504 | (forward-line 1) | 2553 | (when (looking-at (python-rx block-start)) |
| 2505 | (back-to-indentation) | 2554 | (point-marker))))) |
| 2506 | (when (looking-at (python-rx block-start)) | ||
| 2507 | (point-marker)))) | ||
| 2508 | 2555 | ||
| 2509 | (defun python-info-assignment-continuation-line-p () | 2556 | (defun python-info-assignment-continuation-line-p () |
| 2510 | "Return non-nil if current line is a continuation of an assignment." | 2557 | "Check if current line is a continuation of an assignment. |
| 2558 | When current line is continuation of another with an assignment | ||
| 2559 | return the point of the first non-blank character after the | ||
| 2560 | operator." | ||
| 2511 | (save-excursion | 2561 | (save-excursion |
| 2512 | (while (and (not (bobp)) | 2562 | (when (python-info-continuation-line-p) |
| 2513 | (python-info-continuation-line-p)) | 2563 | (forward-line -1) |
| 2514 | (forward-line -1)) | 2564 | (back-to-indentation) |
| 2515 | (forward-line 1) | 2565 | (when (and (not (looking-at (python-rx block-start))) |
| 2516 | (back-to-indentation) | ||
| 2517 | (when (and (not (looking-at (python-rx block-start))) | ||
| 2518 | (save-excursion | ||
| 2519 | (and (re-search-forward (python-rx not-simple-operator | 2566 | (and (re-search-forward (python-rx not-simple-operator |
| 2520 | assignment-operator | 2567 | assignment-operator |
| 2521 | not-simple-operator) | 2568 | not-simple-operator) |
| 2522 | (line-end-position) t) | 2569 | (line-end-position) t) |
| 2523 | (not (or (python-info-ppss-context 'string) | 2570 | (not (or (python-info-ppss-context 'string) |
| 2524 | (python-info-ppss-context 'paren) | 2571 | (python-info-ppss-context 'paren) |
| 2525 | (python-info-ppss-context 'comment)))))) | 2572 | (python-info-ppss-context 'comment))))) |
| 2526 | (point-marker)))) | 2573 | (skip-syntax-forward "\s") |
| 2574 | (point-marker))))) | ||
| 2527 | 2575 | ||
| 2528 | (defun python-info-ppss-context (type &optional syntax-ppss) | 2576 | (defun python-info-ppss-context (type &optional syntax-ppss) |
| 2529 | "Return non-nil if point is on TYPE using SYNTAX-PPSS. | 2577 | "Return non-nil if point is on TYPE using SYNTAX-PPSS. |
| @@ -2578,6 +2626,16 @@ to \"^python-\"." | |||
| 2578 | (cdr pair)))) | 2626 | (cdr pair)))) |
| 2579 | (buffer-local-variables from-buffer))) | 2627 | (buffer-local-variables from-buffer))) |
| 2580 | 2628 | ||
| 2629 | (defun python-util-forward-comment (&optional direction) | ||
| 2630 | "Python mode specific version of `forward-comment'." | ||
| 2631 | (let ((comment-start (python-info-ppss-context 'comment)) | ||
| 2632 | (factor (if (< (or direction 0) 0) | ||
| 2633 | -99999 | ||
| 2634 | 99999))) | ||
| 2635 | (when comment-start | ||
| 2636 | (goto-char comment-start)) | ||
| 2637 | (forward-comment factor))) | ||
| 2638 | |||
| 2581 | 2639 | ||
| 2582 | ;;;###autoload | 2640 | ;;;###autoload |
| 2583 | (define-derived-mode python-mode fundamental-mode "Python" | 2641 | (define-derived-mode python-mode fundamental-mode "Python" |