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