Added simple way of jumping to current buffer's class/function definitions
[bpt/emacs.git] / lisp / progmodes / python.el
CommitLineData
33d0aec1 1;;; python.el --- Python's flying circus support for Emacs
45c138ac 2
e2d8d479 3;; Copyright (C) 2010, 2011 Free Software Foundation, Inc.
45c138ac
FEG
4
5;; Author: Fabián E. Gallina <fabian@anue.biz>
b7f13559
FEG
6;; URL: https://github.com/fgallina/python.el
7;; Version: 0.23.1
45c138ac
FEG
8;; Maintainer: FSF
9;; Created: Jul 2010
10;; Keywords: languages
11
12;; This file is NOT part of GNU Emacs.
13
14;; python.el is free software: you can redistribute it and/or modify
15;; it under the terms of the GNU General Public License as published by
16;; the Free Software Foundation, either version 3 of the License, or
17;; (at your option) any later version.
18
19;; python.el is distributed in the hope that it will be useful,
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
23
24;; You should have received a copy of the GNU General Public License
25;; along with python.el. If not, see <http://www.gnu.org/licenses/>.
26
27;;; Commentary:
28
29;; Major mode for editing Python files with some fontification and
30;; indentation bits extracted from original Dave Love's python.el
31;; found in GNU/Emacs.
32
33;; While it probably has less features than Dave Love's python.el and
34;; PSF's python-mode.el it provides the main stuff you'll need while
35;; keeping it simple :)
36
37;; Implements Syntax highlighting, Indentation, Movement, Shell
64348c32
FEG
38;; interaction, Shell completion, Shell virtualenv support, Pdb
39;; tracking, Symbol completion, Skeletons, FFAP, Code Check, Eldoc,
40;; imenu.
45c138ac
FEG
41
42;; Syntax highlighting: Fontification of code is provided and supports
43;; python's triple quoted strings properly.
44
45;; Indentation: Automatic indentation with indentation cycling is
46;; provided, it allows you to navigate different available levels of
67845102
FEG
47;; indentation by hitting <tab> several times. Also when inserting a
48;; colon the `python-indent-electric-colon' command is invoked and
49;; causes the current line to be dedented automatically if needed.
45c138ac
FEG
50
51;; Movement: `beginning-of-defun' and `end-of-defun' functions are
fc6c545e 52;; properly implemented. There are also specialized
4cafacb5
FEG
53;; `forward-sentence' and `backward-sentence' replacements
54;; (`python-nav-forward-sentence', `python-nav-backward-sentence'
55;; respectively). Extra functions `python-nav-sentence-start' and
56;; `python-nav-sentence-end' are included to move to the beginning and
57;; to the end of a setence while taking care of multiline definitions.
fc6c545e
FEG
58;; `python-nav-jump-to-defun' is provided and allows jumping to a
59;; function or class definition quickly in the current buffer.
45c138ac 60
fc6c545e 61;; Shell interaction: is provided and allows you to execute easily any
45c138ac
FEG
62;; block of code of your current buffer in an inferior Python process.
63
64;; Shell completion: hitting tab will try to complete the current
4e531f7a 65;; word. Shell completion is implemented in a manner that if you
45c138ac
FEG
66;; change the `python-shell-interpreter' to any other (for example
67;; IPython) it should be easy to integrate another way to calculate
57808175 68;; completions. You just need to specify your custom
45c138ac 69;; `python-shell-completion-setup-code' and
4cafacb5 70;; `python-shell-completion-string-code'.
62feb915
FEG
71
72;; Here is a complete example of the settings you would use for
1faf2911 73;; iPython 0.11:
62feb915
FEG
74
75;; (setq
76;; python-shell-interpreter "ipython"
77;; python-shell-interpreter-args ""
78;; python-shell-prompt-regexp "In \\[[0-9]+\\]: "
79;; python-shell-prompt-output-regexp "Out\\[[0-9]+\\]: "
80;; python-shell-completion-setup-code ""
81;; python-shell-completion-string-code
1faf2911
FEG
82;; "';'.join(get_ipython().Completer.all_completions('''%s'''))\n")
83
84;; For iPython 0.10 everything would be the same except for
85;; `python-shell-completion-string-code':
86
87;; (setq python-shell-completion-string-code
88;; "';'.join(__IP.complete('''%s'''))\n")
45c138ac 89
099bf010
FEG
90;; Please note that the default completion system depends on the
91;; readline module, so if you are using some Operating System that
92;; bundles Python without it (like Windows) just install the
93;; pyreadline from http://ipython.scipy.org/moin/PyReadline/Intro and
94;; you should be good to go.
95
64348c32
FEG
96;; Shell virtualenv support: The shell also contains support for
97;; virtualenvs and other special environment modifications thanks to
66bbb27f
FEG
98;; `python-shell-process-environment' and `python-shell-exec-path'.
99;; These two variables allows you to modify execution paths and
307bd2e8 100;; environment variables to make easy for you to setup virtualenv rules
64348c32 101;; or behavior modifications when running shells. Here is an example
66bbb27f
FEG
102;; of how to make shell processes to be run using the /path/to/env/
103;; virtualenv:
104
105;; (setq python-shell-process-environment
106;; (list
107;; (format "PATH=%s" (mapconcat
108;; 'identity
109;; (reverse
110;; (cons (getenv "PATH")
111;; '("/path/to/env/bin/")))
112;; ":"))
113;; "VIRTUAL_ENV=/path/to/env/"))
114;; (python-shell-exec-path . ("/path/to/env/bin/"))
115
64348c32
FEG
116;; Since the above is cumbersome and can be programatically
117;; calculated, the variable `python-shell-virtualenv-path' is
118;; provided. When this variable is set with the path of the
119;; virtualenv to use, `process-environment' and `exec-path' get proper
120;; values in order to run shells inside the specified virtualenv. So
121;; the following will achieve the same as the previous example:
122
123;; (setq python-shell-virtualenv-path "/path/to/env/")
124
45c138ac
FEG
125;; Pdb tracking: when you execute a block of code that contains some
126;; call to pdb (or ipdb) it will prompt the block of code and will
127;; follow the execution of pdb marking the current line with an arrow.
128
4e531f7a 129;; Symbol completion: you can complete the symbol at point. It uses
45c138ac
FEG
130;; the shell completion in background so you should run
131;; `python-shell-send-buffer' from time to time to get better results.
132
e2803784
FEG
133;; Skeletons: 6 skeletons are provided for simple inserting of class,
134;; def, for, if, try and while. These skeletons are integrated with
135;; dabbrev. If you have `dabbrev-mode' activated and
136;; `python-skeleton-autoinsert' is set to t, then whenever you type
137;; the name of any of those defined and hit SPC, they will be
138;; automatically expanded.
139
2947016a
FEG
140;; FFAP: You can find the filename for a given module when using ffap
141;; out of the box. This feature needs an inferior python shell
142;; running.
143
2d63ad56
FEG
144;; Code check: Check the current file for errors with `python-check'
145;; using the program defined in `python-check-command'.
8b3e0e76 146
45c138ac 147;; Eldoc: returns documentation for object at point by using the
4e531f7a 148;; inferior python subprocess to inspect its documentation. As you
45c138ac
FEG
149;; might guessed you should run `python-shell-send-buffer' from time
150;; to time to get better results too.
151
4cafacb5
FEG
152;; imenu: This mode supports imenu. It builds a plain or tree menu
153;; depending on the value of `python-imenu-make-tree'. Also you can
fc2dc7df
FEG
154;; customize if menu items should include its type using
155;; `python-imenu-include-defun-type'.
156
57808175
FEG
157;; If you used python-mode.el you probably will miss auto-indentation
158;; when inserting newlines. To achieve the same behavior you have
159;; two options:
160
161;; 1) Use GNU/Emacs' standard binding for `newline-and-indent': C-j.
162
163;; 2) Add the following hook in your .emacs:
164
165;; (add-hook 'python-mode-hook
166;; #'(lambda ()
167;; (define-key python-mode-map "\C-m" 'newline-and-indent)))
168
169;; I'd recommend the first one since you'll get the same behavior for
170;; all modes out-of-the-box.
171
45c138ac
FEG
172;;; Installation:
173
174;; Add this to your .emacs:
175
176;; (add-to-list 'load-path "/folder/containing/file")
177;; (require 'python)
178
179;;; TODO:
180
45c138ac
FEG
181;;; Code:
182
45c138ac 183(require 'ansi-color)
73ed6836 184(require 'comint)
45c138ac
FEG
185
186(eval-when-compile
73ed6836
FEG
187 (require 'cl)
188 ;; Avoid compiler warnings
189 (defvar view-return-to-alist)
190 (defvar compilation-error-regexp-alist)
191 (defvar outline-heading-end-regexp))
45c138ac
FEG
192
193(autoload 'comint-mode "comint")
194
195;;;###autoload
196(add-to-list 'auto-mode-alist (cons (purecopy "\\.py\\'") 'python-mode))
197;;;###autoload
198(add-to-list 'interpreter-mode-alist (cons (purecopy "python") 'python-mode))
199
200(defgroup python nil
201 "Python Language's flying circus support for Emacs."
202 :group 'languages
203 :version "23.2"
204 :link '(emacs-commentary-link "python"))
205
206\f
207;;; Bindings
208
209(defvar python-mode-map
210 (let ((map (make-sparse-keymap)))
9fff1858
FEG
211 ;; Movement
212 (substitute-key-definition 'backward-sentence
213 'python-nav-backward-sentence
214 map global-map)
215 (substitute-key-definition 'forward-sentence
216 'python-nav-forward-sentence
217 map global-map)
fc6c545e 218 (define-key map "\C-c\C-j" 'python-nav-jump-to-defun)
45c138ac
FEG
219 ;; Indent specific
220 (define-key map "\177" 'python-indent-dedent-line-backspace)
221 (define-key map (kbd "<backtab>") 'python-indent-dedent-line)
222 (define-key map "\C-c<" 'python-indent-shift-left)
223 (define-key map "\C-c>" 'python-indent-shift-right)
ffdb56c3 224 (define-key map ":" 'python-indent-electric-colon)
e2803784
FEG
225 ;; Skeletons
226 (define-key map "\C-c\C-tc" 'python-skeleton-class)
227 (define-key map "\C-c\C-td" 'python-skeleton-def)
228 (define-key map "\C-c\C-tf" 'python-skeleton-for)
229 (define-key map "\C-c\C-ti" 'python-skeleton-if)
230 (define-key map "\C-c\C-tt" 'python-skeleton-try)
231 (define-key map "\C-c\C-tw" 'python-skeleton-while)
45c138ac
FEG
232 ;; Shell interaction
233 (define-key map "\C-c\C-s" 'python-shell-send-string)
234 (define-key map "\C-c\C-r" 'python-shell-send-region)
235 (define-key map "\C-\M-x" 'python-shell-send-defun)
236 (define-key map "\C-c\C-c" 'python-shell-send-buffer)
237 (define-key map "\C-c\C-l" 'python-shell-send-file)
238 (define-key map "\C-c\C-z" 'python-shell-switch-to-shell)
8b3e0e76
FEG
239 ;; Some util commands
240 (define-key map "\C-c\C-v" 'python-check)
78334b43 241 (define-key map "\C-c\C-f" 'python-eldoc-at-point)
45c138ac
FEG
242 ;; Utilities
243 (substitute-key-definition 'complete-symbol 'completion-at-point
244 map global-map)
245 (easy-menu-define python-menu map "Python Mode menu"
246 `("Python"
247 :help "Python-specific Features"
248 ["Shift region left" python-indent-shift-left :active mark-active
249 :help "Shift region left by a single indentation step"]
250 ["Shift region right" python-indent-shift-right :active mark-active
251 :help "Shift region right by a single indentation step"]
252 "-"
45c138ac
FEG
253 ["Start of def/class" beginning-of-defun
254 :help "Go to start of outermost definition around point"]
45c138ac
FEG
255 ["End of def/class" end-of-defun
256 :help "Go to end of definition around point"]
fc6c545e
FEG
257 ["Mark def/class" mark-defun
258 :help "Mark outermost definition around point"]
259 ["Jump to def/class" python-nav-jump-to-defun
260 :help "Jump to a class or function definition"]
261 "--"
e2803784 262 ("Skeletons")
fc6c545e 263 "---"
45c138ac
FEG
264 ["Start interpreter" run-python
265 :help "Run inferior Python process in a separate buffer"]
266 ["Switch to shell" python-shell-switch-to-shell
267 :help "Switch to running inferior Python process"]
268 ["Eval string" python-shell-send-string
269 :help "Eval string in inferior Python session"]
270 ["Eval buffer" python-shell-send-buffer
271 :help "Eval buffer in inferior Python session"]
272 ["Eval region" python-shell-send-region
273 :help "Eval region in inferior Python session"]
274 ["Eval defun" python-shell-send-defun
275 :help "Eval defun in inferior Python session"]
276 ["Eval file" python-shell-send-file
277 :help "Eval file in inferior Python session"]
278 ["Debugger" pdb :help "Run pdb under GUD"]
fc6c545e 279 "----"
8b3e0e76
FEG
280 ["Check file" python-check
281 :help "Check file for errors"]
78334b43
FEG
282 ["Help on symbol" python-eldoc-at-point
283 :help "Get help on symbol at point"]
45c138ac
FEG
284 ["Complete symbol" completion-at-point
285 :help "Complete symbol before point"]))
286 map)
287 "Keymap for `python-mode'.")
288
289\f
290;;; Python specialized rx
291
73ed6836
FEG
292(eval-when-compile
293 (defconst python-rx-constituents
294 (list
295 `(block-start . ,(rx symbol-start
296 (or "def" "class" "if" "elif" "else" "try"
297 "except" "finally" "for" "while" "with")
298 symbol-end))
0567effb
FEG
299 `(decorator . ,(rx line-start (* space) ?@ (any letter ?_)
300 (* (any word ?_))))
73ed6836 301 `(defun . ,(rx symbol-start (or "def" "class") symbol-end))
0567effb 302 `(symbol-name . ,(rx (any letter ?_) (* (any word ?_))))
73ed6836
FEG
303 `(open-paren . ,(rx (or "{" "[" "(")))
304 `(close-paren . ,(rx (or "}" "]" ")")))
305 `(simple-operator . ,(rx (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%)))
306 `(not-simple-operator . ,(rx (not (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%))))
307 `(operator . ,(rx (or "+" "-" "/" "&" "^" "~" "|" "*" "<" ">"
308 "=" "%" "**" "//" "<<" ">>" "<=" "!="
309 "==" ">=" "is" "not")))
310 `(assignment-operator . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**="
e2d8d479
FEG
311 ">>=" "<<=" "&=" "^=" "|="))))
312 "Additional Python specific sexps for `python-rx'"))
45c138ac
FEG
313
314(defmacro python-rx (&rest regexps)
4cafacb5 315 "Python mode specialized rx macro which supports common python named REGEXPS."
45c138ac
FEG
316 (let ((rx-constituents (append python-rx-constituents rx-constituents)))
317 (cond ((null regexps)
318 (error "No regexp"))
319 ((cdr regexps)
320 (rx-to-string `(and ,@regexps) t))
321 (t
322 (rx-to-string (car regexps) t)))))
323
324\f
325;;; Font-lock and syntax
326
327(defvar python-font-lock-keywords
328 ;; Keywords
329 `(,(rx symbol-start
330 (or "and" "del" "from" "not" "while" "as" "elif" "global" "or" "with"
331 "assert" "else" "if" "pass" "yield" "break" "except" "import"
332 "print" "class" "exec" "in" "raise" "continue" "finally" "is"
333 "return" "def" "for" "lambda" "try" "self")
334 symbol-end)
335 ;; functions
336 (,(rx symbol-start "def" (1+ space) (group (1+ (or word ?_))))
337 (1 font-lock-function-name-face))
338 ;; classes
339 (,(rx symbol-start "class" (1+ space) (group (1+ (or word ?_))))
340 (1 font-lock-type-face))
341 ;; Constants
c61d750e
FEG
342 (,(rx symbol-start
343 ;; copyright, license, credits, quit, exit are added by the
344 ;; site module and since they are not intended to be used in
345 ;; programs they are not added here either.
346 (or "None" "True" "False" "Ellipsis" "__debug__" "NotImplemented")
347 symbol-end) . font-lock-constant-face)
45c138ac
FEG
348 ;; Decorators.
349 (,(rx line-start (* (any " \t")) (group "@" (1+ (or word ?_))
350 (0+ "." (1+ (or word ?_)))))
351 (1 font-lock-type-face))
352 ;; Builtin Exceptions
353 (,(rx symbol-start
354 (or "ArithmeticError" "AssertionError" "AttributeError"
355 "BaseException" "BufferError" "BytesWarning" "DeprecationWarning"
356 "EOFError" "EnvironmentError" "Exception" "FloatingPointError"
357 "FutureWarning" "GeneratorExit" "IOError" "ImportError"
358 "ImportWarning" "IndentationError" "IndexError" "KeyError"
359 "KeyboardInterrupt" "LookupError" "MemoryError" "NameError"
c61d750e 360 "NotImplementedError" "OSError" "OverflowError"
45c138ac
FEG
361 "PendingDeprecationWarning" "ReferenceError" "RuntimeError"
362 "RuntimeWarning" "StandardError" "StopIteration" "SyntaxError"
363 "SyntaxWarning" "SystemError" "SystemExit" "TabError" "TypeError"
364 "UnboundLocalError" "UnicodeDecodeError" "UnicodeEncodeError"
365 "UnicodeError" "UnicodeTranslateError" "UnicodeWarning"
366 "UserWarning" "ValueError" "Warning" "ZeroDivisionError")
367 symbol-end) . font-lock-type-face)
368 ;; Builtins
9438f1ef
FEG
369 (,(rx symbol-start
370 (or "_" "__doc__" "__import__" "__name__" "__package__" "abs" "all"
371 "any" "apply" "basestring" "bin" "bool" "buffer" "bytearray"
372 "bytes" "callable" "chr" "classmethod" "cmp" "coerce" "compile"
373 "complex" "delattr" "dict" "dir" "divmod" "enumerate" "eval"
374 "execfile" "file" "filter" "float" "format" "frozenset"
375 "getattr" "globals" "hasattr" "hash" "help" "hex" "id" "input"
376 "int" "intern" "isinstance" "issubclass" "iter" "len" "list"
377 "locals" "long" "map" "max" "min" "next" "object" "oct" "open"
378 "ord" "pow" "print" "property" "range" "raw_input" "reduce"
379 "reload" "repr" "reversed" "round" "set" "setattr" "slice"
380 "sorted" "staticmethod" "str" "sum" "super" "tuple" "type"
381 "unichr" "unicode" "vars" "xrange" "zip")
382 symbol-end) . font-lock-builtin-face)
45c138ac
FEG
383 ;; asignations
384 ;; support for a = b = c = 5
385 (,(lambda (limit)
d8e594db
FEG
386 (let ((re (python-rx (group (+ (any word ?. ?_)))
387 (? ?\[ (+ (not (any ?\]))) ?\]) (* space)
45c138ac
FEG
388 assignment-operator)))
389 (when (re-search-forward re limit t)
14a78495 390 (while (and (python-info-ppss-context 'paren)
45c138ac 391 (re-search-forward re limit t)))
14a78495 392 (if (and (not (python-info-ppss-context 'paren))
534e2438 393 (not (equal (char-after (point-marker)) ?=)))
45c138ac
FEG
394 t
395 (set-match-data nil)))))
396 (1 font-lock-variable-name-face nil nil))
397 ;; support for a, b, c = (1, 2, 3)
398 (,(lambda (limit)
399 (let ((re (python-rx (group (+ (any word ?. ?_))) (* space)
400 (* ?, (* space) (+ (any word ?. ?_)) (* space))
401 ?, (* space) (+ (any word ?. ?_)) (* space)
402 assignment-operator)))
403 (when (and (re-search-forward re limit t)
404 (goto-char (nth 3 (match-data))))
14a78495 405 (while (and (python-info-ppss-context 'paren)
45c138ac
FEG
406 (re-search-forward re limit t))
407 (goto-char (nth 3 (match-data))))
14a78495 408 (if (not (python-info-ppss-context 'paren))
45c138ac
FEG
409 t
410 (set-match-data nil)))))
411 (1 font-lock-variable-name-face nil nil))))
412
45c138ac 413(defconst python-font-lock-syntactic-keywords
ecf24fd7
FEG
414 ;; Make outer chars of matching triple-quote sequences into generic
415 ;; string delimiters. Fixme: Is there a better way?
45c138ac 416 ;; First avoid a sequence preceded by an odd number of backslashes.
ecf24fd7
FEG
417 `((,(concat "\\(?:\\([RUru]\\)[Rr]?\\|^\\|[^\\]\\(?:\\\\.\\)*\\)" ;Prefix.
418 "\\(?:\\('\\)'\\('\\)\\|\\(?2:\"\\)\"\\(?3:\"\\)\\)")
419 (3 (python-quote-syntax)))))
420
421(defun python-quote-syntax ()
45c138ac
FEG
422 "Put `syntax-table' property correctly on triple quote.
423Used for syntactic keywords. N is the match number (1, 2 or 3)."
424 ;; Given a triple quote, we have to check the context to know
425 ;; whether this is an opening or closing triple or whether it's
426 ;; quoted anyhow, and should be ignored. (For that we need to do
427 ;; the same job as `syntax-ppss' to be correct and it seems to be OK
428 ;; to use it here despite initial worries.) We also have to sort
429 ;; out a possible prefix -- well, we don't _have_ to, but I think it
430 ;; should be treated as part of the string.
431
432 ;; Test cases:
433 ;; ur"""ar""" x='"' # """
434 ;; x = ''' """ ' a
435 ;; '''
436 ;; x '"""' x """ \"""" x
437 (save-excursion
438 (goto-char (match-beginning 0))
ecf24fd7
FEG
439 (let ((syntax (save-match-data (syntax-ppss))))
440 (cond
441 ((eq t (nth 3 syntax)) ; after unclosed fence
442 ;; Consider property for the last char if in a fenced string.
443 (goto-char (nth 8 syntax)) ; fence position
444 (skip-chars-forward "uUrR") ; skip any prefix
445 ;; Is it a matching sequence?
446 (if (eq (char-after) (char-after (match-beginning 2)))
447 (put-text-property (match-beginning 3) (match-end 3)
448 'syntax-table (string-to-syntax "|"))))
449 ((match-end 1)
450 ;; Consider property for initial char, accounting for prefixes.
451 (put-text-property (match-beginning 1) (match-end 1)
452 'syntax-table (string-to-syntax "|")))
453 (t
454 ;; Consider property for initial char, accounting for prefixes.
455 (put-text-property (match-beginning 2) (match-end 2)
456 'syntax-table (string-to-syntax "|"))))
457 )))
45c138ac
FEG
458
459(defvar python-mode-syntax-table
460 (let ((table (make-syntax-table)))
461 ;; Give punctuation syntax to ASCII that normally has symbol
462 ;; syntax or has word syntax and isn't a letter.
463 (let ((symbol (string-to-syntax "_"))
464 (sst (standard-syntax-table)))
465 (dotimes (i 128)
466 (unless (= i ?_)
467 (if (equal symbol (aref sst i))
468 (modify-syntax-entry i "." table)))))
469 (modify-syntax-entry ?$ "." table)
470 (modify-syntax-entry ?% "." table)
471 ;; exceptions
472 (modify-syntax-entry ?# "<" table)
473 (modify-syntax-entry ?\n ">" table)
474 (modify-syntax-entry ?' "\"" table)
475 (modify-syntax-entry ?` "$" table)
476 table)
477 "Syntax table for Python files.")
478
479(defvar python-dotty-syntax-table
480 (let ((table (make-syntax-table python-mode-syntax-table)))
481 (modify-syntax-entry ?. "w" table)
482 (modify-syntax-entry ?_ "w" table)
483 table)
484 "Dotty syntax table for Python files.
485It makes underscores and dots word constituent chars.")
486
487\f
488;;; Indentation
489
490(defcustom python-indent-offset 4
491 "Default indentation offset for Python."
492 :group 'python
493 :type 'integer
494 :safe 'integerp)
495
496(defcustom python-indent-guess-indent-offset t
497 "Non-nil tells Python mode to guess `python-indent-offset' value."
498 :type 'boolean
0f55249e
FEG
499 :group 'python
500 :safe 'booleanp)
45c138ac
FEG
501
502(defvar python-indent-current-level 0
503 "Current indentation level `python-indent-line-function' is using.")
504
505(defvar python-indent-levels '(0)
506 "Levels of indentation available for `python-indent-line-function'.")
507
508(defvar python-indent-dedenters '("else" "elif" "except" "finally")
509 "List of words that should be dedented.
510These make `python-indent-calculate-indentation' subtract the value of
511`python-indent-offset'.")
512
513(defun python-indent-guess-indent-offset ()
954aa7bd 514 "Guess and set `python-indent-offset' for the current buffer."
bbac1eb8
FEG
515 (save-excursion
516 (save-restriction
517 (widen)
518 (goto-char (point-min))
519 (let ((found-block))
520 (while (and (not found-block)
521 (re-search-forward
522 (python-rx line-start block-start) nil t))
14a78495
FEG
523 (when (and (not (python-info-ppss-context 'string))
524 (not (python-info-ppss-context 'comment))
bbac1eb8
FEG
525 (progn
526 (goto-char (line-end-position))
589cefd7 527 (forward-comment -9999)
bbac1eb8
FEG
528 (eq ?: (char-before))))
529 (setq found-block t)))
530 (if (not found-block)
531 (message "Can't guess python-indent-offset, using defaults: %s"
532 python-indent-offset)
533 (while (and (progn
534 (goto-char (line-end-position))
535 (python-info-continuation-line-p))
536 (not (eobp)))
537 (forward-line 1))
538 (forward-line 1)
589cefd7 539 (forward-comment 9999)
14d9f80c
FEG
540 (let ((indent-offset (current-indentation)))
541 (when (> indent-offset 0)
542 (setq python-indent-offset indent-offset))))))))
45c138ac 543
e2d8d479
FEG
544(defun python-indent-context ()
545 "Get information on indentation context.
546Context information is returned with a cons with the form:
547 \(STATUS . START)
45c138ac
FEG
548
549Where status can be any of the following symbols:
45c138ac
FEG
550 * inside-paren: If point in between (), {} or []
551 * inside-string: If point is inside a string
552 * after-backslash: Previous line ends in a backslash
553 * after-beginning-of-block: Point is after beginning of block
554 * after-line: Point is after normal line
555 * no-indent: Point is at beginning of buffer or other special case
45c138ac
FEG
556START is the buffer position where the sexp starts."
557 (save-restriction
558 (widen)
559 (let ((ppss (save-excursion (beginning-of-line) (syntax-ppss)))
560 (start))
561 (cons
562 (cond
69bab1de 563 ;; Beginning of buffer
19b122e4
FEG
564 ((save-excursion
565 (goto-char (line-beginning-position))
566 (bobp))
69bab1de 567 'no-indent)
45c138ac 568 ;; Inside a paren
14a78495 569 ((setq start (python-info-ppss-context 'paren ppss))
45c138ac
FEG
570 'inside-paren)
571 ;; Inside string
14a78495 572 ((setq start (python-info-ppss-context 'string ppss))
45c138ac
FEG
573 'inside-string)
574 ;; After backslash
14a78495
FEG
575 ((setq start (when (not (or (python-info-ppss-context 'string ppss)
576 (python-info-ppss-context 'comment ppss)))
45c138ac
FEG
577 (let ((line-beg-pos (line-beginning-position)))
578 (when (eq ?\\ (char-before (1- line-beg-pos)))
579 (- line-beg-pos 2)))))
580 'after-backslash)
581 ;; After beginning of block
582 ((setq start (save-excursion
583 (let ((block-regexp (python-rx block-start))
584 (block-start-line-end ":[[:space:]]*$"))
585 (back-to-indentation)
257b0017 586 (forward-comment -9999)
45c138ac
FEG
587 (back-to-indentation)
588 (when (or (python-info-continuation-line-p)
589 (and (not (looking-at block-regexp))
590 (save-excursion
591 (re-search-forward
592 block-start-line-end
593 (line-end-position) t))))
594 (while (and (forward-line -1)
595 (python-info-continuation-line-p)
596 (not (bobp))))
fad22dec 597 (back-to-indentation)
45c138ac
FEG
598 (when (not (looking-at block-regexp))
599 (forward-line 1)))
600 (back-to-indentation)
601 (when (and (looking-at block-regexp)
602 (or (re-search-forward
603 block-start-line-end
604 (line-end-position) t)
fad22dec
FEG
605 (save-excursion
606 (goto-char (line-end-position))
607 (python-info-continuation-line-p))))
45c138ac
FEG
608 (point-marker)))))
609 'after-beginning-of-block)
610 ;; After normal line
611 ((setq start (save-excursion
257b0017
FEG
612 (back-to-indentation)
613 (forward-comment -9999)
3697b531 614 (python-nav-sentence-start)
45c138ac
FEG
615 (point-marker)))
616 'after-line)
617 ;; Do not indent
618 (t 'no-indent))
619 start))))
620
621(defun python-indent-calculate-indentation ()
622 "Calculate correct indentation offset for the current line."
623 (let* ((indentation-context (python-indent-context))
624 (context-status (car indentation-context))
625 (context-start (cdr indentation-context)))
626 (save-restriction
627 (widen)
628 (save-excursion
629 (case context-status
630 ('no-indent 0)
631 ('after-beginning-of-block
632 (goto-char context-start)
633 (+ (current-indentation) python-indent-offset))
634 ('after-line
635 (-
636 (save-excursion
637 (goto-char context-start)
638 (current-indentation))
639 (if (progn
640 (back-to-indentation)
641 (looking-at (regexp-opt python-indent-dedenters)))
642 python-indent-offset
643 0)))
644 ('inside-string
645 (goto-char context-start)
646 (current-indentation))
647 ('after-backslash
648 (let* ((block-continuation
649 (save-excursion
650 (forward-line -1)
651 (python-info-block-continuation-line-p)))
652 (assignment-continuation
653 (save-excursion
654 (forward-line -1)
655 (python-info-assignment-continuation-line-p)))
9f1537ef
FEG
656 (dot-continuation
657 (save-excursion
658 (back-to-indentation)
659 (when (looking-at "\\.")
660 (forward-line -1)
107c2439
FEG
661 (goto-char (line-end-position))
662 (while (and (re-search-backward "\\." (line-beginning-position) t)
663 (or (python-info-ppss-context 'comment)
664 (python-info-ppss-context 'string)
665 (python-info-ppss-context 'paren))))
666 (if (and (looking-at "\\.")
667 (not (or (python-info-ppss-context 'comment)
668 (python-info-ppss-context 'string)
669 (python-info-ppss-context 'paren))))
670 (current-column)
671 (+ (current-indentation) python-indent-offset)))))
672 (indentation (cond
673 (dot-continuation
674 dot-continuation)
675 (block-continuation
676 (goto-char block-continuation)
677 (re-search-forward
678 (python-rx block-start (* space))
679 (line-end-position) t)
680 (current-column))
681 (assignment-continuation
682 (goto-char assignment-continuation)
683 (re-search-forward
684 (python-rx simple-operator)
685 (line-end-position) t)
686 (forward-char 1)
687 (re-search-forward
688 (python-rx (* space))
689 (line-end-position) t)
690 (current-column))
691 (t
692 (goto-char context-start)
9787f829
FEG
693 (if (not
694 (save-excursion
695 (back-to-indentation)
696 (looking-at
697 "\\(?:return\\|from\\|import\\)\s+")))
107c2439
FEG
698 (current-indentation)
699 (+ (current-indentation)
9787f829
FEG
700 (length
701 (match-string-no-properties 0))))))))
45c138ac
FEG
702 indentation))
703 ('inside-paren
17d13b85 704 (or (save-excursion
f8994527 705 (skip-syntax-forward "\s" (line-end-position))
f9471190
FEG
706 (when (and (looking-at (regexp-opt '(")" "]" "}")))
707 (not (forward-char 1))
708 (not (python-info-ppss-context 'paren)))
17d13b85
FEG
709 (goto-char context-start)
710 (back-to-indentation)
711 (current-column)))
712 (-
713 (save-excursion
714 (goto-char context-start)
715 (forward-char)
716 (save-restriction
717 (narrow-to-region
718 (line-beginning-position)
719 (line-end-position))
589cefd7 720 (forward-comment 9999))
17d13b85
FEG
721 (if (looking-at "$")
722 (+ (current-indentation) python-indent-offset)
589cefd7 723 (forward-comment 9999)
17d13b85
FEG
724 (current-column)))
725 (if (progn
726 (back-to-indentation)
727 (looking-at (regexp-opt '(")" "]" "}"))))
728 python-indent-offset
729 0)))))))))
45c138ac
FEG
730
731(defun python-indent-calculate-levels ()
732 "Calculate `python-indent-levels' and reset `python-indent-current-level'."
733 (let* ((indentation (python-indent-calculate-indentation))
734 (remainder (% indentation python-indent-offset))
735 (steps (/ (- indentation remainder) python-indent-offset)))
65e4f764 736 (setq python-indent-levels (list 0))
45c138ac 737 (dotimes (step steps)
65e4f764 738 (push (* python-indent-offset (1+ step)) python-indent-levels))
45c138ac 739 (when (not (eq 0 remainder))
65e4f764 740 (push (+ (* python-indent-offset steps) remainder) python-indent-levels))
45c138ac
FEG
741 (setq python-indent-levels (nreverse python-indent-levels))
742 (setq python-indent-current-level (1- (length python-indent-levels)))))
743
744(defun python-indent-toggle-levels ()
745 "Toggle `python-indent-current-level' over `python-indent-levels'."
746 (setq python-indent-current-level (1- python-indent-current-level))
747 (when (< python-indent-current-level 0)
748 (setq python-indent-current-level (1- (length python-indent-levels)))))
749
750(defun python-indent-line (&optional force-toggle)
751 "Internal implementation of `python-indent-line-function'.
45c138ac
FEG
752Uses the offset calculated in
753`python-indent-calculate-indentation' and available levels
e2d8d479
FEG
754indicated by the variable `python-indent-levels' to set the
755current indentation.
45c138ac
FEG
756
757When the variable `last-command' is equal to
e2d8d479
FEG
758`indent-for-tab-command' or FORCE-TOGGLE is non-nil it cycles
759levels indicated in the variable `python-indent-levels' by
760setting the current level in the variable
761`python-indent-current-level'.
45c138ac
FEG
762
763When the variable `last-command' is not equal to
e2d8d479
FEG
764`indent-for-tab-command' and FORCE-TOGGLE is nil it calculates
765possible indentation levels and saves it in the variable
766`python-indent-levels'. Afterwards it sets the variable
767`python-indent-current-level' correctly so offset is equal
768to (`nth' `python-indent-current-level' `python-indent-levels')"
45c138ac
FEG
769 (if (or (and (eq this-command 'indent-for-tab-command)
770 (eq last-command this-command))
771 force-toggle)
86f1889a
FEG
772 (if (not (equal python-indent-levels '(0)))
773 (python-indent-toggle-levels)
774 (python-indent-calculate-levels))
45c138ac
FEG
775 (python-indent-calculate-levels))
776 (beginning-of-line)
777 (delete-horizontal-space)
778 (indent-to (nth python-indent-current-level python-indent-levels))
779 (save-restriction
780 (widen)
781 (let ((closing-block-point (python-info-closing-block)))
782 (when closing-block-point
783 (message "Closes %s" (buffer-substring
784 closing-block-point
785 (save-excursion
786 (goto-char closing-block-point)
787 (line-end-position))))))))
788
789(defun python-indent-line-function ()
790 "`indent-line-function' for Python mode.
e2d8d479 791See `python-indent-line' for details."
45c138ac
FEG
792 (python-indent-line))
793
794(defun python-indent-dedent-line ()
e2d8d479 795 "De-indent current line."
45c138ac 796 (interactive "*")
14a78495
FEG
797 (when (and (not (or (python-info-ppss-context 'string)
798 (python-info-ppss-context 'comment)))
45c138ac
FEG
799 (<= (point-marker) (save-excursion
800 (back-to-indentation)
801 (point-marker)))
802 (> (current-column) 0))
803 (python-indent-line t)
804 t))
805
806(defun python-indent-dedent-line-backspace (arg)
e2d8d479 807 "De-indent current line.
45c138ac 808Argument ARG is passed to `backward-delete-char-untabify' when
e2d8d479 809point is not in between the indentation."
45c138ac
FEG
810 (interactive "*p")
811 (when (not (python-indent-dedent-line))
812 (backward-delete-char-untabify arg)))
183f9296 813(put 'python-indent-dedent-line-backspace 'delete-selection 'supersede)
45c138ac
FEG
814
815(defun python-indent-region (start end)
816 "Indent a python region automagically.
817
818Called from a program, START and END specify the region to indent."
cb42456f
FEG
819 (let ((deactivate-mark nil))
820 (save-excursion
821 (goto-char end)
822 (setq end (point-marker))
823 (goto-char start)
824 (or (bolp) (forward-line 1))
825 (while (< (point) end)
826 (or (and (bolp) (eolp))
827 (let (word)
828 (forward-line -1)
829 (back-to-indentation)
830 (setq word (current-word))
831 (forward-line 1)
832 (when word
833 (beginning-of-line)
834 (delete-horizontal-space)
835 (indent-to (python-indent-calculate-indentation)))))
836 (forward-line 1))
837 (move-marker end nil))))
45c138ac
FEG
838
839(defun python-indent-shift-left (start end &optional count)
840 "Shift lines contained in region START END by COUNT columns to the left.
e2d8d479
FEG
841COUNT defaults to `python-indent-offset'. If region isn't
842active, the current line is shifted. The shifted region includes
843the lines in which START and END lie. An error is signaled if
844any lines in the region are indented less than COUNT columns."
45c138ac
FEG
845 (interactive
846 (if mark-active
847 (list (region-beginning) (region-end) current-prefix-arg)
848 (list (line-beginning-position) (line-end-position) current-prefix-arg)))
849 (if count
850 (setq count (prefix-numeric-value count))
851 (setq count python-indent-offset))
852 (when (> count 0)
cb42456f
FEG
853 (let ((deactivate-mark nil))
854 (save-excursion
855 (goto-char start)
856 (while (< (point) end)
857 (if (and (< (current-indentation) count)
858 (not (looking-at "[ \t]*$")))
859 (error "Can't shift all lines enough"))
860 (forward-line))
861 (indent-rigidly start end (- count))))))
45c138ac
FEG
862
863(add-to-list 'debug-ignored-errors "^Can't shift all lines enough")
864
865(defun python-indent-shift-right (start end &optional count)
866 "Shift lines contained in region START END by COUNT columns to the left.
e2d8d479
FEG
867COUNT defaults to `python-indent-offset'. If region isn't
868active, the current line is shifted. The shifted region includes
869the lines in which START and END lie."
45c138ac
FEG
870 (interactive
871 (if mark-active
872 (list (region-beginning) (region-end) current-prefix-arg)
873 (list (line-beginning-position) (line-end-position) current-prefix-arg)))
cb42456f
FEG
874 (let ((deactivate-mark nil))
875 (if count
876 (setq count (prefix-numeric-value count))
877 (setq count python-indent-offset))
878 (indent-rigidly start end count)))
45c138ac 879
ffdb56c3 880(defun python-indent-electric-colon (arg)
e2d8d479
FEG
881 "Insert a colon and maybe de-indent the current line.
882With numeric ARG, just insert that many colons. With
883\\[universal-argument], just insert a single colon."
ffdb56c3
FEG
884 (interactive "*P")
885 (self-insert-command (if (not (integerp arg)) 1 arg))
c43cd8b1
FEG
886 (when (and (not arg)
887 (eolp)
888 (not (equal ?: (char-after (- (point-marker) 2))))
889 (not (or (python-info-ppss-context 'string)
890 (python-info-ppss-context 'comment))))
891 (let ((indentation (current-indentation))
892 (calculated-indentation (python-indent-calculate-indentation)))
893 (when (> indentation calculated-indentation)
894 (save-excursion
895 (indent-line-to calculated-indentation)
896 (when (not (python-info-closing-block))
897 (indent-line-to indentation)))))))
ffdb56c3
FEG
898(put 'python-indent-electric-colon 'delete-selection t)
899
45c138ac
FEG
900\f
901;;; Navigation
902
0567effb 903(defvar python-nav-beginning-of-defun-regexp
af5c1beb 904 (python-rx line-start (* space) defun (+ space) (group symbol-name))
fc6c545e 905 "Regexp matching class or function definition.
fc2dc7df
FEG
906The name of the defun should be grouped so it can be retrieved
907via `match-string'.")
45c138ac 908
6b432853 909(defun python-nav-beginning-of-defun (&optional nodecorators)
053a6c72 910 "Move point to `beginning-of-defun'.
6b432853
FEG
911When NODECORATORS is non-nil decorators are not included. This
912is the main part of`python-beginning-of-defun-function'
74d7b605 913implementation. Return non-nil if point is moved to the
fc2dc7df 914`beginning-of-defun'."
0567effb
FEG
915 (let ((indent-pos (save-excursion
916 (back-to-indentation)
917 (point-marker)))
74d7b605 918 (found)
0567effb
FEG
919 (include-decorators
920 (lambda ()
6b432853
FEG
921 (when (not nodecorators)
922 (when (save-excursion
923 (forward-line -1)
924 (looking-at (python-rx decorator)))
925 (while (and (not (bobp))
926 (forward-line -1)
927 (looking-at (python-rx decorator))))
928 (when (not (bobp)) (forward-line 1)))))))
0567effb
FEG
929 (if (and (> (point) indent-pos)
930 (save-excursion
931 (goto-char (line-beginning-position))
932 (looking-at python-nav-beginning-of-defun-regexp)))
45c138ac 933 (progn
0567effb 934 (goto-char (line-beginning-position))
74d7b605
FEG
935 (funcall include-decorators)
936 (setq found t))
0567effb 937 (goto-char (line-beginning-position))
74d7b605
FEG
938 (when (re-search-backward python-nav-beginning-of-defun-regexp nil t)
939 (setq found t))
0567effb 940 (goto-char (or (python-info-ppss-context 'string) (point)))
74d7b605
FEG
941 (funcall include-decorators))
942 found))
0567effb 943
6b432853 944(defun python-beginning-of-defun-function (&optional arg nodecorators)
0567effb
FEG
945 "Move point to the beginning of def or class.
946With positive ARG move that number of functions forward. With
6b432853 947negative do the same but backwards. When NODECORATORS is non-nil
74d7b605 948decorators are not included. Return non-nil if point is moved to the
fc2dc7df 949`beginning-of-defun'."
0567effb
FEG
950 (when (or (null arg) (= arg 0)) (setq arg 1))
951 (if (> arg 0)
74d7b605
FEG
952 (dotimes (i arg (python-nav-beginning-of-defun nodecorators)))
953 (let ((found))
954 (dotimes (i (- arg) found)
955 (python-end-of-defun-function)
589cefd7 956 (forward-comment 9999)
74d7b605
FEG
957 (goto-char (line-end-position))
958 (when (not (eobp))
959 (setq found
960 (python-nav-beginning-of-defun nodecorators)))))))
45c138ac
FEG
961
962(defun python-end-of-defun-function ()
963 "Move point to the end of def or class.
964Returns nil if point is not in a def or class."
0567effb
FEG
965 (interactive)
966 (let ((beg-defun-indent)
967 (decorator-regexp "[[:space:]]*@"))
968 (when (looking-at decorator-regexp)
969 (while (and (not (eobp))
970 (forward-line 1)
971 (looking-at decorator-regexp))))
972 (when (not (looking-at python-nav-beginning-of-defun-regexp))
973 (python-beginning-of-defun-function))
974 (setq beg-defun-indent (current-indentation))
975 (forward-line 1)
976 (while (and (forward-line 1)
977 (not (eobp))
978 (or (not (current-word))
979 (> (current-indentation) beg-defun-indent))))
589cefd7 980 (forward-comment 9999)
0567effb 981 (goto-char (line-beginning-position))))
45c138ac 982
3697b531
FEG
983(defun python-nav-sentence-start ()
984 "Move to start of current sentence."
985 (interactive "^")
986 (while (and (not (back-to-indentation))
987 (not (bobp))
988 (when (or
989 (save-excursion
990 (forward-line -1)
991 (python-info-line-ends-backslash-p))
9fff1858 992 (python-info-ppss-context 'string)
3697b531
FEG
993 (python-info-ppss-context 'paren))
994 (forward-line -1)))))
995
996(defun python-nav-sentence-end ()
997 "Move to end of current sentence."
998 (interactive "^")
999 (while (and (goto-char (line-end-position))
1000 (not (eobp))
1001 (when (or
1002 (python-info-line-ends-backslash-p)
9fff1858 1003 (python-info-ppss-context 'string)
3697b531
FEG
1004 (python-info-ppss-context 'paren))
1005 (forward-line 1)))))
1006
9fff1858 1007(defun python-nav-backward-sentence (&optional arg)
4cafacb5 1008 "Move backward to start of sentence. With ARG, do it arg times.
9fff1858
FEG
1009See `python-nav-forward-sentence' for more information."
1010 (interactive "^p")
1011 (or arg (setq arg 1))
1012 (python-nav-forward-sentence (- arg)))
1013
1014(defun python-nav-forward-sentence (&optional arg)
4cafacb5 1015 "Move forward to next end of sentence. With ARG, repeat.
9fff1858
FEG
1016With negative argument, move backward repeatedly to start of sentence."
1017 (interactive "^p")
1018 (or arg (setq arg 1))
1019 (while (> arg 0)
1020 (forward-comment 9999)
1021 (python-nav-sentence-end)
1022 (forward-line 1)
1023 (setq arg (1- arg)))
1024 (while (< arg 0)
1025 (python-nav-sentence-end)
1026 (forward-comment -9999)
1027 (python-nav-sentence-start)
1028 (forward-line -1)
1029 (setq arg (1+ arg))))
1030
fc6c545e
FEG
1031(defun python-nav-list-defun-positions (&optional include-type)
1032 "Make an Alist of defun names and point markers for current buffer.
1033When optional argument INCLUDE-TYPE is non-nil the type is
1034included the defun name."
1035 (let ((defs))
1036 (save-restriction
1037 (widen)
1038 (save-excursion
1039 (goto-char (point-max))
1040 (while (re-search-backward python-nav-beginning-of-defun-regexp nil t)
1041 (when (and (not (python-info-ppss-context 'string))
1042 (not (python-info-ppss-context 'comment))
1043 (not (python-info-ppss-context 'parent)))
1044 (add-to-list
1045 'defs (cons
1046 (python-info-current-defun include-type)
1047 (point-marker)))))
1048 defs))))
1049
1050(defun python-nav-read-defun ()
1051 "Read a defun name of current buffer and return its point marker.
1052A cons cell with the form (DEFUN-NAME . POINT-MARKER) is returned
1053when defun is completed, else nil."
1054 (let ((defs (python-nav-list-defun-positions)))
1055 (minibuffer-with-setup-hook
1056 (lambda ()
1057 (setq minibuffer-completion-table (mapcar 'car defs)))
1058 (let ((stringdef
1059 (read-from-minibuffer
1060 "Jump to definition: " nil
1061 minibuffer-local-must-match-map)))
1062 (when (not (string= stringdef ""))
1063 (assoc-string stringdef defs))))))
1064
1065(defun python-nav-jump-to-defun (def)
1066 "Jump to the definition of DEF in current file."
1067 (interactive
1068 (list (python-nav-read-defun)))
1069 (when (not (called-interactively-p 'interactive))
1070 (setq def (assoc-string def (python-nav-list-defun-positions))))
1071 (let ((def-marker (cdr def)))
1072 (when (markerp def-marker)
1073 (goto-char (marker-position def-marker))
1074 (back-to-indentation))))
1075
45c138ac
FEG
1076\f
1077;;; Shell integration
1078
0f55249e
FEG
1079(defcustom python-shell-buffer-name "Python"
1080 "Default buffer name for Python interpreter."
1081 :type 'string
1082 :group 'python
1083 :safe 'stringp)
45c138ac
FEG
1084
1085(defcustom python-shell-interpreter "python"
1086 "Default Python interpreter for shell."
45c138ac 1087 :type 'string
c0428ba0 1088 :group 'python
45c138ac
FEG
1089 :safe 'stringp)
1090
0f55249e
FEG
1091(defcustom python-shell-internal-buffer-name "Python Internal"
1092 "Default buffer name for the Internal Python interpreter."
1093 :type 'string
1094 :group 'python
1095 :safe 'stringp)
1fe1b5aa 1096
45c138ac
FEG
1097(defcustom python-shell-interpreter-args "-i"
1098 "Default arguments for the Python interpreter."
45c138ac 1099 :type 'string
c0428ba0 1100 :group 'python
45c138ac
FEG
1101 :safe 'stringp)
1102
1103(defcustom python-shell-prompt-regexp ">>> "
e2d8d479
FEG
1104 "Regular Expression matching top\-level input prompt of python shell.
1105It should not contain a caret (^) at the beginning."
45c138ac
FEG
1106 :type 'string
1107 :group 'python
1108 :safe 'stringp)
1109
1110(defcustom python-shell-prompt-block-regexp "[.][.][.] "
e2d8d479
FEG
1111 "Regular Expression matching block input prompt of python shell.
1112It should not contain a caret (^) at the beginning."
45c138ac
FEG
1113 :type 'string
1114 :group 'python
1115 :safe 'stringp)
1116
0f55249e 1117(defcustom python-shell-prompt-output-regexp ""
e2d8d479
FEG
1118 "Regular Expression matching output prompt of python shell.
1119It should not contain a caret (^) at the beginning."
62feb915
FEG
1120 :type 'string
1121 :group 'python
1122 :safe 'stringp)
1123
45c138ac 1124(defcustom python-shell-prompt-pdb-regexp "[(<]*[Ii]?[Pp]db[>)]+ "
e2d8d479
FEG
1125 "Regular Expression matching pdb input prompt of python shell.
1126It should not contain a caret (^) at the beginning."
45c138ac
FEG
1127 :type 'string
1128 :group 'python
1129 :safe 'stringp)
1130
30e429dd
FEG
1131(defcustom python-shell-send-setup-max-wait 5
1132 "Seconds to wait for process output before code setup.
1133If output is received before the especified time then control is
1134returned in that moment and not after waiting."
0f55249e 1135 :type 'integer
30e429dd 1136 :group 'python
0f55249e 1137 :safe 'integerp)
30e429dd 1138
66bbb27f 1139(defcustom python-shell-process-environment nil
307bd2e8
FEG
1140 "List of environment variables for Python shell.
1141This variable follows the same rules as `process-environment'
66bbb27f
FEG
1142since it merges with it before the process creation routines are
1143called. When this variable is nil, the Python shell is run with
307bd2e8 1144the default `process-environment'."
66bbb27f
FEG
1145 :type '(repeat string)
1146 :group 'python
1147 :safe 'listp)
1148
1149(defcustom python-shell-exec-path nil
1150 "List of path to search for binaries.
1151This variable follows the same rules as `exec-path' since it
1152merges with it before the process creation routines are called.
1153When this variable is nil, the Python shell is run with the
1154default `exec-path'."
1155 :type '(repeat string)
1156 :group 'python
1157 :safe 'listp)
1158
64348c32
FEG
1159(defcustom python-shell-virtualenv-path nil
1160 "Path to virtualenv root.
1161This variable, when set to a string, makes the values stored in
1162`python-shell-process-environment' and `python-shell-exec-path'
1163to be modified properly so shells are started with the specified
1164virtualenv."
1165 :type 'string
1166 :group 'python
1167 :safe 'stringp)
1168
c0428ba0
FEG
1169(defcustom python-shell-setup-codes '(python-shell-completion-setup-code
1170 python-ffap-setup-code
1171 python-eldoc-setup-code)
1172 "List of code run by `python-shell-send-setup-codes'.
e2d8d479 1173Each variable can contain either a simple string with the code to
c0428ba0
FEG
1174execute or a cons with the form (CODE . DESCRIPTION), where CODE
1175is a string with the code to execute and DESCRIPTION is the
1176description of it."
1177 :type '(repeat symbol)
1178 :group 'python
1179 :safe 'listp)
1180
45c138ac
FEG
1181(defcustom python-shell-compilation-regexp-alist
1182 `((,(rx line-start (1+ (any " \t")) "File \""
1183 (group (1+ (not (any "\"<")))) ; avoid `<stdin>' &c
1184 "\", line " (group (1+ digit)))
1185 1 2)
1186 (,(rx " in file " (group (1+ not-newline)) " on line "
1187 (group (1+ digit)))
1188 1 2)
1189 (,(rx line-start "> " (group (1+ (not (any "(\"<"))))
1190 "(" (group (1+ digit)) ")" (1+ (not (any "("))) "()")
1191 1 2))
1192 "`compilation-error-regexp-alist' for inferior Python."
1193 :type '(alist string)
1194 :group 'python)
1195
1196(defun python-shell-get-process-name (dedicated)
1197 "Calculate the appropiate process name for inferior Python process.
45c138ac
FEG
1198If DEDICATED is t and the variable `buffer-file-name' is non-nil
1199returns a string with the form
1200`python-shell-buffer-name'[variable `buffer-file-name'] else
e2d8d479
FEG
1201returns the value of `python-shell-buffer-name'. After
1202calculating the process name adds the buffer name for the process
1203in the `same-window-buffer-names' list."
45c138ac
FEG
1204 (let ((process-name
1205 (if (and dedicated
1206 buffer-file-name)
1207 (format "%s[%s]" python-shell-buffer-name buffer-file-name)
1208 (format "%s" python-shell-buffer-name))))
1209 (add-to-list 'same-window-buffer-names (purecopy
1210 (format "*%s*" process-name)))
1211 process-name))
1212
1fe1b5aa
FEG
1213(defun python-shell-internal-get-process-name ()
1214 "Calculate the appropiate process name for Internal Python process.
1215The name is calculated from `python-shell-global-buffer-name' and
1216a hash of all relevant global shell settings in order to ensure
1217uniqueness for different types of configurations."
1218 (format "%s [%s]"
1219 python-shell-internal-buffer-name
1220 (md5
1221 (concat
1222 (python-shell-parse-command)
1223 (mapconcat #'symbol-value python-shell-setup-codes "")
1224 (mapconcat #'indentity python-shell-process-environment "")
64348c32 1225 (or python-shell-virtualenv-path "")
1fe1b5aa
FEG
1226 (mapconcat #'indentity python-shell-exec-path "")))))
1227
45c138ac 1228(defun python-shell-parse-command ()
e2d8d479 1229 "Calculate the string used to execute the inferior Python process."
45c138ac
FEG
1230 (format "%s %s" python-shell-interpreter python-shell-interpreter-args))
1231
307bd2e8
FEG
1232(defun python-shell-calculate-process-environment ()
1233 "Calculate process environment given `python-shell-virtualenv-path'."
64348c32
FEG
1234 (let ((env (python-util-merge 'list python-shell-process-environment
1235 process-environment 'string=))
1236 (virtualenv (if python-shell-virtualenv-path
1237 (directory-file-name python-shell-virtualenv-path)
1238 nil)))
1239 (if (not virtualenv)
1240 env
1241 (dolist (envvar env)
1242 (let* ((split (split-string envvar "=" t))
1243 (name (nth 0 split))
1244 (value (nth 1 split)))
1245 (when (not (string= name "PYTHONHOME"))
1246 (when (string= name "PATH")
1247 (setq value (format "%s/bin:%s" virtualenv value)))
1248 (setq env (cons (format "%s=%s" name value) env)))))
1249 (cons (format "VIRTUAL_ENV=%s" virtualenv) env))))
1250
1251(defun python-shell-calculate-exec-path ()
1252 "Calculate exec path given `python-shell-virtualenv-path'."
1253 (let ((path (python-util-merge 'list python-shell-exec-path
1254 exec-path 'string=)))
1255 (if (not python-shell-virtualenv-path)
1256 path
1257 (cons (format "%s/bin"
1258 (directory-file-name python-shell-virtualenv-path))
1259 path))))
1260
45c138ac
FEG
1261(defun python-comint-output-filter-function (output)
1262 "Hook run after content is put into comint buffer.
1263OUTPUT is a string with the contents of the buffer."
1264 (ansi-color-filter-apply output))
1265
1266(defvar inferior-python-mode-current-file nil
1267 "Current file from which a region was sent.")
1268(make-variable-buffer-local 'inferior-python-mode-current-file)
1269
45c138ac 1270(define-derived-mode inferior-python-mode comint-mode "Inferior Python"
62feb915 1271 "Major mode for Python inferior process.
e2d8d479
FEG
1272Runs a Python interpreter as a subprocess of Emacs, with Python
1273I/O through an Emacs buffer. Variables
1274`python-shell-interpreter' and `python-shell-interpreter-args'
1275controls which Python interpreter is run. Variables
1276`python-shell-prompt-regexp',
1277`python-shell-prompt-output-regexp',
1278`python-shell-prompt-block-regexp',
1279`python-shell-completion-setup-code',
1280`python-shell-completion-string-code', `python-eldoc-setup-code',
1281`python-eldoc-string-code', `python-ffap-setup-code' and
1282`python-ffap-string-code' can customize this mode for different
1283Python interpreters.
1284
1285You can also add additional setup code to be run at
1286initialization of the interpreter via `python-shell-setup-codes'
1287variable.
1288
1289\(Type \\[describe-mode] in the process buffer for a list of commands.)"
45c138ac
FEG
1290 (set-syntax-table python-mode-syntax-table)
1291 (setq mode-line-process '(":%s"))
1292 (setq comint-prompt-regexp (format "^\\(?:%s\\|%s\\|%s\\)"
1293 python-shell-prompt-regexp
1294 python-shell-prompt-block-regexp
1295 python-shell-prompt-pdb-regexp))
1296 (make-local-variable 'comint-output-filter-functions)
1297 (add-hook 'comint-output-filter-functions
1298 'python-comint-output-filter-function)
1299 (add-hook 'comint-output-filter-functions
1300 'python-pdbtrack-comint-output-filter-function)
1301 (set (make-local-variable 'compilation-error-regexp-alist)
1302 python-shell-compilation-regexp-alist)
ed0eb594
FEG
1303 (define-key inferior-python-mode-map [remap complete-symbol]
1304 'completion-at-point)
1305 (add-hook 'completion-at-point-functions
1306 'python-shell-completion-complete-at-point nil 'local)
62feb915
FEG
1307 (add-to-list (make-local-variable 'comint-dynamic-complete-functions)
1308 'python-shell-completion-complete-at-point)
1309 (define-key inferior-python-mode-map (kbd "<tab>")
1310 'python-shell-completion-complete-or-indent)
45c138ac
FEG
1311 (compilation-shell-minor-mode 1))
1312
96eeb83a 1313(defun python-shell-make-comint (cmd proc-name &optional pop)
77afb61a 1314 "Create a python shell comint buffer.
96eeb83a 1315CMD is the python command to be executed and PROC-NAME is the
77afb61a 1316process name the comint buffer will get. After the comint buffer
96eeb83a
FEG
1317is created the `inferior-python-mode' is activated. If POP is
1318non-nil the buffer is shown."
77afb61a
FEG
1319 (save-excursion
1320 (let* ((proc-buffer-name (format "*%s*" proc-name))
307bd2e8 1321 (process-environment (python-shell-calculate-process-environment))
77afb61a
FEG
1322 (exec-path (python-shell-calculate-exec-path)))
1323 (when (not (comint-check-proc proc-buffer-name))
96eeb83a
FEG
1324 (let* ((cmdlist (split-string-and-unquote cmd))
1325 (buffer (apply 'make-comint proc-name (car cmdlist) nil
1326 (cdr cmdlist)))
d2190c57 1327 (current-buffer (current-buffer)))
96eeb83a
FEG
1328 (with-current-buffer buffer
1329 (inferior-python-mode)
fbc39529 1330 (python-util-clone-local-variables current-buffer))))
96eeb83a 1331 (when pop
a0686d71
FEG
1332 (pop-to-buffer proc-buffer-name))
1333 proc-buffer-name)))
77afb61a 1334
45c138ac
FEG
1335(defun run-python (dedicated cmd)
1336 "Run an inferior Python process.
e2d8d479
FEG
1337Input and output via buffer named after
1338`python-shell-buffer-name'. If there is a process already
1339running in that buffer, just switch to it.
1340With argument, allows you to define DEDICATED, so a dedicated
1341process for the current buffer is open, and define CMD so you can
1342edit the command used to call the interpreter (default is value
1343of `python-shell-interpreter' and arguments defined in
1344`python-shell-interpreter-args'). Runs the hook
1345`inferior-python-mode-hook' (after the `comint-mode-hook' is
1346run).
1347\(Type \\[describe-mode] in the process buffer for a list of commands.)"
45c138ac
FEG
1348 (interactive
1349 (if current-prefix-arg
1350 (list
1351 (y-or-n-p "Make dedicated process? ")
1352 (read-string "Run Python: " (python-shell-parse-command)))
1353 (list nil (python-shell-parse-command))))
96eeb83a 1354 (python-shell-make-comint cmd (python-shell-get-process-name dedicated) t)
45c138ac
FEG
1355 dedicated)
1356
1fe1b5aa
FEG
1357(defun run-python-internal ()
1358 "Run an inferior Internal Python process.
1359Input and output via buffer named after
1360`python-shell-internal-buffer-name' and what
1361`python-shell-internal-get-process-name' returns. This new kind
1362of shell is intended to be used for generic communication related
1363to defined configurations. The main difference with global or
1364dedicated shells is that these ones are attached to a
1365configuration, not a buffer. This means that can be used for
1366example to retrieve the sys.path and other stuff, without messing
1367with user shells. Runs the hook
1368`inferior-python-mode-hook' (after the `comint-mode-hook' is
1369run). \(Type \\[describe-mode] in the process buffer for a list
1370of commands.)"
1371 (interactive)
a0686d71
FEG
1372 (set-process-query-on-exit-flag
1373 (get-buffer-process
1374 (python-shell-make-comint
1375 (python-shell-parse-command)
1376 (python-shell-internal-get-process-name))) nil))
1fe1b5aa 1377
45c138ac
FEG
1378(defun python-shell-get-process ()
1379 "Get inferior Python process for current buffer and return it."
1380 (let* ((dedicated-proc-name (python-shell-get-process-name t))
1381 (dedicated-proc-buffer-name (format "*%s*" dedicated-proc-name))
1382 (global-proc-name (python-shell-get-process-name nil))
1383 (global-proc-buffer-name (format "*%s*" global-proc-name))
1384 (dedicated-running (comint-check-proc dedicated-proc-buffer-name))
1385 (global-running (comint-check-proc global-proc-buffer-name)))
1386 ;; Always prefer dedicated
1387 (get-buffer-process (or (and dedicated-running dedicated-proc-buffer-name)
1388 (and global-running global-proc-buffer-name)))))
1389
1390(defun python-shell-get-or-create-process ()
1391 "Get or create an inferior Python process for current buffer and return it."
79dafa51
FEG
1392 (let* ((old-buffer (current-buffer))
1393 (dedicated-proc-name (python-shell-get-process-name t))
45c138ac
FEG
1394 (dedicated-proc-buffer-name (format "*%s*" dedicated-proc-name))
1395 (global-proc-name (python-shell-get-process-name nil))
1396 (global-proc-buffer-name (format "*%s*" global-proc-name))
1397 (dedicated-running (comint-check-proc dedicated-proc-buffer-name))
1398 (global-running (comint-check-proc global-proc-buffer-name))
1399 (current-prefix-arg 4))
1400 (when (and (not dedicated-running) (not global-running))
1401 (if (call-interactively 'run-python)
1402 (setq dedicated-running t)
1403 (setq global-running t)))
1404 ;; Always prefer dedicated
79dafa51 1405 (switch-to-buffer old-buffer)
45c138ac
FEG
1406 (get-buffer-process (if dedicated-running
1407 dedicated-proc-buffer-name
1408 global-proc-buffer-name))))
1409
1fe1b5aa
FEG
1410(defun python-shell-internal-get-or-create-process ()
1411 "Get or create an inferior Internal Python process."
1412 (let* ((proc-name (python-shell-internal-get-process-name))
1413 (proc-buffer-name (format "*%s*" proc-name)))
1414 (run-python-internal)
1415 (get-buffer-process proc-buffer-name)))
1416
9ce938be
FEG
1417(defun python-shell-send-string (string &optional process msg)
1418 "Send STRING to inferior Python PROCESS.
1419When MSG is non-nil messages the first line of STRING."
45c138ac 1420 (interactive "sPython command: ")
9ce938be
FEG
1421 (let ((process (or process (python-shell-get-or-create-process)))
1422 (lines (split-string string "\n" t)))
1423 (when msg
1424 (message (format "Sent: %s..." (nth 0 lines))))
1425 (if (> (length lines) 1)
1426 (let* ((temp-file-name (make-temp-file "py"))
1427 (file-name (or (buffer-file-name) temp-file-name)))
1428 (with-temp-file temp-file-name
1429 (insert string)
1430 (delete-trailing-whitespace))
1431 (python-shell-send-file file-name process temp-file-name))
1432 (comint-send-string process string)
1433 (when (or (not (string-match "\n$" string))
1434 (string-match "\n[ \t].*\n?$" string))
1435 (comint-send-string process "\n")))))
1436
1437(defun python-shell-send-string-no-output (string &optional process msg)
1438 "Send STRING to PROCESS and inhibit output.
e2d8d479
FEG
1439When MSG is non-nil messages the first line of STRING. Return
1440the output."
9ce938be
FEG
1441 (let* ((output-buffer)
1442 (process (or process (python-shell-get-or-create-process)))
1443 (comint-preoutput-filter-functions
1444 (append comint-preoutput-filter-functions
1445 '(ansi-color-filter-apply
1446 (lambda (string)
1447 (setq output-buffer (concat output-buffer string))
1448 "")))))
1449 (python-shell-send-string string process msg)
1450 (accept-process-output process)
1451 (mapconcat
1452 (lambda (string) string)
1faf2911
FEG
1453 (split-string
1454 output-buffer
1455 (if (> (length python-shell-prompt-output-regexp) 0)
1456 (format "\n*%s$\\|^%s"
1457 python-shell-prompt-regexp
1458 (or python-shell-prompt-output-regexp ""))
1459 (format "\n$\\|^%s"
1460 python-shell-prompt-regexp)) t) "\n")))
45c138ac 1461
1fe1b5aa
FEG
1462(defun python-shell-internal-send-string (string)
1463 "Send STRING to the Internal Python interpreter.
1464Returns the output. See `python-shell-send-string-no-output'."
1465 (python-shell-send-string-no-output
1466 ;; Makes this function compatible with the old
1467 ;; python-send-receive. (At least for CEDET).
1468 (replace-regexp-in-string "_emacs_out +" "" string)
1469 (python-shell-internal-get-or-create-process) nil))
1470
1471(define-obsolete-function-alias
1472 'python-send-receive 'python-shell-internal-send-string "23.3"
1473 "Send STRING to inferior Python (if any) and return result.
1474The result is what follows `_emacs_out' in the output.
1475This is a no-op if `python-check-comint-prompt' returns nil.")
1476
45c138ac
FEG
1477(defun python-shell-send-region (start end)
1478 "Send the region delimited by START and END to inferior Python process."
1479 (interactive "r")
9ce938be
FEG
1480 (let ((deactivate-mark nil))
1481 (python-shell-send-string (buffer-substring start end) nil t)))
45c138ac
FEG
1482
1483(defun python-shell-send-buffer ()
1484 "Send the entire buffer to inferior Python process."
1485 (interactive)
1486 (save-restriction
1487 (widen)
1488 (python-shell-send-region (point-min) (point-max))))
1489
1490(defun python-shell-send-defun (arg)
2ed294c5 1491 "Send the current defun to inferior Python process.
45c138ac
FEG
1492When argument ARG is non-nil sends the innermost defun."
1493 (interactive "P")
1494 (save-excursion
2ed294c5
FEG
1495 (python-shell-send-region
1496 (progn
1497 (or (python-beginning-of-defun-function)
1498 (progn (beginning-of-line) (point-marker))))
1499 (progn
1500 (or (python-end-of-defun-function)
1501 (progn (end-of-line) (point-marker)))))))
45c138ac 1502
d439cda5
FEG
1503(defun python-shell-send-file (file-name &optional process temp-file-name)
1504 "Send FILE-NAME to inferior Python PROCESS.
1505If TEMP-FILE-NAME is passed then that file is used for processing
1506instead, while internally the shell will continue to use
1507FILE-NAME."
45c138ac 1508 (interactive "fFile to send: ")
9ce938be
FEG
1509 (let* ((process (or process (python-shell-get-or-create-process)))
1510 (temp-file-name (when temp-file-name
1511 (expand-file-name temp-file-name)))
1512 (file-name (or (expand-file-name file-name) temp-file-name)))
1513 (when (not file-name)
1514 (error "If FILE-NAME is nil then TEMP-FILE-NAME must be non-nil"))
d439cda5 1515 (with-current-buffer (process-buffer process)
24b68537
FEG
1516 (setq inferior-python-mode-current-file
1517 (convert-standard-filename file-name)))
13d914ed 1518 (python-shell-send-string
b962ebad 1519 (format
d439cda5
FEG
1520 (concat "__pyfile = open('''%s''');"
1521 "exec(compile(__pyfile.read(), '''%s''', 'exec'));"
1522 "__pyfile.close()")
1523 (or temp-file-name file-name) file-name)
13d914ed 1524 process)))
45c138ac
FEG
1525
1526(defun python-shell-switch-to-shell ()
1527 "Switch to inferior Python process buffer."
1528 (interactive)
1529 (pop-to-buffer (process-buffer (python-shell-get-or-create-process)) t))
1530
c0428ba0
FEG
1531(defun python-shell-send-setup-code ()
1532 "Send all setup code for shell.
1533This function takes the list of setup code to send from the
1534`python-shell-setup-codes' list."
1535 (let ((msg "Sent %s")
1536 (process (get-buffer-process (current-buffer))))
30e429dd 1537 (accept-process-output process python-shell-send-setup-max-wait)
c0428ba0
FEG
1538 (dolist (code python-shell-setup-codes)
1539 (when code
1540 (when (consp code)
1541 (setq msg (cdr code)))
1542 (message (format msg code))
1543 (python-shell-send-string-no-output
1544 (symbol-value code) process)))))
1545
1546(add-hook 'inferior-python-mode-hook
1547 #'python-shell-send-setup-code)
1548
45c138ac
FEG
1549\f
1550;;; Shell completion
1551
0f55249e 1552(defcustom python-shell-completion-setup-code
45c138ac
FEG
1553 "try:
1554 import readline
1555except ImportError:
1556 def __COMPLETER_all_completions(text): []
1557else:
1558 import rlcompleter
1559 readline.set_completer(rlcompleter.Completer().complete)
1560 def __COMPLETER_all_completions(text):
1561 import sys
1562 completions = []
1563 try:
1564 i = 0
1565 while True:
1566 res = readline.get_completer()(text, i)
1567 if not res: break
1568 i += 1
1569 completions.append(res)
1570 except NameError:
1571 pass
1572 return completions"
0f55249e
FEG
1573 "Code used to setup completion in inferior Python processes."
1574 :type 'string
1575 :group 'python
1576 :safe 'stringp)
45c138ac 1577
0f55249e 1578(defcustom python-shell-completion-string-code
45c138ac 1579 "';'.join(__COMPLETER_all_completions('''%s'''))\n"
0f55249e
FEG
1580 "Python code used to get a string of completions separated by semicolons."
1581 :type 'string
1582 :group 'python
1583 :safe 'stringp)
45c138ac 1584
075a0f61
FEG
1585(defun python-shell-completion--get-completions (input process)
1586 "Retrieve available completions for INPUT using PROCESS."
1587 (with-current-buffer (process-buffer process)
62feb915
FEG
1588 (let ((completions (python-shell-send-string-no-output
1589 (format python-shell-completion-string-code input)
1590 process)))
1591 (when (> (length completions) 2)
1592 (split-string completions "^'\\|^\"\\|;\\|'$\\|\"$" t)))))
075a0f61
FEG
1593
1594(defun python-shell-completion--get-completion (input completions)
1595 "Get completion for INPUT using COMPLETIONS."
1596 (let ((completion (when completions
1597 (try-completion input completions))))
1598 (cond ((eq completion t)
1599 input)
1600 ((null completion)
1601 (message "Can't find completion for \"%s\"" input)
1602 (ding)
1603 input)
1604 ((not (string= input completion))
1605 completion)
1606 (t
1607 (message "Making completion list...")
1608 (with-output-to-temp-buffer "*Python Completions*"
1609 (display-completion-list
1610 (all-completions input completions)))
1611 input))))
1612
45c138ac
FEG
1613(defun python-shell-completion-complete-at-point ()
1614 "Perform completion at point in inferior Python process."
1615 (interactive)
3d6913c7
FEG
1616 (with-syntax-table python-dotty-syntax-table
1617 (when (and comint-last-prompt-overlay
1618 (> (point-marker) (overlay-end comint-last-prompt-overlay)))
1619 (let* ((process (get-buffer-process (current-buffer)))
075a0f61
FEG
1620 (input (substring-no-properties
1621 (or (comint-word (current-word)) "") nil nil)))
1622 (delete-char (- (length input)))
1623 (insert
1624 (python-shell-completion--get-completion
1625 input (python-shell-completion--get-completions input process)))))))
45c138ac 1626
45c138ac
FEG
1627(defun python-shell-completion-complete-or-indent ()
1628 "Complete or indent depending on the context.
e2d8d479
FEG
1629If content before pointer is all whitespace indent. If not try
1630to complete."
45c138ac
FEG
1631 (interactive)
1632 (if (string-match "^[[:space:]]*$"
1633 (buffer-substring (comint-line-beginning-position)
1634 (point-marker)))
1635 (indent-for-tab-command)
1636 (comint-dynamic-complete)))
1637
45c138ac
FEG
1638\f
1639;;; PDB Track integration
1640
0f55249e 1641(defcustom python-pdbtrack-stacktrace-info-regexp
45c138ac 1642 "> %s(\\([0-9]+\\))\\([?a-zA-Z0-9_<>]+\\)()"
e2d8d479 1643 "Regular Expression matching stacktrace information.
0f55249e 1644Used to extract the current line and module being inspected. The
e2d8d479
FEG
1645regexp should not start with a caret (^) and can contain a string
1646placeholder (\%s) which is replaced with the filename beign
1647inspected (so other files in the debugging process are not
0f55249e
FEG
1648opened)"
1649 :type 'string
1650 :group 'python
1651 :safe 'stringp)
45c138ac
FEG
1652
1653(defvar python-pdbtrack-tracking-buffers '()
1654 "Alist containing elements of form (#<buffer> . #<buffer>).
1655The car of each element of the alist is the tracking buffer and
1656the cdr is the tracked buffer.")
1657
1658(defun python-pdbtrack-get-or-add-tracking-buffers ()
1659 "Get/Add a tracked buffer for the current buffer.
1660Internally it uses the `python-pdbtrack-tracking-buffers' alist.
1661Returns a cons with the form:
1662 * (#<tracking buffer> . #< tracked buffer>)."
1663 (or
1664 (assq (current-buffer) python-pdbtrack-tracking-buffers)
1665 (let* ((file (with-current-buffer (current-buffer)
d439cda5 1666 inferior-python-mode-current-file))
45c138ac
FEG
1667 (tracking-buffers
1668 `(,(current-buffer) .
1669 ,(or (get-file-buffer file)
1670 (find-file-noselect file)))))
1671 (set-buffer (cdr tracking-buffers))
1672 (python-mode)
1673 (set-buffer (car tracking-buffers))
1674 (setq python-pdbtrack-tracking-buffers
1675 (cons tracking-buffers python-pdbtrack-tracking-buffers))
1676 tracking-buffers)))
1677
1678(defun python-pdbtrack-comint-output-filter-function (output)
1679 "Move overlay arrow to current pdb line in tracked buffer.
1680Argument OUTPUT is a string with the output from the comint process."
1681 (when (not (string= output ""))
1682 (let ((full-output (ansi-color-filter-apply
1683 (buffer-substring comint-last-input-end
1684 (point-max)))))
1685 (if (string-match python-shell-prompt-pdb-regexp full-output)
1686 (let* ((tracking-buffers (python-pdbtrack-get-or-add-tracking-buffers))
1687 (line-num
1688 (save-excursion
1689 (string-match
1690 (format python-pdbtrack-stacktrace-info-regexp
1691 (regexp-quote
d439cda5 1692 inferior-python-mode-current-file))
45c138ac
FEG
1693 full-output)
1694 (string-to-number (or (match-string-no-properties 1 full-output) ""))))
1695 (tracked-buffer-window (get-buffer-window (cdr tracking-buffers)))
1696 (tracked-buffer-line-pos))
1697 (when line-num
1698 (with-current-buffer (cdr tracking-buffers)
1699 (set (make-local-variable 'overlay-arrow-string) "=>")
1700 (set (make-local-variable 'overlay-arrow-position) (make-marker))
1701 (setq tracked-buffer-line-pos (progn
1702 (goto-char (point-min))
1703 (forward-line (1- line-num))
1704 (point-marker)))
1705 (when tracked-buffer-window
1706 (set-window-point tracked-buffer-window tracked-buffer-line-pos))
1707 (set-marker overlay-arrow-position tracked-buffer-line-pos)))
1708 (pop-to-buffer (cdr tracking-buffers))
1709 (switch-to-buffer-other-window (car tracking-buffers)))
1710 (let ((tracking-buffers (assq (current-buffer)
1711 python-pdbtrack-tracking-buffers)))
1712 (when tracking-buffers
1713 (if inferior-python-mode-current-file
1714 (with-current-buffer (cdr tracking-buffers)
1715 (set-marker overlay-arrow-position nil))
1716 (kill-buffer (cdr tracking-buffers)))
1717 (setq python-pdbtrack-tracking-buffers
1718 (assq-delete-all (current-buffer)
1719 python-pdbtrack-tracking-buffers)))))))
1720 output)
1721
1722\f
1723;;; Symbol completion
1724
1725(defun python-completion-complete-at-point ()
1726 "Complete current symbol at point.
1727For this to work the best as possible you should call
1728`python-shell-send-buffer' from time to time so context in
1729inferior python process is updated properly."
1730 (interactive)
1731 (let ((process (python-shell-get-process)))
1732 (if (not process)
4e531f7a 1733 (error "Completion needs an inferior Python process running")
075a0f61
FEG
1734 (with-syntax-table python-dotty-syntax-table
1735 (let* ((input (substring-no-properties
1736 (or (comint-word (current-word)) "") nil nil))
1737 (completions (python-shell-completion--get-completions
1738 input process)))
1739 (delete-char (- (length input)))
1740 (insert
1741 (python-shell-completion--get-completion
1742 input completions)))))))
45c138ac
FEG
1743
1744(add-to-list 'debug-ignored-errors "^Completion needs an inferior Python process running.")
1745
1746\f
1747;;; Fill paragraph
1748
c2cb97ae
FEG
1749(defcustom python-fill-comment-function 'python-fill-comment
1750 "Function to fill comments.
1751This is the function used by `python-fill-paragraph-function' to
1752fill comments."
1753 :type 'symbol
1754 :group 'python
1755 :safe 'symbolp)
1756
1757(defcustom python-fill-string-function 'python-fill-string
1758 "Function to fill strings.
1759This is the function used by `python-fill-paragraph-function' to
1760fill strings."
1761 :type 'symbol
1762 :group 'python
1763 :safe 'symbolp)
1764
1765(defcustom python-fill-decorator-function 'python-fill-decorator
1766 "Function to fill decorators.
1767This is the function used by `python-fill-paragraph-function' to
1768fill decorators."
1769 :type 'symbol
1770 :group 'python
1771 :safe 'symbolp)
1772
1773(defcustom python-fill-paren-function 'python-fill-paren
1774 "Function to fill parens.
1775This is the function used by `python-fill-paragraph-function' to
1776fill parens."
1777 :type 'symbol
1778 :group 'python
1779 :safe 'symbolp)
1780
45c138ac
FEG
1781(defun python-fill-paragraph-function (&optional justify)
1782 "`fill-paragraph-function' handling multi-line strings and possibly comments.
1783If any of the current line is in or at the end of a multi-line string,
1784fill the string or the paragraph of it that point is in, preserving
4e531f7a
FEG
1785the string's indentation.
1786Optional argument JUSTIFY defines if the paragraph should be justified."
45c138ac
FEG
1787 (interactive "P")
1788 (save-excursion
1789 (back-to-indentation)
1790 (cond
1791 ;; Comments
c2cb97ae
FEG
1792 ((funcall python-fill-comment-function justify))
1793 ;; Strings/Docstrings
45c138ac 1794 ((save-excursion (skip-chars-forward "\"'uUrR")
14a78495 1795 (python-info-ppss-context 'string))
c2cb97ae 1796 (funcall python-fill-string-function justify))
45c138ac
FEG
1797 ;; Decorators
1798 ((equal (char-after (save-excursion
1799 (back-to-indentation)
c2cb97ae
FEG
1800 (point-marker))) ?@)
1801 (funcall python-fill-decorator-function justify))
45c138ac 1802 ;; Parens
14a78495 1803 ((or (python-info-ppss-context 'paren)
45c138ac
FEG
1804 (looking-at (python-rx open-paren))
1805 (save-excursion
1806 (skip-syntax-forward "^(" (line-end-position))
1807 (looking-at (python-rx open-paren))))
c2cb97ae 1808 (funcall python-fill-paren-function justify))
45c138ac
FEG
1809 (t t))))
1810
c2cb97ae 1811(defun python-fill-comment (&optional justify)
053a6c72
FEG
1812 "Comment fill function for `python-fill-paragraph-function'.
1813JUSTIFY should be used (if applicable) as in `fill-paragraph'."
c2cb97ae
FEG
1814 (fill-comment-paragraph justify))
1815
1816(defun python-fill-string (&optional justify)
053a6c72
FEG
1817 "String fill function for `python-fill-paragraph-function'.
1818JUSTIFY should be used (if applicable) as in `fill-paragraph'."
c2cb97ae
FEG
1819 (let ((marker (point-marker))
1820 (string-start-marker
1821 (progn
1822 (skip-chars-forward "\"'uUrR")
1823 (goto-char (python-info-ppss-context 'string))
1824 (skip-chars-forward "\"'uUrR")
1825 (point-marker)))
1826 (reg-start (line-beginning-position))
1827 (string-end-marker
1828 (progn
1829 (while (python-info-ppss-context 'string)
1830 (goto-char (1+ (point-marker))))
1831 (skip-chars-backward "\"'")
1832 (point-marker)))
1833 (reg-end (line-end-position))
1834 (fill-paragraph-function))
1835 (save-restriction
1836 (narrow-to-region reg-start reg-end)
1837 (save-excursion
1838 (goto-char string-start-marker)
1839 (delete-region (point-marker) (progn
1840 (skip-syntax-forward "> ")
1841 (point-marker)))
1842 (goto-char string-end-marker)
1843 (delete-region (point-marker) (progn
1844 (skip-syntax-backward "> ")
1845 (point-marker)))
1846 (save-excursion
1847 (goto-char marker)
1848 (fill-paragraph justify))
1849 ;; If there is a newline in the docstring lets put triple
1850 ;; quote in it's own line to follow pep 8
1851 (when (save-excursion
1852 (re-search-backward "\n" string-start-marker t))
1853 (newline)
1854 (newline-and-indent))
1855 (fill-paragraph justify)))) t)
1856
1857(defun python-fill-decorator (&optional justify)
053a6c72
FEG
1858 "Decorator fill function for `python-fill-paragraph-function'.
1859JUSTIFY should be used (if applicable) as in `fill-paragraph'."
c2cb97ae
FEG
1860 t)
1861
1862(defun python-fill-paren (&optional justify)
053a6c72
FEG
1863 "Paren fill function for `python-fill-paragraph-function'.
1864JUSTIFY should be used (if applicable) as in `fill-paragraph'."
c2cb97ae
FEG
1865 (save-restriction
1866 (narrow-to-region (progn
1867 (while (python-info-ppss-context 'paren)
1868 (goto-char (1- (point-marker))))
1869 (point-marker)
1870 (line-beginning-position))
1871 (progn
1872 (when (not (python-info-ppss-context 'paren))
1873 (end-of-line)
1874 (when (not (python-info-ppss-context 'paren))
1875 (skip-syntax-backward "^)")))
1876 (while (python-info-ppss-context 'paren)
1877 (goto-char (1+ (point-marker))))
1878 (point-marker)))
1879 (let ((paragraph-start "\f\\|[ \t]*$")
1880 (paragraph-separate ",")
1881 (fill-paragraph-function))
1882 (goto-char (point-min))
1883 (fill-paragraph justify))
1884 (while (not (eobp))
1885 (forward-line 1)
1886 (python-indent-line)
1887 (goto-char (line-end-position)))) t)
1888
45c138ac 1889\f
e2803784
FEG
1890;;; Skeletons
1891
1892(defcustom python-skeleton-autoinsert nil
1893 "Non-nil means template skeletons will be automagically inserted.
1894This happens when pressing \"if<SPACE>\", for example, to prompt for
1895the if condition."
1896 :type 'boolean
0f55249e
FEG
1897 :group 'python
1898 :safe 'booleanp)
e2803784
FEG
1899
1900(defvar python-skeleton-available '()
1901 "Internal list of available skeletons.")
e2803784
FEG
1902
1903(define-abbrev-table 'python-mode-abbrev-table ()
1904 "Abbrev table for Python mode."
1905 :case-fixed t
1906 ;; Allow / inside abbrevs.
1907 :regexp "\\(?:^\\|[^/]\\)\\<\\([[:word:]/]+\\)\\W*"
1908 ;; Only expand in code.
1909 :enable-function (lambda ()
e2803784 1910 (and
14a78495
FEG
1911 (not (or (python-info-ppss-context 'string)
1912 (python-info-ppss-context 'comment)))
e2803784
FEG
1913 python-skeleton-autoinsert)))
1914
1915(defmacro python-skeleton-define (name doc &rest skel)
1916 "Define a `python-mode' skeleton using NAME DOC and SKEL.
1917The skeleton will be bound to python-skeleton-NAME and will
1918be added to `python-mode-abbrev-table'."
1919 (let* ((name (symbol-name name))
1920 (function-name (intern (concat "python-skeleton-" name))))
73ed6836
FEG
1921 `(progn
1922 (define-abbrev python-mode-abbrev-table ,name "" ',function-name)
1923 (setq python-skeleton-available
1924 (cons ',function-name python-skeleton-available))
1925 (define-skeleton ,function-name
1926 ,(or doc
1927 (format "Insert %s statement." name))
1928 ,@skel))))
e2803784
FEG
1929(put 'python-skeleton-define 'lisp-indent-function 2)
1930
1931(defmacro python-define-auxiliary-skeleton (name doc &optional &rest skel)
1932 "Define a `python-mode' auxiliary skeleton using NAME DOC and SKEL.
1933The skeleton will be bound to python-skeleton-NAME."
1934 (let* ((name (symbol-name name))
1935 (function-name (intern (concat "python-skeleton--" name)))
1936 (msg (format
1937 "Add '%s' clause? " name)))
1938 (when (not skel)
1939 (setq skel
1940 `(< ,(format "%s:" name) \n \n
1941 > _ \n)))
1942 `(define-skeleton ,function-name
1943 ,(or doc
1944 (format "Auxiliary skeleton for %s statement." name))
1945 nil
1946 (unless (y-or-n-p ,msg)
1947 (signal 'quit t))
1948 ,@skel)))
1949(put 'python-define-auxiliary-skeleton 'lisp-indent-function 2)
1950
1951(python-define-auxiliary-skeleton else nil)
1952
1953(python-define-auxiliary-skeleton except nil)
1954
1955(python-define-auxiliary-skeleton finally nil)
1956
1957(python-skeleton-define if nil
1958 "Condition: "
1959 "if " str ":" \n
1960 _ \n
1961 ("other condition, %s: "
1962 <
1963 "elif " str ":" \n
1964 > _ \n nil)
1965 '(python-skeleton--else) | ^)
1966
1967(python-skeleton-define while nil
1968 "Condition: "
1969 "while " str ":" \n
1970 > _ \n
1971 '(python-skeleton--else) | ^)
1972
1973(python-skeleton-define for nil
1974 "Iteration spec: "
1975 "for " str ":" \n
1976 > _ \n
1977 '(python-skeleton--else) | ^)
1978
1979(python-skeleton-define try nil
1980 nil
1981 "try:" \n
1982 > _ \n
1983 ("Exception, %s: "
1984 <
1985 "except " str ":" \n
1986 > _ \n nil)
1987 resume:
1988 '(python-skeleton--except)
1989 '(python-skeleton--else)
1990 '(python-skeleton--finally) | ^)
1991
1992(python-skeleton-define def nil
1993 "Function name: "
1994 "def " str " (" ("Parameter, %s: "
1995 (unless (equal ?\( (char-before)) ", ")
1996 str) "):" \n
1997 "\"\"\"" - "\"\"\"" \n
1998 > _ \n)
1999
2000(python-skeleton-define class nil
2001 "Class name: "
2002 "class " str " (" ("Inheritance, %s: "
2003 (unless (equal ?\( (char-before)) ", ")
2004 str)
2005 & ")" | -2
2006 ":" \n
2007 "\"\"\"" - "\"\"\"" \n
2008 > _ \n)
2009
2010(defun python-skeleton-add-menu-items ()
2011 "Add menu items to Python->Skeletons menu."
2012 (let ((skeletons (sort python-skeleton-available 'string<))
2013 (items))
2014 (dolist (skeleton skeletons)
2015 (easy-menu-add-item
2016 nil '("Python" "Skeletons")
2017 `[,(format
2018 "Insert %s" (caddr (split-string (symbol-name skeleton) "-")))
2019 ,skeleton t]))))
2020\f
046428d3
FEG
2021;;; FFAP
2022
0f55249e 2023(defcustom python-ffap-setup-code
046428d3
FEG
2024 "def __FFAP_get_module_path(module):
2025 try:
2026 import os
2027 path = __import__(module).__file__
2028 if path[-4:] == '.pyc' and os.path.exists(path[0:-1]):
2029 path = path[:-1]
2030 return path
2031 except:
2032 return ''"
0f55249e
FEG
2033 "Python code to get a module path."
2034 :type 'string
2035 :group 'python
2036 :safe 'stringp)
046428d3 2037
0f55249e 2038(defcustom python-ffap-string-code
046428d3 2039 "__FFAP_get_module_path('''%s''')\n"
0f55249e
FEG
2040 "Python code used to get a string with the path of a module."
2041 :type 'string
2042 :group 'python
2043 :safe 'stringp)
046428d3 2044
046428d3
FEG
2045(defun python-ffap-module-path (module)
2046 "Function for `ffap-alist' to return path for MODULE."
2047 (let ((process (or
2048 (and (eq major-mode 'inferior-python-mode)
2049 (get-buffer-process (current-buffer)))
2050 (python-shell-get-process))))
2051 (if (not process)
2052 nil
2053 (let ((module-file
9ce938be 2054 (python-shell-send-string-no-output
046428d3
FEG
2055 (format python-ffap-string-code module) process)))
2056 (when module-file
2947016a 2057 (substring-no-properties module-file 1 -1))))))
046428d3
FEG
2058
2059(eval-after-load "ffap"
2060 '(progn
2061 (push '(python-mode . python-ffap-module-path) ffap-alist)
2062 (push '(inferior-python-mode . python-ffap-module-path) ffap-alist)))
2063
046428d3 2064\f
8b3e0e76
FEG
2065;;; Code check
2066
0f55249e 2067(defcustom python-check-command
8b3e0e76 2068 "pychecker --stdlib"
0f55249e
FEG
2069 "Command used to check a Python file."
2070 :type 'string
2071 :group 'python
2072 :safe 'stringp)
8b3e0e76
FEG
2073
2074(defvar python-check-custom-command nil
2075 "Internal use.")
2076
2077(defun python-check (command)
2078 "Check a Python file (default current buffer's file).
2079Runs COMMAND, a shell command, as if by `compile'. See
2080`python-check-command' for the default."
2081 (interactive
2082 (list (read-string "Check command: "
2083 (or python-check-custom-command
2084 (concat python-check-command " "
2085 (shell-quote-argument
2086 (or
2087 (let ((name (buffer-file-name)))
2088 (and name
2089 (file-name-nondirectory name)))
2090 "")))))))
2091 (setq python-check-custom-command command)
2092 (save-some-buffers (not compilation-ask-about-save) nil)
2093 (compilation-start command))
2094
2095\f
45c138ac
FEG
2096;;; Eldoc
2097
0f55249e 2098(defcustom python-eldoc-setup-code
45c138ac
FEG
2099 "def __PYDOC_get_help(obj):
2100 try:
15cc40b8 2101 import inspect
9e662938
FEG
2102 if hasattr(obj, 'startswith'):
2103 obj = eval(obj, globals())
15cc40b8
FEG
2104 doc = inspect.getdoc(obj)
2105 if not doc and callable(obj):
2106 target = None
2107 if inspect.isclass(obj) and hasattr(obj, '__init__'):
2108 target = obj.__init__
2109 objtype = 'class'
2110 else:
2111 target = obj
2112 objtype = 'def'
2113 if target:
2114 args = inspect.formatargspec(
2115 *inspect.getargspec(target)
2116 )
2117 name = obj.__name__
2118 doc = '{objtype} {name}{args}'.format(
2119 objtype=objtype, name=name, args=args
2120 )
2121 else:
2122 doc = doc.splitlines()[0]
45c138ac 2123 except:
9e662938
FEG
2124 doc = ''
2125 try:
2126 exec('print doc')
2127 except SyntaxError:
2128 print(doc)"
0f55249e
FEG
2129 "Python code to setup documentation retrieval."
2130 :type 'string
2131 :group 'python
2132 :safe 'stringp)
45c138ac 2133
0f55249e 2134(defcustom python-eldoc-string-code
9e662938 2135 "__PYDOC_get_help('''%s''')\n"
0f55249e
FEG
2136 "Python code used to get a string with the documentation of an object."
2137 :type 'string
2138 :group 'python
2139 :safe 'stringp)
45c138ac 2140
78334b43 2141(defun python-eldoc--get-doc-at-point (&optional force-input force-process)
d439cda5
FEG
2142 "Internal implementation to get documentation at point.
2143If not FORCE-INPUT is passed then what `current-word' returns
2144will be used. If not FORCE-PROCESS is passed what
2145`python-shell-get-process' returns is used."
78334b43 2146 (let ((process (or force-process (python-shell-get-process))))
45c138ac
FEG
2147 (if (not process)
2148 "Eldoc needs an inferior Python process running."
2149 (let* ((current-defun (python-info-current-defun))
78334b43
FEG
2150 (input (or force-input
2151 (with-syntax-table python-dotty-syntax-table
2152 (if (not current-defun)
2153 (current-word)
2154 (concat current-defun "." (current-word))))))
45c138ac
FEG
2155 (ppss (syntax-ppss))
2156 (help (when (and input
2157 (not (string= input (concat current-defun ".")))
14a78495
FEG
2158 (not (or (python-info-ppss-context 'string ppss)
2159 (python-info-ppss-context 'comment ppss))))
45c138ac
FEG
2160 (when (string-match (concat
2161 (regexp-quote (concat current-defun "."))
2162 "self\\.") input)
2163 (with-temp-buffer
2164 (insert input)
2165 (goto-char (point-min))
2166 (forward-word)
2167 (forward-char)
2168 (delete-region (point-marker) (search-forward "self."))
2169 (setq input (buffer-substring (point-min) (point-max)))))
9ce938be 2170 (python-shell-send-string-no-output
1066882c 2171 (format python-eldoc-string-code input) process))))
45c138ac
FEG
2172 (with-current-buffer (process-buffer process)
2173 (when comint-last-prompt-overlay
2174 (delete-region comint-last-input-end
2175 (overlay-start comint-last-prompt-overlay))))
2176 (when (and help
2177 (not (string= help "\n")))
2178 help)))))
2179
78334b43
FEG
2180(defun python-eldoc-function ()
2181 "`eldoc-documentation-function' for Python.
2182For this to work the best as possible you should call
2183`python-shell-send-buffer' from time to time so context in
2184inferior python process is updated properly."
2185 (python-eldoc--get-doc-at-point))
2186
2187(defun python-eldoc-at-point (symbol)
2188 "Get help on SYMBOL using `help'.
2189Interactively, prompt for symbol."
2190 (interactive
2191 (let ((symbol (with-syntax-table python-dotty-syntax-table
2192 (current-word)))
2193 (enable-recursive-minibuffers t))
2194 (list (read-string (if symbol
2195 (format "Describe symbol (default %s): " symbol)
2196 "Describe symbol: ")
2197 nil nil symbol))))
2198 (let ((process (python-shell-get-process)))
2199 (if (not process)
2200 (message "Eldoc needs an inferior Python process running.")
15cc40b8 2201 (message (python-eldoc--get-doc-at-point symbol process)))))
78334b43 2202
45c138ac 2203\f
fc2dc7df
FEG
2204;;; Imenu
2205
2206(defcustom python-imenu-include-defun-type t
2207 "Non-nil make imenu items to include its type."
2208 :type 'boolean
2209 :group 'python
2210 :safe 'booleanp)
2211
c942de99 2212(defcustom python-imenu-make-tree t
fc2dc7df
FEG
2213 "Non-nil make imenu to build a tree menu.
2214Set to nil for speed."
2215 :type 'boolean
2216 :group 'python
2217 :safe 'booleanp)
2218
2219(defcustom python-imenu-subtree-root-label "<Jump to %s>"
2220 "Label displayed to navigate to root from a subtree.
2221It can contain a \"%s\" which will be replaced with the root name."
2222 :type 'string
2223 :group 'python
2224 :safe 'stringp)
2225
2226(defvar python-imenu-index-alist nil
2227 "Calculated index tree for imenu.")
2228
2229(defun python-imenu-tree-assoc (keylist tree)
2230 "Using KEYLIST traverse TREE."
2231 (if keylist
2232 (python-imenu-tree-assoc (cdr keylist)
2233 (ignore-errors (assoc (car keylist) tree)))
2234 tree))
2235
2236(defun python-imenu-make-element-tree (element-list full-element plain-index)
2237 "Make a tree from plain alist of module names.
2238ELEMENT-LIST is the defun name splitted by \".\" and FULL-ELEMENT
2239is the same thing, the difference is that FULL-ELEMENT remains
2240untouched in all recursive calls.
2241Argument PLAIN-INDEX is the calculated plain index used to build the tree."
2242 (when (not (python-imenu-tree-assoc full-element python-imenu-index-alist))
2243 (when element-list
2244 (let* ((subelement-point (cdr (assoc
2245 (mapconcat #'identity full-element ".")
2246 plain-index)))
2247 (subelement-name (car element-list))
c942de99
FEG
2248 (subelement-position (python-util-position
2249 subelement-name full-element))
fc2dc7df
FEG
2250 (subelement-path (when subelement-position
2251 (butlast
2252 full-element
2253 (- (length full-element)
2254 subelement-position)))))
2255 (let ((path-ref (python-imenu-tree-assoc subelement-path
2256 python-imenu-index-alist)))
2257 (if (not path-ref)
2258 (push (cons subelement-name subelement-point)
2259 python-imenu-index-alist)
2260 (when (not (listp (cdr path-ref)))
2261 ;; Modifiy root cdr to be a list
2262 (setcdr path-ref
2263 (list (cons (format python-imenu-subtree-root-label
2264 (car path-ref))
2265 (cdr (assoc
2266 (mapconcat #'identity
2267 subelement-path ".")
2268 plain-index))))))
2269 (when (not (assoc subelement-name path-ref))
2270 (push (cons subelement-name subelement-point) (cdr path-ref))))))
2271 (python-imenu-make-element-tree (cdr element-list)
2272 full-element plain-index))))
2273
2274(defun python-imenu-make-tree (index)
fc6c545e 2275 "Build the imenu alist tree from plain INDEX.
fc2dc7df
FEG
2276
2277The idea of this function is that given the alist:
2278
2279 '((\"Test\" . 100)
2280 (\"Test.__init__\" . 200)
2281 (\"Test.some_method\" . 300)
2282 (\"Test.some_method.another\" . 400)
2283 (\"Test.something_else\" . 500)
2284 (\"test\" . 600)
2285 (\"test.reprint\" . 700)
2286 (\"test.reprint\" . 800))
2287
2288This tree gets built:
2289
2290 '((\"Test\" . ((\"jump to...\" . 100)
2291 (\"__init__\" . 200)
2292 (\"some_method\" . ((\"jump to...\" . 300)
2293 (\"another\" . 400)))
2294 (\"something_else\" . 500)))
2295 (\"test\" . ((\"jump to...\" . 600)
2296 (\"reprint\" . 700)
2297 (\"reprint\" . 800))))
2298
2299Internally it uses `python-imenu-make-element-tree' to create all
2300branches for each element."
fc6c545e
FEG
2301 (setq python-imenu-index-alist nil)
2302 (mapc (lambda (element)
2303 (python-imenu-make-element-tree element element index))
2304 (mapcar (lambda (element)
2305 (split-string (car element) "\\." t)) index))
2306 python-imenu-index-alist)
fc2dc7df
FEG
2307
2308(defun python-imenu-create-index ()
2309 "`imenu-create-index-function' for Python."
fc6c545e
FEG
2310 (let ((index
2311 (python-nav-list-defun-positions python-imenu-include-defun-type)))
fc2dc7df
FEG
2312 (if python-imenu-make-tree
2313 (python-imenu-make-tree index)
2314 index)))
2315
2316\f
45c138ac
FEG
2317;;; Misc helpers
2318
fc2dc7df 2319(defun python-info-current-defun (&optional include-type)
45c138ac 2320 "Return name of surrounding function with Python compatible dotty syntax.
fc2dc7df 2321Optional argument INCLUDE-TYPE indicates to include the type of the defun.
45c138ac
FEG
2322This function is compatible to be used as
2323`add-log-current-defun-function' since it returns nil if point is
2324not inside a defun."
6b432853 2325 (let ((names '())
0b7b2e51
FEG
2326 (min-indent)
2327 (first-run t))
45c138ac
FEG
2328 (save-restriction
2329 (widen)
2330 (save-excursion
6b432853 2331 (goto-char (line-end-position))
589cefd7 2332 (forward-comment -9999)
15cc40b8 2333 (setq min-indent (current-indentation))
fc2dc7df 2334 (while (python-beginning-of-defun-function 1 t)
0b7b2e51
FEG
2335 (when (or (< (current-indentation) min-indent)
2336 first-run)
2337 (setq first-run nil)
6b432853 2338 (setq min-indent (current-indentation))
af5c1beb 2339 (looking-at python-nav-beginning-of-defun-regexp)
fc2dc7df
FEG
2340 (setq names (cons
2341 (if (not include-type)
2342 (match-string-no-properties 1)
2343 (mapconcat 'identity
2344 (split-string
2345 (match-string-no-properties 0)) " "))
2346 names))))))
45c138ac
FEG
2347 (when names
2348 (mapconcat (lambda (string) string) names "."))))
2349
2350(defun python-info-closing-block ()
e2d8d479 2351 "Return the point of the block the current line closes."
45c138ac
FEG
2352 (let ((closing-word (save-excursion
2353 (back-to-indentation)
2354 (current-word)))
2355 (indentation (current-indentation)))
2356 (when (member closing-word python-indent-dedenters)
2357 (save-excursion
2358 (forward-line -1)
2359 (while (and (> (current-indentation) indentation)
2360 (not (bobp))
2361 (not (back-to-indentation))
2362 (forward-line -1)))
2363 (back-to-indentation)
2364 (cond
2365 ((not (equal indentation (current-indentation))) nil)
2366 ((string= closing-word "elif")
2367 (when (member (current-word) '("if" "elif"))
2368 (point-marker)))
2369 ((string= closing-word "else")
2370 (when (member (current-word) '("if" "elif" "except" "for" "while"))
2371 (point-marker)))
2372 ((string= closing-word "except")
2373 (when (member (current-word) '("try"))
2374 (point-marker)))
2375 ((string= closing-word "finally")
2376 (when (member (current-word) '("except" "else"))
2377 (point-marker))))))))
2378
2379(defun python-info-line-ends-backslash-p ()
2380 "Return non-nil if current line ends with backslash."
2381 (string= (or (ignore-errors
2382 (buffer-substring
2383 (line-end-position)
2384 (- (line-end-position) 1))) "") "\\"))
2385
2386(defun python-info-continuation-line-p ()
2387 "Return non-nil if current line is continuation of another."
85655287
FEG
2388 (let ((current-ppss-context-type (python-info-ppss-context-type)))
2389 (and
2390 (equal (save-excursion
2391 (goto-char (line-end-position))
2392 (forward-comment 9999)
2393 (python-info-ppss-context-type))
2394 current-ppss-context-type)
2395 (or (python-info-line-ends-backslash-p)
2396 (string-match ",[[:space:]]*$" (buffer-substring
2397 (line-beginning-position)
2398 (line-end-position)))
2399 (save-excursion
2400 (let ((innermost-paren (progn
2401 (goto-char (line-end-position))
2402 (python-info-ppss-context 'paren))))
2403 (when (and innermost-paren
2404 (and (<= (line-beginning-position) innermost-paren)
2405 (>= (line-end-position) innermost-paren)))
2406 (goto-char innermost-paren)
2407 (looking-at (python-rx open-paren (* space) line-end)))))
2408 (save-excursion
2409 (back-to-indentation)
2410 (python-info-ppss-context 'paren))))))
45c138ac
FEG
2411
2412(defun python-info-block-continuation-line-p ()
2413 "Return non-nil if current line is a continuation of a block."
2414 (save-excursion
2415 (while (and (not (bobp))
2416 (python-info-continuation-line-p))
2417 (forward-line -1))
2418 (forward-line 1)
2419 (back-to-indentation)
2420 (when (looking-at (python-rx block-start))
2421 (point-marker))))
2422
2423(defun python-info-assignment-continuation-line-p ()
2424 "Return non-nil if current line is a continuation of an assignment."
2425 (save-excursion
2426 (while (and (not (bobp))
2427 (python-info-continuation-line-p))
2428 (forward-line -1))
2429 (forward-line 1)
2430 (back-to-indentation)
2431 (when (and (not (looking-at (python-rx block-start)))
2432 (save-excursion
2433 (and (re-search-forward (python-rx not-simple-operator
2434 assignment-operator
2435 not-simple-operator)
2436 (line-end-position) t)
14a78495 2437 (not (or (python-info-ppss-context 'string)
9f1537ef 2438 (python-info-ppss-context 'paren)
14a78495 2439 (python-info-ppss-context 'comment))))))
45c138ac
FEG
2440 (point-marker))))
2441
14a78495
FEG
2442(defun python-info-ppss-context (type &optional syntax-ppss)
2443 "Return non-nil if point is on TYPE using SYNTAX-PPSS.
85655287 2444TYPE can be 'comment, 'string or 'paren. It returns the start
14a78495
FEG
2445character address of the specified TYPE."
2446 (let ((ppss (or syntax-ppss (syntax-ppss))))
2447 (case type
2448 ('comment
2449 (and (nth 4 ppss)
2450 (nth 8 ppss)))
2451 ('string
2452 (nth 8 ppss))
2453 ('paren
2454 (nth 1 ppss))
2455 (t nil))))
2456
85655287
FEG
2457(defun python-info-ppss-context-type (&optional syntax-ppss)
2458 "Return the context type using SYNTAX-PPSS.
2459The type returned can be 'comment, 'string or 'paren."
2460 (let ((ppss (or syntax-ppss (syntax-ppss))))
2461 (cond
2462 ((and (nth 4 ppss)
2463 (nth 8 ppss))
2464 'comment)
2465 ((nth 8 ppss)
2466 'string)
2467 ((nth 1 ppss)
2468 'paren)
2469 (t nil))))
2470
45c138ac 2471\f
c942de99
FEG
2472;;; Utility functions
2473
2474;; Stolen from GNUS
2475(defun python-util-merge (type list1 list2 pred)
4cafacb5
FEG
2476 "Destructively merge lists to produce a new one.
2477Argument TYPE is for compatibility and ignored. LIST1 and LIST2
2478are the list to be merged. Ordering of the elements is preserved
2479according to PRED, a `less-than' predicate on the elements."
c942de99
FEG
2480 (let ((res nil))
2481 (while (and list1 list2)
2482 (if (funcall pred (car list2) (car list1))
2483 (push (pop list2) res)
2484 (push (pop list1) res)))
2485 (nconc (nreverse res) list1 list2)))
2486
2487(defun python-util-position (item seq)
2488 "Find the first occurrence of ITEM in SEQ.
2489Return the index of the matching item, or nil if not found."
2490 (let ((member-result (member item seq)))
2491 (when member-result
2492 (- (length seq) (length member-result)))))
2493
d2190c57 2494;; Stolen from org-mode
fbc39529 2495(defun python-util-clone-local-variables (from-buffer &optional regexp)
d2190c57
FEG
2496 "Clone local variables from FROM-BUFFER.
2497Optional argument REGEXP selects variables to clone and defaults
2498to \"^python-\"."
2499 (mapc
2500 (lambda (pair)
2501 (and (symbolp (car pair))
2502 (string-match (or regexp "^python-")
2503 (symbol-name (car pair)))
2504 (set (make-local-variable (car pair))
2505 (cdr pair))))
2506 (buffer-local-variables from-buffer)))
2507
c942de99 2508\f
45c138ac
FEG
2509;;;###autoload
2510(define-derived-mode python-mode fundamental-mode "Python"
e2d8d479
FEG
2511 "Major mode for editing Python files.
2512
2513\\{python-mode-map}
2514Entry to this mode calls the value of `python-mode-hook'
2515if that value is non-nil."
45c138ac
FEG
2516 (set (make-local-variable 'tab-width) 8)
2517 (set (make-local-variable 'indent-tabs-mode) nil)
2518
2519 (set (make-local-variable 'comment-start) "# ")
2520 (set (make-local-variable 'comment-start-skip) "#+\\s-*")
2521
2522 (set (make-local-variable 'parse-sexp-lookup-properties) t)
2523 (set (make-local-variable 'parse-sexp-ignore-comments) t)
2524
2525 (set (make-local-variable 'font-lock-defaults)
2526 '(python-font-lock-keywords
2527 nil nil nil nil
2528 (font-lock-syntactic-keywords . python-font-lock-syntactic-keywords)))
2529
2530 (set (make-local-variable 'indent-line-function) #'python-indent-line-function)
2531 (set (make-local-variable 'indent-region-function) #'python-indent-region)
2532
2533 (set (make-local-variable 'paragraph-start) "\\s-*$")
2534 (set (make-local-variable 'fill-paragraph-function) 'python-fill-paragraph-function)
2535
2536 (set (make-local-variable 'beginning-of-defun-function)
2537 #'python-beginning-of-defun-function)
2538 (set (make-local-variable 'end-of-defun-function)
2539 #'python-end-of-defun-function)
2540
2541 (add-hook 'completion-at-point-functions
2542 'python-completion-complete-at-point nil 'local)
2543
fc2dc7df
FEG
2544 (setq imenu-create-index-function #'python-imenu-create-index)
2545
45c138ac
FEG
2546 (set (make-local-variable 'add-log-current-defun-function)
2547 #'python-info-current-defun)
2548
e2803784
FEG
2549 (set (make-local-variable 'skeleton-further-elements)
2550 '((abbrev-mode nil)
2551 (< '(backward-delete-char-untabify (min python-indent-offset
2552 (current-column))))
2553 (^ '(- (1+ (current-indentation))))))
2554
45c138ac
FEG
2555 (set (make-local-variable 'eldoc-documentation-function)
2556 #'python-eldoc-function)
2557
2558 (add-to-list 'hs-special-modes-alist
2559 `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#"
2560 ,(lambda (arg)
2561 (python-end-of-defun-function)) nil))
2562
82c2b0de
FEG
2563 (set (make-local-variable 'mode-require-final-newline) t)
2564
45c138ac
FEG
2565 (set (make-local-variable 'outline-regexp)
2566 (python-rx (* space) block-start))
2567 (set (make-local-variable 'outline-heading-end-regexp) ":\\s-*\n")
2568 (set (make-local-variable 'outline-level)
2569 #'(lambda ()
2570 "`outline-level' function for Python mode."
2571 (1+ (/ (current-indentation) python-indent-offset))))
2572
e2803784
FEG
2573 (python-skeleton-add-menu-items)
2574
45c138ac
FEG
2575 (when python-indent-guess-indent-offset
2576 (python-indent-guess-indent-offset)))
2577
2578
2579(provide 'python)
2580;;; python.el ends here