aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorFabián Ezequiel Gallina2015-01-28 01:08:18 -0300
committerFabián Ezequiel Gallina2015-01-28 01:08:18 -0300
commit95a2cb24b0697558e6629460d8bc693b394f0138 (patch)
treecf6cc03950fc6b0982497f00ff6c92eec1912b45 /lisp/progmodes/python.el
parentf5ebe84d75bb75156db9e2e0a7ab356941b4ea75 (diff)
parent9664defd262252faf037c5fe1ea095f1cc4b308b (diff)
downloademacs-95a2cb24b0697558e6629460d8bc693b394f0138.tar.gz
emacs-95a2cb24b0697558e6629460d8bc693b394f0138.zip
Merge from origin/emacs-24
9664def Signal a file-error from directory-files on MS-Windows (Bug#19701) fd4e65e Added missing test for previous commit 5485e3e5 python.el: New non-global state dependent indentation engine. 3b23e6a Fix the description of --insert command-line option (Bug#19694) 7a7e594 Add a cross-reference in ELisp manual. (Bug#19668) b4f4075 Fixes: debbugs:19660 83b3c31 * test/automated/regexp-tests.el: Require regexp-opt Conflicts: lisp/progmodes/python.el
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el702
1 files changed, 360 insertions, 342 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 13ff439bef2..d340550a017 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -463,9 +463,14 @@ The type returned can be `comment', `string' or `paren'."
463 ((nth 8 ppss) (if (nth 4 ppss) 'comment 'string)) 463 ((nth 8 ppss) (if (nth 4 ppss) 'comment 'string))
464 ((nth 1 ppss) 'paren)))) 464 ((nth 1 ppss) 'paren))))
465 465
466(defsubst python-syntax-comment-or-string-p () 466(defsubst python-syntax-comment-or-string-p (&optional ppss)
467 "Return non-nil if point is inside 'comment or 'string." 467 "Return non-nil if PPSS is inside 'comment or 'string."
468 (nth 8 (syntax-ppss))) 468 (nth 8 (or ppss (syntax-ppss))))
469
470(defsubst python-syntax-closing-paren-p ()
471 "Return non-nil if char after point is a closing paren."
472 (= (syntax-class (syntax-after (point)))
473 (syntax-class (string-to-syntax ")"))))
469 474
470(define-obsolete-function-alias 475(define-obsolete-function-alias
471 'python-info-ppss-context #'python-syntax-context "24.3") 476 'python-info-ppss-context #'python-syntax-context "24.3")
@@ -704,11 +709,28 @@ It makes underscores and dots word constituent chars.")
704 'python-guess-indent 'python-indent-guess-indent-offset "24.3") 709 'python-guess-indent 'python-indent-guess-indent-offset "24.3")
705 710
706(defvar python-indent-current-level 0 711(defvar python-indent-current-level 0
707 "Current indentation level `python-indent-line-function' is using.") 712 "Deprecated var available for compatibility.")
708 713
709(defvar python-indent-levels '(0) 714(defvar python-indent-levels '(0)
710 "Levels of indentation available for `python-indent-line-function'. 715 "Deprecated var available for compatibility.")
711Can also be `noindent' if automatic indentation can't be used.") 716
717(make-obsolete-variable
718 'python-indent-current-level
719 "The indentation API changed to avoid global state.
720The function `python-indent-calculate-levels' does not use it
721anymore. If you were defadvising it and or depended on this
722variable for indentation customizations, refactor your code to
723work on `python-indent-calculate-indentation' instead."
724 "24.5")
725
726(make-obsolete-variable
727 'python-indent-levels
728 "The indentation API changed to avoid global state.
729The function `python-indent-calculate-levels' does not use it
730anymore. If you were defadvising it and or depended on this
731variable for indentation customizations, refactor your code to
732work on `python-indent-calculate-indentation' instead."
733 "24.5")
712 734
713(defun python-indent-guess-indent-offset () 735(defun python-indent-guess-indent-offset ()
714 "Guess and set `python-indent-offset' for the current buffer." 736 "Guess and set `python-indent-offset' for the current buffer."
@@ -748,362 +770,358 @@ Can also be `noindent' if automatic indentation can't be used.")
748 python-indent-offset))))))) 770 python-indent-offset)))))))
749 771
750(defun python-indent-context () 772(defun python-indent-context ()
751 "Get information on indentation context. 773 "Get information about the current indentation context.
752Context information is returned with a cons with the form: 774Context is returned in a cons with the form (STATUS . START).
753 (STATUS . START) 775
754 776STATUS can be one of the following:
755Where status can be any of the following symbols: 777
756 778keyword
757 * after-comment: When current line might continue a comment block 779-------
758 * inside-paren: If point in between (), {} or [] 780
759 * inside-string: If point is inside a string 781:after-comment
760 * after-backslash: Previous line ends in a backslash 782 - Point is after a comment line.
761 * after-beginning-of-block: Point is after beginning of block 783 - START is the position of the \"#\" character.
762 * after-line: Point is after normal line 784:inside-string
763 * dedenter-statement: Point is on a dedenter statement. 785 - Point is inside string.
764 * no-indent: Point is at beginning of buffer or other special case 786 - START is the position of the first quote that starts it.
765START is the buffer position where the sexp starts." 787:no-indent
788 - No possible indentation case matches.
789 - START is always zero.
790
791:inside-paren
792 - Fallback case when point is inside paren.
793 - START is the first non space char position *after* the open paren.
794:inside-paren-at-closing-nested-paren
795 - Point is on a line that contains a nested paren closer.
796 - START is the position of the open paren it closes.
797:inside-paren-at-closing-paren
798 - Point is on a line that contains a paren closer.
799 - START is the position of the open paren.
800:inside-paren-newline-start
801 - Point is inside a paren with items starting in their own line.
802 - START is the position of the open paren.
803:inside-paren-newline-start-from-block
804 - Point is inside a paren with items starting in their own line
805 from a block start.
806 - START is the position of the open paren.
807
808:after-backslash
809 - Fallback case when point is after backslash.
810 - START is the char after the position of the backslash.
811:after-backslash-assignment-continuation
812 - Point is after a backslashed assignment.
813 - START is the char after the position of the backslash.
814:after-backslash-block-continuation
815 - Point is after a backslashed block continuation.
816 - START is the char after the position of the backslash.
817:after-backslash-dotted-continuation
818 - Point is after a backslashed dotted continuation. Previous
819 line must contain a dot to align with.
820 - START is the char after the position of the backslash.
821:after-backslash-first-line
822 - First line following a backslashed continuation.
823 - START is the char after the position of the backslash.
824
825:after-block-end
826 - Point is after a line containing a block ender.
827 - START is the position where the ender starts.
828:after-block-start
829 - Point is after a line starting a block.
830 - START is the position where the block starts.
831:after-line
832 - Point is after a simple line.
833 - START is the position where the previous line starts.
834:at-dedenter-block-start
835 - Point is on a line starting a dedenter block.
836 - START is the position where the dedenter block starts."
766 (save-restriction 837 (save-restriction
767 (widen) 838 (widen)
768 (let ((ppss (save-excursion (beginning-of-line) (syntax-ppss))) 839 (let ((ppss (save-excursion
769 (start)) 840 (beginning-of-line)
770 (cons 841 (syntax-ppss))))
771 (cond 842 (cond
772 ;; Beginning of buffer 843 ;; Beginning of buffer.
773 ((save-excursion 844 ((= (line-number-at-pos) 1)
774 (goto-char (line-beginning-position)) 845 (cons :no-indent 0))
775 (bobp)) 846 ;; Comment continuation (maybe).
776 'no-indent) 847 ((save-excursion
777 ;; Comment continuation 848 (when (and
778 ((save-excursion 849 (or
779 (when (and 850 (python-info-current-line-comment-p)
780 (or 851 (python-info-current-line-empty-p))
781 (python-info-current-line-comment-p) 852 (forward-comment -1)
782 (python-info-current-line-empty-p)) 853 (python-info-current-line-comment-p))
783 (progn 854 (cons :after-comment (point)))))
784 (forward-comment -1) 855 ;; Inside a string.
785 (python-info-current-line-comment-p))) 856 ((let ((start (python-syntax-context 'string ppss)))
786 (setq start (point)) 857 (when start
787 'after-comment))) 858 (cons :inside-string start))))
788 ;; Inside string 859 ;; Inside a paren.
789 ((setq start (python-syntax-context 'string ppss)) 860 ((let* ((start (python-syntax-context 'paren ppss))
790 'inside-string) 861 (starts-in-newline
791 ;; Inside a paren 862 (when start
792 ((setq start (python-syntax-context 'paren ppss)) 863 (save-excursion
793 'inside-paren) 864 (goto-char start)
794 ;; After backslash 865 (forward-char)
795 ((setq start (when (not (or (python-syntax-context 'string ppss) 866 (not
796 (python-syntax-context 'comment ppss))) 867 (= (line-number-at-pos)
797 (let ((line-beg-pos (line-number-at-pos))) 868 (progn
798 (python-info-line-ends-backslash-p 869 (python-util-forward-comment)
799 (1- line-beg-pos))))) 870 (line-number-at-pos))))))))
800 'after-backslash) 871 (when start
801 ;; After beginning of block 872 (cond
802 ((setq start (save-excursion 873 ;; Current line only holds the closing paren.
803 (when (progn 874 ((save-excursion
804 (back-to-indentation) 875 (skip-syntax-forward " ")
805 (python-util-forward-comment -1) 876 (when (and (python-syntax-closing-paren-p)
806 (equal (char-before) ?:)) 877 (progn
807 ;; Move to the first block start that's not in within 878 (forward-char 1)
808 ;; a string, comment or paren and that's not a 879 (not (python-syntax-context 'paren))))
809 ;; continuation line. 880 (cons :inside-paren-at-closing-paren start))))
810 (while (and (re-search-backward 881 ;; Current line only holds a closing paren for nested.
811 (python-rx block-start) nil t) 882 ((save-excursion
812 (or 883 (back-to-indentation)
813 (python-syntax-context-type) 884 (python-syntax-closing-paren-p))
814 (python-info-continuation-line-p)))) 885 (cons :inside-paren-at-closing-nested-paren start))
815 (when (looking-at (python-rx block-start)) 886 ;; This line starts from a opening block in its own line.
816 (point-marker))))) 887 ((save-excursion
817 'after-beginning-of-block) 888 (goto-char start)
818 ((when (setq start (python-info-dedenter-statement-p)) 889 (when (and
819 'dedenter-statement)) 890 starts-in-newline
820 ;; After normal line 891 (save-excursion
821 ((setq start (save-excursion 892 (back-to-indentation)
893 (looking-at (python-rx block-start))))
894 (cons
895 :inside-paren-newline-start-from-block start))))
896 (starts-in-newline
897 (cons :inside-paren-newline-start start))
898 ;; General case.
899 (t (cons :inside-paren
900 (save-excursion
901 (goto-char (1+ start))
902 (skip-syntax-forward "(" 1)
903 (skip-syntax-forward " ")
904 (point))))))))
905 ;; After backslash.
906 ((let ((start (when (not (python-syntax-comment-or-string-p ppss))
907 (python-info-line-ends-backslash-p
908 (1- (line-number-at-pos))))))
909 (when start
910 (cond
911 ;; Continuation of dotted expression.
912 ((save-excursion
913 (back-to-indentation)
914 (when (eq (char-after) ?\.)
915 ;; Move point back until it's not inside a paren.
916 (while (prog2
917 (forward-line -1)
918 (and (not (bobp))
919 (python-syntax-context 'paren))))
920 (goto-char (line-end-position))
921 (while (and (search-backward
922 "." (line-beginning-position) t)
923 (python-syntax-context-type)))
924 ;; Ensure previous statement has dot to align with.
925 (when (and (eq (char-after) ?\.)
926 (not (python-syntax-context-type)))
927 (cons :after-backslash-dotted-continuation (point))))))
928 ;; Continuation of block definition.
929 ((let ((block-continuation-start
930 (python-info-block-continuation-line-p)))
931 (when block-continuation-start
932 (save-excursion
933 (goto-char block-continuation-start)
934 (re-search-forward
935 (python-rx block-start (* space))
936 (line-end-position) t)
937 (cons :after-backslash-block-continuation (point))))))
938 ;; Continuation of assignment.
939 ((let ((assignment-continuation-start
940 (python-info-assignment-continuation-line-p)))
941 (when assignment-continuation-start
942 (save-excursion
943 (goto-char assignment-continuation-start)
944 (cons :after-backslash-assignment-continuation (point))))))
945 ;; First line after backslash continuation start.
946 ((save-excursion
947 (goto-char start)
948 (when (or (= (line-number-at-pos) 1)
949 (not (python-info-beginning-of-backslash
950 (1- (line-number-at-pos)))))
951 (cons :after-backslash-first-line start))))
952 ;; General case.
953 (t (cons :after-backslash start))))))
954 ;; After beginning of block.
955 ((let ((start (save-excursion
956 (back-to-indentation)
957 (python-util-forward-comment -1)
958 (when (equal (char-before) ?:)
959 (python-nav-beginning-of-block)))))
960 (when start
961 (cons :after-block-start start))))
962 ;; At dedenter statement.
963 ((let ((start (python-info-dedenter-statement-p)))
964 (when start
965 (cons :at-dedenter-block-start start))))
966 ;; After normal line.
967 ((let ((start (save-excursion
822 (back-to-indentation) 968 (back-to-indentation)
823 (skip-chars-backward (rx (or whitespace ?\n))) 969 (skip-chars-backward " \t\n")
824 (python-nav-beginning-of-statement) 970 (python-nav-beginning-of-statement)
825 (point-marker))) 971 (point))))
826 'after-line) 972 (when start
827 ;; Do not indent 973 (if (save-excursion
828 (t 'no-indent)) 974 (python-util-forward-comment -1)
829 start)))) 975 (python-nav-beginning-of-statement)
830 976 (looking-at (python-rx block-ender)))
831(defun python-indent-calculate-indentation () 977 (cons :after-block-end start)
832 "Calculate correct indentation offset for the current line. 978 (cons :after-line start)))))
833Returns `noindent' if the indentation does not depend on Python syntax, 979 ;; Default case: do not indent.
834such as in strings." 980 (t (cons :no-indent 0))))))
835 (let* ((indentation-context (python-indent-context)) 981
836 (context-status (car indentation-context)) 982(defun python-indent--calculate-indentation ()
837 (context-start (cdr indentation-context))) 983 "Internal implementation of `python-indent-calculate-indentation'.
838 (save-restriction 984May return an integer for the maximum possible indentation at
839 (widen) 985current context or a list of integers. The latter case is only
840 (save-excursion 986happening for :at-dedenter-block-start context since the
841 (pcase context-status 987possibilities can be narrowed to especific indentation points."
842 (`no-indent 0) 988 (save-restriction
843 (`after-comment 989 (widen)
844 (goto-char context-start) 990 (save-excursion
845 (current-indentation)) 991 (pcase (python-indent-context)
846 ;; When point is after beginning of block just add one level 992 (`(:no-indent . ,_) 0)
847 ;; of indentation relative to the context-start 993 (`(,(or :after-line
848 (`after-beginning-of-block 994 :after-comment
849 (goto-char context-start) 995 :inside-string
850 (+ (current-indentation) python-indent-offset)) 996 :after-backslash
851 ;; When after a simple line just use previous line 997 :inside-paren-at-closing-paren
852 ;; indentation. 998 :inside-paren-at-closing-nested-paren) . ,start)
853 (`after-line 999 ;; Copy previous indentation.
854 (let* ((pair (save-excursion 1000 (goto-char start)
855 (goto-char context-start) 1001 (current-indentation))
856 (cons 1002 (`(,(or :after-block-start
857 (current-indentation) 1003 :after-backslash-first-line
858 (python-info-beginning-of-block-p)))) 1004 :inside-paren-newline-start) . ,start)
859 (context-indentation (car pair)) 1005 ;; Add one indentation level.
860 ;; TODO: Separate block enders into its own case. 1006 (goto-char start)
861 (adjustment 1007 (+ (current-indentation) python-indent-offset))
862 (if (save-excursion 1008 (`(,(or :inside-paren
863 (python-util-forward-comment -1) 1009 :after-backslash-block-continuation
864 (python-nav-beginning-of-statement) 1010 :after-backslash-assignment-continuation
865 (looking-at (python-rx block-ender))) 1011 :after-backslash-dotted-continuation) . ,start)
866 python-indent-offset 1012 ;; Use the column given by the context.
867 0))) 1013 (goto-char start)
868 (- context-indentation adjustment))) 1014 (current-column))
869 ;; When point is on a dedenter statement, search for the 1015 (`(:after-block-end . ,start)
870 ;; opening block that corresponds to it and use its 1016 ;; Subtract one indentation level.
871 ;; indentation. If no opening block is found just remove 1017 (goto-char start)
872 ;; indentation as this is an invalid python file. 1018 (- (current-indentation) python-indent-offset))
873 (`dedenter-statement 1019 (`(:at-dedenter-block-start . ,_)
874 (let ((block-start-point 1020 ;; List all possible indentation levels from opening blocks.
875 (python-info-dedenter-opening-block-position))) 1021 (let ((opening-block-start-points
876 (save-excursion 1022 (python-info-dedenter-opening-block-positions)))
877 (if (not block-start-point) 1023 (if (not opening-block-start-points)
878 0 1024 0 ; if not found default to first column
879 (goto-char block-start-point) 1025 (mapcar (lambda (pos)
880 (current-indentation))))) 1026 (save-excursion
881 ;; When inside of a string, do nothing. just use the current 1027 (goto-char pos)
882 ;; indentation. XXX: perhaps it would be a good idea to 1028 (current-indentation)))
883 ;; invoke standard text indentation here 1029 opening-block-start-points))))
884 (`inside-string 'noindent) 1030 (`(,(or :inside-paren-newline-start-from-block) . ,start)
885 ;; After backslash we have several possibilities. 1031 ;; Add two indentation levels to make the suite stand out.
886 (`after-backslash 1032 (goto-char start)
887 (cond 1033 (+ (current-indentation) (* python-indent-offset 2)))))))
888 ;; Check if current line is a dot continuation. For this 1034
889 ;; the current line must start with a dot and previous 1035(defun python-indent--calculate-levels (indentation)
890 ;; line must contain a dot too. 1036 "Calculate levels list given INDENTATION.
891 ((save-excursion 1037Argument INDENTATION can either be an integer or a list of
892 (back-to-indentation) 1038integers. Levels are returned in ascending order, and in the
893 (when (looking-at "\\.") 1039case INDENTATION is a list, this order is enforced."
894 ;; If after moving one line back point is inside a paren it 1040 (if (listp indentation)
895 ;; needs to move back until it's not anymore 1041 (sort (copy-sequence indentation) #'<)
896 (while (prog2 1042 (let* ((remainder (% indentation python-indent-offset))
897 (forward-line -1) 1043 (steps (/ (- indentation remainder) python-indent-offset))
898 (and (not (bobp)) 1044 (levels (mapcar (lambda (step)
899 (python-syntax-context 'paren)))) 1045 (* python-indent-offset step))
900 (goto-char (line-end-position)) 1046 (number-sequence steps 0 -1))))
901 (while (and (re-search-backward 1047 (reverse
902 "\\." (line-beginning-position) t) 1048 (if (not (zerop remainder))
903 (python-syntax-context-type))) 1049 (cons indentation levels)
904 (if (and (looking-at "\\.") 1050 levels)))))
905 (not (python-syntax-context-type))) 1051
906 ;; The indentation is the same column of the 1052(defun python-indent--previous-level (levels indentation)
907 ;; first matching dot that's not inside a 1053 "Return previous level from LEVELS relative to INDENTATION."
908 ;; comment, a string or a paren 1054 (let* ((levels (sort (copy-sequence levels) #'>))
909 (current-column) 1055 (default (car levels)))
910 ;; No dot found on previous line, just add another 1056 (catch 'return
911 ;; indentation level. 1057 (dolist (level levels)
912 (+ (current-indentation) python-indent-offset))))) 1058 (when (funcall #'< level indentation)
913 ;; Check if prev line is a block continuation 1059 (throw 'return level)))
914 ((let ((block-continuation-start 1060 default)))
915 (python-info-block-continuation-line-p))) 1061
916 (when block-continuation-start 1062(defun python-indent-calculate-indentation (&optional previous)
917 ;; If block-continuation-start is set jump to that 1063 "Calculate indentation.
918 ;; marker and use first column after the block start 1064Get indentation of PREVIOUS level when argument is non-nil.
919 ;; as indentation value. 1065Return the max level of the cycle when indentation reaches the
920 (goto-char block-continuation-start) 1066minimum."
921 (re-search-forward 1067 (let* ((indentation (python-indent--calculate-indentation))
922 (python-rx block-start (* space)) 1068 (levels (python-indent--calculate-levels indentation)))
923 (line-end-position) t) 1069 (if previous
924 (current-column)))) 1070 (python-indent--previous-level levels (current-indentation))
925 ;; Check if current line is an assignment continuation 1071 (apply #'max levels))))
926 ((let ((assignment-continuation-start 1072
927 (python-info-assignment-continuation-line-p))) 1073(defun python-indent-line (&optional previous)
928 (when assignment-continuation-start
929 ;; If assignment-continuation is set jump to that
930 ;; marker and use first column after the assignment
931 ;; operator as indentation value.
932 (goto-char assignment-continuation-start)
933 (current-column))))
934 (t
935 (forward-line -1)
936 (goto-char (python-info-beginning-of-backslash))
937 (if (save-excursion
938 (and
939 (forward-line -1)
940 (goto-char
941 (or (python-info-beginning-of-backslash) (point)))
942 (python-info-line-ends-backslash-p)))
943 ;; The two previous lines ended in a backslash so we must
944 ;; respect previous line indentation.
945 (current-indentation)
946 ;; What happens here is that we are dealing with the second
947 ;; line of a backslash continuation, in that case we just going
948 ;; to add one indentation level.
949 (+ (current-indentation) python-indent-offset)))))
950 ;; When inside a paren there's a need to handle nesting
951 ;; correctly
952 (`inside-paren
953 (cond
954 ;; If current line closes the outermost open paren use the
955 ;; current indentation of the context-start line.
956 ((save-excursion
957 (skip-syntax-forward "\s" (line-end-position))
958 (when (and (looking-at (regexp-opt '(")" "]" "}")))
959 (progn
960 (forward-char 1)
961 (not (python-syntax-context 'paren))))
962 (goto-char context-start)
963 (current-indentation))))
964 ;; If open paren is contained on a line by itself add another
965 ;; indentation level, else look for the first word after the
966 ;; opening paren and use it's column position as indentation
967 ;; level.
968 ((let* ((content-starts-in-newline)
969 (indent
970 (save-excursion
971 (if (setq content-starts-in-newline
972 (progn
973 (goto-char context-start)
974 (forward-char)
975 (save-restriction
976 (narrow-to-region
977 (line-beginning-position)
978 (line-end-position))
979 (python-util-forward-comment))
980 (looking-at "$")))
981 (+ (current-indentation) python-indent-offset)
982 (current-column)))))
983 ;; Adjustments
984 (cond
985 ;; If current line closes a nested open paren de-indent one
986 ;; level.
987 ((progn
988 (back-to-indentation)
989 (looking-at (regexp-opt '(")" "]" "}"))))
990 (- indent python-indent-offset))
991 ;; If the line of the opening paren that wraps the current
992 ;; line starts a block add another level of indentation to
993 ;; follow new pep8 recommendation. See: http://ur1.ca/5rojx
994 ((save-excursion
995 (when (and content-starts-in-newline
996 (progn
997 (goto-char context-start)
998 (back-to-indentation)
999 (looking-at (python-rx block-start))))
1000 (+ indent python-indent-offset))))
1001 (t indent)))))))))))
1002
1003(defun python-indent-calculate-levels ()
1004 "Calculate `python-indent-levels' and reset `python-indent-current-level'."
1005 (if (or (python-info-continuation-line-p)
1006 (not (python-info-dedenter-statement-p)))
1007 ;; XXX: This asks for a refactor. Even if point is on a
1008 ;; dedenter statement, it could be multiline and in that case
1009 ;; the continuation lines should be indented with normal rules.
1010 (let* ((indentation (python-indent-calculate-indentation)))
1011 (if (not (numberp indentation))
1012 (setq python-indent-levels indentation)
1013 (let* ((remainder (% indentation python-indent-offset))
1014 (steps (/ (- indentation remainder) python-indent-offset)))
1015 (setq python-indent-levels (list 0))
1016 (dotimes (step steps)
1017 (push (* python-indent-offset (1+ step)) python-indent-levels))
1018 (when (not (eq 0 remainder))
1019 (push (+ (* python-indent-offset steps) remainder)
1020 python-indent-levels)))))
1021 (setq python-indent-levels
1022 (or
1023 (mapcar (lambda (pos)
1024 (save-excursion
1025 (goto-char pos)
1026 (current-indentation)))
1027 (python-info-dedenter-opening-block-positions))
1028 (list 0))))
1029 (when (listp python-indent-levels)
1030 (setq python-indent-current-level (1- (length python-indent-levels))
1031 python-indent-levels (nreverse python-indent-levels))))
1032
1033(defun python-indent-toggle-levels ()
1034 "Toggle `python-indent-current-level' over `python-indent-levels'."
1035 (setq python-indent-current-level (1- python-indent-current-level))
1036 (when (< python-indent-current-level 0)
1037 (setq python-indent-current-level (1- (length python-indent-levels)))))
1038
1039(defun python-indent-line (&optional force-toggle)
1040 "Internal implementation of `python-indent-line-function'. 1074 "Internal implementation of `python-indent-line-function'.
1041Uses the offset calculated in 1075Use the PREVIOUS level when argument is non-nil, otherwise indent
1042`python-indent-calculate-indentation' and available levels 1076to the maxium available level. When indentation is the minimum
1043indicated by the variable `python-indent-levels' to set the 1077possible and PREVIOUS is non-nil, cycle back to the maximum
1044current indentation. 1078level."
1079 (let ((follow-indentation-p
1080 ;; Check if point is within indentation.
1081 (and (<= (line-beginning-position) (point))
1082 (>= (+ (line-beginning-position)
1083 (current-indentation))
1084 (point)))))
1085 (save-excursion
1086 (indent-line-to
1087 (python-indent-calculate-indentation previous))
1088 (python-info-dedenter-opening-block-message))
1089 (when follow-indentation-p
1090 (back-to-indentation))))
1045 1091
1046When the variable `last-command' is equal to one of the symbols 1092(defun python-indent-calculate-levels ()
1047inside `python-indent-trigger-commands' or FORCE-TOGGLE is 1093 "Return possible indentation levels."
1048non-nil it cycles levels indicated in the variable 1094 (python-indent--calculate-levels
1049`python-indent-levels' by setting the current level in the 1095 (python-indent--calculate-indentation)))
1050variable `python-indent-current-level'.
1051
1052When the variable `last-command' is not equal to one of the
1053symbols inside `python-indent-trigger-commands' and FORCE-TOGGLE
1054is nil it calculates possible indentation levels and saves them
1055in the variable `python-indent-levels'. Afterwards it sets the
1056variable `python-indent-current-level' correctly so offset is
1057equal to
1058 (nth python-indent-current-level python-indent-levels)"
1059 (if (and (or (and (memq this-command python-indent-trigger-commands)
1060 (eq last-command this-command))
1061 force-toggle)
1062 (not (equal python-indent-levels '(0))))
1063 (if (listp python-indent-levels)
1064 (python-indent-toggle-levels))
1065 (python-indent-calculate-levels))
1066 (if (eq python-indent-levels 'noindent)
1067 python-indent-levels
1068 (let* ((starting-pos (point-marker))
1069 (indent-ending-position
1070 (+ (line-beginning-position) (current-indentation)))
1071 (follow-indentation-p
1072 (or (bolp)
1073 (and (<= (line-beginning-position) starting-pos)
1074 (>= indent-ending-position starting-pos))))
1075 (next-indent (nth python-indent-current-level python-indent-levels)))
1076 (unless (= next-indent (current-indentation))
1077 (beginning-of-line)
1078 (delete-horizontal-space)
1079 (indent-to next-indent)
1080 (goto-char starting-pos))
1081 (and follow-indentation-p (back-to-indentation)))
1082 (python-info-dedenter-opening-block-message)))
1083 1096
1084(defun python-indent-line-function () 1097(defun python-indent-line-function ()
1085 "`indent-line-function' for Python mode. 1098 "`indent-line-function' for Python mode.
1086See `python-indent-line' for details." 1099When the variable `last-command' is equal to one of the symbols
1087 (python-indent-line)) 1100inside `python-indent-trigger-commands' it cycles possible
1101indentation levels from right to left."
1102 (python-indent-line
1103 (and (memq this-command python-indent-trigger-commands)
1104 (eq last-command this-command))))
1088 1105
1089(defun python-indent-dedent-line () 1106(defun python-indent-dedent-line ()
1090 "De-indent current line." 1107 "De-indent current line."
1091 (interactive "*") 1108 (interactive "*")
1092 (when (and (not (python-syntax-comment-or-string-p)) 1109 (when (and (not (bolp))
1093 (<= (point) (save-excursion 1110 (not (python-syntax-comment-or-string-p))
1094 (back-to-indentation) 1111 (= (+ (line-beginning-position)
1095 (point))) 1112 (current-indentation))
1096 (> (current-column) 0)) 1113 (point)))
1097 (python-indent-line t) 1114 (python-indent-line t)
1098 t)) 1115 t))
1099 1116
1100(defun python-indent-dedent-line-backspace (arg) 1117(defun python-indent-dedent-line-backspace (arg)
1101 "De-indent current line. 1118 "De-indent current line.
1102Argument ARG is passed to `backward-delete-char-untabify' when 1119Argument ARG is passed to `backward-delete-char-untabify' when
1103point is not in between the indentation." 1120point is not in between the indentation."
1104 (interactive "*p") 1121 (interactive "*p")
1105 (when (not (python-indent-dedent-line)) 1122 (unless (python-indent-dedent-line)
1106 (backward-delete-char-untabify arg))) 1123 (backward-delete-char-untabify arg)))
1124
1107(put 'python-indent-dedent-line-backspace 'delete-selection 'supersede) 1125(put 'python-indent-dedent-line-backspace 'delete-selection 'supersede)
1108 1126
1109(defun python-indent-region (start end) 1127(defun python-indent-region (start end)