Small fix to python-indent-electric-colon
[bpt/emacs.git] / lisp / progmodes / python.el
CommitLineData
45c138ac
FEG
1;;; python.el -- Python's flying circus support for Emacs
2
3;; Copyright (C) 2010 Free Software Foundation, Inc.
4
5;; Author: Fabián E. Gallina <fabian@anue.biz>
6;; Maintainer: FSF
7;; Created: Jul 2010
8;; Keywords: languages
9
10;; This file is NOT part of GNU Emacs.
11
12;; python.el is free software: you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
16
17;; python.el is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with python.el. If not, see <http://www.gnu.org/licenses/>.
24
25;;; Commentary:
26
27;; Major mode for editing Python files with some fontification and
28;; indentation bits extracted from original Dave Love's python.el
29;; found in GNU/Emacs.
30
31;; While it probably has less features than Dave Love's python.el and
32;; PSF's python-mode.el it provides the main stuff you'll need while
33;; keeping it simple :)
34
35;; Implements Syntax highlighting, Indentation, Movement, Shell
36;; interaction, Shell completion, Pdb tracking, Symbol completion,
37;; Eldoc.
38
39;; Syntax highlighting: Fontification of code is provided and supports
40;; python's triple quoted strings properly.
41
42;; Indentation: Automatic indentation with indentation cycling is
43;; provided, it allows you to navigate different available levels of
44;; indentation by hitting <tab> several times.
45
46;; Movement: `beginning-of-defun' and `end-of-defun' functions are
47;; properly implemented. A `beginning-of-innermost-defun' is defined
48;; to navigate nested defuns.
49
50;; Shell interaction: is provided and allows you easily execute any
51;; block of code of your current buffer in an inferior Python process.
52
53;; Shell completion: hitting tab will try to complete the current
4e531f7a 54;; word. Shell completion is implemented in a manner that if you
45c138ac
FEG
55;; change the `python-shell-interpreter' to any other (for example
56;; IPython) it should be easy to integrate another way to calculate
57808175 57;; completions. You just need to specify your custom
45c138ac
FEG
58;; `python-shell-completion-setup-code' and
59;; `python-shell-completion-strings-code'
60
61;; Pdb tracking: when you execute a block of code that contains some
62;; call to pdb (or ipdb) it will prompt the block of code and will
63;; follow the execution of pdb marking the current line with an arrow.
64
4e531f7a 65;; Symbol completion: you can complete the symbol at point. It uses
45c138ac
FEG
66;; the shell completion in background so you should run
67;; `python-shell-send-buffer' from time to time to get better results.
68
2947016a
FEG
69;; FFAP: You can find the filename for a given module when using ffap
70;; out of the box. This feature needs an inferior python shell
71;; running.
72
8b3e0e76
FEG
73;; Code check: Check the current file for errors using
74;; `python-check-command'
75
45c138ac 76;; Eldoc: returns documentation for object at point by using the
4e531f7a 77;; inferior python subprocess to inspect its documentation. As you
45c138ac
FEG
78;; might guessed you should run `python-shell-send-buffer' from time
79;; to time to get better results too.
80
57808175
FEG
81;; If you used python-mode.el you probably will miss auto-indentation
82;; when inserting newlines. To achieve the same behavior you have
83;; two options:
84
85;; 1) Use GNU/Emacs' standard binding for `newline-and-indent': C-j.
86
87;; 2) Add the following hook in your .emacs:
88
89;; (add-hook 'python-mode-hook
90;; #'(lambda ()
91;; (define-key python-mode-map "\C-m" 'newline-and-indent)))
92
93;; I'd recommend the first one since you'll get the same behavior for
94;; all modes out-of-the-box.
95
45c138ac
FEG
96;;; Installation:
97
98;; Add this to your .emacs:
99
100;; (add-to-list 'load-path "/folder/containing/file")
101;; (require 'python)
102
103;;; TODO:
104
105;; Ordered by priority:
106
107;; Better decorator support for beginning of defun
108
db1497be 109;; Review code and cleanup
45c138ac 110
db1497be 111;; (Perhaps) some skeletons (I never use them because of yasnippet)
45c138ac
FEG
112
113;;; Code:
114
115(require 'comint)
116(require 'ansi-color)
117(require 'outline)
118
119(eval-when-compile
120 (require 'cl))
121
122(autoload 'comint-mode "comint")
123
124;;;###autoload
125(add-to-list 'auto-mode-alist (cons (purecopy "\\.py\\'") 'python-mode))
126;;;###autoload
127(add-to-list 'interpreter-mode-alist (cons (purecopy "python") 'python-mode))
128
129(defgroup python nil
130 "Python Language's flying circus support for Emacs."
131 :group 'languages
132 :version "23.2"
133 :link '(emacs-commentary-link "python"))
134
135\f
136;;; Bindings
137
138(defvar python-mode-map
139 (let ((map (make-sparse-keymap)))
140 ;; Indent specific
141 (define-key map "\177" 'python-indent-dedent-line-backspace)
142 (define-key map (kbd "<backtab>") 'python-indent-dedent-line)
143 (define-key map "\C-c<" 'python-indent-shift-left)
144 (define-key map "\C-c>" 'python-indent-shift-right)
ffdb56c3 145 (define-key map ":" 'python-indent-electric-colon)
45c138ac
FEG
146 ;; Shell interaction
147 (define-key map "\C-c\C-s" 'python-shell-send-string)
148 (define-key map "\C-c\C-r" 'python-shell-send-region)
149 (define-key map "\C-\M-x" 'python-shell-send-defun)
150 (define-key map "\C-c\C-c" 'python-shell-send-buffer)
151 (define-key map "\C-c\C-l" 'python-shell-send-file)
152 (define-key map "\C-c\C-z" 'python-shell-switch-to-shell)
8b3e0e76
FEG
153 ;; Some util commands
154 (define-key map "\C-c\C-v" 'python-check)
78334b43 155 (define-key map "\C-c\C-f" 'python-eldoc-at-point)
45c138ac
FEG
156 ;; Utilities
157 (substitute-key-definition 'complete-symbol 'completion-at-point
158 map global-map)
159 (easy-menu-define python-menu map "Python Mode menu"
160 `("Python"
161 :help "Python-specific Features"
162 ["Shift region left" python-indent-shift-left :active mark-active
163 :help "Shift region left by a single indentation step"]
164 ["Shift region right" python-indent-shift-right :active mark-active
165 :help "Shift region right by a single indentation step"]
166 "-"
167 ["Mark def/class" mark-defun
168 :help "Mark outermost definition around point"]
169 "-"
170 ["Start of def/class" beginning-of-defun
171 :help "Go to start of outermost definition around point"]
172 ["Start of def/class" python-beginning-of-innermost-defun
173 :help "Go to start of innermost definition around point"]
174 ["End of def/class" end-of-defun
175 :help "Go to end of definition around point"]
176 "-"
177 ["Start interpreter" run-python
178 :help "Run inferior Python process in a separate buffer"]
179 ["Switch to shell" python-shell-switch-to-shell
180 :help "Switch to running inferior Python process"]
181 ["Eval string" python-shell-send-string
182 :help "Eval string in inferior Python session"]
183 ["Eval buffer" python-shell-send-buffer
184 :help "Eval buffer in inferior Python session"]
185 ["Eval region" python-shell-send-region
186 :help "Eval region in inferior Python session"]
187 ["Eval defun" python-shell-send-defun
188 :help "Eval defun in inferior Python session"]
189 ["Eval file" python-shell-send-file
190 :help "Eval file in inferior Python session"]
191 ["Debugger" pdb :help "Run pdb under GUD"]
192 "-"
8b3e0e76
FEG
193 ["Check file" python-check
194 :help "Check file for errors"]
78334b43
FEG
195 ["Help on symbol" python-eldoc-at-point
196 :help "Get help on symbol at point"]
45c138ac
FEG
197 ["Complete symbol" completion-at-point
198 :help "Complete symbol before point"]))
199 map)
200 "Keymap for `python-mode'.")
201
202\f
203;;; Python specialized rx
204
205(defconst python-rx-constituents
206 (list
207 `(block-start . ,(rx symbol-start
208 (or "def" "class" "if" "elif" "else" "try"
209 "except" "finally" "for" "while" "with")
210 symbol-end))
211 `(defun . ,(rx symbol-start (or "def" "class") symbol-end))
212 `(open-paren . ,(rx (or "{" "[" "(")))
213 `(close-paren . ,(rx (or "}" "]" ")")))
214 `(simple-operator . ,(rx (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%)))
215 `(not-simple-operator . ,(rx (not (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%))))
216 `(operator . ,(rx (or "+" "-" "/" "&" "^" "~" "|" "*" "<" ">"
217 "=" "%" "**" "//" "<<" ">>" "<=" "!="
218 "==" ">=" "is" "not")))
219 `(assignment-operator . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**="
220 ">>=" "<<=" "&=" "^=" "|=")))))
221
222(defmacro python-rx (&rest regexps)
4e531f7a 223 "Python mode especialized rx macro which supports common python named REGEXPS."
45c138ac
FEG
224 (let ((rx-constituents (append python-rx-constituents rx-constituents)))
225 (cond ((null regexps)
226 (error "No regexp"))
227 ((cdr regexps)
228 (rx-to-string `(and ,@regexps) t))
229 (t
230 (rx-to-string (car regexps) t)))))
231
232\f
233;;; Font-lock and syntax
234
235(defvar python-font-lock-keywords
236 ;; Keywords
237 `(,(rx symbol-start
238 (or "and" "del" "from" "not" "while" "as" "elif" "global" "or" "with"
239 "assert" "else" "if" "pass" "yield" "break" "except" "import"
240 "print" "class" "exec" "in" "raise" "continue" "finally" "is"
241 "return" "def" "for" "lambda" "try" "self")
242 symbol-end)
243 ;; functions
244 (,(rx symbol-start "def" (1+ space) (group (1+ (or word ?_))))
245 (1 font-lock-function-name-face))
246 ;; classes
247 (,(rx symbol-start "class" (1+ space) (group (1+ (or word ?_))))
248 (1 font-lock-type-face))
249 ;; Constants
250 (,(rx symbol-start (group "None" symbol-end))
251 (1 font-lock-constant-face))
252 ;; Decorators.
253 (,(rx line-start (* (any " \t")) (group "@" (1+ (or word ?_))
254 (0+ "." (1+ (or word ?_)))))
255 (1 font-lock-type-face))
256 ;; Builtin Exceptions
257 (,(rx symbol-start
258 (or "ArithmeticError" "AssertionError" "AttributeError"
259 "BaseException" "BufferError" "BytesWarning" "DeprecationWarning"
260 "EOFError" "EnvironmentError" "Exception" "FloatingPointError"
261 "FutureWarning" "GeneratorExit" "IOError" "ImportError"
262 "ImportWarning" "IndentationError" "IndexError" "KeyError"
263 "KeyboardInterrupt" "LookupError" "MemoryError" "NameError"
264 "NotImplemented" "NotImplementedError" "OSError" "OverflowError"
265 "PendingDeprecationWarning" "ReferenceError" "RuntimeError"
266 "RuntimeWarning" "StandardError" "StopIteration" "SyntaxError"
267 "SyntaxWarning" "SystemError" "SystemExit" "TabError" "TypeError"
268 "UnboundLocalError" "UnicodeDecodeError" "UnicodeEncodeError"
269 "UnicodeError" "UnicodeTranslateError" "UnicodeWarning"
270 "UserWarning" "ValueError" "Warning" "ZeroDivisionError")
271 symbol-end) . font-lock-type-face)
272 ;; Builtins
273 (,(rx (or line-start (not (any ". \t"))) (* (any " \t")) symbol-start
274 (group
275 (or "_" "__debug__" "__doc__" "__import__" "__name__" "__package__"
276 "abs" "all" "any" "apply" "basestring" "bin" "bool" "buffer"
277 "bytearray" "bytes" "callable" "chr" "classmethod" "cmp" "coerce"
278 "compile" "complex" "copyright" "credits" "delattr" "dict" "dir"
279 "divmod" "enumerate" "eval" "execfile" "exit" "file" "filter"
280 "float" "format" "frozenset" "getattr" "globals" "hasattr" "hash"
281 "help" "hex" "id" "input" "int" "intern" "isinstance" "issubclass"
282 "iter" "len" "license" "list" "locals" "long" "map" "max" "min"
283 "next" "object" "oct" "open" "ord" "pow" "print" "property" "quit"
284 "range" "raw_input" "reduce" "reload" "repr" "reversed" "round"
285 "set" "setattr" "slice" "sorted" "staticmethod" "str" "sum"
286 "super" "tuple" "type" "unichr" "unicode" "vars" "xrange" "zip"
287 "True" "False" "Ellipsis")) symbol-end)
288 (1 font-lock-builtin-face))
289 ;; asignations
290 ;; support for a = b = c = 5
291 (,(lambda (limit)
d8e594db
FEG
292 (let ((re (python-rx (group (+ (any word ?. ?_)))
293 (? ?\[ (+ (not (any ?\]))) ?\]) (* space)
45c138ac
FEG
294 assignment-operator)))
295 (when (re-search-forward re limit t)
296 (while (and (not (equal (nth 0 (syntax-ppss)) 0))
297 (re-search-forward re limit t)))
534e2438
FEG
298 (if (and (equal (nth 0 (syntax-ppss)) 0)
299 (not (equal (char-after (point-marker)) ?=)))
45c138ac
FEG
300 t
301 (set-match-data nil)))))
302 (1 font-lock-variable-name-face nil nil))
303 ;; support for a, b, c = (1, 2, 3)
304 (,(lambda (limit)
305 (let ((re (python-rx (group (+ (any word ?. ?_))) (* space)
306 (* ?, (* space) (+ (any word ?. ?_)) (* space))
307 ?, (* space) (+ (any word ?. ?_)) (* space)
308 assignment-operator)))
309 (when (and (re-search-forward re limit t)
310 (goto-char (nth 3 (match-data))))
311 (while (and (not (equal (nth 0 (syntax-ppss)) 0))
312 (re-search-forward re limit t))
313 (goto-char (nth 3 (match-data))))
314 (if (equal (nth 0 (syntax-ppss)) 0)
315 t
316 (set-match-data nil)))))
317 (1 font-lock-variable-name-face nil nil))))
318
319;; Fixme: Is there a better way?
320(defconst python-font-lock-syntactic-keywords
321 ;; First avoid a sequence preceded by an odd number of backslashes.
322 `((,(rx (not (any ?\\))
323 ?\\ (* (and ?\\ ?\\))
324 (group (syntax string-quote))
325 (backref 1)
326 (group (backref 1)))
327 (2 ,(string-to-syntax "\""))) ; dummy
328 (,(rx (group (optional (any "uUrR"))) ; prefix gets syntax property
329 (optional (any "rR")) ; possible second prefix
330 (group (syntax string-quote)) ; maybe gets property
331 (backref 2) ; per first quote
332 (group (backref 2))) ; maybe gets property
333 (1 (python-quote-syntax 1))
334 (2 (python-quote-syntax 2))
335 (3 (python-quote-syntax 3))))
336 "Make outer chars of triple-quote strings into generic string delimiters.")
337
338(defun python-quote-syntax (n)
339 "Put `syntax-table' property correctly on triple quote.
340Used for syntactic keywords. N is the match number (1, 2 or 3)."
341 ;; Given a triple quote, we have to check the context to know
342 ;; whether this is an opening or closing triple or whether it's
343 ;; quoted anyhow, and should be ignored. (For that we need to do
344 ;; the same job as `syntax-ppss' to be correct and it seems to be OK
345 ;; to use it here despite initial worries.) We also have to sort
346 ;; out a possible prefix -- well, we don't _have_ to, but I think it
347 ;; should be treated as part of the string.
348
349 ;; Test cases:
350 ;; ur"""ar""" x='"' # """
351 ;; x = ''' """ ' a
352 ;; '''
353 ;; x '"""' x """ \"""" x
354 (save-excursion
355 (goto-char (match-beginning 0))
356 (cond
357 ;; Consider property for the last char if in a fenced string.
358 ((= n 3)
359 (let* ((font-lock-syntactic-keywords nil)
360 (syntax (syntax-ppss)))
361 (when (eq t (nth 3 syntax)) ; after unclosed fence
362 (goto-char (nth 8 syntax)) ; fence position
363 (skip-chars-forward "uUrR") ; skip any prefix
364 ;; Is it a matching sequence?
365 (if (eq (char-after) (char-after (match-beginning 2)))
366 (eval-when-compile (string-to-syntax "|"))))))
367 ;; Consider property for initial char, accounting for prefixes.
368 ((or (and (= n 2) ; leading quote (not prefix)
369 (= (match-beginning 1) (match-end 1))) ; prefix is null
370 (and (= n 1) ; prefix
371 (/= (match-beginning 1) (match-end 1)))) ; non-empty
372 (let ((font-lock-syntactic-keywords nil))
373 (unless (eq 'string (syntax-ppss-context (syntax-ppss)))
374 (eval-when-compile (string-to-syntax "|")))))
375 ;; Otherwise (we're in a non-matching string) the property is
376 ;; nil, which is OK.
377 )))
378
379(defvar python-mode-syntax-table
380 (let ((table (make-syntax-table)))
381 ;; Give punctuation syntax to ASCII that normally has symbol
382 ;; syntax or has word syntax and isn't a letter.
383 (let ((symbol (string-to-syntax "_"))
384 (sst (standard-syntax-table)))
385 (dotimes (i 128)
386 (unless (= i ?_)
387 (if (equal symbol (aref sst i))
388 (modify-syntax-entry i "." table)))))
389 (modify-syntax-entry ?$ "." table)
390 (modify-syntax-entry ?% "." table)
391 ;; exceptions
392 (modify-syntax-entry ?# "<" table)
393 (modify-syntax-entry ?\n ">" table)
394 (modify-syntax-entry ?' "\"" table)
395 (modify-syntax-entry ?` "$" table)
396 table)
397 "Syntax table for Python files.")
398
399(defvar python-dotty-syntax-table
400 (let ((table (make-syntax-table python-mode-syntax-table)))
401 (modify-syntax-entry ?. "w" table)
402 (modify-syntax-entry ?_ "w" table)
403 table)
404 "Dotty syntax table for Python files.
405It makes underscores and dots word constituent chars.")
406
407\f
408;;; Indentation
409
410(defcustom python-indent-offset 4
411 "Default indentation offset for Python."
412 :group 'python
413 :type 'integer
414 :safe 'integerp)
415
416(defcustom python-indent-guess-indent-offset t
417 "Non-nil tells Python mode to guess `python-indent-offset' value."
418 :type 'boolean
419 :group 'python)
420
421(defvar python-indent-current-level 0
422 "Current indentation level `python-indent-line-function' is using.")
423
424(defvar python-indent-levels '(0)
425 "Levels of indentation available for `python-indent-line-function'.")
426
427(defvar python-indent-dedenters '("else" "elif" "except" "finally")
428 "List of words that should be dedented.
429These make `python-indent-calculate-indentation' subtract the value of
430`python-indent-offset'.")
431
432(defun python-indent-guess-indent-offset ()
954aa7bd 433 "Guess and set `python-indent-offset' for the current buffer."
bbac1eb8
FEG
434 (save-excursion
435 (save-restriction
436 (widen)
437 (goto-char (point-min))
438 (let ((found-block))
439 (while (and (not found-block)
440 (re-search-forward
441 (python-rx line-start block-start) nil t))
442 (when (and (not (syntax-ppss-context (syntax-ppss)))
443 (progn
444 (goto-char (line-end-position))
445 (forward-comment -1)
446 (eq ?: (char-before))))
447 (setq found-block t)))
448 (if (not found-block)
449 (message "Can't guess python-indent-offset, using defaults: %s"
450 python-indent-offset)
451 (while (and (progn
452 (goto-char (line-end-position))
453 (python-info-continuation-line-p))
454 (not (eobp)))
455 (forward-line 1))
456 (forward-line 1)
457 (forward-comment 1)
14d9f80c
FEG
458 (let ((indent-offset (current-indentation)))
459 (when (> indent-offset 0)
460 (setq python-indent-offset indent-offset))))))))
45c138ac
FEG
461
462(defun python-indent-context (&optional stop)
463 "Return information on indentation context.
464Optional argument STOP serves to stop recursive calls.
465
466Returns a cons with the form:
467
468\(STATUS . START)
469
470Where status can be any of the following symbols:
471
472 * inside-paren: If point in between (), {} or []
473 * inside-string: If point is inside a string
474 * after-backslash: Previous line ends in a backslash
475 * after-beginning-of-block: Point is after beginning of block
476 * after-line: Point is after normal line
477 * no-indent: Point is at beginning of buffer or other special case
478
479START is the buffer position where the sexp starts."
480 (save-restriction
481 (widen)
482 (let ((ppss (save-excursion (beginning-of-line) (syntax-ppss)))
483 (start))
484 (cons
485 (cond
69bab1de 486 ;; Beginning of buffer
19b122e4
FEG
487 ((save-excursion
488 (goto-char (line-beginning-position))
489 (bobp))
69bab1de 490 'no-indent)
45c138ac
FEG
491 ;; Inside a paren
492 ((setq start (nth 1 ppss))
493 'inside-paren)
494 ;; Inside string
495 ((setq start (when (and (nth 3 ppss))
496 (nth 8 ppss)))
497 'inside-string)
498 ;; After backslash
499 ((setq start (when (not (syntax-ppss-context ppss))
500 (let ((line-beg-pos (line-beginning-position)))
501 (when (eq ?\\ (char-before (1- line-beg-pos)))
502 (- line-beg-pos 2)))))
503 'after-backslash)
504 ;; After beginning of block
505 ((setq start (save-excursion
506 (let ((block-regexp (python-rx block-start))
507 (block-start-line-end ":[[:space:]]*$"))
508 (back-to-indentation)
509 (while (and (forward-comment -1) (not (bobp))))
510 (back-to-indentation)
511 (when (or (python-info-continuation-line-p)
512 (and (not (looking-at block-regexp))
513 (save-excursion
514 (re-search-forward
515 block-start-line-end
516 (line-end-position) t))))
517 (while (and (forward-line -1)
518 (python-info-continuation-line-p)
519 (not (bobp))))
520 (when (not (looking-at block-regexp))
521 (forward-line 1)))
522 (back-to-indentation)
523 (when (and (looking-at block-regexp)
524 (or (re-search-forward
525 block-start-line-end
526 (line-end-position) t)
527 (python-info-continuation-line-p)))
528 (point-marker)))))
529 'after-beginning-of-block)
530 ;; After normal line
531 ((setq start (save-excursion
532 (while (and (forward-comment -1) (not (bobp))))
533 (while (and (not (back-to-indentation))
534 (not (bobp))
535 (if (> (nth 0 (syntax-ppss)) 0)
536 (forward-line -1)
537 (if (save-excursion
538 (forward-line -1)
539 (python-info-line-ends-backslash-p))
540 (forward-line -1)))))
541 (point-marker)))
542 'after-line)
543 ;; Do not indent
544 (t 'no-indent))
545 start))))
546
547(defun python-indent-calculate-indentation ()
548 "Calculate correct indentation offset for the current line."
549 (let* ((indentation-context (python-indent-context))
550 (context-status (car indentation-context))
551 (context-start (cdr indentation-context)))
552 (save-restriction
553 (widen)
554 (save-excursion
555 (case context-status
556 ('no-indent 0)
557 ('after-beginning-of-block
558 (goto-char context-start)
559 (+ (current-indentation) python-indent-offset))
560 ('after-line
561 (-
562 (save-excursion
563 (goto-char context-start)
564 (current-indentation))
565 (if (progn
566 (back-to-indentation)
567 (looking-at (regexp-opt python-indent-dedenters)))
568 python-indent-offset
569 0)))
570 ('inside-string
571 (goto-char context-start)
572 (current-indentation))
573 ('after-backslash
574 (let* ((block-continuation
575 (save-excursion
576 (forward-line -1)
577 (python-info-block-continuation-line-p)))
578 (assignment-continuation
579 (save-excursion
580 (forward-line -1)
581 (python-info-assignment-continuation-line-p)))
582 (indentation (cond (block-continuation
583 (goto-char block-continuation)
584 (re-search-forward
585 (python-rx block-start (* space))
586 (line-end-position) t)
587 (current-column))
588 (assignment-continuation
589 (goto-char assignment-continuation)
590 (re-search-forward
591 (python-rx simple-operator)
592 (line-end-position) t)
593 (forward-char 1)
594 (re-search-forward
595 (python-rx (* space))
596 (line-end-position) t)
597 (current-column))
598 (t
599 (goto-char context-start)
600 (current-indentation)))))
601 indentation))
602 ('inside-paren
17d13b85
FEG
603 (or (save-excursion
604 (forward-comment 1)
605 (looking-at (regexp-opt '(")" "]" "}")))
606 (forward-char 1)
607 (when (not (nth 1 (syntax-ppss)))
608 (goto-char context-start)
609 (back-to-indentation)
610 (current-column)))
611 (-
612 (save-excursion
613 (goto-char context-start)
614 (forward-char)
615 (save-restriction
616 (narrow-to-region
617 (line-beginning-position)
618 (line-end-position))
619 (forward-comment 1))
620 (if (looking-at "$")
621 (+ (current-indentation) python-indent-offset)
622 (forward-comment 1)
623 (current-column)))
624 (if (progn
625 (back-to-indentation)
626 (looking-at (regexp-opt '(")" "]" "}"))))
627 python-indent-offset
628 0)))))))))
45c138ac
FEG
629
630(defun python-indent-calculate-levels ()
631 "Calculate `python-indent-levels' and reset `python-indent-current-level'."
632 (let* ((indentation (python-indent-calculate-indentation))
633 (remainder (% indentation python-indent-offset))
634 (steps (/ (- indentation remainder) python-indent-offset)))
635 (setq python-indent-levels '())
636 (setq python-indent-levels (cons 0 python-indent-levels))
637 (dotimes (step steps)
638 (setq python-indent-levels
639 (cons (* python-indent-offset (1+ step)) python-indent-levels)))
640 (when (not (eq 0 remainder))
641 (setq python-indent-levels
642 (cons (+ (* python-indent-offset steps) remainder)
643 python-indent-levels)))
644 (setq python-indent-levels (nreverse python-indent-levels))
645 (setq python-indent-current-level (1- (length python-indent-levels)))))
646
647(defun python-indent-toggle-levels ()
648 "Toggle `python-indent-current-level' over `python-indent-levels'."
649 (setq python-indent-current-level (1- python-indent-current-level))
650 (when (< python-indent-current-level 0)
651 (setq python-indent-current-level (1- (length python-indent-levels)))))
652
653(defun python-indent-line (&optional force-toggle)
654 "Internal implementation of `python-indent-line-function'.
655
656Uses the offset calculated in
657`python-indent-calculate-indentation' and available levels
658indicated by the variable `python-indent-levels'.
659
660When the variable `last-command' is equal to
661`indent-for-tab-command' or FORCE-TOGGLE is non-nil:
662
663* Cycles levels indicated in the variable `python-indent-levels'
664 by setting the current level in the variable
665 `python-indent-current-level'.
666
667When the variable `last-command' is not equal to
668`indent-for-tab-command' and FORCE-TOGGLE is nil:
669
670* calculates possible indentation levels and saves it in the
671 variable `python-indent-levels'.
672
673* sets the variable `python-indent-current-level' correctly so
674 offset is equal to (`nth' `python-indent-current-level'
675 `python-indent-levels')"
676 (if (or (and (eq this-command 'indent-for-tab-command)
677 (eq last-command this-command))
678 force-toggle)
679 (python-indent-toggle-levels)
680 (python-indent-calculate-levels))
681 (beginning-of-line)
682 (delete-horizontal-space)
683 (indent-to (nth python-indent-current-level python-indent-levels))
684 (save-restriction
685 (widen)
686 (let ((closing-block-point (python-info-closing-block)))
687 (when closing-block-point
688 (message "Closes %s" (buffer-substring
689 closing-block-point
690 (save-excursion
691 (goto-char closing-block-point)
692 (line-end-position))))))))
693
694(defun python-indent-line-function ()
695 "`indent-line-function' for Python mode.
696Internally just calls `python-indent-line'."
697 (python-indent-line))
698
699(defun python-indent-dedent-line ()
700 "Dedent current line."
701 (interactive "*")
702 (when (and (not (syntax-ppss-context (syntax-ppss)))
703 (<= (point-marker) (save-excursion
704 (back-to-indentation)
705 (point-marker)))
706 (> (current-column) 0))
707 (python-indent-line t)
708 t))
709
710(defun python-indent-dedent-line-backspace (arg)
711 "Dedent current line.
712Argument ARG is passed to `backward-delete-char-untabify' when
713point is not in between the indentation."
714 (interactive "*p")
715 (when (not (python-indent-dedent-line))
716 (backward-delete-char-untabify arg)))
183f9296 717(put 'python-indent-dedent-line-backspace 'delete-selection 'supersede)
45c138ac
FEG
718
719(defun python-indent-region (start end)
720 "Indent a python region automagically.
721
722Called from a program, START and END specify the region to indent."
723 (save-excursion
724 (goto-char end)
725 (setq end (point-marker))
726 (goto-char start)
727 (or (bolp) (forward-line 1))
728 (while (< (point) end)
729 (or (and (bolp) (eolp))
730 (let (word)
731 (forward-line -1)
732 (back-to-indentation)
733 (setq word (current-word))
734 (forward-line 1)
735 (when word
736 (beginning-of-line)
737 (delete-horizontal-space)
738 (indent-to (python-indent-calculate-indentation)))))
739 (forward-line 1))
740 (move-marker end nil)))
741
742(defun python-indent-shift-left (start end &optional count)
743 "Shift lines contained in region START END by COUNT columns to the left.
744
745COUNT defaults to `python-indent-offset'.
746
747If region isn't active, the current line is shifted.
748
749The shifted region includes the lines in which START and END lie.
750
751An error is signaled if any lines in the region are indented less
752than COUNT columns."
753 (interactive
754 (if mark-active
755 (list (region-beginning) (region-end) current-prefix-arg)
756 (list (line-beginning-position) (line-end-position) current-prefix-arg)))
757 (if count
758 (setq count (prefix-numeric-value count))
759 (setq count python-indent-offset))
760 (when (> count 0)
761 (save-excursion
762 (goto-char start)
763 (while (< (point) end)
764 (if (and (< (current-indentation) count)
765 (not (looking-at "[ \t]*$")))
766 (error "Can't shift all lines enough"))
767 (forward-line))
768 (indent-rigidly start end (- count)))))
769
770(add-to-list 'debug-ignored-errors "^Can't shift all lines enough")
771
772(defun python-indent-shift-right (start end &optional count)
773 "Shift lines contained in region START END by COUNT columns to the left.
774
775COUNT defaults to `python-indent-offset'.
776
777If region isn't active, the current line is shifted.
778
779The shifted region includes the lines in which START and END
780lie."
781 (interactive
782 (if mark-active
783 (list (region-beginning) (region-end) current-prefix-arg)
784 (list (line-beginning-position) (line-end-position) current-prefix-arg)))
785 (if count
786 (setq count (prefix-numeric-value count))
787 (setq count python-indent-offset))
788 (indent-rigidly start end count))
789
ffdb56c3
FEG
790;; Directly from Dave Love's python.el
791(defun python-indent-electric-colon (arg)
792 "Insert a colon and maybe outdent the line if it is a statement like `else'.
793With numeric ARG, just insert that many colons. With \\[universal-argument],
794just insert a single colon."
795 (interactive "*P")
796 (self-insert-command (if (not (integerp arg)) 1 arg))
797 (and (not arg)
798 (eolp)
799 (not (nth 8 (syntax-ppss)))
76eefb1f 800 (> (current-indentation) (python-indent-calculate-indentation))
ffdb56c3
FEG
801 (save-excursion (python-indent-line))))
802(put 'python-indent-electric-colon 'delete-selection t)
803
45c138ac
FEG
804\f
805;;; Navigation
806
807(defvar python-beginning-of-defun-regexp
808 "^\\(def\\|class\\)[[:space:]]+[[:word:]]+"
809 "Regular expresion matching beginning of outermost class or function.")
810
811(defvar python-beginning-of-innermost-defun-regexp
812 "^[[:space:]]*\\(def\\|class\\)[[:space:]]+[[:word:]]+"
813 "Regular expresion matching beginning of innermost class or function.")
814
815(defun python-beginning-of-defun (&optional innermost)
816 "Move point to the beginning of innermost/outermost def or class.
817If INNERMOST is non-nil then move to the beginning of the
818innermost definition."
819 (let ((starting-point (point-marker))
820 (nonblank-line-indent)
821 (defun-indent)
822 (defun-point)
823 (regexp (if innermost
824 python-beginning-of-innermost-defun-regexp
825 python-beginning-of-defun-regexp)))
826 (back-to-indentation)
827 (if (and (not (looking-at "@"))
828 (not (looking-at regexp)))
829 (forward-comment -1)
830 (while (and (not (eobp))
831 (forward-line 1)
832 (not (back-to-indentation))
833 (looking-at "@"))))
834 (when (not (looking-at regexp))
835 (re-search-backward regexp nil t))
836 (setq nonblank-line-indent (+ (current-indentation) python-indent-offset))
837 (setq defun-indent (current-indentation))
838 (setq defun-point (point-marker))
839 (if (> nonblank-line-indent defun-indent)
840 (progn
841 (goto-char defun-point)
842 (forward-line -1)
843 (while (and (looking-at "@")
844 (forward-line -1)
845 (not (bobp))
846 (not (back-to-indentation))))
df700cc9
FEG
847 (unless (bobp)
848 (forward-line 1))
45c138ac
FEG
849 (point-marker))
850 (if innermost
851 (python-beginning-of-defun)
852 (goto-char starting-point)
853 nil))))
854
855(defun python-beginning-of-defun-function ()
856 "Move point to the beginning of outermost def or class.
857Returns nil if point is not in a def or class."
858 (python-beginning-of-defun nil))
859
860(defun python-beginning-of-innermost-defun ()
861 "Move point to the beginning of innermost def or class.
862Returns nil if point is not in a def or class."
863 (interactive)
864 (python-beginning-of-defun t))
865
866(defun python-end-of-defun-function ()
867 "Move point to the end of def or class.
868Returns nil if point is not in a def or class."
869 (let ((starting-point (point-marker))
870 (defun-regexp (python-rx defun))
871 (beg-defun-indent))
872 (back-to-indentation)
873 (if (looking-at "@")
874 (while (and (not (eobp))
875 (forward-line 1)
876 (not (back-to-indentation))
877 (looking-at "@")))
878 (while (and (not (bobp))
879 (not (progn (back-to-indentation) (current-word)))
880 (forward-line -1))))
881 (when (or (not (equal (current-indentation) 0))
882 (string-match defun-regexp (current-word)))
883 (setq beg-defun-indent (save-excursion
884 (or (looking-at defun-regexp)
885 (python-beginning-of-innermost-defun))
886 (current-indentation)))
887 (while (and (forward-line 1)
888 (not (eobp))
889 (or (not (current-word))
890 (> (current-indentation) beg-defun-indent))))
891 (while (and (forward-comment -1)
892 (not (bobp))))
893 (forward-line 1)
894 (point-marker))))
895
896\f
897;;; Shell integration
898
899(defvar python-shell-buffer-name "Python"
900 "Default buffer name for Python interpreter.")
901
902(defcustom python-shell-interpreter "python"
903 "Default Python interpreter for shell."
904 :group 'python
905 :type 'string
906 :safe 'stringp)
907
908(defcustom python-shell-interpreter-args "-i"
909 "Default arguments for the Python interpreter."
910 :group 'python
911 :type 'string
912 :safe 'stringp)
913
914(defcustom python-shell-prompt-regexp ">>> "
915 "Regex matching top\-level input prompt of python shell.
916The regex should not contain a caret (^) at the beginning."
917 :type 'string
918 :group 'python
919 :safe 'stringp)
920
921(defcustom python-shell-prompt-block-regexp "[.][.][.] "
922 "Regex matching block input prompt of python shell.
923The regex should not contain a caret (^) at the beginning."
924 :type 'string
925 :group 'python
926 :safe 'stringp)
927
928(defcustom python-shell-prompt-pdb-regexp "[(<]*[Ii]?[Pp]db[>)]+ "
929 "Regex matching pdb input prompt of python shell.
930The regex should not contain a caret (^) at the beginning."
931 :type 'string
932 :group 'python
933 :safe 'stringp)
934
935(defcustom python-shell-compilation-regexp-alist
936 `((,(rx line-start (1+ (any " \t")) "File \""
937 (group (1+ (not (any "\"<")))) ; avoid `<stdin>' &c
938 "\", line " (group (1+ digit)))
939 1 2)
940 (,(rx " in file " (group (1+ not-newline)) " on line "
941 (group (1+ digit)))
942 1 2)
943 (,(rx line-start "> " (group (1+ (not (any "(\"<"))))
944 "(" (group (1+ digit)) ")" (1+ (not (any "("))) "()")
945 1 2))
946 "`compilation-error-regexp-alist' for inferior Python."
947 :type '(alist string)
948 :group 'python)
949
950(defun python-shell-get-process-name (dedicated)
951 "Calculate the appropiate process name for inferior Python process.
952
953If DEDICATED is t and the variable `buffer-file-name' is non-nil
954returns a string with the form
955`python-shell-buffer-name'[variable `buffer-file-name'] else
956returns the value of `python-shell-buffer-name'.
957
958After calculating the process name add the buffer name for the
959process in the `same-window-buffer-names' list"
960 (let ((process-name
961 (if (and dedicated
962 buffer-file-name)
963 (format "%s[%s]" python-shell-buffer-name buffer-file-name)
964 (format "%s" python-shell-buffer-name))))
965 (add-to-list 'same-window-buffer-names (purecopy
966 (format "*%s*" process-name)))
967 process-name))
968
969(defun python-shell-parse-command ()
970 "Calculates the string used to execute the inferior Python process."
971 (format "%s %s" python-shell-interpreter python-shell-interpreter-args))
972
973(defun python-comint-output-filter-function (output)
974 "Hook run after content is put into comint buffer.
975OUTPUT is a string with the contents of the buffer."
976 (ansi-color-filter-apply output))
977
978(defvar inferior-python-mode-current-file nil
979 "Current file from which a region was sent.")
980(make-variable-buffer-local 'inferior-python-mode-current-file)
981
45c138ac
FEG
982(define-derived-mode inferior-python-mode comint-mode "Inferior Python"
983 "Major mode for Python inferior process."
984 (set-syntax-table python-mode-syntax-table)
985 (setq mode-line-process '(":%s"))
986 (setq comint-prompt-regexp (format "^\\(?:%s\\|%s\\|%s\\)"
987 python-shell-prompt-regexp
988 python-shell-prompt-block-regexp
989 python-shell-prompt-pdb-regexp))
990 (make-local-variable 'comint-output-filter-functions)
991 (add-hook 'comint-output-filter-functions
992 'python-comint-output-filter-function)
993 (add-hook 'comint-output-filter-functions
994 'python-pdbtrack-comint-output-filter-function)
995 (set (make-local-variable 'compilation-error-regexp-alist)
996 python-shell-compilation-regexp-alist)
ed0eb594
FEG
997 (define-key inferior-python-mode-map [remap complete-symbol]
998 'completion-at-point)
999 (add-hook 'completion-at-point-functions
1000 'python-shell-completion-complete-at-point nil 'local)
45c138ac
FEG
1001 (compilation-shell-minor-mode 1))
1002
1003(defun run-python (dedicated cmd)
1004 "Run an inferior Python process.
1005
1006Input and output via buffer *\\[python-shell-buffer-name]*.
1007
1008If there is a process already running in
1009*\\[python-shell-buffer-name]*, switch to that buffer.
1010
1011With argument, allows you to:
1012
1013 * Define DEDICATED so a dedicated process for the current buffer
1014 is open.
1015
1016 * Define CMD so you can edit the command used to call the
1017interpreter (default is value of `python-shell-interpreter' and
1018arguments defined in `python-shell-interpreter-args').
1019
1020Runs the hook `inferior-python-mode-hook' (after the
1021`comint-mode-hook' is run).
1022
1023\(Type \\[describe-mode] in the process buffer for a list of
1024commands.)"
1025 (interactive
1026 (if current-prefix-arg
1027 (list
1028 (y-or-n-p "Make dedicated process? ")
1029 (read-string "Run Python: " (python-shell-parse-command)))
1030 (list nil (python-shell-parse-command))))
1031 (let* ((proc-name (python-shell-get-process-name dedicated))
1032 (proc-buffer-name (format "*%s*" proc-name)))
1033 (when (not (comint-check-proc proc-buffer-name))
1034 (let ((cmdlist (split-string-and-unquote cmd)))
1035 (set-buffer
1036 (apply 'make-comint proc-name (car cmdlist) nil
1037 (cdr cmdlist)))
1038 (inferior-python-mode)))
1039 (pop-to-buffer proc-buffer-name))
1040 dedicated)
1041
1042(defun python-shell-get-process ()
1043 "Get inferior Python process for current buffer and return it."
1044 (let* ((dedicated-proc-name (python-shell-get-process-name t))
1045 (dedicated-proc-buffer-name (format "*%s*" dedicated-proc-name))
1046 (global-proc-name (python-shell-get-process-name nil))
1047 (global-proc-buffer-name (format "*%s*" global-proc-name))
1048 (dedicated-running (comint-check-proc dedicated-proc-buffer-name))
1049 (global-running (comint-check-proc global-proc-buffer-name)))
1050 ;; Always prefer dedicated
1051 (get-buffer-process (or (and dedicated-running dedicated-proc-buffer-name)
1052 (and global-running global-proc-buffer-name)))))
1053
1054(defun python-shell-get-or-create-process ()
1055 "Get or create an inferior Python process for current buffer and return it."
79dafa51
FEG
1056 (let* ((old-buffer (current-buffer))
1057 (dedicated-proc-name (python-shell-get-process-name t))
45c138ac
FEG
1058 (dedicated-proc-buffer-name (format "*%s*" dedicated-proc-name))
1059 (global-proc-name (python-shell-get-process-name nil))
1060 (global-proc-buffer-name (format "*%s*" global-proc-name))
1061 (dedicated-running (comint-check-proc dedicated-proc-buffer-name))
1062 (global-running (comint-check-proc global-proc-buffer-name))
1063 (current-prefix-arg 4))
1064 (when (and (not dedicated-running) (not global-running))
1065 (if (call-interactively 'run-python)
1066 (setq dedicated-running t)
1067 (setq global-running t)))
1068 ;; Always prefer dedicated
79dafa51 1069 (switch-to-buffer old-buffer)
45c138ac
FEG
1070 (get-buffer-process (if dedicated-running
1071 dedicated-proc-buffer-name
1072 global-proc-buffer-name))))
1073
13d914ed 1074(defun python-shell-send-string (string &optional process)
138df813 1075 "Send STRING to inferior Python PROCESS."
45c138ac 1076 (interactive "sPython command: ")
13d914ed 1077 (let ((process (or process (python-shell-get-or-create-process))))
fc87f759 1078 (when (called-interactively-p 'interactive)
13d914ed 1079 (message (format "Sent: %s..." string)))
45c138ac
FEG
1080 (comint-send-string process string)
1081 (when (or (not (string-match "\n$" string))
1082 (string-match "\n[ \t].*\n?$" string))
1083 (comint-send-string process "\n"))))
1084
1085(defun python-shell-send-region (start end)
1086 "Send the region delimited by START and END to inferior Python process."
1087 (interactive "r")
1088 (let* ((contents (buffer-substring start end))
1089 (current-file (buffer-file-name))
1090 (process (python-shell-get-or-create-process))
24b68537 1091 (temp-file (make-temp-file "py")))
45c138ac
FEG
1092 (with-temp-file temp-file
1093 (insert contents)
1094 (delete-trailing-whitespace)
1095 (goto-char (point-min))
1096 (message (format "Sent: %s..."
1097 (buffer-substring (point-min)
1098 (line-end-position)))))
d439cda5 1099 (python-shell-send-file current-file process temp-file)))
45c138ac
FEG
1100
1101(defun python-shell-send-buffer ()
1102 "Send the entire buffer to inferior Python process."
1103 (interactive)
1104 (save-restriction
1105 (widen)
1106 (python-shell-send-region (point-min) (point-max))))
1107
1108(defun python-shell-send-defun (arg)
1109 "Send the (inner|outer)most def or class to inferior Python process.
1110When argument ARG is non-nil sends the innermost defun."
1111 (interactive "P")
1112 (save-excursion
1113 (python-shell-send-region (progn
1114 (or (if arg
1115 (python-beginning-of-innermost-defun)
1116 (python-beginning-of-defun-function))
1117 (progn (beginning-of-line) (point-marker))))
1118 (progn
1119 (or (python-end-of-defun-function)
1120 (progn (end-of-line) (point-marker)))))))
1121
d439cda5
FEG
1122(defun python-shell-send-file (file-name &optional process temp-file-name)
1123 "Send FILE-NAME to inferior Python PROCESS.
1124If TEMP-FILE-NAME is passed then that file is used for processing
1125instead, while internally the shell will continue to use
1126FILE-NAME."
45c138ac 1127 (interactive "fFile to send: ")
b962ebad 1128 (let ((process (or process (python-shell-get-or-create-process)))
24b68537 1129 (file-name (expand-file-name file-name))
d439cda5 1130 (temp-file-name (when temp-file-name
24b68537 1131 (expand-file-name temp-file-name))))
d439cda5
FEG
1132 (find-file-noselect file-name)
1133 (with-current-buffer (process-buffer process)
24b68537
FEG
1134 (setq inferior-python-mode-current-file
1135 (convert-standard-filename file-name)))
13d914ed 1136 (python-shell-send-string
b962ebad 1137 (format
d439cda5
FEG
1138 (concat "__pyfile = open('''%s''');"
1139 "exec(compile(__pyfile.read(), '''%s''', 'exec'));"
1140 "__pyfile.close()")
1141 (or temp-file-name file-name) file-name)
13d914ed 1142 process)))
45c138ac 1143
138df813
FEG
1144(defun python-shell-clear-latest-output ()
1145 "Clear latest output from the Python shell.
1146Return the cleaned output."
1147 (interactive)
1148 (when (and comint-last-output-start
1149 comint-last-prompt-overlay)
1150 (save-excursion
1151 (let* ((last-output-end
1152 (save-excursion
1153 (goto-char
1154 (overlay-start comint-last-prompt-overlay))
1155 (forward-comment -1)
1156 (point-marker)))
1157 (last-output
1158 (buffer-substring-no-properties
1159 comint-last-output-start last-output-end)))
1160 (when (< 0 (length last-output))
1161 (goto-char comint-last-output-start)
1162 (delete-region comint-last-output-start last-output-end)
1163 (delete-char -1)
1164 last-output)))))
1165
1166(defun python-shell-send-and-clear-output (string process)
1167 "Send STRING to PROCESS and clear the output.
1168Return the cleaned output."
1169 (interactive)
1170 (python-shell-send-string string process)
1171 (accept-process-output process)
1172 (with-current-buffer (process-buffer process)
1173 (let ((output (python-shell-clear-latest-output)))
1174 (forward-line -1)
1175 (kill-whole-line)
1176 (goto-char (overlay-end comint-last-prompt-overlay))
1177 output)))
1178
45c138ac
FEG
1179(defun python-shell-switch-to-shell ()
1180 "Switch to inferior Python process buffer."
1181 (interactive)
1182 (pop-to-buffer (process-buffer (python-shell-get-or-create-process)) t))
1183
1184\f
1185;;; Shell completion
1186
1187(defvar python-shell-completion-setup-code
1188 "try:
1189 import readline
1190except ImportError:
1191 def __COMPLETER_all_completions(text): []
1192else:
1193 import rlcompleter
1194 readline.set_completer(rlcompleter.Completer().complete)
1195 def __COMPLETER_all_completions(text):
1196 import sys
1197 completions = []
1198 try:
1199 i = 0
1200 while True:
1201 res = readline.get_completer()(text, i)
1202 if not res: break
1203 i += 1
1204 completions.append(res)
1205 except NameError:
1206 pass
1207 return completions"
1208 "Code used to setup completion in inferior Python processes.")
1209
1210(defvar python-shell-completion-strings-code
1211 "';'.join(__COMPLETER_all_completions('''%s'''))\n"
1212 "Python code used to get a string of completions separated by semicolons.")
1213
1214(defun python-shell-completion-setup ()
1215 "Send `python-shell-completion-setup-code' to inferior Python process.
1216Also binds <tab> to `python-shell-complete-or-indent' in the
1217`inferior-python-mode-map' and adds
1218`python-shell-completion-complete-at-point' to the
1219`comint-dynamic-complete-functions' list.
1220It is specially designed to be added to the
1221`inferior-python-mode-hook'."
1222 (when python-shell-completion-setup-code
1223 (let ((temp-file (make-temp-file "py"))
1224 (process (get-buffer-process (current-buffer))))
1225 (with-temp-file temp-file
1226 (insert python-shell-completion-setup-code)
1227 (delete-trailing-whitespace)
1228 (goto-char (point-min)))
66b0b492 1229 (python-shell-send-file temp-file process)
45c138ac
FEG
1230 (message (format "Completion setup code sent.")))
1231 (add-to-list (make-local-variable
1232 'comint-dynamic-complete-functions)
1233 'python-shell-completion-complete-at-point)
1234 (define-key inferior-python-mode-map (kbd "<tab>")
1235 'python-shell-completion-complete-or-indent)))
1236
075a0f61
FEG
1237(defun python-shell-completion--get-completions (input process)
1238 "Retrieve available completions for INPUT using PROCESS."
1239 (with-current-buffer (process-buffer process)
138df813
FEG
1240 (split-string
1241 (or (python-shell-send-and-clear-output
1242 (format python-shell-completion-strings-code input)
1243 process) "")
1244 ";\\|\"\\|'\\|(" t)))
075a0f61
FEG
1245
1246(defun python-shell-completion--get-completion (input completions)
1247 "Get completion for INPUT using COMPLETIONS."
1248 (let ((completion (when completions
1249 (try-completion input completions))))
1250 (cond ((eq completion t)
1251 input)
1252 ((null completion)
1253 (message "Can't find completion for \"%s\"" input)
1254 (ding)
1255 input)
1256 ((not (string= input completion))
1257 completion)
1258 (t
1259 (message "Making completion list...")
1260 (with-output-to-temp-buffer "*Python Completions*"
1261 (display-completion-list
1262 (all-completions input completions)))
1263 input))))
1264
45c138ac
FEG
1265(defun python-shell-completion-complete-at-point ()
1266 "Perform completion at point in inferior Python process."
1267 (interactive)
3d6913c7
FEG
1268 (with-syntax-table python-dotty-syntax-table
1269 (when (and comint-last-prompt-overlay
1270 (> (point-marker) (overlay-end comint-last-prompt-overlay)))
1271 (let* ((process (get-buffer-process (current-buffer)))
075a0f61
FEG
1272 (input (substring-no-properties
1273 (or (comint-word (current-word)) "") nil nil)))
1274 (delete-char (- (length input)))
1275 (insert
1276 (python-shell-completion--get-completion
1277 input (python-shell-completion--get-completions input process)))))))
45c138ac 1278
45c138ac
FEG
1279(defun python-shell-completion-complete-or-indent ()
1280 "Complete or indent depending on the context.
1281If content before pointer is all whitespace indent. If not try to
1282complete."
1283 (interactive)
1284 (if (string-match "^[[:space:]]*$"
1285 (buffer-substring (comint-line-beginning-position)
1286 (point-marker)))
1287 (indent-for-tab-command)
1288 (comint-dynamic-complete)))
1289
1290(add-hook 'inferior-python-mode-hook
1291 #'python-shell-completion-setup)
1292
1293\f
1294;;; PDB Track integration
1295
1296(defvar python-pdbtrack-stacktrace-info-regexp
1297 "> %s(\\([0-9]+\\))\\([?a-zA-Z0-9_<>]+\\)()"
1298 "Regexp matching stacktrace information.
1299It is used to extract the current line and module beign
1300inspected.
1301The regexp should not start with a caret (^) and can contain a
1302string placeholder (\%s) which is replaced with the filename
1303beign inspected (so other files in the debugging process are not
1304opened)")
1305
1306(defvar python-pdbtrack-tracking-buffers '()
1307 "Alist containing elements of form (#<buffer> . #<buffer>).
1308The car of each element of the alist is the tracking buffer and
1309the cdr is the tracked buffer.")
1310
1311(defun python-pdbtrack-get-or-add-tracking-buffers ()
1312 "Get/Add a tracked buffer for the current buffer.
1313Internally it uses the `python-pdbtrack-tracking-buffers' alist.
1314Returns a cons with the form:
1315 * (#<tracking buffer> . #< tracked buffer>)."
1316 (or
1317 (assq (current-buffer) python-pdbtrack-tracking-buffers)
1318 (let* ((file (with-current-buffer (current-buffer)
d439cda5 1319 inferior-python-mode-current-file))
45c138ac
FEG
1320 (tracking-buffers
1321 `(,(current-buffer) .
1322 ,(or (get-file-buffer file)
1323 (find-file-noselect file)))))
1324 (set-buffer (cdr tracking-buffers))
1325 (python-mode)
1326 (set-buffer (car tracking-buffers))
1327 (setq python-pdbtrack-tracking-buffers
1328 (cons tracking-buffers python-pdbtrack-tracking-buffers))
1329 tracking-buffers)))
1330
1331(defun python-pdbtrack-comint-output-filter-function (output)
1332 "Move overlay arrow to current pdb line in tracked buffer.
1333Argument OUTPUT is a string with the output from the comint process."
1334 (when (not (string= output ""))
1335 (let ((full-output (ansi-color-filter-apply
1336 (buffer-substring comint-last-input-end
1337 (point-max)))))
1338 (if (string-match python-shell-prompt-pdb-regexp full-output)
1339 (let* ((tracking-buffers (python-pdbtrack-get-or-add-tracking-buffers))
1340 (line-num
1341 (save-excursion
1342 (string-match
1343 (format python-pdbtrack-stacktrace-info-regexp
1344 (regexp-quote
d439cda5 1345 inferior-python-mode-current-file))
45c138ac
FEG
1346 full-output)
1347 (string-to-number (or (match-string-no-properties 1 full-output) ""))))
1348 (tracked-buffer-window (get-buffer-window (cdr tracking-buffers)))
1349 (tracked-buffer-line-pos))
1350 (when line-num
1351 (with-current-buffer (cdr tracking-buffers)
1352 (set (make-local-variable 'overlay-arrow-string) "=>")
1353 (set (make-local-variable 'overlay-arrow-position) (make-marker))
1354 (setq tracked-buffer-line-pos (progn
1355 (goto-char (point-min))
1356 (forward-line (1- line-num))
1357 (point-marker)))
1358 (when tracked-buffer-window
1359 (set-window-point tracked-buffer-window tracked-buffer-line-pos))
1360 (set-marker overlay-arrow-position tracked-buffer-line-pos)))
1361 (pop-to-buffer (cdr tracking-buffers))
1362 (switch-to-buffer-other-window (car tracking-buffers)))
1363 (let ((tracking-buffers (assq (current-buffer)
1364 python-pdbtrack-tracking-buffers)))
1365 (when tracking-buffers
1366 (if inferior-python-mode-current-file
1367 (with-current-buffer (cdr tracking-buffers)
1368 (set-marker overlay-arrow-position nil))
1369 (kill-buffer (cdr tracking-buffers)))
1370 (setq python-pdbtrack-tracking-buffers
1371 (assq-delete-all (current-buffer)
1372 python-pdbtrack-tracking-buffers)))))))
1373 output)
1374
1375\f
1376;;; Symbol completion
1377
1378(defun python-completion-complete-at-point ()
1379 "Complete current symbol at point.
1380For this to work the best as possible you should call
1381`python-shell-send-buffer' from time to time so context in
1382inferior python process is updated properly."
1383 (interactive)
1384 (let ((process (python-shell-get-process)))
1385 (if (not process)
4e531f7a 1386 (error "Completion needs an inferior Python process running")
075a0f61
FEG
1387 (with-syntax-table python-dotty-syntax-table
1388 (let* ((input (substring-no-properties
1389 (or (comint-word (current-word)) "") nil nil))
1390 (completions (python-shell-completion--get-completions
1391 input process)))
1392 (delete-char (- (length input)))
1393 (insert
1394 (python-shell-completion--get-completion
1395 input completions)))))))
45c138ac
FEG
1396
1397(add-to-list 'debug-ignored-errors "^Completion needs an inferior Python process running.")
1398
1399\f
1400;;; Fill paragraph
1401
1402(defun python-fill-paragraph-function (&optional justify)
1403 "`fill-paragraph-function' handling multi-line strings and possibly comments.
1404If any of the current line is in or at the end of a multi-line string,
1405fill the string or the paragraph of it that point is in, preserving
4e531f7a
FEG
1406the string's indentation.
1407Optional argument JUSTIFY defines if the paragraph should be justified."
45c138ac
FEG
1408 (interactive "P")
1409 (save-excursion
1410 (back-to-indentation)
1411 (cond
1412 ;; Comments
1413 ((fill-comment-paragraph justify))
1414 ;; Docstrings
1415 ((save-excursion (skip-chars-forward "\"'uUrR")
1416 (nth 3 (syntax-ppss)))
1417 (let ((marker (point-marker))
1418 (string-start-marker
1419 (progn
1420 (skip-chars-forward "\"'uUrR")
1421 (goto-char (nth 8 (syntax-ppss)))
1422 (skip-chars-forward "\"'uUrR")
1423 (point-marker)))
1424 (reg-start (line-beginning-position))
1425 (string-end-marker
1426 (progn
1427 (while (nth 3 (syntax-ppss)) (goto-char (1+ (point-marker))))
1428 (skip-chars-backward "\"'")
1429 (point-marker)))
1430 (reg-end (line-end-position))
1431 (fill-paragraph-function))
1432 (save-restriction
1433 (narrow-to-region reg-start reg-end)
1434 (save-excursion
1435 (goto-char string-start-marker)
1436 (delete-region (point-marker) (progn
1437 (skip-syntax-forward "> ")
1438 (point-marker)))
1439 (goto-char string-end-marker)
1440 (delete-region (point-marker) (progn
1441 (skip-syntax-backward "> ")
1442 (point-marker)))
1443 (save-excursion
1444 (goto-char marker)
1445 (fill-paragraph justify))
1446 ;; If there is a newline in the docstring lets put triple
1447 ;; quote in it's own line to follow pep 8
1448 (when (save-excursion
1449 (re-search-backward "\n" string-start-marker t))
1450 (newline)
1451 (newline-and-indent))
1452 (fill-paragraph justify)))) t)
1453 ;; Decorators
1454 ((equal (char-after (save-excursion
1455 (back-to-indentation)
1456 (point-marker))) ?@) t)
1457 ;; Parens
1458 ((or (> (nth 0 (syntax-ppss)) 0)
1459 (looking-at (python-rx open-paren))
1460 (save-excursion
1461 (skip-syntax-forward "^(" (line-end-position))
1462 (looking-at (python-rx open-paren))))
1463 (save-restriction
1464 (narrow-to-region (progn
1465 (while (> (nth 0 (syntax-ppss)) 0)
1466 (goto-char (1- (point-marker))))
1467 (point-marker)
1468 (line-beginning-position))
1469 (progn
1470 (when (not (> (nth 0 (syntax-ppss)) 0))
1471 (end-of-line)
1472 (when (not (> (nth 0 (syntax-ppss)) 0))
1473 (skip-syntax-backward "^)")))
1474 (while (> (nth 0 (syntax-ppss)) 0)
1475 (goto-char (1+ (point-marker))))
1476 (point-marker)))
1477 (let ((paragraph-start "\f\\|[ \t]*$")
1478 (paragraph-separate ",")
1479 (fill-paragraph-function))
1480 (goto-char (point-min))
1481 (fill-paragraph justify))
1482 (while (not (eobp))
1483 (forward-line 1)
1484 (python-indent-line)
1485 (goto-char (line-end-position)))) t)
1486 (t t))))
1487
1488\f
046428d3
FEG
1489;;; FFAP
1490
1491(defvar python-ffap-setup-code
1492 "def __FFAP_get_module_path(module):
1493 try:
1494 import os
1495 path = __import__(module).__file__
1496 if path[-4:] == '.pyc' and os.path.exists(path[0:-1]):
1497 path = path[:-1]
1498 return path
1499 except:
1500 return ''"
1501 "Python code to get a module path.")
1502
1503(defvar python-ffap-string-code
1504 "__FFAP_get_module_path('''%s''')\n"
1505 "Python code used to get a string with the path of a module.")
1506
1507(defun python-ffap-setup ()
1508 "Send `python-ffap-setup-code' to inferior Python process.
1509It is specially designed to be added to the
1510`inferior-python-mode-hook'."
1511 (when python-ffap-setup-code
1512 (let ((temp-file (make-temp-file "py")))
1513 (with-temp-file temp-file
1514 (insert python-ffap-setup-code)
1515 (delete-trailing-whitespace)
1516 (goto-char (point-min)))
1517 (python-shell-send-file temp-file (get-buffer-process (current-buffer)))
1518 (message (format "FFAP setup code sent.")))))
1519
1520(defun python-ffap-module-path (module)
1521 "Function for `ffap-alist' to return path for MODULE."
1522 (let ((process (or
1523 (and (eq major-mode 'inferior-python-mode)
1524 (get-buffer-process (current-buffer)))
1525 (python-shell-get-process))))
1526 (if (not process)
1527 nil
1528 (let ((module-file
1529 (python-shell-send-and-clear-output
1530 (format python-ffap-string-code module) process)))
1531 (when module-file
2947016a 1532 (substring-no-properties module-file 1 -1))))))
046428d3
FEG
1533
1534(eval-after-load "ffap"
1535 '(progn
1536 (push '(python-mode . python-ffap-module-path) ffap-alist)
1537 (push '(inferior-python-mode . python-ffap-module-path) ffap-alist)))
1538
1539(add-hook 'inferior-python-mode-hook
1540 #'python-ffap-setup)
1541
1542\f
8b3e0e76
FEG
1543;;; Code check
1544
1545(defvar python-check-command
1546 "pychecker --stdlib"
1547 "Command used to check a Python file.")
1548
1549(defvar python-check-custom-command nil
1550 "Internal use.")
1551
1552(defun python-check (command)
1553 "Check a Python file (default current buffer's file).
1554Runs COMMAND, a shell command, as if by `compile'. See
1555`python-check-command' for the default."
1556 (interactive
1557 (list (read-string "Check command: "
1558 (or python-check-custom-command
1559 (concat python-check-command " "
1560 (shell-quote-argument
1561 (or
1562 (let ((name (buffer-file-name)))
1563 (and name
1564 (file-name-nondirectory name)))
1565 "")))))))
1566 (setq python-check-custom-command command)
1567 (save-some-buffers (not compilation-ask-about-save) nil)
1568 (compilation-start command))
1569
1570\f
45c138ac
FEG
1571;;; Eldoc
1572
1573(defvar python-eldoc-setup-code
1574 "def __PYDOC_get_help(obj):
1575 try:
1576 import pydoc
9e662938
FEG
1577 if hasattr(obj, 'startswith'):
1578 obj = eval(obj, globals())
1579 doc = pydoc.getdoc(obj)
45c138ac 1580 except:
9e662938
FEG
1581 doc = ''
1582 try:
1583 exec('print doc')
1584 except SyntaxError:
1585 print(doc)"
45c138ac
FEG
1586 "Python code to setup documentation retrieval.")
1587
1588(defvar python-eldoc-string-code
9e662938 1589 "__PYDOC_get_help('''%s''')\n"
45c138ac
FEG
1590 "Python code used to get a string with the documentation of an object.")
1591
1592(defun python-eldoc-setup ()
1593 "Send `python-eldoc-setup-code' to inferior Python process.
1594It is specially designed to be added to the
1595`inferior-python-mode-hook'."
1596 (when python-eldoc-setup-code
1597 (let ((temp-file (make-temp-file "py")))
1598 (with-temp-file temp-file
1599 (insert python-eldoc-setup-code)
1600 (delete-trailing-whitespace)
1601 (goto-char (point-min)))
66b0b492 1602 (python-shell-send-file temp-file (get-buffer-process (current-buffer)))
046428d3 1603 (message (format "Eldoc setup code sent.")))))
45c138ac 1604
78334b43 1605(defun python-eldoc--get-doc-at-point (&optional force-input force-process)
d439cda5
FEG
1606 "Internal implementation to get documentation at point.
1607If not FORCE-INPUT is passed then what `current-word' returns
1608will be used. If not FORCE-PROCESS is passed what
1609`python-shell-get-process' returns is used."
78334b43 1610 (let ((process (or force-process (python-shell-get-process))))
45c138ac
FEG
1611 (if (not process)
1612 "Eldoc needs an inferior Python process running."
1613 (let* ((current-defun (python-info-current-defun))
78334b43
FEG
1614 (input (or force-input
1615 (with-syntax-table python-dotty-syntax-table
1616 (if (not current-defun)
1617 (current-word)
1618 (concat current-defun "." (current-word))))))
45c138ac
FEG
1619 (ppss (syntax-ppss))
1620 (help (when (and input
1621 (not (string= input (concat current-defun ".")))
1622 (eq nil (nth 3 ppss))
1623 (eq nil (nth 4 ppss)))
1624 (when (string-match (concat
1625 (regexp-quote (concat current-defun "."))
1626 "self\\.") input)
1627 (with-temp-buffer
1628 (insert input)
1629 (goto-char (point-min))
1630 (forward-word)
1631 (forward-char)
1632 (delete-region (point-marker) (search-forward "self."))
1633 (setq input (buffer-substring (point-min) (point-max)))))
1066882c
FEG
1634 (python-shell-send-and-clear-output
1635 (format python-eldoc-string-code input) process))))
45c138ac
FEG
1636 (with-current-buffer (process-buffer process)
1637 (when comint-last-prompt-overlay
1638 (delete-region comint-last-input-end
1639 (overlay-start comint-last-prompt-overlay))))
1640 (when (and help
1641 (not (string= help "\n")))
1642 help)))))
1643
78334b43
FEG
1644(defun python-eldoc-function ()
1645 "`eldoc-documentation-function' for Python.
1646For this to work the best as possible you should call
1647`python-shell-send-buffer' from time to time so context in
1648inferior python process is updated properly."
1649 (python-eldoc--get-doc-at-point))
1650
1651(defun python-eldoc-at-point (symbol)
1652 "Get help on SYMBOL using `help'.
1653Interactively, prompt for symbol."
1654 (interactive
1655 (let ((symbol (with-syntax-table python-dotty-syntax-table
1656 (current-word)))
1657 (enable-recursive-minibuffers t))
1658 (list (read-string (if symbol
1659 (format "Describe symbol (default %s): " symbol)
1660 "Describe symbol: ")
1661 nil nil symbol))))
1662 (let ((process (python-shell-get-process)))
1663 (if (not process)
1664 (message "Eldoc needs an inferior Python process running.")
1665 (let ((temp-buffer-show-hook
1666 (lambda ()
1667 (toggle-read-only 1)
1668 (setq view-return-to-alist
1669 (list (cons (selected-window) help-return-method))))))
1670 (with-output-to-temp-buffer (help-buffer)
1671 (with-current-buffer standard-output
1672 (insert
1673 (python-eldoc--get-doc-at-point symbol process))
1674 (help-print-return-message)))))))
1675
45c138ac
FEG
1676(add-hook 'inferior-python-mode-hook
1677 #'python-eldoc-setup)
1678
1679\f
1680;;; Misc helpers
1681
1682(defun python-info-current-defun ()
1683 "Return name of surrounding function with Python compatible dotty syntax.
1684This function is compatible to be used as
1685`add-log-current-defun-function' since it returns nil if point is
1686not inside a defun."
1687 (let ((names '()))
1688 (save-restriction
1689 (widen)
1690 (save-excursion
1691 (beginning-of-line)
1692 (when (not (>= (current-indentation) python-indent-offset))
1693 (while (and (not (eobp)) (forward-comment 1))))
1694 (while (and (not (equal 0 (current-indentation)))
1695 (python-beginning-of-innermost-defun))
1696 (back-to-indentation)
1697 (looking-at "\\(?:def\\|class\\) +\\([^(]+\\)[^:]+:\\s-*\n")
1698 (setq names (cons (match-string-no-properties 1) names)))))
1699 (when names
1700 (mapconcat (lambda (string) string) names "."))))
1701
1702(defun python-info-closing-block ()
1703 "Return the point of the block that the current line closes."
1704 (let ((closing-word (save-excursion
1705 (back-to-indentation)
1706 (current-word)))
1707 (indentation (current-indentation)))
1708 (when (member closing-word python-indent-dedenters)
1709 (save-excursion
1710 (forward-line -1)
1711 (while (and (> (current-indentation) indentation)
1712 (not (bobp))
1713 (not (back-to-indentation))
1714 (forward-line -1)))
1715 (back-to-indentation)
1716 (cond
1717 ((not (equal indentation (current-indentation))) nil)
1718 ((string= closing-word "elif")
1719 (when (member (current-word) '("if" "elif"))
1720 (point-marker)))
1721 ((string= closing-word "else")
1722 (when (member (current-word) '("if" "elif" "except" "for" "while"))
1723 (point-marker)))
1724 ((string= closing-word "except")
1725 (when (member (current-word) '("try"))
1726 (point-marker)))
1727 ((string= closing-word "finally")
1728 (when (member (current-word) '("except" "else"))
1729 (point-marker))))))))
1730
1731(defun python-info-line-ends-backslash-p ()
1732 "Return non-nil if current line ends with backslash."
1733 (string= (or (ignore-errors
1734 (buffer-substring
1735 (line-end-position)
1736 (- (line-end-position) 1))) "") "\\"))
1737
1738(defun python-info-continuation-line-p ()
1739 "Return non-nil if current line is continuation of another."
1740 (or (python-info-line-ends-backslash-p)
1741 (string-match ",[[:space:]]*$" (buffer-substring
1742 (line-beginning-position)
1743 (line-end-position)))
1744 (save-excursion
1745 (let ((innermost-paren (progn
1746 (goto-char (line-end-position))
1747 (nth 1 (syntax-ppss)))))
1748 (when (and innermost-paren
1749 (and (<= (line-beginning-position) innermost-paren)
1750 (>= (line-end-position) innermost-paren)))
1751 (goto-char innermost-paren)
1752 (looking-at (python-rx open-paren (* space) line-end)))))
1753 (save-excursion
1754 (back-to-indentation)
1755 (nth 1 (syntax-ppss)))))
1756
1757(defun python-info-block-continuation-line-p ()
1758 "Return non-nil if current line is a continuation of a block."
1759 (save-excursion
1760 (while (and (not (bobp))
1761 (python-info-continuation-line-p))
1762 (forward-line -1))
1763 (forward-line 1)
1764 (back-to-indentation)
1765 (when (looking-at (python-rx block-start))
1766 (point-marker))))
1767
1768(defun python-info-assignment-continuation-line-p ()
1769 "Return non-nil if current line is a continuation of an assignment."
1770 (save-excursion
1771 (while (and (not (bobp))
1772 (python-info-continuation-line-p))
1773 (forward-line -1))
1774 (forward-line 1)
1775 (back-to-indentation)
1776 (when (and (not (looking-at (python-rx block-start)))
1777 (save-excursion
1778 (and (re-search-forward (python-rx not-simple-operator
1779 assignment-operator
1780 not-simple-operator)
1781 (line-end-position) t)
1782 (not (syntax-ppss-context (syntax-ppss))))))
1783 (point-marker))))
1784
1785\f
1786;;;###autoload
1787(define-derived-mode python-mode fundamental-mode "Python"
1788 "A major mode for editing Python files."
1789 (set (make-local-variable 'tab-width) 8)
1790 (set (make-local-variable 'indent-tabs-mode) nil)
1791
1792 (set (make-local-variable 'comment-start) "# ")
1793 (set (make-local-variable 'comment-start-skip) "#+\\s-*")
1794
1795 (set (make-local-variable 'parse-sexp-lookup-properties) t)
1796 (set (make-local-variable 'parse-sexp-ignore-comments) t)
1797
1798 (set (make-local-variable 'font-lock-defaults)
1799 '(python-font-lock-keywords
1800 nil nil nil nil
1801 (font-lock-syntactic-keywords . python-font-lock-syntactic-keywords)))
1802
1803 (set (make-local-variable 'indent-line-function) #'python-indent-line-function)
1804 (set (make-local-variable 'indent-region-function) #'python-indent-region)
1805
1806 (set (make-local-variable 'paragraph-start) "\\s-*$")
1807 (set (make-local-variable 'fill-paragraph-function) 'python-fill-paragraph-function)
1808
1809 (set (make-local-variable 'beginning-of-defun-function)
1810 #'python-beginning-of-defun-function)
1811 (set (make-local-variable 'end-of-defun-function)
1812 #'python-end-of-defun-function)
1813
1814 (add-hook 'completion-at-point-functions
1815 'python-completion-complete-at-point nil 'local)
1816
1817 (set (make-local-variable 'add-log-current-defun-function)
1818 #'python-info-current-defun)
1819
1820 (set (make-local-variable 'eldoc-documentation-function)
1821 #'python-eldoc-function)
1822
1823 (add-to-list 'hs-special-modes-alist
1824 `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#"
1825 ,(lambda (arg)
1826 (python-end-of-defun-function)) nil))
1827
1828 (set (make-local-variable 'outline-regexp)
1829 (python-rx (* space) block-start))
1830 (set (make-local-variable 'outline-heading-end-regexp) ":\\s-*\n")
1831 (set (make-local-variable 'outline-level)
1832 #'(lambda ()
1833 "`outline-level' function for Python mode."
1834 (1+ (/ (current-indentation) python-indent-offset))))
1835
1836 (when python-indent-guess-indent-offset
1837 (python-indent-guess-indent-offset)))
1838
1839
1840(provide 'python)
1841;;; python.el ends here