aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el1126
1 files changed, 701 insertions, 425 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 601850ed0fb..67388c0339b 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -33,7 +33,7 @@
33;; Implements Syntax highlighting, Indentation, Movement, Shell 33;; Implements Syntax highlighting, Indentation, Movement, Shell
34;; interaction, Shell completion, Shell virtualenv support, Pdb 34;; interaction, Shell completion, Shell virtualenv support, Pdb
35;; tracking, Symbol completion, Skeletons, FFAP, Code Check, Eldoc, 35;; tracking, Symbol completion, Skeletons, FFAP, Code Check, Eldoc,
36;; imenu. 36;; Imenu.
37 37
38;; Syntax highlighting: Fontification of code is provided and supports 38;; Syntax highlighting: Fontification of code is provided and supports
39;; python's triple quoted strings properly. 39;; python's triple quoted strings properly.
@@ -169,10 +169,12 @@
169;; might guessed you should run `python-shell-send-buffer' from time 169;; might guessed you should run `python-shell-send-buffer' from time
170;; to time to get better results too. 170;; to time to get better results too.
171 171
172;; imenu: This mode supports imenu in its most basic form, letting it 172;; Imenu: This mode supports Imenu in its most basic form, letting it
173;; build the necessary alist via `imenu-default-create-index-function' 173;; build the necessary alist via `imenu-default-create-index-function'
174;; by having set `imenu-extract-index-name-function' to 174;; by having set `imenu-extract-index-name-function' to
175;; `python-info-current-defun'. 175;; `python-info-current-defun' and
176;; `imenu-prev-index-position-function' to
177;; `python-imenu-prev-index-position'.
176 178
177;; If you used python-mode.el you probably will miss auto-indentation 179;; If you used python-mode.el you probably will miss auto-indentation
178;; when inserting newlines. To achieve the same behavior you have 180;; when inserting newlines. To achieve the same behavior you have
@@ -202,13 +204,12 @@
202 204
203(require 'ansi-color) 205(require 'ansi-color)
204(require 'comint) 206(require 'comint)
207(eval-when-compile (require 'cl-lib))
205 208
206(eval-when-compile 209;; Avoid compiler warnings
207 (require 'cl) 210(defvar view-return-to-alist)
208 ;; Avoid compiler warnings 211(defvar compilation-error-regexp-alist)
209 (defvar view-return-to-alist) 212(defvar outline-heading-end-regexp)
210 (defvar compilation-error-regexp-alist)
211 (defvar outline-heading-end-regexp))
212 213
213(autoload 'comint-mode "comint") 214(autoload 'comint-mode "comint")
214 215
@@ -229,12 +230,9 @@
229(defvar python-mode-map 230(defvar python-mode-map
230 (let ((map (make-sparse-keymap))) 231 (let ((map (make-sparse-keymap)))
231 ;; Movement 232 ;; Movement
232 (substitute-key-definition 'backward-sentence 233 (define-key map [remap backward-sentence] 'python-nav-backward-block)
233 'python-nav-backward-block 234 (define-key map [remap forward-sentence] 'python-nav-forward-block)
234 map global-map) 235 (define-key map [remap backward-up-list] 'python-nav-backward-up-list)
235 (substitute-key-definition 'forward-sentence
236 'python-nav-forward-block
237 map global-map)
238 (define-key map "\C-c\C-j" 'imenu) 236 (define-key map "\C-c\C-j" 'imenu)
239 ;; Indent specific 237 ;; Indent specific
240 (define-key map "\177" 'python-indent-dedent-line-backspace) 238 (define-key map "\177" 'python-indent-dedent-line-backspace)
@@ -337,19 +335,28 @@
337 "==" ">=" "is" "not"))) 335 "==" ">=" "is" "not")))
338 ;; FIXME: Use regexp-opt. 336 ;; FIXME: Use regexp-opt.
339 (assignment-operator . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**=" 337 (assignment-operator . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**="
340 ">>=" "<<=" "&=" "^=" "|=")))) 338 ">>=" "<<=" "&=" "^=" "|=")))
341 "Additional Python specific sexps for `python-rx'")) 339 (string-delimiter . ,(rx (and
342 340 ;; Match even number of backslashes.
343(defmacro python-rx (&rest regexps) 341 (or (not (any ?\\ ?\' ?\")) point
344 "Python mode specialized rx macro. 342 ;; Quotes might be preceded by a escaped quote.
343 (and (or (not (any ?\\)) point) ?\\
344 (* ?\\ ?\\) (any ?\' ?\")))
345 (* ?\\ ?\\)
346 ;; Match single or triple quotes of any kind.
347 (group (or "\"" "\"\"\"" "'" "'''"))))))
348 "Additional Python specific sexps for `python-rx'")
349
350 (defmacro python-rx (&rest regexps)
351 "Python mode specialized rx macro.
345This variant of `rx' supports common python named REGEXPS." 352This variant of `rx' supports common python named REGEXPS."
346 (let ((rx-constituents (append python-rx-constituents rx-constituents))) 353 (let ((rx-constituents (append python-rx-constituents rx-constituents)))
347 (cond ((null regexps) 354 (cond ((null regexps)
348 (error "No regexp")) 355 (error "No regexp"))
349 ((cdr regexps) 356 ((cdr regexps)
350 (rx-to-string `(and ,@regexps) t)) 357 (rx-to-string `(and ,@regexps) t))
351 (t 358 (t
352 (rx-to-string (car regexps) t))))) 359 (rx-to-string (car regexps) t))))))
353 360
354 361
355;;; Font-lock and syntax 362;;; Font-lock and syntax
@@ -358,12 +365,24 @@ This variant of `rx' supports common python named REGEXPS."
358 "Return non-nil if point is on TYPE using SYNTAX-PPSS. 365 "Return non-nil if point is on TYPE using SYNTAX-PPSS.
359TYPE can be `comment', `string' or `paren'. It returns the start 366TYPE can be `comment', `string' or `paren'. It returns the start
360character address of the specified TYPE." 367character address of the specified TYPE."
368 (declare (compiler-macro
369 (lambda (form)
370 (pcase type
371 (`'comment
372 `(let ((ppss (or ,syntax-ppss (syntax-ppss))))
373 (and (nth 4 ppss) (nth 8 ppss))))
374 (`'string
375 `(let ((ppss (or ,syntax-ppss (syntax-ppss))))
376 (and (nth 3 ppss) (nth 8 ppss))))
377 (`'paren
378 `(nth 1 (or ,syntax-ppss (syntax-ppss))))
379 (_ form)))))
361 (let ((ppss (or syntax-ppss (syntax-ppss)))) 380 (let ((ppss (or syntax-ppss (syntax-ppss))))
362 (case type 381 (pcase type
363 (comment (and (nth 4 ppss) (nth 8 ppss))) 382 (`comment (and (nth 4 ppss) (nth 8 ppss)))
364 (string (and (not (nth 4 ppss)) (nth 8 ppss))) 383 (`string (and (nth 3 ppss) (nth 8 ppss)))
365 (paren (nth 1 ppss)) 384 (`paren (nth 1 ppss))
366 (t nil)))) 385 (_ nil))))
367 386
368(defun python-syntax-context-type (&optional syntax-ppss) 387(defun python-syntax-context-type (&optional syntax-ppss)
369 "Return the context type using SYNTAX-PPSS. 388 "Return the context type using SYNTAX-PPSS.
@@ -475,8 +494,8 @@ The type returned can be `comment', `string' or `paren'."
475 (when (re-search-forward re limit t) 494 (when (re-search-forward re limit t)
476 (while (and (python-syntax-context 'paren) 495 (while (and (python-syntax-context 'paren)
477 (re-search-forward re limit t))) 496 (re-search-forward re limit t)))
478 (if (and (not (python-syntax-context 'paren)) 497 (if (not (or (python-syntax-context 'paren)
479 (not (equal (char-after (point-marker)) ?=))) 498 (equal (char-after (point-marker)) ?=)))
480 t 499 t
481 (set-match-data nil))))) 500 (set-match-data nil)))))
482 (1 font-lock-variable-name-face nil nil)) 501 (1 font-lock-variable-name-face nil nil))
@@ -497,52 +516,54 @@ The type returned can be `comment', `string' or `paren'."
497 (1 font-lock-variable-name-face nil nil)))) 516 (1 font-lock-variable-name-face nil nil))))
498 517
499(defconst python-syntax-propertize-function 518(defconst python-syntax-propertize-function
500 ;; Make outer chars of matching triple-quote sequences into generic
501 ;; string delimiters. Fixme: Is there a better way?
502 ;; First avoid a sequence preceded by an odd number of backslashes.
503 (syntax-propertize-rules 519 (syntax-propertize-rules
504 (;; ¡Backrefs don't work in syntax-propertize-rules! 520 ((python-rx string-delimiter)
505 (concat "\\(?:\\([RUru]\\)[Rr]?\\|^\\|[^\\]\\(?:\\\\.\\)*\\)" ;Prefix. 521 (0 (ignore (python-syntax-stringify))))))
506 "\\(?:\\('\\)'\\('\\)\\|\\(?2:\"\\)\"\\(?3:\"\\)\\)") 522
507 (3 (ignore (python-quote-syntax)))))) 523(defsubst python-syntax-count-quotes (quote-char &optional point limit)
508 524 "Count number of quotes around point (max is 3).
509(defun python-quote-syntax () 525QUOTE-CHAR is the quote char to count. Optional argument POINT is
510 "Put `syntax-table' property correctly on triple quote. 526the point where scan starts (defaults to current point) and LIMIT
511Used for syntactic keywords. N is the match number (1, 2 or 3)." 527is used to limit the scan."
512 ;; Given a triple quote, we have to check the context to know 528 (let ((i 0))
513 ;; whether this is an opening or closing triple or whether it's 529 (while (and (< i 3)
514 ;; quoted anyhow, and should be ignored. (For that we need to do 530 (or (not limit) (< (+ point i) limit))
515 ;; the same job as `syntax-ppss' to be correct and it seems to be OK 531 (eq (char-after (+ point i)) quote-char))
516 ;; to use it here despite initial worries.) We also have to sort 532 (cl-incf i))
517 ;; out a possible prefix -- well, we don't _have_ to, but I think it 533 i))
518 ;; should be treated as part of the string. 534
519 535(defun python-syntax-stringify ()
520 ;; Test cases: 536 "Put `syntax-table' property correctly on single/triple quotes."
521 ;; ur"""ar""" x='"' # """ 537 (let* ((num-quotes (length (match-string-no-properties 1)))
522 ;; x = ''' """ ' a 538 (ppss (prog2
523 ;; ''' 539 (backward-char num-quotes)
524 ;; x '"""' x """ \"""" x 540 (syntax-ppss)
525 (save-excursion 541 (forward-char num-quotes)))
526 (goto-char (match-beginning 0)) 542 (string-start (and (not (nth 4 ppss)) (nth 8 ppss)))
527 (let ((syntax (save-match-data (syntax-ppss)))) 543 (quote-starting-pos (- (point) num-quotes))
528 (cond 544 (quote-ending-pos (point))
529 ((eq t (nth 3 syntax)) ; after unclosed fence 545 (num-closing-quotes
530 ;; Consider property for the last char if in a fenced string. 546 (and string-start
531 (goto-char (nth 8 syntax)) ; fence position 547 (python-syntax-count-quotes
532 (skip-chars-forward "uUrR") ; skip any prefix 548 (char-before) string-start quote-starting-pos))))
533 ;; Is it a matching sequence? 549 (cond ((and string-start (= num-closing-quotes 0))
534 (if (eq (char-after) (char-after (match-beginning 2))) 550 ;; This set of quotes doesn't match the string starting
535 (put-text-property (match-beginning 3) (match-end 3) 551 ;; kind. Do nothing.
536 'syntax-table (string-to-syntax "|")))) 552 nil)
537 ((match-end 1) 553 ((not string-start)
538 ;; Consider property for initial char, accounting for prefixes. 554 ;; This set of quotes delimit the start of a string.
539 (put-text-property (match-beginning 1) (match-end 1) 555 (put-text-property quote-starting-pos (1+ quote-starting-pos)
540 'syntax-table (string-to-syntax "|"))) 556 'syntax-table (string-to-syntax "|")))
541 (t 557 ((= num-quotes num-closing-quotes)
542 ;; Consider property for initial char, accounting for prefixes. 558 ;; This set of quotes delimit the end of a string.
543 (put-text-property (match-beginning 2) (match-end 2) 559 (put-text-property (1- quote-ending-pos) quote-ending-pos
544 'syntax-table (string-to-syntax "|")))) 560 'syntax-table (string-to-syntax "|")))
545 ))) 561 ((> num-quotes num-closing-quotes)
562 ;; This may only happen whenever a triple quote is closing
563 ;; a single quoted string. Add string delimiter syntax to
564 ;; all three quotes.
565 (put-text-property quote-starting-pos quote-ending-pos
566 'syntax-table (string-to-syntax "|"))))))
546 567
547(defvar python-mode-syntax-table 568(defvar python-mode-syntax-table
548 (let ((table (make-syntax-table))) 569 (let ((table (make-syntax-table)))
@@ -637,7 +658,7 @@ These make `python-indent-calculate-indentation' subtract the value of
637 (python-util-forward-comment) 658 (python-util-forward-comment)
638 (current-indentation)))) 659 (current-indentation))))
639 (if indentation 660 (if indentation
640 (setq python-indent-offset indentation) 661 (set (make-local-variable 'python-indent-offset) indentation)
641 (message "Can't guess python-indent-offset, using defaults: %s" 662 (message "Can't guess python-indent-offset, using defaults: %s"
642 python-indent-offset))))))) 663 python-indent-offset)))))))
643 664
@@ -665,12 +686,12 @@ START is the buffer position where the sexp starts."
665 (goto-char (line-beginning-position)) 686 (goto-char (line-beginning-position))
666 (bobp)) 687 (bobp))
667 'no-indent) 688 'no-indent)
668 ;; Inside a paren
669 ((setq start (python-syntax-context 'paren ppss))
670 'inside-paren)
671 ;; Inside string 689 ;; Inside string
672 ((setq start (python-syntax-context 'string ppss)) 690 ((setq start (python-syntax-context 'string ppss))
673 'inside-string) 691 'inside-string)
692 ;; Inside a paren
693 ((setq start (python-syntax-context 'paren ppss))
694 'inside-paren)
674 ;; After backslash 695 ;; After backslash
675 ((setq start (when (not (or (python-syntax-context 'string ppss) 696 ((setq start (when (not (or (python-syntax-context 'string ppss)
676 (python-syntax-context 'comment ppss))) 697 (python-syntax-context 'comment ppss)))
@@ -699,7 +720,7 @@ START is the buffer position where the sexp starts."
699 ;; After normal line 720 ;; After normal line
700 ((setq start (save-excursion 721 ((setq start (save-excursion
701 (back-to-indentation) 722 (back-to-indentation)
702 (python-util-forward-comment -1) 723 (skip-chars-backward (rx (or whitespace ?\n)))
703 (python-nav-beginning-of-statement) 724 (python-nav-beginning-of-statement)
704 (point-marker))) 725 (point-marker)))
705 'after-line) 726 'after-line)
@@ -715,17 +736,17 @@ START is the buffer position where the sexp starts."
715 (save-restriction 736 (save-restriction
716 (widen) 737 (widen)
717 (save-excursion 738 (save-excursion
718 (case context-status 739 (pcase context-status
719 ('no-indent 0) 740 (`no-indent 0)
720 ;; When point is after beginning of block just add one level 741 ;; When point is after beginning of block just add one level
721 ;; of indentation relative to the context-start 742 ;; of indentation relative to the context-start
722 ('after-beginning-of-block 743 (`after-beginning-of-block
723 (goto-char context-start) 744 (goto-char context-start)
724 (+ (current-indentation) python-indent-offset)) 745 (+ (current-indentation) python-indent-offset))
725 ;; When after a simple line just use previous line 746 ;; When after a simple line just use previous line
726 ;; indentation, in the case current line starts with a 747 ;; indentation, in the case current line starts with a
727 ;; `python-indent-dedenters' de-indent one level. 748 ;; `python-indent-dedenters' de-indent one level.
728 ('after-line 749 (`after-line
729 (- 750 (-
730 (save-excursion 751 (save-excursion
731 (goto-char context-start) 752 (goto-char context-start)
@@ -738,11 +759,11 @@ START is the buffer position where the sexp starts."
738 ;; When inside of a string, do nothing. just use the current 759 ;; When inside of a string, do nothing. just use the current
739 ;; indentation. XXX: perhaps it would be a good idea to 760 ;; indentation. XXX: perhaps it would be a good idea to
740 ;; invoke standard text indentation here 761 ;; invoke standard text indentation here
741 ('inside-string 762 (`inside-string
742 (goto-char context-start) 763 (goto-char context-start)
743 (current-indentation)) 764 (current-indentation))
744 ;; After backslash we have several possibilities. 765 ;; After backslash we have several possibilities.
745 ('after-backslash 766 (`after-backslash
746 (cond 767 (cond
747 ;; Check if current line is a dot continuation. For this 768 ;; Check if current line is a dot continuation. For this
748 ;; the current line must start with a dot and previous 769 ;; the current line must start with a dot and previous
@@ -808,7 +829,7 @@ START is the buffer position where the sexp starts."
808 (+ (current-indentation) python-indent-offset))))) 829 (+ (current-indentation) python-indent-offset)))))
809 ;; When inside a paren there's a need to handle nesting 830 ;; When inside a paren there's a need to handle nesting
810 ;; correctly 831 ;; correctly
811 ('inside-paren 832 (`inside-paren
812 (cond 833 (cond
813 ;; If current line closes the outermost open paren use the 834 ;; If current line closes the outermost open paren use the
814 ;; current indentation of the context-start line. 835 ;; current indentation of the context-start line.
@@ -897,16 +918,27 @@ possible indentation levels and saves it in the variable
897`python-indent-levels'. Afterwards it sets the variable 918`python-indent-levels'. Afterwards it sets the variable
898`python-indent-current-level' correctly so offset is equal 919`python-indent-current-level' correctly so offset is equal
899to (`nth' `python-indent-current-level' `python-indent-levels')" 920to (`nth' `python-indent-current-level' `python-indent-levels')"
900 (if (or (and (eq this-command 'indent-for-tab-command) 921 (or
901 (eq last-command this-command)) 922 (and (or (and (eq this-command 'indent-for-tab-command)
902 force-toggle) 923 (eq last-command this-command))
903 (if (not (equal python-indent-levels '(0))) 924 force-toggle)
904 (python-indent-toggle-levels) 925 (not (equal python-indent-levels '(0)))
905 (python-indent-calculate-levels)) 926 (or (python-indent-toggle-levels) t))
906 (python-indent-calculate-levels)) 927 (python-indent-calculate-levels))
907 (beginning-of-line) 928 (let* ((starting-pos (point-marker))
908 (delete-horizontal-space) 929 (indent-ending-position
909 (indent-to (nth python-indent-current-level python-indent-levels)) 930 (+ (line-beginning-position) (current-indentation)))
931 (follow-indentation-p
932 (or (bolp)
933 (and (<= (line-beginning-position) starting-pos)
934 (>= indent-ending-position starting-pos))))
935 (next-indent (nth python-indent-current-level python-indent-levels)))
936 (unless (= next-indent (current-indentation))
937 (beginning-of-line)
938 (delete-horizontal-space)
939 (indent-to next-indent)
940 (goto-char starting-pos))
941 (and follow-indentation-p (back-to-indentation)))
910 (python-info-closing-block-message)) 942 (python-info-closing-block-message))
911 943
912(defun python-indent-line-function () 944(defun python-indent-line-function ()
@@ -951,7 +983,16 @@ Called from a program, START and END specify the region to indent."
951 (back-to-indentation) 983 (back-to-indentation)
952 (setq word (current-word)) 984 (setq word (current-word))
953 (forward-line 1) 985 (forward-line 1)
954 (when word 986 (when (and word
987 ;; Don't mess with strings, unless it's the
988 ;; enclosing set of quotes.
989 (or (not (python-syntax-context 'string))
990 (eq
991 (syntax-after
992 (+ (1- (point))
993 (current-indentation)
994 (python-syntax-count-quotes (char-after) (point))))
995 (string-to-syntax "|"))))
955 (beginning-of-line) 996 (beginning-of-line)
956 (delete-horizontal-space) 997 (delete-horizontal-space)
957 (indent-to (python-indent-calculate-indentation))))) 998 (indent-to (python-indent-calculate-indentation)))))
@@ -1046,12 +1087,9 @@ automatically if needed."
1046The name of the defun should be grouped so it can be retrieved 1087The name of the defun should be grouped so it can be retrieved
1047via `match-string'.") 1088via `match-string'.")
1048 1089
1049(defun python-nav-beginning-of-defun (&optional arg) 1090(defun python-nav--beginning-of-defun (&optional arg)
1050 "Move point to `beginning-of-defun'. 1091 "Internal implementation of `python-nav-beginning-of-defun'.
1051With positive ARG move search backwards. With negative do the 1092With positive ARG search backwards, else search forwards."
1052same but forward. When ARG is nil or 0 defaults to 1. This is
1053the main part of `python-beginning-of-defun-function'. Return
1054non-nil if point is moved to `beginning-of-defun'."
1055 (when (or (null arg) (= arg 0)) (setq arg 1)) 1093 (when (or (null arg) (= arg 0)) (setq arg 1))
1056 (let* ((re-search-fn (if (> arg 0) 1094 (let* ((re-search-fn (if (> arg 0)
1057 #'re-search-backward 1095 #'re-search-backward
@@ -1059,6 +1097,15 @@ non-nil if point is moved to `beginning-of-defun'."
1059 (line-beg-pos (line-beginning-position)) 1097 (line-beg-pos (line-beginning-position))
1060 (line-content-start (+ line-beg-pos (current-indentation))) 1098 (line-content-start (+ line-beg-pos (current-indentation)))
1061 (pos (point-marker)) 1099 (pos (point-marker))
1100 (beg-indentation
1101 (and (> arg 0)
1102 (save-excursion
1103 (while (and
1104 (not (python-info-looking-at-beginning-of-defun))
1105 (python-nav-backward-block)))
1106 (or (and (python-info-looking-at-beginning-of-defun)
1107 (+ (current-indentation) python-indent-offset))
1108 0))))
1062 (found 1109 (found
1063 (progn 1110 (progn
1064 (when (and (< arg 0) 1111 (when (and (< arg 0)
@@ -1066,7 +1113,12 @@ non-nil if point is moved to `beginning-of-defun'."
1066 (end-of-line 1)) 1113 (end-of-line 1))
1067 (while (and (funcall re-search-fn 1114 (while (and (funcall re-search-fn
1068 python-nav-beginning-of-defun-regexp nil t) 1115 python-nav-beginning-of-defun-regexp nil t)
1069 (python-syntax-context-type))) 1116 (or (python-syntax-context-type)
1117 ;; Handle nested defuns when moving
1118 ;; backwards by checking indentation.
1119 (and (> arg 0)
1120 (not (= (current-indentation) 0))
1121 (>= (current-indentation) beg-indentation)))))
1070 (and (python-info-looking-at-beginning-of-defun) 1122 (and (python-info-looking-at-beginning-of-defun)
1071 (or (not (= (line-number-at-pos pos) 1123 (or (not (= (line-number-at-pos pos)
1072 (line-number-at-pos))) 1124 (line-number-at-pos)))
@@ -1077,55 +1129,43 @@ non-nil if point is moved to `beginning-of-defun'."
1077 (or (beginning-of-line 1) t) 1129 (or (beginning-of-line 1) t)
1078 (and (goto-char pos) nil)))) 1130 (and (goto-char pos) nil))))
1079 1131
1080(defun python-beginning-of-defun-function (&optional arg) 1132(defun python-nav-beginning-of-defun (&optional arg)
1081 "Move point to the beginning of def or class. 1133 "Move point to `beginning-of-defun'.
1082With positive ARG move that number of functions backwards. With 1134With positive ARG search backwards else search forward. When ARG
1083negative do the same but forward. When ARG is nil or 0 defaults 1135is nil or 0 defaults to 1. When searching backwards nested
1084to 1. Return non-nil if point is moved to `beginning-of-defun'." 1136defuns are handled with care depending on current point
1137position. Return non-nil if point is moved to
1138`beginning-of-defun'."
1085 (when (or (null arg) (= arg 0)) (setq arg 1)) 1139 (when (or (null arg) (= arg 0)) (setq arg 1))
1086 (let ((found)) 1140 (let ((found))
1087 (cond ((and (eq this-command 'mark-defun) 1141 (cond ((and (eq this-command 'mark-defun)
1088 (python-info-looking-at-beginning-of-defun))) 1142 (python-info-looking-at-beginning-of-defun)))
1089 (t 1143 (t
1090 (dotimes (i (if (> arg 0) arg (- arg))) 1144 (dotimes (i (if (> arg 0) arg (- arg)))
1091 (when (and (python-nav-beginning-of-defun arg) 1145 (when (and (python-nav--beginning-of-defun arg)
1092 (not found)) 1146 (not found))
1093 (setq found t))))) 1147 (setq found t)))))
1094 found)) 1148 found))
1095 1149
1096(defun python-end-of-defun-function () 1150(defun python-nav-end-of-defun ()
1097 "Move point to the end of def or class. 1151 "Move point to the end of def or class.
1098Returns nil if point is not in a def or class." 1152Returns nil if point is not in a def or class."
1099 (interactive) 1153 (interactive)
1100 (let ((beg-defun-indent)) 1154 (let ((beg-defun-indent)
1155 (beg-pos (point)))
1101 (when (or (python-info-looking-at-beginning-of-defun) 1156 (when (or (python-info-looking-at-beginning-of-defun)
1102 (python-beginning-of-defun-function 1) 1157 (python-nav-beginning-of-defun 1)
1103 (python-beginning-of-defun-function -1)) 1158 (python-nav-beginning-of-defun -1))
1104 (setq beg-defun-indent (current-indentation)) 1159 (setq beg-defun-indent (current-indentation))
1160 (while (progn
1161 (python-nav-end-of-statement)
1162 (python-util-forward-comment 1)
1163 (and (> (current-indentation) beg-defun-indent)
1164 (not (eobp)))))
1165 (python-util-forward-comment -1)
1105 (forward-line 1) 1166 (forward-line 1)
1106 ;; Go as forward as possible 1167 ;; Ensure point moves forward.
1107 (while (and (or 1168 (and (> beg-pos (point)) (goto-char beg-pos)))))
1108 (python-nav-beginning-of-defun -1)
1109 (and (goto-char (point-max)) nil))
1110 (> (current-indentation) beg-defun-indent)))
1111 (beginning-of-line 1)
1112 ;; Go as backwards as possible
1113 (while (and (forward-line -1)
1114 (not (bobp))
1115 (or (not (current-word))
1116 (equal (char-after (+ (point) (current-indentation))) ?#)
1117 (<= (current-indentation) beg-defun-indent)
1118 (looking-at (python-rx decorator))
1119 (python-syntax-context-type))))
1120 (forward-line 1)
1121 ;; If point falls inside a paren or string context the point is
1122 ;; forwarded at the end of it (or end of buffer if its not closed)
1123 (let ((context-type (python-syntax-context-type)))
1124 (when (memq context-type '(paren string))
1125 ;; Slow but safe.
1126 (while (and (not (eobp))
1127 (python-syntax-context-type))
1128 (forward-line 1)))))))
1129 1169
1130(defun python-nav-beginning-of-statement () 1170(defun python-nav-beginning-of-statement ()
1131 "Move to start of current statement." 1171 "Move to start of current statement."
@@ -1138,7 +1178,8 @@ Returns nil if point is not in a def or class."
1138 (python-info-line-ends-backslash-p)) 1178 (python-info-line-ends-backslash-p))
1139 (python-syntax-context 'string) 1179 (python-syntax-context 'string)
1140 (python-syntax-context 'paren)) 1180 (python-syntax-context 'paren))
1141 (forward-line -1))))) 1181 (forward-line -1))))
1182 (point-marker))
1142 1183
1143(defun python-nav-end-of-statement () 1184(defun python-nav-end-of-statement ()
1144 "Move to end of current statement." 1185 "Move to end of current statement."
@@ -1149,7 +1190,8 @@ Returns nil if point is not in a def or class."
1149 (python-info-line-ends-backslash-p) 1190 (python-info-line-ends-backslash-p)
1150 (python-syntax-context 'string) 1191 (python-syntax-context 'string)
1151 (python-syntax-context 'paren)) 1192 (python-syntax-context 'paren))
1152 (forward-line 1))))) 1193 (forward-line 1))))
1194 (point-marker))
1153 1195
1154(defun python-nav-backward-statement (&optional arg) 1196(defun python-nav-backward-statement (&optional arg)
1155 "Move backward to previous statement. 1197 "Move backward to previous statement.
@@ -1264,151 +1306,104 @@ When ARG > 0 move forward, else if ARG is < 0."
1264 (while (and (funcall search-fn paren-regexp nil t) 1306 (while (and (funcall search-fn paren-regexp nil t)
1265 (python-syntax-context 'paren))))))) 1307 (python-syntax-context 'paren)))))))
1266 1308
1267(defun python-nav--forward-sexp () 1309(defun python-nav--forward-sexp (&optional dir)
1268 "Move to forward sexp." 1310 "Move to forward sexp.
1269 (case (python-syntax-context-type) 1311With positive Optional argument DIR direction move forward, else
1270 (string 1312backwards."
1271 ;; Inside of a string, get out of it. 1313 (setq dir (or dir 1))
1272 (while (and (re-search-forward "[\"']" nil t) 1314 (unless (= dir 0)
1273 (python-syntax-context 'string)))) 1315 (let* ((forward-p (if (> dir 0)
1274 (comment 1316 (and (setq dir 1) t)
1275 ;; Inside of a comment, just move forward. 1317 (and (setq dir -1) nil)))
1276 (python-util-forward-comment)) 1318 (re-search-fn (if forward-p
1277 (paren 1319 're-search-forward
1278 (python-nav-lisp-forward-sexp-safe 1)) 1320 're-search-backward))
1279 (t 1321 (context-type (python-syntax-context-type)))
1280 (if (and (not (eobp)) 1322 (cond
1281 (= (syntax-class (syntax-after (point))) 4)) 1323 ((eq context-type 'string)
1282 ;; Looking an open-paren 1324 ;; Inside of a string, get out of it.
1283 (python-nav-lisp-forward-sexp-safe 1) 1325 (while (and (funcall re-search-fn "[\"']" nil t)
1284 (let ((block-starting-pos 1326 (python-syntax-context 'string))))
1285 (save-excursion (python-nav-beginning-of-block))) 1327 ((eq context-type 'comment)
1286 (block-ending-pos 1328 ;; Inside of a comment, just move forward.
1287 (save-excursion (python-nav-end-of-block))) 1329 (python-util-forward-comment dir))
1288 (next-block-starting-pos 1330 ((or (eq context-type 'paren)
1289 (save-excursion (python-nav-forward-block)))) 1331 (and forward-p (looking-at (python-rx open-paren)))
1290 (cond 1332 (and (not forward-p)
1291 ((not block-starting-pos) 1333 (eq (syntax-class (syntax-after (1- (point))))
1292 ;; Not inside a block, move to closest one. 1334 (car (string-to-syntax ")")))))
1293 (and next-block-starting-pos 1335 ;; Inside a paren or looking at it, lisp knows what to do.
1294 (goto-char next-block-starting-pos))) 1336 (python-nav-lisp-forward-sexp-safe dir))
1295 ((= (point) block-starting-pos) 1337 (t
1296 ;; Point is at beginning of block 1338 ;; This part handles the lispy feel of
1297 (if (and next-block-starting-pos 1339 ;; `python-nav-forward-sexp'. Knowing everything about the
1298 (< next-block-starting-pos block-ending-pos)) 1340 ;; current context and the context of the next sexp tries to
1299 ;; Beginning of next block is closer than current's 1341 ;; follow the lisp sexp motion commands in a symmetric manner.
1300 ;; end, move to it. 1342 (let* ((context
1301 (goto-char next-block-starting-pos) 1343 (cond
1302 (goto-char block-ending-pos))) 1344 ((python-info-beginning-of-block-p) 'block-start)
1303 ((= block-ending-pos (point)) 1345 ((python-info-end-of-block-p) 'block-end)
1304 ;; Point is at end of current block 1346 ((python-info-beginning-of-statement-p) 'statement-start)
1305 (let ((parent-block-end-pos 1347 ((python-info-end-of-statement-p) 'statement-end)))
1306 (save-excursion 1348 (next-sexp-pos
1307 (python-util-forward-comment) 1349 (save-excursion
1308 (python-nav-beginning-of-block) 1350 (python-nav-lisp-forward-sexp-safe dir)
1309 (python-nav-end-of-block)))) 1351 (point)))
1310 (if (and parent-block-end-pos 1352 (next-sexp-context
1311 (or (not next-block-starting-pos) 1353 (save-excursion
1312 (> next-block-starting-pos parent-block-end-pos))) 1354 (goto-char next-sexp-pos)
1313 ;; If the parent block ends before next block 1355 (cond
1314 ;; starts move to it. 1356 ((python-info-beginning-of-block-p) 'block-start)
1315 (goto-char parent-block-end-pos) 1357 ((python-info-end-of-block-p) 'block-end)
1316 (and next-block-starting-pos 1358 ((python-info-beginning-of-statement-p) 'statement-start)
1317 (goto-char next-block-starting-pos))))) 1359 ((python-info-end-of-statement-p) 'statement-end)
1318 (t (python-nav-end-of-block)))))))) 1360 ((python-info-statement-starts-block-p) 'starts-block)
1361 ((python-info-statement-ends-block-p) 'ends-block)))))
1362 (if forward-p
1363 (cond ((and (not (eobp))
1364 (python-info-current-line-empty-p))
1365 (python-util-forward-comment dir)
1366 (python-nav--forward-sexp dir))
1367 ((eq context 'block-start)
1368 (python-nav-end-of-block))
1369 ((eq context 'statement-start)
1370 (python-nav-end-of-statement))
1371 ((and (memq context '(statement-end block-end))
1372 (eq next-sexp-context 'ends-block))
1373 (goto-char next-sexp-pos)
1374 (python-nav-end-of-block))
1375 ((and (memq context '(statement-end block-end))
1376 (eq next-sexp-context 'starts-block))
1377 (goto-char next-sexp-pos)
1378 (python-nav-end-of-block))
1379 ((memq context '(statement-end block-end))
1380 (goto-char next-sexp-pos)
1381 (python-nav-end-of-statement))
1382 (t (goto-char next-sexp-pos)))
1383 (cond ((and (not (bobp))
1384 (python-info-current-line-empty-p))
1385 (python-util-forward-comment dir)
1386 (python-nav--forward-sexp dir))
1387 ((eq context 'block-end)
1388 (python-nav-beginning-of-block))
1389 ((eq context 'statement-end)
1390 (python-nav-beginning-of-statement))
1391 ((and (memq context '(statement-start block-start))
1392 (eq next-sexp-context 'starts-block))
1393 (goto-char next-sexp-pos)
1394 (python-nav-beginning-of-block))
1395 ((and (memq context '(statement-start block-start))
1396 (eq next-sexp-context 'ends-block))
1397 (goto-char next-sexp-pos)
1398 (python-nav-beginning-of-block))
1399 ((memq context '(statement-start block-start))
1400 (goto-char next-sexp-pos)
1401 (python-nav-beginning-of-statement))
1402 (t (goto-char next-sexp-pos))))))))))
1319 1403
1320(defun python-nav--backward-sexp () 1404(defun python-nav--backward-sexp ()
1321 "Move to backward sexp." 1405 "Move to backward sexp."
1322 (case (python-syntax-context-type) 1406 (python-nav--forward-sexp -1))
1323 (string
1324 ;; Inside of a string, get out of it.
1325 (while (and (re-search-backward "[\"']" nil t)
1326 (python-syntax-context 'string))))
1327 (comment
1328 ;; Inside of a comment, just move backward.
1329 (python-util-forward-comment -1))
1330 (paren
1331 ;; Handle parens like we are lisp.
1332 (python-nav-lisp-forward-sexp-safe -1))
1333 (t
1334 (let* ((block-starting-pos
1335 (save-excursion (python-nav-beginning-of-block)))
1336 (block-ending-pos
1337 (save-excursion (python-nav-end-of-block)))
1338 (prev-block-ending-pos
1339 (save-excursion (when (python-nav-backward-block)
1340 (python-nav-end-of-block))))
1341 (prev-block-parent-ending-pos
1342 (save-excursion
1343 (when prev-block-ending-pos
1344 (goto-char prev-block-ending-pos)
1345 (python-util-forward-comment)
1346 (python-nav-beginning-of-block)
1347 (python-nav-end-of-block)))))
1348 (if (and (not (bobp))
1349 (= (syntax-class (syntax-after (1- (point)))) 5))
1350 ;; Char before point is a paren closing char, handle it
1351 ;; like we are lisp.
1352 (python-nav-lisp-forward-sexp-safe -1)
1353 (cond
1354 ((not block-ending-pos)
1355 ;; Not in and ending pos, move to end of previous block.
1356 (and (python-nav-backward-block)
1357 (python-nav-end-of-block)))
1358 ((= (point) block-ending-pos)
1359 ;; In ending pos, we need to search backwards for the
1360 ;; closest point looking the list of candidates from here.
1361 (let ((candidates))
1362 (dolist (name
1363 '(prev-block-parent-ending-pos
1364 prev-block-ending-pos
1365 block-ending-pos
1366 block-starting-pos))
1367 (when (and (symbol-value name)
1368 (< (symbol-value name) (point)))
1369 (add-to-list 'candidates (symbol-value name))))
1370 (goto-char (apply 'max candidates))))
1371 ((> (point) block-ending-pos)
1372 ;; After an ending position, move to it.
1373 (goto-char block-ending-pos))
1374 ((= (point) block-starting-pos)
1375 ;; On a block starting position.
1376 (if (not (> (point) (or prev-block-ending-pos (point))))
1377 ;; Point is after the end position of the block that
1378 ;; wraps the current one, just move a block backward.
1379 (python-nav-backward-block)
1380 ;; If we got here we are facing a case like this one:
1381 ;;
1382 ;; try:
1383 ;; return here()
1384 ;; except Exception as e:
1385 ;;
1386 ;; Where point is on the "except" and must move to the
1387 ;; end of "here()".
1388 (goto-char prev-block-ending-pos)
1389 (let ((parent-block-ending-pos
1390 (save-excursion
1391 (python-nav-forward-sexp)
1392 (and (not (looking-at (python-rx block-start)))
1393 (point)))))
1394 (when (and parent-block-ending-pos
1395 (> parent-block-ending-pos prev-block-ending-pos))
1396 ;; If we got here we are facing a case like this one:
1397 ;;
1398 ;; except ImportError:
1399 ;; if predicate():
1400 ;; processing()
1401 ;; here()
1402 ;; except AttributeError:
1403 ;;
1404 ;; Where point is on the "except" and must move to
1405 ;; the end of "here()". Without this extra step we'd
1406 ;; just get to the end of processing().
1407 (goto-char parent-block-ending-pos)))))
1408 (t
1409 (if (and prev-block-ending-pos (< prev-block-ending-pos (point)))
1410 (goto-char prev-block-ending-pos)
1411 (python-nav-beginning-of-block)))))))))
1412 1407
1413(defun python-nav-forward-sexp (&optional arg) 1408(defun python-nav-forward-sexp (&optional arg)
1414 "Move forward across one block of code. 1409 "Move forward across one block of code.
@@ -1423,6 +1418,67 @@ move backward N times."
1423 (python-nav--backward-sexp) 1418 (python-nav--backward-sexp)
1424 (setq arg (1+ arg)))) 1419 (setq arg (1+ arg))))
1425 1420
1421(defun python-nav--up-list (&optional dir)
1422 "Internal implementation of `python-nav-up-list'.
1423DIR is always 1 or -1 and comes sanitized from
1424`python-nav-up-list' calls."
1425 (let ((context (python-syntax-context-type))
1426 (forward-p (> dir 0)))
1427 (cond
1428 ((memq context '(string comment)))
1429 ((eq context 'paren)
1430 (let ((forward-sexp-function))
1431 (up-list dir)))
1432 ((and forward-p (python-info-end-of-block-p))
1433 (let ((parent-end-pos
1434 (save-excursion
1435 (let ((indentation (and
1436 (python-nav-beginning-of-block)
1437 (current-indentation))))
1438 (while (and indentation
1439 (> indentation 0)
1440 (>= (current-indentation) indentation)
1441 (python-nav-backward-block)))
1442 (python-nav-end-of-block)))))
1443 (and (> (or parent-end-pos (point)) (point))
1444 (goto-char parent-end-pos))))
1445 (forward-p (python-nav-end-of-block))
1446 ((and (not forward-p)
1447 (> (current-indentation) 0)
1448 (python-info-beginning-of-block-p))
1449 (let ((prev-block-pos
1450 (save-excursion
1451 (let ((indentation (current-indentation)))
1452 (while (and (python-nav-backward-block)
1453 (>= (current-indentation) indentation))))
1454 (point))))
1455 (and (> (point) prev-block-pos)
1456 (goto-char prev-block-pos))))
1457 ((not forward-p) (python-nav-beginning-of-block)))))
1458
1459(defun python-nav-up-list (&optional arg)
1460 "Move forward out of one level of parentheses (or blocks).
1461With ARG, do this that many times.
1462A negative argument means move backward but still to a less deep spot.
1463This command assumes point is not in a string or comment."
1464 (interactive "^p")
1465 (or arg (setq arg 1))
1466 (while (> arg 0)
1467 (python-nav--up-list 1)
1468 (setq arg (1- arg)))
1469 (while (< arg 0)
1470 (python-nav--up-list -1)
1471 (setq arg (1+ arg))))
1472
1473(defun python-nav-backward-up-list (&optional arg)
1474 "Move backward out of one level of parentheses (or blocks).
1475With ARG, do this that many times.
1476A negative argument means move backward but still to a less deep spot.
1477This command assumes point is not in a string or comment."
1478 (interactive "^p")
1479 (or arg (setq arg 1))
1480 (python-nav-up-list (- arg)))
1481
1426 1482
1427;;; Shell integration 1483;;; Shell integration
1428 1484
@@ -1621,6 +1677,22 @@ uniqueness for different types of configurations."
1621OUTPUT is a string with the contents of the buffer." 1677OUTPUT is a string with the contents of the buffer."
1622 (ansi-color-filter-apply output)) 1678 (ansi-color-filter-apply output))
1623 1679
1680(defvar python-shell--parent-buffer nil)
1681
1682(defvar python-shell-output-syntax-table
1683 (let ((table (make-syntax-table python-dotty-syntax-table)))
1684 (modify-syntax-entry ?\' "." table)
1685 (modify-syntax-entry ?\" "." table)
1686 (modify-syntax-entry ?\( "." table)
1687 (modify-syntax-entry ?\[ "." table)
1688 (modify-syntax-entry ?\{ "." table)
1689 (modify-syntax-entry ?\) "." table)
1690 (modify-syntax-entry ?\] "." table)
1691 (modify-syntax-entry ?\} "." table)
1692 table)
1693 "Syntax table for shell output.
1694It makes parens and quotes be treated as punctuation chars.")
1695
1624(define-derived-mode inferior-python-mode comint-mode "Inferior Python" 1696(define-derived-mode inferior-python-mode comint-mode "Inferior Python"
1625 "Major mode for Python inferior process. 1697 "Major mode for Python inferior process.
1626Runs a Python interpreter as a subprocess of Emacs, with Python 1698Runs a Python interpreter as a subprocess of Emacs, with Python
@@ -1643,12 +1715,13 @@ initialization of the interpreter via `python-shell-setup-codes'
1643variable. 1715variable.
1644 1716
1645\(Type \\[describe-mode] in the process buffer for a list of commands.)" 1717\(Type \\[describe-mode] in the process buffer for a list of commands.)"
1646 (set-syntax-table python-mode-syntax-table) 1718 (and python-shell--parent-buffer
1647 (setq mode-line-process '(":%s")) 1719 (python-util-clone-local-variables python-shell--parent-buffer))
1648 (setq comint-prompt-regexp (format "^\\(?:%s\\|%s\\|%s\\)" 1720 (setq comint-prompt-regexp (format "^\\(?:%s\\|%s\\|%s\\)"
1649 python-shell-prompt-regexp 1721 python-shell-prompt-regexp
1650 python-shell-prompt-block-regexp 1722 python-shell-prompt-block-regexp
1651 python-shell-prompt-pdb-regexp)) 1723 python-shell-prompt-pdb-regexp))
1724 (setq mode-line-process '(":%s"))
1652 (make-local-variable 'comint-output-filter-functions) 1725 (make-local-variable 'comint-output-filter-functions)
1653 (add-hook 'comint-output-filter-functions 1726 (add-hook 'comint-output-filter-functions
1654 'python-comint-output-filter-function) 1727 'python-comint-output-filter-function)
@@ -1668,10 +1741,28 @@ variable.
1668 (make-local-variable 'python-pdbtrack-tracked-buffer) 1741 (make-local-variable 'python-pdbtrack-tracked-buffer)
1669 (make-local-variable 'python-shell-internal-last-output) 1742 (make-local-variable 'python-shell-internal-last-output)
1670 (when python-shell-enable-font-lock 1743 (when python-shell-enable-font-lock
1744 (set-syntax-table python-mode-syntax-table)
1671 (set (make-local-variable 'font-lock-defaults) 1745 (set (make-local-variable 'font-lock-defaults)
1672 '(python-font-lock-keywords nil nil nil nil)) 1746 '(python-font-lock-keywords nil nil nil nil))
1673 (set (make-local-variable 'syntax-propertize-function) 1747 (set (make-local-variable 'syntax-propertize-function)
1674 python-syntax-propertize-function)) 1748 (eval
1749 ;; XXX: Unfortunately eval is needed here to make use of the
1750 ;; dynamic value of `comint-prompt-regexp'.
1751 `(syntax-propertize-rules
1752 (,comint-prompt-regexp
1753 (0 (ignore
1754 (put-text-property
1755 comint-last-input-start end 'syntax-table
1756 python-shell-output-syntax-table)
1757 ;; XXX: This might look weird, but it is the easiest
1758 ;; way to ensure font lock gets cleaned up before the
1759 ;; current prompt, which is needed for unclosed
1760 ;; strings to not mess up with current input.
1761 (font-lock-unfontify-region comint-last-input-start end))))
1762 (,(python-rx string-delimiter)
1763 (0 (ignore
1764 (and (not (eq (get-text-property start 'field) 'output))
1765 (python-syntax-stringify)))))))))
1675 (compilation-shell-minor-mode 1)) 1766 (compilation-shell-minor-mode 1))
1676 1767
1677(defun python-shell-make-comint (cmd proc-name &optional pop internal) 1768(defun python-shell-make-comint (cmd proc-name &optional pop internal)
@@ -1694,11 +1785,10 @@ killed."
1694 (let* ((cmdlist (split-string-and-unquote cmd)) 1785 (let* ((cmdlist (split-string-and-unquote cmd))
1695 (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name 1786 (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name
1696 (car cmdlist) nil (cdr cmdlist))) 1787 (car cmdlist) nil (cdr cmdlist)))
1697 (current-buffer (current-buffer)) 1788 (python-shell--parent-buffer (current-buffer))
1698 (process (get-buffer-process buffer))) 1789 (process (get-buffer-process buffer)))
1699 (with-current-buffer buffer 1790 (with-current-buffer buffer
1700 (inferior-python-mode) 1791 (inferior-python-mode))
1701 (python-util-clone-local-variables current-buffer))
1702 (accept-process-output process) 1792 (accept-process-output process)
1703 (and pop (pop-to-buffer buffer t)) 1793 (and pop (pop-to-buffer buffer t))
1704 (and internal (set-process-query-on-exit-flag process nil)))) 1794 (and internal (set-process-query-on-exit-flag process nil))))
@@ -1824,7 +1914,11 @@ When MSG is non-nil messages the first line of STRING."
1824 (lines (split-string string "\n" t))) 1914 (lines (split-string string "\n" t)))
1825 (and msg (message "Sent: %s..." (nth 0 lines))) 1915 (and msg (message "Sent: %s..." (nth 0 lines)))
1826 (if (> (length lines) 1) 1916 (if (> (length lines) 1)
1827 (let* ((temp-file-name (make-temp-file "py")) 1917 (let* ((temporary-file-directory
1918 (if (file-remote-p default-directory)
1919 (concat (file-remote-p default-directory) "/tmp")
1920 temporary-file-directory))
1921 (temp-file-name (make-temp-file "py"))
1828 (file-name (or (buffer-file-name) temp-file-name))) 1922 (file-name (or (buffer-file-name) temp-file-name)))
1829 (with-temp-file temp-file-name 1923 (with-temp-file temp-file-name
1830 (insert string) 1924 (insert string)
@@ -1835,31 +1929,62 @@ When MSG is non-nil messages the first line of STRING."
1835 (string-match "\n[ \t].*\n?$" string)) 1929 (string-match "\n[ \t].*\n?$" string))
1836 (comint-send-string process "\n"))))) 1930 (comint-send-string process "\n")))))
1837 1931
1932(defvar python-shell-output-filter-in-progress nil)
1933(defvar python-shell-output-filter-buffer nil)
1934
1935(defun python-shell-output-filter (string)
1936 "Filter used in `python-shell-send-string-no-output' to grab output.
1937STRING is the output received to this point from the process.
1938This filter saves received output from the process in
1939`python-shell-output-filter-buffer' and stops receiving it after
1940detecting a prompt at the end of the buffer."
1941 (setq
1942 string (ansi-color-filter-apply string)
1943 python-shell-output-filter-buffer
1944 (concat python-shell-output-filter-buffer string))
1945 (when (string-match
1946 ;; XXX: It seems on OSX an extra carriage return is attached
1947 ;; at the end of output, this handles that too.
1948 (format "\r?\n\\(?:%s\\|%s\\|%s\\)$"
1949 python-shell-prompt-regexp
1950 python-shell-prompt-block-regexp
1951 python-shell-prompt-pdb-regexp)
1952 python-shell-output-filter-buffer)
1953 ;; Output ends when `python-shell-output-filter-buffer' contains
1954 ;; the prompt attached at the end of it.
1955 (setq python-shell-output-filter-in-progress nil
1956 python-shell-output-filter-buffer
1957 (substring python-shell-output-filter-buffer
1958 0 (match-beginning 0)))
1959 (when (and (> (length python-shell-prompt-output-regexp) 0)
1960 (string-match (concat "^" python-shell-prompt-output-regexp)
1961 python-shell-output-filter-buffer))
1962 ;; Some shells, like iPython might append a prompt before the
1963 ;; output, clean that.
1964 (setq python-shell-output-filter-buffer
1965 (substring python-shell-output-filter-buffer (match-end 0)))))
1966 "")
1967
1838(defun python-shell-send-string-no-output (string &optional process msg) 1968(defun python-shell-send-string-no-output (string &optional process msg)
1839 "Send STRING to PROCESS and inhibit output. 1969 "Send STRING to PROCESS and inhibit output.
1840When MSG is non-nil messages the first line of STRING. Return 1970When MSG is non-nil messages the first line of STRING. Return
1841the output." 1971the output."
1842 (let* ((output-buffer "") 1972 (let ((process (or process (python-shell-get-or-create-process)))
1843 (process (or process (python-shell-get-or-create-process))) 1973 (comint-preoutput-filter-functions
1844 (comint-preoutput-filter-functions 1974 '(python-shell-output-filter))
1845 (append comint-preoutput-filter-functions 1975 (python-shell-output-filter-in-progress t)
1846 '(ansi-color-filter-apply 1976 (inhibit-quit t))
1847 (lambda (string)
1848 (setq output-buffer (concat output-buffer string))
1849 ""))))
1850 (inhibit-quit t))
1851 (or 1977 (or
1852 (with-local-quit 1978 (with-local-quit
1853 (python-shell-send-string string process msg) 1979 (python-shell-send-string string process msg)
1854 (accept-process-output process) 1980 (while python-shell-output-filter-in-progress
1855 (replace-regexp-in-string 1981 ;; `python-shell-output-filter' takes care of setting
1856 (if (> (length python-shell-prompt-output-regexp) 0) 1982 ;; `python-shell-output-filter-in-progress' to NIL after it
1857 (format "\n*%s$\\|^%s\\|\n$" 1983 ;; detects end of output.
1858 python-shell-prompt-regexp 1984 (accept-process-output process))
1859 (or python-shell-prompt-output-regexp "")) 1985 (prog1
1860 (format "\n*$\\|^%s\\|\n$" 1986 python-shell-output-filter-buffer
1861 python-shell-prompt-regexp)) 1987 (setq python-shell-output-filter-buffer nil)))
1862 "" output-buffer))
1863 (with-current-buffer (process-buffer process) 1988 (with-current-buffer (process-buffer process)
1864 (comint-interrupt-subjob))))) 1989 (comint-interrupt-subjob)))))
1865 1990
@@ -1888,19 +2013,18 @@ Returns the output. See `python-shell-send-string-no-output'."
1888 2013
1889(defun python-shell-send-buffer (&optional arg) 2014(defun python-shell-send-buffer (&optional arg)
1890 "Send the entire buffer to inferior Python process. 2015 "Send the entire buffer to inferior Python process.
1891 2016With prefix ARG allow execution of code inside blocks delimited
1892With prefix ARG include lines surrounded by \"if __name__ == '__main__':\"" 2017by \"if __name__== '__main__':\""
1893 (interactive "P") 2018 (interactive "P")
1894 (save-restriction 2019 (save-restriction
1895 (widen) 2020 (widen)
1896 (python-shell-send-region 2021 (let ((str (buffer-substring (point-min) (point-max))))
1897 (point-min) 2022 (and
1898 (or (and 2023 (not arg)
1899 (not arg) 2024 (setq str (replace-regexp-in-string
1900 (save-excursion 2025 (python-rx if-name-main)
1901 (re-search-forward (python-rx if-name-main) nil t)) 2026 "if __name__ == '__main__ ':" str)))
1902 (match-beginning 0)) 2027 (python-shell-send-string str))))
1903 (point-max)))))
1904 2028
1905(defun python-shell-send-defun (arg) 2029(defun python-shell-send-defun (arg)
1906 "Send the current defun to inferior Python process. 2030 "Send the current defun to inferior Python process.
@@ -1910,7 +2034,7 @@ When argument ARG is non-nil do not include decorators."
1910 (python-shell-send-region 2034 (python-shell-send-region
1911 (progn 2035 (progn
1912 (end-of-line 1) 2036 (end-of-line 1)
1913 (while (and (or (python-beginning-of-defun-function) 2037 (while (and (or (python-nav-beginning-of-defun)
1914 (beginning-of-line 1)) 2038 (beginning-of-line 1))
1915 (> (current-indentation) 0))) 2039 (> (current-indentation) 0)))
1916 (when (not arg) 2040 (when (not arg)
@@ -1919,7 +2043,7 @@ When argument ARG is non-nil do not include decorators."
1919 (forward-line 1)) 2043 (forward-line 1))
1920 (point-marker)) 2044 (point-marker))
1921 (progn 2045 (progn
1922 (or (python-end-of-defun-function) 2046 (or (python-nav-end-of-defun)
1923 (end-of-line 1)) 2047 (end-of-line 1))
1924 (point-marker))))) 2048 (point-marker)))))
1925 2049
@@ -1931,8 +2055,14 @@ FILE-NAME."
1931 (interactive "fFile to send: ") 2055 (interactive "fFile to send: ")
1932 (let* ((process (or process (python-shell-get-or-create-process))) 2056 (let* ((process (or process (python-shell-get-or-create-process)))
1933 (temp-file-name (when temp-file-name 2057 (temp-file-name (when temp-file-name
1934 (expand-file-name temp-file-name))) 2058 (expand-file-name
1935 (file-name (or (expand-file-name file-name) temp-file-name))) 2059 (or (file-remote-p temp-file-name 'localname)
2060 temp-file-name))))
2061 (file-name (or (when file-name
2062 (expand-file-name
2063 (or (file-remote-p file-name 'localname)
2064 file-name)))
2065 temp-file-name)))
1936 (when (not file-name) 2066 (when (not file-name)
1937 (error "If FILE-NAME is nil then TEMP-FILE-NAME must be non-nil")) 2067 (error "If FILE-NAME is nil then TEMP-FILE-NAME must be non-nil"))
1938 (python-shell-send-string 2068 (python-shell-send-string
@@ -2047,11 +2177,11 @@ INPUT."
2047 'default) 2177 'default)
2048 (t nil))) 2178 (t nil)))
2049 (completion-code 2179 (completion-code
2050 (case completion-context 2180 (pcase completion-context
2051 (pdb python-shell-completion-pdb-string-code) 2181 (`pdb python-shell-completion-pdb-string-code)
2052 (import python-shell-completion-module-string-code) 2182 (`import python-shell-completion-module-string-code)
2053 (default python-shell-completion-string-code) 2183 (`default python-shell-completion-string-code)
2054 (t nil))) 2184 (_ nil)))
2055 (input 2185 (input
2056 (if (eq completion-context 'import) 2186 (if (eq completion-context 'import)
2057 (replace-regexp-in-string "^[ \t]+" "" line) 2187 (replace-regexp-in-string "^[ \t]+" "" line)
@@ -2219,37 +2349,105 @@ inferior python process is updated properly."
2219 2349
2220(defcustom python-fill-comment-function 'python-fill-comment 2350(defcustom python-fill-comment-function 'python-fill-comment
2221 "Function to fill comments. 2351 "Function to fill comments.
2222This is the function used by `python-fill-paragraph-function' to 2352This is the function used by `python-fill-paragraph' to
2223fill comments." 2353fill comments."
2224 :type 'symbol 2354 :type 'symbol
2225 :group 'python 2355 :group 'python)
2226 :safe 'symbolp)
2227 2356
2228(defcustom python-fill-string-function 'python-fill-string 2357(defcustom python-fill-string-function 'python-fill-string
2229 "Function to fill strings. 2358 "Function to fill strings.
2230This is the function used by `python-fill-paragraph-function' to 2359This is the function used by `python-fill-paragraph' to
2231fill strings." 2360fill strings."
2232 :type 'symbol 2361 :type 'symbol
2233 :group 'python 2362 :group 'python)
2234 :safe 'symbolp)
2235 2363
2236(defcustom python-fill-decorator-function 'python-fill-decorator 2364(defcustom python-fill-decorator-function 'python-fill-decorator
2237 "Function to fill decorators. 2365 "Function to fill decorators.
2238This is the function used by `python-fill-paragraph-function' to 2366This is the function used by `python-fill-paragraph' to
2239fill decorators." 2367fill decorators."
2240 :type 'symbol 2368 :type 'symbol
2241 :group 'python 2369 :group 'python)
2242 :safe 'symbolp)
2243 2370
2244(defcustom python-fill-paren-function 'python-fill-paren 2371(defcustom python-fill-paren-function 'python-fill-paren
2245 "Function to fill parens. 2372 "Function to fill parens.
2246This is the function used by `python-fill-paragraph-function' to 2373This is the function used by `python-fill-paragraph' to
2247fill parens." 2374fill parens."
2248 :type 'symbol 2375 :type 'symbol
2376 :group 'python)
2377
2378(defcustom python-fill-docstring-style 'pep-257
2379 "Style used to fill docstrings.
2380This affects `python-fill-string' behavior with regards to
2381triple quotes positioning.
2382
2383Possible values are DJANGO, ONETWO, PEP-257, PEP-257-NN,
2384SYMMETRIC, and NIL. A value of NIL won't care about quotes
2385position and will treat docstrings a normal string, any other
2386value may result in one of the following docstring styles:
2387
2388DJANGO:
2389
2390 \"\"\"
2391 Process foo, return bar.
2392 \"\"\"
2393
2394 \"\"\"
2395 Process foo, return bar.
2396
2397 If processing fails throw ProcessingError.
2398 \"\"\"
2399
2400ONETWO:
2401
2402 \"\"\"Process foo, return bar.\"\"\"
2403
2404 \"\"\"
2405 Process foo, return bar.
2406
2407 If processing fails throw ProcessingError.
2408
2409 \"\"\"
2410
2411PEP-257:
2412
2413 \"\"\"Process foo, return bar.\"\"\"
2414
2415 \"\"\"Process foo, return bar.
2416
2417 If processing fails throw ProcessingError.
2418
2419 \"\"\"
2420
2421PEP-257-NN:
2422
2423 \"\"\"Process foo, return bar.\"\"\"
2424
2425 \"\"\"Process foo, return bar.
2426
2427 If processing fails throw ProcessingError.
2428 \"\"\"
2429
2430SYMMETRIC:
2431
2432 \"\"\"Process foo, return bar.\"\"\"
2433
2434 \"\"\"
2435 Process foo, return bar.
2436
2437 If processing fails throw ProcessingError.
2438 \"\"\""
2439 :type '(choice
2440 (const :tag "Don't format docstrings" nil)
2441 (const :tag "Django's coding standards style." django)
2442 (const :tag "One newline and start and Two at end style." onetwo)
2443 (const :tag "PEP-257 with 2 newlines at end of string." pep-257)
2444 (const :tag "PEP-257 with 1 newline at end of string." pep-257-nn)
2445 (const :tag "Symmetric style." symmetric))
2249 :group 'python 2446 :group 'python
2250 :safe 'symbolp) 2447 :safe (lambda (val)
2448 (memq val '(django onetwo pep-257 pep-257-nn symmetric nil))))
2251 2449
2252(defun python-fill-paragraph-function (&optional justify) 2450(defun python-fill-paragraph (&optional justify)
2253 "`fill-paragraph-function' handling multi-line strings and possibly comments. 2451 "`fill-paragraph-function' handling multi-line strings and possibly comments.
2254If any of the current line is in or at the end of a multi-line string, 2452If any of the current line is in or at the end of a multi-line string,
2255fill the string or the paragraph of it that point is in, preserving 2453fill the string or the paragraph of it that point is in, preserving
@@ -2257,18 +2455,18 @@ the string's indentation.
2257Optional argument JUSTIFY defines if the paragraph should be justified." 2455Optional argument JUSTIFY defines if the paragraph should be justified."
2258 (interactive "P") 2456 (interactive "P")
2259 (save-excursion 2457 (save-excursion
2260 (back-to-indentation)
2261 (cond 2458 (cond
2262 ;; Comments 2459 ;; Comments
2263 ((funcall python-fill-comment-function justify)) 2460 ((python-syntax-context 'comment)
2461 (funcall python-fill-comment-function justify))
2264 ;; Strings/Docstrings 2462 ;; Strings/Docstrings
2265 ((save-excursion (skip-chars-forward "\"'uUrR") 2463 ((save-excursion (or (python-syntax-context 'string)
2266 (python-syntax-context 'string)) 2464 (equal (string-to-syntax "|")
2465 (syntax-after (point)))))
2267 (funcall python-fill-string-function justify)) 2466 (funcall python-fill-string-function justify))
2268 ;; Decorators 2467 ;; Decorators
2269 ((equal (char-after (save-excursion 2468 ((equal (char-after (save-excursion
2270 (back-to-indentation) 2469 (python-nav-beginning-of-statement))) ?@)
2271 (point-marker))) ?@)
2272 (funcall python-fill-decorator-function justify)) 2470 (funcall python-fill-decorator-function justify))
2273 ;; Parens 2471 ;; Parens
2274 ((or (python-syntax-context 'paren) 2472 ((or (python-syntax-context 'paren)
@@ -2280,58 +2478,87 @@ Optional argument JUSTIFY defines if the paragraph should be justified."
2280 (t t)))) 2478 (t t))))
2281 2479
2282(defun python-fill-comment (&optional justify) 2480(defun python-fill-comment (&optional justify)
2283 "Comment fill function for `python-fill-paragraph-function'. 2481 "Comment fill function for `python-fill-paragraph'.
2284JUSTIFY should be used (if applicable) as in `fill-paragraph'." 2482JUSTIFY should be used (if applicable) as in `fill-paragraph'."
2285 (fill-comment-paragraph justify)) 2483 (fill-comment-paragraph justify))
2286 2484
2287(defun python-fill-string (&optional justify) 2485(defun python-fill-string (&optional justify)
2288 "String fill function for `python-fill-paragraph-function'. 2486 "String fill function for `python-fill-paragraph'.
2289JUSTIFY should be used (if applicable) as in `fill-paragraph'." 2487JUSTIFY should be used (if applicable) as in `fill-paragraph'."
2290 (let ((marker (point-marker)) 2488 (let* ((marker (point-marker))
2291 (string-start-marker 2489 (str-start-pos
2292 (progn 2490 (let ((m (make-marker)))
2293 (skip-chars-forward "\"'uUrR") 2491 (setf (marker-position m)
2294 (goto-char (python-syntax-context 'string)) 2492 (or (python-syntax-context 'string)
2295 (skip-chars-forward "\"'uUrR") 2493 (and (equal (string-to-syntax "|")
2296 (point-marker))) 2494 (syntax-after (point)))
2297 (reg-start (line-beginning-position)) 2495 (point)))) m))
2298 (string-end-marker 2496 (num-quotes (python-syntax-count-quotes
2299 (progn 2497 (char-after str-start-pos) str-start-pos))
2300 (while (python-syntax-context 'string) 2498 (str-end-pos
2301 (goto-char (1+ (point-marker)))) 2499 (save-excursion
2302 (skip-chars-backward "\"'") 2500 (goto-char (+ str-start-pos num-quotes))
2303 (point-marker))) 2501 (or (re-search-forward (rx (syntax string-delimiter)) nil t)
2304 (reg-end (line-end-position)) 2502 (goto-char (point-max)))
2305 (fill-paragraph-function)) 2503 (point-marker)))
2504 (multi-line-p
2505 ;; Docstring styles may vary for oneliners and multi-liners.
2506 (> (count-matches "\n" str-start-pos str-end-pos) 0))
2507 (delimiters-style
2508 (pcase python-fill-docstring-style
2509 ;; delimiters-style is a cons cell with the form
2510 ;; (START-NEWLINES . END-NEWLINES). When any of the sexps
2511 ;; is NIL means to not add any newlines for start or end
2512 ;; of docstring. See `python-fill-docstring-style' for a
2513 ;; graphic idea of each style.
2514 (`django (cons 1 1))
2515 (`onetwo (and multi-line-p (cons 1 2)))
2516 (`pep-257 (and multi-line-p (cons nil 2)))
2517 (`pep-257-nn (and multi-line-p (cons nil 1)))
2518 (`symmetric (and multi-line-p (cons 1 1)))))
2519 (docstring-p (save-excursion
2520 ;; Consider docstrings those strings which
2521 ;; start on a line by themselves.
2522 (python-nav-beginning-of-statement)
2523 (and (= (point) str-start-pos))))
2524 (fill-paragraph-function))
2306 (save-restriction 2525 (save-restriction
2307 (narrow-to-region reg-start reg-end) 2526 (narrow-to-region str-start-pos str-end-pos)
2308 (save-excursion 2527 (fill-paragraph justify))
2309 (goto-char string-start-marker) 2528 (save-excursion
2310 (delete-region (point-marker) (progn 2529 (when (and docstring-p python-fill-docstring-style)
2311 (skip-syntax-forward "> ") 2530 ;; Add the number of newlines indicated by the selected style
2312 (point-marker))) 2531 ;; at the start of the docstring.
2313 (goto-char string-end-marker) 2532 (goto-char (+ str-start-pos num-quotes))
2314 (delete-region (point-marker) (progn 2533 (delete-region (point) (progn
2315 (skip-syntax-backward "> ") 2534 (skip-syntax-forward "> ")
2316 (point-marker))) 2535 (point)))
2317 (save-excursion 2536 (and (car delimiters-style)
2318 (goto-char marker) 2537 (or (newline (car delimiters-style)) t)
2319 (fill-paragraph justify)) 2538 ;; Indent only if a newline is added.
2320 ;; If there is a newline in the docstring lets put triple 2539 (indent-according-to-mode))
2321 ;; quote in it's own line to follow pep 8 2540 ;; Add the number of newlines indicated by the selected style
2322 (when (save-excursion 2541 ;; at the end of the docstring.
2323 (re-search-backward "\n" string-start-marker t)) 2542 (goto-char (if (not (= str-end-pos (point-max)))
2324 (newline) 2543 (- str-end-pos num-quotes)
2325 (newline-and-indent)) 2544 str-end-pos))
2326 (fill-paragraph justify)))) t) 2545 (delete-region (point) (progn
2546 (skip-syntax-backward "> ")
2547 (point)))
2548 (and (cdr delimiters-style)
2549 ;; Add newlines only if string ends.
2550 (not (= str-end-pos (point-max)))
2551 (or (newline (cdr delimiters-style)) t)
2552 ;; Again indent only if a newline is added.
2553 (indent-according-to-mode))))) t)
2327 2554
2328(defun python-fill-decorator (&optional justify) 2555(defun python-fill-decorator (&optional justify)
2329 "Decorator fill function for `python-fill-paragraph-function'. 2556 "Decorator fill function for `python-fill-paragraph'.
2330JUSTIFY should be used (if applicable) as in `fill-paragraph'." 2557JUSTIFY should be used (if applicable) as in `fill-paragraph'."
2331 t) 2558 t)
2332 2559
2333(defun python-fill-paren (&optional justify) 2560(defun python-fill-paren (&optional justify)
2334 "Paren fill function for `python-fill-paragraph-function'. 2561 "Paren fill function for `python-fill-paragraph'.
2335JUSTIFY should be used (if applicable) as in `fill-paragraph'." 2562JUSTIFY should be used (if applicable) as in `fill-paragraph'."
2336 (save-restriction 2563 (save-restriction
2337 (narrow-to-region (progn 2564 (narrow-to-region (progn
@@ -2465,17 +2692,17 @@ The skeleton will be bound to python-skeleton-NAME."
2465 2692
2466(python-skeleton-define def nil 2693(python-skeleton-define def nil
2467 "Function name: " 2694 "Function name: "
2468 "def " str " (" ("Parameter, %s: " 2695 "def " str "(" ("Parameter, %s: "
2469 (unless (equal ?\( (char-before)) ", ") 2696 (unless (equal ?\( (char-before)) ", ")
2470 str) "):" \n 2697 str) "):" \n
2471 "\"\"\"" - "\"\"\"" \n 2698 "\"\"\"" - "\"\"\"" \n
2472 > _ \n) 2699 > _ \n)
2473 2700
2474(python-skeleton-define class nil 2701(python-skeleton-define class nil
2475 "Class name: " 2702 "Class name: "
2476 "class " str " (" ("Inheritance, %s: " 2703 "class " str "(" ("Inheritance, %s: "
2477 (unless (equal ?\( (char-before)) ", ") 2704 (unless (equal ?\( (char-before)) ", ")
2478 str) 2705 str)
2479 & ")" | -2 2706 & ")" | -2
2480 ":" \n 2707 ":" \n
2481 "\"\"\"" - "\"\"\"" \n 2708 "\"\"\"" - "\"\"\"" \n
@@ -2489,7 +2716,7 @@ The skeleton will be bound to python-skeleton-NAME."
2489 (easy-menu-add-item 2716 (easy-menu-add-item
2490 nil '("Python" "Skeletons") 2717 nil '("Python" "Skeletons")
2491 `[,(format 2718 `[,(format
2492 "Insert %s" (caddr (split-string (symbol-name skeleton) "-"))) 2719 "Insert %s" (nth 2 (split-string (symbol-name skeleton) "-")))
2493 ,skeleton t])))) 2720 ,skeleton t]))))
2494 2721
2495;;; FFAP 2722;;; FFAP
@@ -2656,6 +2883,19 @@ Interactively, prompt for symbol."
2656 "^Eldoc needs an inferior Python process running.") 2883 "^Eldoc needs an inferior Python process running.")
2657 2884
2658 2885
2886;;; Imenu
2887
2888(defun python-imenu-prev-index-position ()
2889 "Python mode's `imenu-prev-index-position-function'."
2890 (let ((found))
2891 (while (and (setq found
2892 (re-search-backward python-nav-beginning-of-defun-regexp nil t))
2893 (not (python-info-looking-at-beginning-of-defun))))
2894 (and found
2895 (python-info-looking-at-beginning-of-defun)
2896 (python-info-current-defun))))
2897
2898
2659;;; Misc helpers 2899;;; Misc helpers
2660 2900
2661(defun python-info-current-defun (&optional include-type) 2901(defun python-info-current-defun (&optional include-type)
@@ -2664,38 +2904,40 @@ Optional argument INCLUDE-TYPE indicates to include the type of the defun.
2664This function is compatible to be used as 2904This function is compatible to be used as
2665`add-log-current-defun-function' since it returns nil if point is 2905`add-log-current-defun-function' since it returns nil if point is
2666not inside a defun." 2906not inside a defun."
2667 (let ((names '())
2668 (starting-indentation)
2669 (starting-point)
2670 (first-run t))
2671 (save-restriction 2907 (save-restriction
2672 (widen) 2908 (widen)
2673 (save-excursion 2909 (save-excursion
2674 (setq starting-point (point-marker))
2675 (setq starting-indentation (save-excursion
2676 (python-nav-beginning-of-statement)
2677 (current-indentation)))
2678 (end-of-line 1) 2910 (end-of-line 1)
2679 (while (python-beginning-of-defun-function 1) 2911 (let ((names)
2680 (when (or (< (current-indentation) starting-indentation) 2912 (starting-indentation
2681 (and first-run 2913 (save-excursion
2682 (< 2914 (and
2683 starting-point 2915 (python-nav-beginning-of-defun 1)
2684 (save-excursion 2916 ;; This extra number is just for checking code
2685 (python-end-of-defun-function) 2917 ;; against indentation to work well on first run.
2686 (point-marker))))) 2918 (+ (current-indentation) 4))))
2687 (setq first-run nil) 2919 (starting-point (point)))
2688 (setq starting-indentation (current-indentation)) 2920 ;; Check point is inside a defun.
2689 (looking-at python-nav-beginning-of-defun-regexp) 2921 (when (and starting-indentation
2690 (setq names (cons 2922 (< starting-point
2923 (save-excursion
2924 (python-nav-end-of-defun)
2925 (point))))
2926 (catch 'exit
2927 (while (python-nav-beginning-of-defun 1)
2928 (when (< (current-indentation) starting-indentation)
2929 (setq starting-indentation (current-indentation))
2930 (setq names
2931 (cons
2691 (if (not include-type) 2932 (if (not include-type)
2692 (match-string-no-properties 1) 2933 (match-string-no-properties 1)
2693 (mapconcat 'identity 2934 (mapconcat 'identity
2694 (split-string 2935 (split-string
2695 (match-string-no-properties 0)) " ")) 2936 (match-string-no-properties 0)) " "))
2696 names)))))) 2937 names)))
2697 (when names 2938 (and (= (current-indentation) 0) (throw 'exit t)))))
2698 (mapconcat (lambda (string) string) names ".")))) 2939 (and names
2940 (mapconcat (lambda (string) string) names "."))))))
2699 2941
2700(defun python-info-current-symbol (&optional replace-self) 2942(defun python-info-current-symbol (&optional replace-self)
2701 "Return current symbol using dotty syntax. 2943 "Return current symbol using dotty syntax.
@@ -2721,12 +2963,43 @@ parent defun name."
2721 ".") ".") 2963 ".") ".")
2722 name))))))) 2964 name)))))))
2723 2965
2724(defsubst python-info-beginning-of-block-statement-p () 2966(defun python-info-statement-starts-block-p ()
2725 "Return non-nil if current statement opens a block." 2967 "Return non-nil if current statement opens a block."
2726 (save-excursion 2968 (save-excursion
2727 (python-nav-beginning-of-statement) 2969 (python-nav-beginning-of-statement)
2728 (looking-at (python-rx block-start)))) 2970 (looking-at (python-rx block-start))))
2729 2971
2972(defun python-info-statement-ends-block-p ()
2973 "Return non-nil if point is at end of block."
2974 (let ((end-of-block-pos (save-excursion
2975 (python-nav-end-of-block)))
2976 (end-of-statement-pos (save-excursion
2977 (python-nav-end-of-statement))))
2978 (and end-of-block-pos end-of-statement-pos
2979 (= end-of-block-pos end-of-statement-pos))))
2980
2981(defun python-info-beginning-of-statement-p ()
2982 "Return non-nil if point is at beginning of statement."
2983 (= (point) (save-excursion
2984 (python-nav-beginning-of-statement)
2985 (point))))
2986
2987(defun python-info-end-of-statement-p ()
2988 "Return non-nil if point is at end of statement."
2989 (= (point) (save-excursion
2990 (python-nav-end-of-statement)
2991 (point))))
2992
2993(defun python-info-beginning-of-block-p ()
2994 "Return non-nil if point is at beginning of block."
2995 (and (python-info-beginning-of-statement-p)
2996 (python-info-statement-starts-block-p)))
2997
2998(defun python-info-end-of-block-p ()
2999 "Return non-nil if point is at end of block."
3000 (and (python-info-end-of-statement-p)
3001 (python-info-statement-ends-block-p)))
3002
2730(defun python-info-closing-block () 3003(defun python-info-closing-block ()
2731 "Return the point of the block the current line closes." 3004 "Return the point of the block the current line closes."
2732 (let ((closing-word (save-excursion 3005 (let ((closing-word (save-excursion
@@ -2951,12 +3224,12 @@ if that value is non-nil."
2951 3224
2952 (set (make-local-variable 'paragraph-start) "\\s-*$") 3225 (set (make-local-variable 'paragraph-start) "\\s-*$")
2953 (set (make-local-variable 'fill-paragraph-function) 3226 (set (make-local-variable 'fill-paragraph-function)
2954 'python-fill-paragraph-function) 3227 'python-fill-paragraph)
2955 3228
2956 (set (make-local-variable 'beginning-of-defun-function) 3229 (set (make-local-variable 'beginning-of-defun-function)
2957 #'python-beginning-of-defun-function) 3230 #'python-nav-beginning-of-defun)
2958 (set (make-local-variable 'end-of-defun-function) 3231 (set (make-local-variable 'end-of-defun-function)
2959 #'python-end-of-defun-function) 3232 #'python-nav-end-of-defun)
2960 3233
2961 (add-hook 'completion-at-point-functions 3234 (add-hook 'completion-at-point-functions
2962 'python-completion-complete-at-point nil 'local) 3235 'python-completion-complete-at-point nil 'local)
@@ -2967,6 +3240,9 @@ if that value is non-nil."
2967 (set (make-local-variable 'imenu-extract-index-name-function) 3240 (set (make-local-variable 'imenu-extract-index-name-function)
2968 #'python-info-current-defun) 3241 #'python-info-current-defun)
2969 3242
3243 (set (make-local-variable 'imenu-prev-index-position-function)
3244 #'python-imenu-prev-index-position)
3245
2970 (set (make-local-variable 'add-log-current-defun-function) 3246 (set (make-local-variable 'add-log-current-defun-function)
2971 #'python-info-current-defun) 3247 #'python-info-current-defun)
2972 3248
@@ -2984,7 +3260,7 @@ if that value is non-nil."
2984 (add-to-list 'hs-special-modes-alist 3260 (add-to-list 'hs-special-modes-alist
2985 `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#" 3261 `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#"
2986 ,(lambda (arg) 3262 ,(lambda (arg)
2987 (python-end-of-defun-function)) nil)) 3263 (python-nav-end-of-defun)) nil))
2988 3264
2989 (set (make-local-variable 'mode-require-final-newline) t) 3265 (set (make-local-variable 'mode-require-final-newline) t)
2990 3266