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