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.el341
1 files changed, 212 insertions, 129 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 550c5f5a129..f0f67d01845 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -1,6 +1,6 @@
1;;; python.el --- Python's flying circus support for Emacs 1;;; python.el --- Python's flying circus support for Emacs
2 2
3;; Copyright (C) 2003-2012 Free Software Foundation, Inc. 3;; Copyright (C) 2003-2013 Free Software Foundation, Inc.
4 4
5;; Author: Fabián E. Gallina <fabian@anue.biz> 5;; Author: Fabián E. Gallina <fabian@anue.biz>
6;; URL: https://github.com/fgallina/python.el 6;; URL: https://github.com/fgallina/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.
@@ -54,8 +54,13 @@
54;; `python-nav-beginning-of-statement', `python-nav-end-of-statement', 54;; `python-nav-beginning-of-statement', `python-nav-end-of-statement',
55;; `python-nav-beginning-of-block' and `python-nav-end-of-block' are 55;; `python-nav-beginning-of-block' and `python-nav-end-of-block' are
56;; included but no bound to any key. At last but not least the 56;; included but no bound to any key. At last but not least the
57;; specialized `python-nav-forward-sexp' allows easy 57;; specialized `python-nav-forward-sexp' allows easy navigation
58;; navigation between code blocks. 58;; between code blocks. If you prefer `cc-mode'-like `forward-sexp'
59;; movement, setting `forward-sexp-function' to nil is enough, You can
60;; do that using the `python-mode-hook':
61
62;; (add-hook 'python-mode-hook
63;; (lambda () (setq forward-sexp-function nil)))
59 64
60;; Shell interaction: is provided and allows you to execute easily any 65;; Shell interaction: is provided and allows you to execute easily any
61;; block of code of your current buffer in an inferior Python process. 66;; block of code of your current buffer in an inferior Python process.
@@ -155,7 +160,10 @@
155;; dabbrev. If you have `dabbrev-mode' activated and 160;; dabbrev. If you have `dabbrev-mode' activated and
156;; `python-skeleton-autoinsert' is set to t, then whenever you type 161;; `python-skeleton-autoinsert' is set to t, then whenever you type
157;; the name of any of those defined and hit SPC, they will be 162;; the name of any of those defined and hit SPC, they will be
158;; automatically expanded. 163;; automatically expanded. As an alternative you can use the defined
164;; skeleton commands: `python-skeleton-class', `python-skeleton-def'
165;; `python-skeleton-for', `python-skeleton-if', `python-skeleton-try'
166;; and `python-skeleton-while'.
159 167
160;; FFAP: You can find the filename for a given module when using ffap 168;; FFAP: You can find the filename for a given module when using ffap
161;; out of the box. This feature needs an inferior python shell 169;; out of the box. This feature needs an inferior python shell
@@ -169,10 +177,12 @@
169;; might guessed you should run `python-shell-send-buffer' from time 177;; might guessed you should run `python-shell-send-buffer' from time
170;; to time to get better results too. 178;; to time to get better results too.
171 179
172;; imenu: This mode supports imenu in its most basic form, letting it 180;; Imenu: This mode supports Imenu in its most basic form, letting it
173;; build the necessary alist via `imenu-default-create-index-function' 181;; build the necessary alist via `imenu-default-create-index-function'
174;; by having set `imenu-extract-index-name-function' to 182;; by having set `imenu-extract-index-name-function' to
175;; `python-info-current-defun'. 183;; `python-info-current-defun' and
184;; `imenu-prev-index-position-function' to
185;; `python-imenu-prev-index-position'.
176 186
177;; If you used python-mode.el you probably will miss auto-indentation 187;; If you used python-mode.el you probably will miss auto-indentation
178;; when inserting newlines. To achieve the same behavior you have 188;; when inserting newlines. To achieve the same behavior you have
@@ -202,7 +212,6 @@
202 212
203(require 'ansi-color) 213(require 'ansi-color)
204(require 'comint) 214(require 'comint)
205(eval-when-compile (require 'cl-lib))
206 215
207;; Avoid compiler warnings 216;; Avoid compiler warnings
208(defvar view-return-to-alist) 217(defvar view-return-to-alist)
@@ -219,7 +228,7 @@
219(defgroup python nil 228(defgroup python nil
220 "Python Language's flying circus support for Emacs." 229 "Python Language's flying circus support for Emacs."
221 :group 'languages 230 :group 'languages
222 :version "23.2" 231 :version "24.3"
223 :link '(emacs-commentary-link "python")) 232 :link '(emacs-commentary-link "python"))
224 233
225 234
@@ -527,7 +536,7 @@ is used to limit the scan."
527 (while (and (< i 3) 536 (while (and (< i 3)
528 (or (not limit) (< (+ point i) limit)) 537 (or (not limit) (< (+ point i) limit))
529 (eq (char-after (+ point i)) quote-char)) 538 (eq (char-after (+ point i)) quote-char))
530 (cl-incf i)) 539 (setq i (1+ i)))
531 i)) 540 i))
532 541
533(defun python-syntax-stringify () 542(defun python-syntax-stringify ()
@@ -606,6 +615,12 @@ It makes underscores and dots word constituent chars.")
606 :group 'python 615 :group 'python
607 :safe 'booleanp) 616 :safe 'booleanp)
608 617
618(defcustom python-indent-trigger-commands
619 '(indent-for-tab-command yas-expand yas/expand)
620 "Commands that might trigger a `python-indent-line' call."
621 :type '(repeat symbol)
622 :group 'python)
623
609(define-obsolete-variable-alias 624(define-obsolete-variable-alias
610 'python-indent 'python-indent-offset "24.3") 625 'python-indent 'python-indent-offset "24.3")
611 626
@@ -656,7 +671,7 @@ These make `python-indent-calculate-indentation' subtract the value of
656 (python-util-forward-comment) 671 (python-util-forward-comment)
657 (current-indentation)))) 672 (current-indentation))))
658 (if indentation 673 (if indentation
659 (setq python-indent-offset indentation) 674 (set (make-local-variable 'python-indent-offset) indentation)
660 (message "Can't guess python-indent-offset, using defaults: %s" 675 (message "Can't guess python-indent-offset, using defaults: %s"
661 python-indent-offset))))))) 676 python-indent-offset)))))))
662 677
@@ -693,10 +708,9 @@ START is the buffer position where the sexp starts."
693 ;; After backslash 708 ;; After backslash
694 ((setq start (when (not (or (python-syntax-context 'string ppss) 709 ((setq start (when (not (or (python-syntax-context 'string ppss)
695 (python-syntax-context 'comment ppss))) 710 (python-syntax-context 'comment ppss)))
696 (let ((line-beg-pos (line-beginning-position))) 711 (let ((line-beg-pos (line-number-at-pos)))
697 (when (python-info-line-ends-backslash-p 712 (python-info-line-ends-backslash-p
698 (1- line-beg-pos)) 713 (1- line-beg-pos)))))
699 (- line-beg-pos 2)))))
700 'after-backslash) 714 'after-backslash)
701 ;; After beginning of block 715 ;; After beginning of block
702 ((setq start (save-excursion 716 ((setq start (save-excursion
@@ -904,20 +918,21 @@ Uses the offset calculated in
904indicated by the variable `python-indent-levels' to set the 918indicated by the variable `python-indent-levels' to set the
905current indentation. 919current indentation.
906 920
907When the variable `last-command' is equal to 921When the variable `last-command' is equal to one of the symbols
908`indent-for-tab-command' or FORCE-TOGGLE is non-nil it cycles 922inside `python-indent-trigger-commands' or FORCE-TOGGLE is
909levels indicated in the variable `python-indent-levels' by 923non-nil it cycles levels indicated in the variable
910setting the current level in the variable 924`python-indent-levels' by setting the current level in the
911`python-indent-current-level'. 925variable `python-indent-current-level'.
912 926
913When the variable `last-command' is not equal to 927When the variable `last-command' is not equal to one of the
914`indent-for-tab-command' and FORCE-TOGGLE is nil it calculates 928symbols inside `python-indent-trigger-commands' and FORCE-TOGGLE
915possible indentation levels and saves it in the variable 929is nil it calculates possible indentation levels and saves it in
916`python-indent-levels'. Afterwards it sets the variable 930the variable `python-indent-levels'. Afterwards it sets the
917`python-indent-current-level' correctly so offset is equal 931variable `python-indent-current-level' correctly so offset is
918to (`nth' `python-indent-current-level' `python-indent-levels')" 932equal to (`nth' `python-indent-current-level'
933`python-indent-levels')"
919 (or 934 (or
920 (and (or (and (eq this-command 'indent-for-tab-command) 935 (and (or (and (memq this-command python-indent-trigger-commands)
921 (eq last-command this-command)) 936 (eq last-command this-command))
922 force-toggle) 937 force-toggle)
923 (not (equal python-indent-levels '(0))) 938 (not (equal python-indent-levels '(0)))
@@ -1098,12 +1113,12 @@ With positive ARG search backwards, else search forwards."
1098 (beg-indentation 1113 (beg-indentation
1099 (and (> arg 0) 1114 (and (> arg 0)
1100 (save-excursion 1115 (save-excursion
1101 (and (python-info-current-line-empty-p) 1116 (while (and
1102 (python-util-forward-comment -1)) 1117 (not (python-info-looking-at-beginning-of-defun))
1103 (python-nav-beginning-of-statement) 1118 (python-nav-backward-block)))
1104 (if (python-info-looking-at-beginning-of-defun) 1119 (or (and (python-info-looking-at-beginning-of-defun)
1105 (+ (current-indentation) python-indent-offset) 1120 (+ (current-indentation) python-indent-offset))
1106 (current-indentation))))) 1121 0))))
1107 (found 1122 (found
1108 (progn 1123 (progn
1109 (when (and (< arg 0) 1124 (when (and (< arg 0)
@@ -1179,16 +1194,36 @@ Returns nil if point is not in a def or class."
1179 (forward-line -1)))) 1194 (forward-line -1))))
1180 (point-marker)) 1195 (point-marker))
1181 1196
1182(defun python-nav-end-of-statement () 1197(defun python-nav-end-of-statement (&optional noend)
1183 "Move to end of current statement." 1198 "Move to end of current statement.
1199Optional argument NOEND is internal and makes the logic to not
1200jump to the end of line when moving forward searching for the end
1201of the statement."
1184 (interactive "^") 1202 (interactive "^")
1185 (while (and (goto-char (line-end-position)) 1203 (let (string-start bs-pos)
1186 (not (eobp)) 1204 (while (and (or noend (goto-char (line-end-position)))
1187 (when (or 1205 (not (eobp))
1188 (python-info-line-ends-backslash-p) 1206 (cond ((setq string-start (python-syntax-context 'string))
1189 (python-syntax-context 'string) 1207 (goto-char string-start)
1190 (python-syntax-context 'paren)) 1208 (if (python-syntax-context 'paren)
1191 (forward-line 1)))) 1209 ;; Ended up inside a paren, roll again.
1210 (python-nav-end-of-statement t)
1211 ;; This is not inside a paren, move to the
1212 ;; end of this string.
1213 (goto-char (+ (point)
1214 (python-syntax-count-quotes
1215 (char-after (point)) (point))))
1216 (or (re-search-forward (rx (syntax string-delimiter)) nil t)
1217 (goto-char (point-max)))))
1218 ((python-syntax-context 'paren)
1219 ;; The statement won't end before we've escaped
1220 ;; at least one level of parenthesis.
1221 (condition-case err
1222 (goto-char (scan-lists (point) 1 -1))
1223 (scan-error (goto-char (nth 3 err)))))
1224 ((setq bs-pos (python-info-line-ends-backslash-p))
1225 (goto-char bs-pos)
1226 (forward-line 1))))))
1192 (point-marker)) 1227 (point-marker))
1193 1228
1194(defun python-nav-backward-statement (&optional arg) 1229(defun python-nav-backward-statement (&optional arg)
@@ -1293,7 +1328,7 @@ backward to previous block."
1293 "Safe version of standard `forward-sexp'. 1328 "Safe version of standard `forward-sexp'.
1294When ARG > 0 move forward, else if ARG is < 0." 1329When ARG > 0 move forward, else if ARG is < 0."
1295 (or arg (setq arg 1)) 1330 (or arg (setq arg 1))
1296 (let ((forward-sexp-function nil) 1331 (let ((forward-sexp-function)
1297 (paren-regexp 1332 (paren-regexp
1298 (if (> arg 0) (python-rx close-paren) (python-rx open-paren))) 1333 (if (> arg 0) (python-rx close-paren) (python-rx open-paren)))
1299 (search-fn 1334 (search-fn
@@ -1318,13 +1353,10 @@ backwards."
1318 're-search-backward)) 1353 're-search-backward))
1319 (context-type (python-syntax-context-type))) 1354 (context-type (python-syntax-context-type)))
1320 (cond 1355 (cond
1321 ((eq context-type 'string) 1356 ((memq context-type '(string comment))
1322 ;; Inside of a string, get out of it. 1357 ;; Inside of a string, get out of it.
1323 (while (and (funcall re-search-fn "[\"']" nil t) 1358 (let ((forward-sexp-function))
1324 (python-syntax-context 'string)))) 1359 (forward-sexp dir)))
1325 ((eq context-type 'comment)
1326 ;; Inside of a comment, just move forward.
1327 (python-util-forward-comment dir))
1328 ((or (eq context-type 'paren) 1360 ((or (eq context-type 'paren)
1329 (and forward-p (looking-at (python-rx open-paren))) 1361 (and forward-p (looking-at (python-rx open-paren)))
1330 (and (not forward-p) 1362 (and (not forward-p)
@@ -1347,16 +1379,16 @@ backwards."
1347 (save-excursion 1379 (save-excursion
1348 (python-nav-lisp-forward-sexp-safe dir) 1380 (python-nav-lisp-forward-sexp-safe dir)
1349 (point))) 1381 (point)))
1350 (next-sexp-context 1382 (next-sexp-context
1351 (save-excursion 1383 (save-excursion
1352 (goto-char next-sexp-pos) 1384 (goto-char next-sexp-pos)
1353 (cond 1385 (cond
1354 ((python-info-beginning-of-block-p) 'block-start) 1386 ((python-info-beginning-of-block-p) 'block-start)
1355 ((python-info-end-of-block-p) 'block-end) 1387 ((python-info-end-of-block-p) 'block-end)
1356 ((python-info-beginning-of-statement-p) 'statement-start) 1388 ((python-info-beginning-of-statement-p) 'statement-start)
1357 ((python-info-end-of-statement-p) 'statement-end) 1389 ((python-info-end-of-statement-p) 'statement-end)
1358 ((python-info-statement-starts-block-p) 'starts-block) 1390 ((python-info-statement-starts-block-p) 'starts-block)
1359 ((python-info-statement-ends-block-p) 'ends-block))))) 1391 ((python-info-statement-ends-block-p) 'ends-block)))))
1360 (if forward-p 1392 (if forward-p
1361 (cond ((and (not (eobp)) 1393 (cond ((and (not (eobp))
1362 (python-info-current-line-empty-p)) 1394 (python-info-current-line-empty-p))
@@ -1380,8 +1412,8 @@ backwards."
1380 (t (goto-char next-sexp-pos))) 1412 (t (goto-char next-sexp-pos)))
1381 (cond ((and (not (bobp)) 1413 (cond ((and (not (bobp))
1382 (python-info-current-line-empty-p)) 1414 (python-info-current-line-empty-p))
1383 (python-util-forward-comment dir) 1415 (python-util-forward-comment dir)
1384 (python-nav--forward-sexp dir)) 1416 (python-nav--forward-sexp dir))
1385 ((eq context 'block-end) 1417 ((eq context 'block-end)
1386 (python-nav-beginning-of-block)) 1418 (python-nav-beginning-of-block))
1387 ((eq context 'statement-end) 1419 ((eq context 'statement-end)
@@ -1633,7 +1665,11 @@ uniqueness for different types of configurations."
1633 1665
1634(defun python-shell-parse-command () 1666(defun python-shell-parse-command ()
1635 "Calculate the string used to execute the inferior Python process." 1667 "Calculate the string used to execute the inferior Python process."
1636 (format "%s %s" python-shell-interpreter python-shell-interpreter-args)) 1668 (let ((process-environment (python-shell-calculate-process-environment))
1669 (exec-path (python-shell-calculate-exec-path)))
1670 (format "%s %s"
1671 (executable-find python-shell-interpreter)
1672 python-shell-interpreter-args)))
1637 1673
1638(defun python-shell-calculate-process-environment () 1674(defun python-shell-calculate-process-environment ()
1639 "Calculate process environment given `python-shell-virtualenv-path'." 1675 "Calculate process environment given `python-shell-virtualenv-path'."
@@ -2007,7 +2043,14 @@ Returns the output. See `python-shell-send-string-no-output'."
2007(defun python-shell-send-region (start end) 2043(defun python-shell-send-region (start end)
2008 "Send the region delimited by START and END to inferior Python process." 2044 "Send the region delimited by START and END to inferior Python process."
2009 (interactive "r") 2045 (interactive "r")
2010 (python-shell-send-string (buffer-substring start end) nil t)) 2046 (python-shell-send-string
2047 (concat
2048 (let ((line-num (line-number-at-pos start)))
2049 ;; When sending a region, add blank lines for non sent code so
2050 ;; backtraces remain correct.
2051 (make-string (1- line-num) ?\n))
2052 (buffer-substring start end))
2053 nil t))
2011 2054
2012(defun python-shell-send-buffer (&optional arg) 2055(defun python-shell-send-buffer (&optional arg)
2013 "Send the entire buffer to inferior Python process. 2056 "Send the entire buffer to inferior Python process.
@@ -2285,15 +2328,17 @@ Argument OUTPUT is a string with the output from the comint process."
2285 (file-name 2328 (file-name
2286 (with-temp-buffer 2329 (with-temp-buffer
2287 (insert full-output) 2330 (insert full-output)
2288 (goto-char (point-min)) 2331 ;; When the debugger encounters a pdb.set_trace()
2289 ;; OK, this sucked but now it became a cool hack. The 2332 ;; command, it prints a single stack frame. Sometimes
2290 ;; stacktrace information normally is on the first line 2333 ;; it prints a bit of extra information about the
2291 ;; but in some cases (like when doing a step-in) it is 2334 ;; arguments of the present function. When ipdb
2292 ;; on the second. 2335 ;; encounters an exception, it prints the _entire_ stack
2293 (when (or (looking-at python-pdbtrack-stacktrace-info-regexp) 2336 ;; trace. To handle all of these cases, we want to find
2294 (and 2337 ;; the _last_ stack frame printed in the most recent
2295 (forward-line) 2338 ;; batch of output, then jump to the corresponding
2296 (looking-at python-pdbtrack-stacktrace-info-regexp))) 2339 ;; file/line number.
2340 (goto-char (point-max))
2341 (when (re-search-backward python-pdbtrack-stacktrace-info-regexp nil t)
2297 (setq line-number (string-to-number 2342 (setq line-number (string-to-number
2298 (match-string-no-properties 2))) 2343 (match-string-no-properties 2)))
2299 (match-string-no-properties 1))))) 2344 (match-string-no-properties 1)))))
@@ -2485,12 +2530,12 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'."
2485JUSTIFY should be used (if applicable) as in `fill-paragraph'." 2530JUSTIFY should be used (if applicable) as in `fill-paragraph'."
2486 (let* ((marker (point-marker)) 2531 (let* ((marker (point-marker))
2487 (str-start-pos 2532 (str-start-pos
2488 (let ((m (make-marker))) 2533 (set-marker
2489 (setf (marker-position m) 2534 (make-marker)
2490 (or (python-syntax-context 'string) 2535 (or (python-syntax-context 'string)
2491 (and (equal (string-to-syntax "|") 2536 (and (equal (string-to-syntax "|")
2492 (syntax-after (point))) 2537 (syntax-after (point)))
2493 (point)))) m)) 2538 (point)))))
2494 (num-quotes (python-syntax-count-quotes 2539 (num-quotes (python-syntax-count-quotes
2495 (char-after str-start-pos) str-start-pos)) 2540 (char-after str-start-pos) str-start-pos))
2496 (str-end-pos 2541 (str-end-pos
@@ -2690,17 +2735,17 @@ The skeleton will be bound to python-skeleton-NAME."
2690 2735
2691(python-skeleton-define def nil 2736(python-skeleton-define def nil
2692 "Function name: " 2737 "Function name: "
2693 "def " str " (" ("Parameter, %s: " 2738 "def " str "(" ("Parameter, %s: "
2694 (unless (equal ?\( (char-before)) ", ") 2739 (unless (equal ?\( (char-before)) ", ")
2695 str) "):" \n 2740 str) "):" \n
2696 "\"\"\"" - "\"\"\"" \n 2741 "\"\"\"" - "\"\"\"" \n
2697 > _ \n) 2742 > _ \n)
2698 2743
2699(python-skeleton-define class nil 2744(python-skeleton-define class nil
2700 "Class name: " 2745 "Class name: "
2701 "class " str " (" ("Inheritance, %s: " 2746 "class " str "(" ("Inheritance, %s: "
2702 (unless (equal ?\( (char-before)) ", ") 2747 (unless (equal ?\( (char-before)) ", ")
2703 str) 2748 str)
2704 & ")" | -2 2749 & ")" | -2
2705 ":" \n 2750 ":" \n
2706 "\"\"\"" - "\"\"\"" \n 2751 "\"\"\"" - "\"\"\"" \n
@@ -2881,6 +2926,19 @@ Interactively, prompt for symbol."
2881 "^Eldoc needs an inferior Python process running.") 2926 "^Eldoc needs an inferior Python process running.")
2882 2927
2883 2928
2929;;; Imenu
2930
2931(defun python-imenu-prev-index-position ()
2932 "Python mode's `imenu-prev-index-position-function'."
2933 (let ((found))
2934 (while (and (setq found
2935 (re-search-backward python-nav-beginning-of-defun-regexp nil t))
2936 (not (python-info-looking-at-beginning-of-defun))))
2937 (and found
2938 (python-info-looking-at-beginning-of-defun)
2939 (python-info-current-defun))))
2940
2941
2884;;; Misc helpers 2942;;; Misc helpers
2885 2943
2886(defun python-info-current-defun (&optional include-type) 2944(defun python-info-current-defun (&optional include-type)
@@ -2889,40 +2947,62 @@ Optional argument INCLUDE-TYPE indicates to include the type of the defun.
2889This function is compatible to be used as 2947This function is compatible to be used as
2890`add-log-current-defun-function' since it returns nil if point is 2948`add-log-current-defun-function' since it returns nil if point is
2891not inside a defun." 2949not inside a defun."
2892 (save-restriction 2950 (save-restriction
2893 (widen) 2951 (widen)
2894 (save-excursion 2952 (save-excursion
2895 (end-of-line 1) 2953 (end-of-line 1)
2896 (let ((names) 2954 (let ((names)
2897 (starting-indentation 2955 (starting-indentation (current-indentation))
2898 (save-excursion 2956 (starting-pos (point))
2899 (and 2957 (first-run t)
2900 (python-nav-beginning-of-defun 1) 2958 (last-indent)
2901 ;; This extra number is just for checking code 2959 (type))
2902 ;; against indentation to work well on first run. 2960 (catch 'exit
2903 (+ (current-indentation) 4)))) 2961 (while (python-nav-beginning-of-defun 1)
2904 (starting-point (point))) 2962 (when (save-match-data
2905 ;; Check point is inside a defun. 2963 (and
2906 (when (and starting-indentation 2964 (or (not last-indent)
2907 (< starting-point 2965 (< (current-indentation) last-indent))
2966 (or
2967 (and first-run
2968 (save-excursion
2969 ;; If this is the first run, we may add
2970 ;; the current defun at point.
2971 (setq first-run nil)
2972 (goto-char starting-pos)
2973 (python-nav-beginning-of-statement)
2974 (beginning-of-line 1)
2975 (looking-at-p
2976 python-nav-beginning-of-defun-regexp)))
2977 (< starting-pos
2908 (save-excursion 2978 (save-excursion
2909 (python-nav-end-of-defun) 2979 (let ((min-indent
2910 (point)))) 2980 (+ (current-indentation)
2911 (catch 'exit 2981 python-indent-offset)))
2912 (while (python-nav-beginning-of-defun 1) 2982 (if (< starting-indentation min-indent)
2913 (when (< (current-indentation) starting-indentation) 2983 ;; If the starting indentation is not
2914 (setq starting-indentation (current-indentation)) 2984 ;; within the min defun indent make the
2915 (setq names 2985 ;; check fail.
2916 (cons 2986 starting-pos
2917 (if (not include-type) 2987 ;; Else go to the end of defun and add
2918 (match-string-no-properties 1) 2988 ;; up the current indentation to the
2919 (mapconcat 'identity 2989 ;; ending position.
2920 (split-string 2990 (python-nav-end-of-defun)
2921 (match-string-no-properties 0)) " ")) 2991 (+ (point)
2922 names))) 2992 (if (>= (current-indentation) min-indent)
2923 (and (= (current-indentation) 0) (throw 'exit t))))) 2993 (1+ (current-indentation))
2924 (and names 2994 0)))))))))
2925 (mapconcat (lambda (string) string) names ".")))))) 2995 (save-match-data (setq last-indent (current-indentation)))
2996 (if (or (not include-type) type)
2997 (setq names (cons (match-string-no-properties 1) names))
2998 (let ((match (split-string (match-string-no-properties 0))))
2999 (setq type (car match))
3000 (setq names (cons (cadr match) names)))))
3001 ;; Stop searching ASAP.
3002 (and (= (current-indentation) 0) (throw 'exit t))))
3003 (and names
3004 (concat (and type (format "%s " type))
3005 (mapconcat 'identity names ".")))))))
2926 3006
2927(defun python-info-current-symbol (&optional replace-self) 3007(defun python-info-current-symbol (&optional replace-self)
2928 "Return current symbol using dotty syntax. 3008 "Return current symbol using dotty syntax.
@@ -3035,7 +3115,7 @@ With optional argument LINE-NUMBER, check that line instead."
3035 (save-restriction 3115 (save-restriction
3036 (widen) 3116 (widen)
3037 (when line-number 3117 (when line-number
3038 (goto-char line-number)) 3118 (python-util-goto-line line-number))
3039 (while (and (not (eobp)) 3119 (while (and (not (eobp))
3040 (goto-char (line-end-position)) 3120 (goto-char (line-end-position))
3041 (python-syntax-context 'paren) 3121 (python-syntax-context 'paren)
@@ -3051,7 +3131,7 @@ Optional argument LINE-NUMBER forces the line number to check against."
3051 (save-restriction 3131 (save-restriction
3052 (widen) 3132 (widen)
3053 (when line-number 3133 (when line-number
3054 (goto-char line-number)) 3134 (python-util-goto-line line-number))
3055 (when (python-info-line-ends-backslash-p) 3135 (when (python-info-line-ends-backslash-p)
3056 (while (save-excursion 3136 (while (save-excursion
3057 (goto-char (line-beginning-position)) 3137 (goto-char (line-beginning-position))
@@ -3130,7 +3210,9 @@ operator."
3130 3210
3131(defun python-info-current-line-comment-p () 3211(defun python-info-current-line-comment-p ()
3132 "Check if current line is a comment line." 3212 "Check if current line is a comment line."
3133 (char-equal (or (char-after (+ (point) (current-indentation))) ?_) ?#)) 3213 (char-equal
3214 (or (char-after (+ (line-beginning-position) (current-indentation))) ?_)
3215 ?#))
3134 3216
3135(defun python-info-current-line-empty-p () 3217(defun python-info-current-line-empty-p ()
3136 "Check if current line is empty, ignoring whitespace." 3218 "Check if current line is empty, ignoring whitespace."
@@ -3145,12 +3227,10 @@ operator."
3145 3227
3146;;; Utility functions 3228;;; Utility functions
3147 3229
3148(defun python-util-position (item seq) 3230(defun python-util-goto-line (line-number)
3149 "Find the first occurrence of ITEM in SEQ. 3231 "Move point to LINE-NUMBER."
3150Return the index of the matching item, or nil if not found." 3232 (goto-char (point-min))
3151 (let ((member-result (member item seq))) 3233 (forward-line (1- line-number)))
3152 (when member-result
3153 (- (length seq) (length member-result)))))
3154 3234
3155;; Stolen from org-mode 3235;; Stolen from org-mode
3156(defun python-util-clone-local-variables (from-buffer &optional regexp) 3236(defun python-util-clone-local-variables (from-buffer &optional regexp)
@@ -3225,6 +3305,9 @@ if that value is non-nil."
3225 (set (make-local-variable 'imenu-extract-index-name-function) 3305 (set (make-local-variable 'imenu-extract-index-name-function)
3226 #'python-info-current-defun) 3306 #'python-info-current-defun)
3227 3307
3308 (set (make-local-variable 'imenu-prev-index-position-function)
3309 #'python-imenu-prev-index-position)
3310
3228 (set (make-local-variable 'add-log-current-defun-function) 3311 (set (make-local-variable 'add-log-current-defun-function)
3229 #'python-info-current-defun) 3312 #'python-info-current-defun)
3230 3313