comparison lisp/progmodes/python.el @ 54789:9d1d7f062a4f

New file.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Mon, 12 Apr 2004 01:58:43 +0000
parents
children 6072018b576e
comparison
equal deleted inserted replaced
54788:8ef1dfe52aef 54789:9d1d7f062a4f
1 ;;; python.el --- silly walks for Python
2
3 ;; Copyright (C) 2003, 04 Free Software Foundation, Inc.
4
5 ;; Author: Dave Love <fx@gnu.org>
6 ;; Created: Nov 2003
7 ;; Keywords: languages
8
9 ;; This file is part of GNU Emacs.
10
11 ;; This file is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; This file is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to
23 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
25
26 ;;; Commentary:
27
28 ;; Major mode for editing Python, with support for inferior processes.
29
30 ;; There is another Python mode, python-mode.el, used by XEmacs and
31 ;; maintained with Python. That isn't covered by an FSF copyright
32 ;; assignment, unlike this code, and seems not to be well-maintained
33 ;; for Emacs (though I've submitted fixes). This mode is rather
34 ;; simpler and is, perhaps, better in other ways. In particular,
35 ;; using the syntax functions with text properties maintained by
36 ;; font-lock should make it more correct with arbitrary string and
37 ;; comment contents.
38
39 ;; This doesn't implement all the facilities of python-mode.el. Some
40 ;; just need doing, e.g. catching exceptions in the inferior Python
41 ;; buffer (but see M-x pdb for debugging). [Atually, the use of
42 ;; `compilation-minor-mode' now is probably enough for that.] Others
43 ;; don't seem appropriate. For instance, `forward-into-nomenclature'
44 ;; should be done separately, since it's not specific to Python, and
45 ;; I've installed a minor mode to do the job properly in Emacs 22.
46 ;; Other things seem more natural or canonical here, e.g. the
47 ;; {beginning,end}-of-defun implementation dealing with nested
48 ;; definitions, and the inferior mode following `cmuscheme'. (The
49 ;; inferior mode should be able to find the source of errors from
50 ;; `python-send-region' & al via `compilation-minor-mode', but I can't
51 ;; make that work with the current (March '04) compile.el.)
52 ;; Successive TABs cycle between possible indentations for the line.
53
54 ;; Even where it has similar facilities, this is incompatible with
55 ;; python-mode.el in various respects. For instance, various key
56 ;; bindings are changed to obey Emacs conventions, and things like
57 ;; marking blocks and `beginning-of-defun' behave differently.
58
59 ;;; Code:
60
61 (require 'syntax) ; ensure appropriate version
62 ;; It's messy to autoload the relevant comint functions so that comint
63 ;; is only required when inferior Python is used.
64 (require 'comint)
65
66 (defgroup python nil
67 "Silly walks in the Python language"
68 :group 'languages
69 :link '(emacs-commentary-link "python"))
70
71 ;;;###autoload
72 (add-to-list 'interpreter-mode-alist '("jython" . jython-mode))
73 ;;;###autoload
74 (add-to-list 'interpreter-mode-alist '("python" . python-mode))
75 ;;;###autoload
76 (add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode))
77
78 ;;;; Font lock
79
80 (defvar python-font-lock-keywords
81 `(,(rx (and word-start
82 ;; From v 2.3 reference.
83 ;; def and class dealt with separately below
84 (or "and" "assert" "break" "continue" "del" "elif" "else"
85 "except" "exec" "finally" "for" "from" "global" "if"
86 "import" "in" "is" "lambda" "not" "or" "pass" "print"
87 "raise" "return" "try" "while" "yield"
88 ;; Future keywords
89 "as" "None")
90 word-end))
91 (,(rx (and word-start (group "class") (1+ space) (group (1+ word))))
92 (1 font-lock-keyword-face) (2 font-lock-type-face))
93 (,(rx (and word-start (group "def") (1+ space) (group (1+ word))))
94 (1 font-lock-keyword-face) (2 font-lock-function-name-face))))
95
96 (defconst python-font-lock-syntactic-keywords
97 ;; Make outer chars of matching triple-quote sequences into generic
98 ;; string delimiters. Fixme: Is there a better way?
99 `((,(rx (and (group (optional (any "uUrR"))) ; prefix gets syntax property
100 (optional (any "rR")) ; possible second prefix
101 (group (syntax string-quote)) ; maybe gets property
102 (backref 2) ; per first quote
103 (group (backref 2)))) ; maybe gets property
104 (1 (python-quote-syntax 1)) (2 (python-quote-syntax 2))
105 (3 (python-quote-syntax 3)))
106 ;; This doesn't really help.
107 ;;; (,(rx (and ?\\ (group ?\n))) (1 " "))
108 ))
109
110 (defun python-quote-syntax (n)
111 "Put `syntax-table' property correctly on triple quote.
112 Used for syntactic keywords. N is the match number (1, 2 or 3)."
113 ;; Given a triple quote, we have to look backwards for a previous
114 ;; occurrence of the sequence to know whether this is an opening or
115 ;; closing triple. We also have to sort out a possible prefix --
116 ;; well, we don't _have_ to, but I think it should be treated as
117 ;; part of the string.
118 (let ((tag (save-excursion
119 (goto-char (match-beginning 0))
120 (unless (eq ?\\ (char-before))
121 (cond
122 ;; Look for a previous string fence.
123 ((or (zerop (skip-syntax-backward "^|"))
124 (bobp))
125 'start) ; no previous string fence
126 ;; Check fence on a matching quote.
127 ((eq (char-before) (char-after (match-beginning 2)))
128 (if (eq (char-before) (char-after))
129 'end ; fence ended string
130 'start)) ; began string
131 ;; Check for matching prefixed string.
132 ((and (memq (char-before) '(?u ?U ?r ?R))
133 (skip-chars-forward "rR"))
134 (if (eq (char-after) (char-after (match-beginning 2)))
135 'end)) ; else non-matching: return nil
136 ;; For non-matching quote, start new string.
137 ((/= (char-before) (char-after))
138 'start))))))
139 (if (if (eq tag 'start) ; Maybe starts a new string.
140 ;; Initial property if this is the prefix (empty or not) or
141 ;; isn't the prefix and the prefix is empty.
142 (or (= n 1) (and (= n 2) (= (match-beginning 1) (match-end 1))))
143 (and (eq tag 'end) ; Maybe ends existing string.
144 (= n 3))) ; Match is at end.
145 (eval-when-compile (string-to-syntax "|"))
146 ;; Otherwise the property is nil, which is OK.
147 )))
148
149 ;; This isn't currently in `font-lock-defaults' as probably not worth
150 ;; it -- we basically only mess with a few normally-symbol characters.
151
152 ;; (defun python-font-lock-syntactic-face-function (state)
153 ;; "`font-lock-syntactic-face-function' for Python mode.
154 ;; Returns the string or comment face as usual, with side effect of putting
155 ;; a `syntax-table' property on the inside of the string or comment which is
156 ;; the standard syntax table."
157 ;; (if (nth 3 state)
158 ;; (save-excursion
159 ;; (goto-char (nth 8 state))
160 ;; (condition-case nil
161 ;; (forward-sexp)
162 ;; (error nil))
163 ;; (put-text-property (1+ (nth 8 state)) (1- (point))
164 ;; 'syntax-table (standard-syntax-table))
165 ;; 'font-lock-string-face)
166 ;; (put-text-property (1+ (nth 8 state)) (line-end-position)
167 ;; 'syntax-table (standard-syntax-table))
168 ;; 'font-lock-comment-face))
169
170 ;;;; Keymap and syntax
171
172 (defvar python-mode-map
173 (let ((map (make-sparse-keymap)))
174 ;; Mostly taken from python-mode.el.
175 (define-key map ":" 'python-electric-colon)
176 (define-key map "\177" 'python-backspace)
177 (define-key map "\C-c<" 'python-shift-left)
178 (define-key map "\C-c>" 'python-shift-right)
179 (define-key map "\C-c\C-k" 'python-mark-block)
180 (define-key map "\C-c\C-n" 'python-next-statement)
181 (define-key map "\C-c\C-p" 'python-previous-statement)
182 (define-key map "\C-c\C-u" 'python-beginning-of-block)
183 (define-key map "\C-c\C-f" 'python-describe-symbol)
184 (define-key map "\C-c\C-w" 'python-check)
185 (define-key map "\C-c\C-v" 'python-check) ; a la sgml-mode
186 (define-key map "\C-c\C-s" 'python-send-string)
187 (define-key map [?\C-\M-x] 'python-send-defun)
188 (define-key map "\C-c\C-r" 'python-send-region)
189 (define-key map "\C-c\M-r" 'python-send-region-and-go)
190 (define-key map "\C-c\C-c" 'python-send-buffer)
191 (define-key map "\C-c\C-z" 'python-switch-to-python)
192 (define-key map "\C-c\C-m" 'python-load-file)
193 (define-key map "\C-c\C-l" 'python-load-file) ; a la cmuscheme
194 ;; Fixme: Add :help to menu.
195 (easy-menu-define python-menu map "Python Mode menu"
196 '("Python"
197 ["Shift region left" python-shift-left :active mark-active]
198 ["Shift region right" python-shift-right :active mark-active]
199 "-"
200 ["Mark block" python-mark-block]
201 ["Mark def/class" mark-defun
202 :help "Mark innermost definition around point"]
203 "-"
204 ["Start of block" python-beginning-of-block]
205 ["End of block" python-end-of-block]
206 ["Start of def/class" beginning-of-defun
207 :help "Go to start of innermost definition around point"]
208 ["End of def/class" end-of-defun
209 :help "Go to end of innermost definition around point"]
210 "-"
211 ["Start interpreter" run-python
212 :help "Run `inferior' Python in separate buffer"]
213 ["Import/reload file" python-load-file
214 :help "Load into inferior Python session"]
215 ["Eval buffer" python-send-buffer
216 :help "Evaluate buffer en bloc in inferior Python session"]
217 ["Eval region" python-send-region :active mark-active
218 :help "Evaluate region en bloc in inferior Python session"]
219 ["Eval def/class" python-send-defun
220 :help "Evaluate current definition in inferior Python session"]
221 ["Switch to interpreter" python-switch-to-python
222 :help "Switch to inferior Python buffer"]
223 ["Check file" python-check :help "Run pychecker"]
224 ["Debugger" pdb :help "Run pdb under GUD"]
225 "-"
226 ["Help on symbol" python-describe-symbol
227 :help "Use pydoc on symbol at point"]))
228 map))
229
230 (defvar python-mode-syntax-table
231 (let ((table (make-syntax-table)))
232 ;; Give punctuation syntax to ASCII that normally has symbol
233 ;; syntax or has word syntax and isn't a letter.
234 (let ((symbol (string-to-syntax "_"))
235 (sst (standard-syntax-table)))
236 (dotimes (i 128)
237 (unless (= i ?_)
238 (if (equal symbol (aref sst i))
239 (modify-syntax-entry i "." table)))))
240 (modify-syntax-entry ?$ "." table)
241 (modify-syntax-entry ?% "." table)
242 ;; exceptions
243 (modify-syntax-entry ?# "<" table)
244 (modify-syntax-entry ?\n ">" table)
245 (modify-syntax-entry ?' "\"" table)
246 (modify-syntax-entry ?` "$" table)
247 table))
248
249 ;;;; Utility stuff
250
251 (defsubst python-in-string/comment ()
252 "Return non-nil if point is in a Python literal (a comment or string).
253 Optional argument LIM indicates the beginning of the containing form,
254 i.e. the limit on how far back to scan."
255 (syntax-ppss-context (syntax-ppss)))
256
257 (defconst python-space-backslash-table
258 (let ((table (copy-syntax-table python-mode-syntax-table)))
259 (modify-syntax-entry ?\\ " " table)
260 table)
261 "`python-mode-syntax-table' with backslash given whitespace syntax.")
262
263 (defun python-skip-comments/blanks (&optional backward)
264 "Skip comments and blank lines.
265 BACKWARD non-nil means go backwards, otherwise go forwards. Backslash is
266 treated as whitespace so that continued blank lines are skipped.
267 Doesn't move out of comments -- should be outside or at end of line."
268 (with-syntax-table python-space-backslash-table
269 (forward-comment (if backward
270 most-negative-fixnum
271 most-positive-fixnum))))
272
273 (defun python-backslash-continuation-line-p ()
274 "Non-nil if preceding line ends with backslash that is not in a comment."
275 (and (eq ?\\ (char-before (line-end-position 0)))
276 (not (syntax-ppss-context (syntax-ppss)))))
277
278 (defun python-continuation-line-p ()
279 "Return non-nil if current line continues a previous one.
280 The criteria are that the previous line ends in a backslash outside
281 comments and strings, or that the bracket/paren nesting depth is nonzero."
282 (or (and (eq ?\\ (char-before (line-end-position 0)))
283 (not (syntax-ppss-context (syntax-ppss))))
284 (/= 0 (syntax-ppss-depth
285 (save-excursion ; syntax-ppss with arg changes point
286 (syntax-ppss (line-beginning-position)))))))
287
288 (defun python-comment-line-p ()
289 "Return non-nil if current line has only a comment or is blank."
290 (save-excursion
291 (back-to-indentation)
292 (looking-at (rx (or (syntax comment-start) line-end)))))
293
294 (defun python-beginning-of-string ()
295 "Go to beginning of string around point.
296 Do nothing if not in string."
297 (let ((state (syntax-ppss)))
298 (when (nth 3 state)
299 (goto-char (nth 8 state)))))
300
301 (defun python-open-block-statement-p (&optional bos)
302 "Return non-nil if statement at point opens a block.
303 BOS non-nil means point is known to be at beginning of statement."
304 (save-excursion
305 (unless bos (python-beginning-of-statement))
306 (and (not (python-comment-line-p))
307 (re-search-forward (rx (and ?: (0+ space)
308 (optional (and (syntax comment-start)
309 (0+ not-newline)))
310 line-end))
311 (save-excursion (python-end-of-statement))
312 t)
313 (not (python-in-string/comment)))))
314
315 (defun python-close-block-statement-p (&optional bos)
316 "Return non-nil if current line is a statement closing a block.
317 BOS non-nil means point is at beginning of statement.
318 The criteria are that the line isn't a comment or in string and starts with
319 keyword `raise', `break', `continue' or `pass'."
320 (save-excursion
321 (unless bos (python-beginning-of-statement))
322 (back-to-indentation)
323 (looking-at (rx (and (or "return" "raise" "break" "continue" "pass")
324 word-end)))))
325
326 (defun python-outdent-p ()
327 "Return non-nil if current line should outdent a level."
328 (save-excursion
329 (back-to-indentation)
330 (and (looking-at (rx (and (or (and (or "else" "finally") word-end)
331 (and (or "except" "elif") word-end
332 (1+ (not (any ?:)))))
333 (optional space) ":" (optional space)
334 (or (syntax comment-start) line-end))))
335 (progn (end-of-line)
336 (not (python-in-string/comment)))
337 ;; Ensure there's a previous statement and move to it.
338 (zerop (python-previous-statement))
339 (not (python-close-block-statement-p t))
340 ;; Fixme: check this
341 (not (looking-at (rx (and (or (and (or "if" "elif" "except"
342 "for" "while")
343 word-end (1+ (not (any ?:))))
344 (and "try" word-end))
345 (optional space) ":" (optional space)
346 (or (syntax comment-start) line-end)))))
347 (progn (end-of-line)
348 (not (python-in-string/comment))))))
349
350 ;;;; Indentation.
351
352 (defcustom python-indent 4
353 "*Number of columns for a unit of indentation in Python mode.
354 See also `\\[python-guess-indent]'"
355 :group 'python
356 :type 'integer)
357
358 (defcustom python-guess-indent t
359 "*Non-nil means Python mode guesses `python-indent' for the buffer."
360 :type 'boolean
361 :group 'python)
362
363 (defcustom python-indent-string-contents t
364 "*Non-nil means indent contents of multi-line strings together.
365 This means indent them the same as the preceding non-blank line.
366 Otherwise indent them to column zero."
367 :type '(choice (const :tag "Align with preceding" t)
368 (const :tag "Indent to column 0" nil))
369 :group 'python)
370
371 (defcustom python-honour-comment-indentation nil
372 "Non-nil means indent relative to preceding comment line.
373 Only do this for comments where the leading comment character is followed
374 by space."
375 :type 'boolean
376 :group 'python)
377
378 (defcustom python-continuation-offset 4
379 "*Number of columns of additional indentation for continuation lines.
380 Continuation lines follow a backslash-terminated line starting a statement."
381 :group 'python
382 :type 'integer)
383
384 (defun python-guess-indent ()
385 "Guess step for indentation of current buffer.
386 Set `python-indent' locally to the value guessed."
387 (interactive)
388 (save-excursion
389 (goto-char (point-min))
390 (let (done indent)
391 (while (and (not done) (not (eobp)))
392 (when (and (re-search-forward (rx (and ?: (0+ space)
393 (or (syntax comment-start)
394 line-end)))
395 nil 'move)
396 (python-open-block-statement-p))
397 (save-excursion
398 (python-beginning-of-statement)
399 (let ((initial (current-indentation)))
400 (if (zerop (python-next-statement))
401 (setq indent (- (current-indentation) initial)))
402 (if (and (>= indent 2) (<= indent 8)) ; sanity check
403 (setq done t))))))
404 (when done
405 (when (/= indent (default-value 'python-indent))
406 (set (make-local-variable 'python-indent) indent)
407 (unless (= tab-width python-indent)
408 (setq indent-tabs-mode nil)))
409 indent))))
410
411 (defun python-calculate-indentation ()
412 "Calculate Python indentation for line at point."
413 (save-excursion
414 (beginning-of-line)
415 (let ((syntax (syntax-ppss))
416 start)
417 (cond
418 ((eq 'string (syntax-ppss-context syntax)) ; multi-line string
419 (if (not python-indent-string-contents)
420 0
421 (save-excursion
422 ;; Find indentation of preceding non-blank line within string.
423 (setq start (nth 8 syntax))
424 (forward-line -1)
425 (while (and (< start (point)) (looking-at "\\s-*$"))
426 (forward-line -1))
427 (current-indentation))))
428 ((python-continuation-line-p)
429 (let ((point (point))
430 (open-start (cadr syntax)))
431 (if open-start
432 ;; Inside bracketed expression.
433 (progn
434 (goto-char (1+ open-start))
435 ;; Look for first item in list (preceding point) and
436 ;; align with it, if found.
437 (if (with-syntax-table python-space-backslash-table
438 (let ((parse-sexp-ignore-comments t))
439 (condition-case ()
440 (progn (forward-sexp)
441 (backward-sexp)
442 (< (point) point))
443 (error nil))))
444 (current-column)
445 ;; Otherwise indent relative to statement start, one
446 ;; level per bracketing level.
447 (goto-char (1+ open-start))
448 (python-beginning-of-statement)
449 (+ (current-indentation) (* (car syntax) python-indent))))
450 ;; Otherwise backslash-continued.
451 (forward-line -1)
452 (if (python-continuation-line-p)
453 ;; We're past first continuation line. Align with
454 ;; previous line.
455 (current-indentation)
456 ;; First continuation line. Indent one step, with an
457 ;; extra one if statement opens a block.
458 (save-excursion
459 (python-beginning-of-statement)
460 (+ (current-indentation) python-continuation-offset
461 (if (python-open-block-statement-p t)
462 python-indent
463 0)))))))
464 ((bobp) 0)
465 ;; Fixme: Like python-mode.el; not convinced by this.
466 ((looking-at (rx (and (0+ space) (syntax comment-start)
467 (not (any " \t\n"))))) ; non-indentable comment
468 (current-indentation))
469 (t (let ((point (point)))
470 (if python-honour-comment-indentation
471 ;; Back over whitespace, newlines, non-indentable comments.
472 (catch 'done
473 (while t
474 (if (cond ((bobp))
475 ;; not at comment start
476 ((not (forward-comment -1))
477 (python-beginning-of-statement)
478 t)
479 ;; trailing comment
480 ((/= (current-column) (current-indentation))
481 (python-beginning-of-statement)
482 t)
483 ;; indentable comment like python-mode.el
484 ((and (looking-at (rx (and (syntax comment-start)
485 (or space line-end))))
486 (/= 0 (current-column)))))
487 (throw 'done t))))
488 ;; Else back over all comments.
489 (python-skip-comments/blanks t)
490 (python-beginning-of-statement))
491 ;; don't lose on bogus outdent
492 (max 0 (+ (current-indentation)
493 (or (cond ((python-open-block-statement-p t)
494 python-indent)
495 ((python-close-block-statement-p t)
496 (- python-indent)))
497 (progn (goto-char point)
498 (if (python-outdent-p)
499 (- python-indent)))
500 0)))))))))
501
502 ;;;; Cycling through the possible indentations with successive TABs.
503
504 ;; These don't need to be buffer-local since they're only relevant
505 ;; during a cycle.
506
507 ;; Alist of possible indentations and start of statement they would close.
508 (defvar python-indent-list nil
509 "Internal use.")
510 ;; Length of the above
511 (defvar python-indent-list-length nil
512 "Internal use.")
513 ;; Current index into the alist.
514 (defvar python-indent-index nil
515 "Internal use.")
516
517 (defun python-initial-text ()
518 "Text of line following indentation and ignoring any trailing comment."
519 (buffer-substring (+ (line-beginning-position) (current-indentation))
520 (save-excursion
521 (end-of-line)
522 (forward-comment -1)
523 (point))))
524
525 (defun python-indentation-levels ()
526 "Return a list of possible indentations for this statement.
527 Includes the default indentation and those which would close all
528 enclosing blocks."
529 (save-excursion
530 (let ((levels (list (cons (current-indentation) nil))))
531 ;; Only one possibility if we immediately follow a block open or
532 ;; are in a continuation line.
533 (unless (or (python-continuation-line-p)
534 (save-excursion (and (python-previous-statement)
535 (python-open-block-statement-p t))))
536 (while (python-beginning-of-block)
537 (push (cons (current-indentation) (python-initial-text))
538 levels)))
539 levels)))
540
541 ;; This is basically what `python-indent-line' would be if we didn't
542 ;; do the cycling.
543 (defun python-indent-line-1 ()
544 "Subroutine of `python-indent-line'."
545 (let ((target (python-calculate-indentation))
546 (pos (- (point-max) (point))))
547 (if (= target (current-indentation))
548 (if (< (current-column) (current-indentation))
549 (back-to-indentation))
550 (beginning-of-line)
551 (delete-horizontal-space)
552 (indent-to target)
553 (if (> (- (point-max) pos) (point))
554 (goto-char (- (point-max) pos))))))
555
556 ;; Fixme: Is the arg necessary?
557 (defun python-indent-line (&optional arg)
558 "Indent current line as Python code.
559 When invoked via `indent-for-tab-command', cycle through possible
560 indentations for current line. The cycle is broken by a command different
561 from `indent-for-tab-command', i.e. successive TABs do the cycling."
562 (interactive)
563 ;; Don't do extra work if invoked via `indent-region', for instance.
564 (if (not (eq this-command 'indent-for-tab-command))
565 (python-indent-line-1)
566 (if (eq last-command this-command)
567 (if (= 1 python-indent-list-length)
568 (message "Sole indentation")
569 (progn (setq python-indent-index (% (1+ python-indent-index)
570 python-indent-list-length))
571 (beginning-of-line)
572 (delete-horizontal-space)
573 (indent-to (car (nth python-indent-index python-indent-list)))
574 (let ((text (cdr (nth python-indent-index
575 python-indent-list))))
576 (if text (message "Closes: %s" text)))))
577 (python-indent-line-1)
578 (setq python-indent-list (python-indentation-levels)
579 python-indent-list-length (length python-indent-list)
580 python-indent-index (1- python-indent-list-length)))))
581
582 ;;;; Movement.
583
584 (defun python-beginning-of-defun ()
585 "`beginning-of-defun-function' for Python.
586 Finds beginning of innermost nested class or method definition.
587 Returns the name of the definition found at the end, or nil if reached
588 start of buffer."
589 (let ((ci (current-indentation))
590 (def-re (rx (and line-start (0+ space) (or "def" "class")
591 (1+ space)
592 (group (1+ (or word (syntax symbol)))))))
593 point found lep def-line)
594 (if (python-comment-line-p)
595 (setq ci most-positive-fixnum))
596 (while (and (not (bobp)) (not found))
597 ;; Treat bol at beginning of function as outside function so
598 ;; that successive C-M-a makes progress backwards.
599 (setq def-line (looking-at def-re))
600 (unless (bolp) (end-of-line))
601 (setq lep (line-end-position))
602 (if (and (re-search-backward def-re nil 'move)
603 ;; Must be less indented or matching top level, or
604 ;; equally indented if we started on a definition line.
605 (let ((in (current-indentation)))
606 (or (and (zerop ci) (zerop in))
607 (= lep (line-end-position)) ; on initial line
608 (and def-line (= in ci))
609 (< in ci)))
610 (not (python-in-string/comment)))
611 (setq found t)))))
612
613 (defun python-end-of-defun ()
614 "`end-of-defun-function' for Python.
615 Finds end of innermost nested class or method definition."
616 (let ((orig (point))
617 (pattern (rx (and line-start (0+ space)
618 (or "def" "class") space))))
619 ;; Go to start of current block and check whether it's at top
620 ;; level. If it is, and not a block start, look forward for
621 ;; definition statement.
622 (when (python-comment-line-p)
623 (end-of-line)
624 (forward-comment most-positive-fixnum))
625 (if (not (python-open-block-statement-p))
626 (python-beginning-of-block))
627 (if (zerop (current-indentation))
628 (unless (python-open-block-statement-p)
629 (while (and (re-search-forward pattern nil 'move)
630 (python-in-string/comment))) ; just loop
631 (unless (eobp)
632 (beginning-of-line)))
633 ;; Don't move before top-level statement that would end defun.
634 (end-of-line)
635 (python-beginning-of-defun))
636 ;; If we got to the start of buffer, look forward for
637 ;; definition statement.
638 (if (and (bobp) (not (looking-at "def\\|class")))
639 (while (and (not (eobp))
640 (re-search-forward pattern nil 'move)
641 (python-in-string/comment)))) ; just loop
642 ;; We're at a definition statement (or end-of-buffer).
643 (unless (eobp)
644 (python-end-of-block)
645 ;; Count trailing space in defun (but not trailing comments).
646 (skip-syntax-forward " >")
647 (beginning-of-line))
648 ;; Catch pathological case like this, where the beginning-of-defun
649 ;; skips to a definition we're not in:
650 ;; if ...:
651 ;; ...
652 ;; else:
653 ;; ... # point here
654 ;; ...
655 ;; def ...
656 (if (< (point) orig)
657 (goto-char (point-max)))))
658
659 (defun python-beginning-of-statement ()
660 "Go to start of current statement.
661 Accounts for continuation lines, multi-line strings, and multi-line bracketed
662 expressions."
663 (beginning-of-line)
664 (python-beginning-of-string)
665 (while (python-continuation-line-p)
666 (beginning-of-line)
667 (if (python-backslash-continuation-line-p)
668 (while (python-backslash-continuation-line-p)
669 (forward-line -1))
670 (python-beginning-of-string)
671 ;; Skip forward out of nested brackets.
672 (condition-case () ; beware invalid syntax
673 (progn (backward-up-list (syntax-ppss-depth (syntax-ppss))) t)
674 (error (end-of-line)))))
675 (back-to-indentation))
676
677 (defun python-end-of-statement ()
678 "Go to the end of the current statement and return point.
679 Usually this is the start of the next line, but if this is a
680 multi-line statement we need to skip over the continuation lines.
681 On a comment line, go to end of line."
682 (end-of-line)
683 (while (let (comment)
684 ;; Move past any enclosing strings and sexps, or stop if
685 ;; we're in a comment.
686 (while (let ((s (syntax-ppss)))
687 (cond ((eq 'comment (syntax-ppss-context s))
688 (setq comment t)
689 nil)
690 ((eq 'string (syntax-ppss-context s))
691 ;; Go to start of string and skip it.
692 (goto-char (nth 8 s))
693 (condition-case () ; beware invalid syntax
694 (progn (forward-sexp) t)
695 (error (end-of-line))))
696 ((> (syntax-ppss-depth s) 0)
697 ;; Skip forward out of nested brackets.
698 (condition-case () ; beware invalid syntax
699 (progn (backward-up-list
700 (- (syntax-ppss-depth s)))
701 t)
702 (error (end-of-line))))))
703 (end-of-line))
704 (unless comment
705 (eq ?\\ (char-before)))) ; Line continued?
706 (end-of-line 2)) ; Try next line.
707 (point))
708
709 (defun python-previous-statement (&optional count)
710 "Go to start of previous statement.
711 With argument COUNT, do it COUNT times. Stop at beginning of buffer.
712 Return count of statements left to move."
713 (interactive "p")
714 (unless count (setq count 1))
715 (if (< count 0)
716 (python-next-statement (- count))
717 (python-beginning-of-statement)
718 (while (and (> count 0) (not (bobp)))
719 (python-skip-comments/blanks t)
720 (python-beginning-of-statement)
721 (unless (bobp) (setq count (1- count))))
722 count))
723
724 (defun python-next-statement (&optional count)
725 "Go to start of next statement.
726 With argument COUNT, do it COUNT times. Stop at end of buffer.
727 Return count of statements left to move."
728 (interactive "p")
729 (unless count (setq count 1))
730 (if (< count 0)
731 (python-previous-statement (- count))
732 (beginning-of-line)
733 (while (and (> count 0) (not (eobp)))
734 (python-end-of-statement)
735 (python-skip-comments/blanks)
736 (setq count (1- count)))
737 count))
738
739 (defun python-beginning-of-block (&optional arg)
740 "Go to start of current block.
741 With numeric arg, do it that many times. If ARG is negative, call
742 `python-end-of-block' instead.
743 If point is on the first line of a block, use its outer block.
744 If current statement is in column zero, don't move and return nil.
745 Otherwise return non-nil."
746 (interactive "p")
747 (unless arg (setq arg 1))
748 (cond
749 ((zerop arg))
750 ((< arg 0) (python-end-of-block (- arg)))
751 (t
752 (let ((point (point)))
753 (if (python-comment-line-p)
754 (python-skip-comments/blanks t))
755 (python-beginning-of-statement)
756 (let ((ci (current-indentation)))
757 (if (zerop ci)
758 (not (goto-char point)) ; return nil
759 ;; Look upwards for less indented statement.
760 (if (catch 'done
761 ;;; This is slower than the below.
762 ;;; (while (zerop (python-previous-statement))
763 ;;; (when (and (< (current-indentation) ci)
764 ;;; (python-open-block-statement-p t))
765 ;;; (beginning-of-line)
766 ;;; (throw 'done t)))
767 (while (and (zerop (forward-line -1)))
768 (when (and (< (current-indentation) ci)
769 (not (python-comment-line-p))
770 ;; Move to beginning to save effort in case
771 ;; this is in string.
772 (progn (python-beginning-of-statement) t)
773 (python-open-block-statement-p t))
774 (beginning-of-line)
775 (throw 'done t)))
776 (not (goto-char point))) ; Failed -- return nil
777 (python-beginning-of-block (1- arg)))))))))
778
779 (defun python-end-of-block (&optional arg)
780 "Go to end of current block.
781 With numeric arg, do it that many times. If ARG is negative, call
782 `python-beginning-of-block' instead.
783 If current statement is in column zero and doesn't open a block, don't
784 move and return nil. Otherwise return t."
785 (interactive "p")
786 (unless arg (setq arg 1))
787 (if (< arg 0)
788 (python-beginning-of-block (- arg)))
789 (while (and (> arg 0)
790 (let* ((point (point))
791 (_ (if (python-comment-line-p)
792 (python-skip-comments/blanks t)))
793 (ci (current-indentation))
794 (open (python-open-block-statement-p)))
795 (if (and (zerop ci) (not open))
796 (not (goto-char point))
797 (catch 'done
798 (while (zerop (python-next-statement))
799 (when (or (and open (<= (current-indentation) ci))
800 (< (current-indentation) ci))
801 (python-skip-comments/blanks t)
802 (beginning-of-line 2)
803 (throw 'done t)))
804 (not (goto-char point))))))
805 (setq arg (1- arg)))
806 (zerop arg))
807
808 ;;;; Imenu.
809
810 (defun python-imenu-create-index ()
811 "`imenu-create-index-function' for Python.
812
813 Makes nested Imenu menus from nested `class' and `def' statements.
814 The nested menus are headed by an item referencing the outer
815 definition; it has a space prepended to the name so that it sorts
816 first with `imenu--sort-by-name'."
817 (unless (boundp 'recursing) ; dynamically bound below
818 (goto-char (point-min))) ; normal call from Imenu
819 (let (index-alist ; accumulated value to return
820 name is-class pos)
821 (while (re-search-forward
822 (rx (and line-start (0+ space) ; leading space
823 (or (group "def") (group "class")) ; type
824 (1+ space) (group (1+ (or word ?_))))) ; name
825 nil t)
826 (unless (python-in-string/comment)
827 (let ((pos (match-beginning 0))
828 (name (match-string-no-properties 3)))
829 (if (match-beginning 2) ; def or class?
830 (setq name (concat "class " name)))
831 (save-restriction
832 (narrow-to-defun)
833 (let* ((recursing t)
834 (sublist (python-imenu-create-index)))
835 (if sublist
836 (progn (push (cons (concat " " name) pos) sublist)
837 (push (cons name sublist) index-alist))
838 (push (cons name pos) index-alist)))))))
839 (nreverse index-alist)))
840
841 ;;;; `Electric' commands.
842
843 (defun python-electric-colon (arg)
844 "Insert a colon and maybe outdent the line if it is a statement like `else'.
845 With numeric ARG, just insert that many colons. With \\[universal-argument],
846 just insert a single colon."
847 (interactive "*P")
848 (self-insert-command (if (not (integerp arg)) 1 arg))
849 (and (not arg)
850 (eolp)
851 (python-outdent-p)
852 (not (python-in-string/comment))
853 (> (current-indentation) (python-calculate-indentation))
854 (python-indent-line))) ; OK, do it
855 (put 'python-electric-colon 'delete-selection t)
856
857 (defun python-backspace (arg)
858 "Maybe delete a level of indentation on the current line.
859 If not at the end of line's indentation, or on a comment line, just call
860 `backward-delete-char-untabify'. With ARG, repeat that many times."
861 (interactive "*p")
862 (if (or (/= (current-indentation) (current-column))
863 (bolp)
864 (python-continuation-line-p))
865 (backward-delete-char-untabify arg)
866 (let ((indent 0))
867 (save-excursion
868 (while (and (> arg 0) (python-beginning-of-block))
869 (setq arg (1- arg)))
870 (when (zerop arg)
871 (setq indent (current-indentation))
872 (message "Closes %s" (python-initial-text))))
873 (delete-horizontal-space)
874 (indent-to indent))))
875 (put 'python-backspace 'delete-selection 'supersede)
876
877 ;;;; pychecker
878
879 (defcustom python-check-command "pychecker --stdlib"
880 "*Command used to check a Python file."
881 :type 'string
882 :group 'python)
883
884 (defvar python-saved-check-command nil
885 "Internal use.")
886
887 (autoload 'compilation-start "compile")
888
889 ;; After `sgml-validate-command'.
890 (defun python-check (command)
891 "Check a Python file (default current buffer's file).
892 Runs COMMAND, a shell command, as if by `compile'.
893 See `python-check-command' for the default."
894 (interactive
895 (list (read-string "Checker command: "
896 (or python-saved-check-command
897 (concat python-check-command " "
898 (let ((name (buffer-file-name)))
899 (if name
900 (file-name-nondirectory name))))))))
901 (setq python-saved-check-command command)
902 (save-some-buffers (not compilation-ask-about-save) nil)
903 (compilation-start command))
904
905 ;;;; Inferior mode stuff (following cmuscheme).
906
907 (defcustom python-python-command "python"
908 "*Shell command to run Python interpreter.
909 Any arguments can't contain whitespace."
910 :group 'python
911 :type 'string)
912
913 (defcustom python-jython-command "jython"
914 "*Shell command to run Jython interpreter.
915 Any arguments can't contain whitespace."
916 :group 'python
917 :type 'string)
918
919 (defvar python-command python-python-command
920 "Actual command used to run Python.
921 May be `python-python-command' or `python-jython-command'.
922 Additional arguments are added when the command is used by `run-python'
923 et al.")
924
925 (defvar python-buffer nil
926 "*The current python process buffer.
927 To run multiple Python processes, start the first with \\[run-python].
928 It will be in a buffer named *Python*. Rename that with
929 \\[rename-buffer]. Now start a new process with \\[run-python]. It
930 will be in a new buffer, named *Python*. Switch between the different
931 process buffers with \\[switch-to-buffer].
932
933 Commands that send text from source buffers to Python processes have
934 to choose a process to send to. This is determined by global variable
935 `python-buffer'. Suppose you have three inferior Pythons running:
936 Buffer Process
937 foo python
938 bar python<2>
939 *Python* python<3>
940 If you do a \\[python-send-region-and-go] command on some Python source
941 code, what process does it go to?
942
943 - In a process buffer (foo, bar, or *Python*), send it to that process.
944 - In some other buffer (e.g. a source file), send it to the process
945 attached to `python-buffer'.
946 Process selection is done by function `python-proc'.
947
948 Whenever \\[run-python] starts a new process, it resets `python-buffer'
949 to be the new process's buffer. If you only run one process, this will
950 do the right thing. If you run multiple processes, you can change
951 `python-buffer' to another process buffer with \\[set-variable].")
952
953 (define-derived-mode inferior-python-mode comint-mode "Inferior Python"
954 "Major mode for interacting with an inferior Python process.
955 A Python process can be started with \\[run-python].
956
957 Hooks `comint-mode-hook' and `inferior-python-mode-hook' are run in
958 that order.
959
960 You can send text to the inferior Python process from other buffers containing
961 Python source.
962 * `python-switch-to-python' switches the current buffer to the Python
963 process buffer.
964 * `python-send-region' sends the current region to the Python process.
965 * `python-send-region-and-go' switches to the Python process buffer
966 after sending the text.
967 For running multiple processes in multiple buffers, see `python-buffer'.
968
969 \\{inferior-python-mode-map}"
970 :group 'python
971 (set-syntax-table python-mode-syntax-table)
972 (setq mode-line-process '(":%s"))
973 ;; Fixme: Maybe install some python-mode bindings too.
974 (define-key inferior-python-mode-map "\C-c\C-l" 'python-load-file)
975 (define-key inferior-python-mode-map "\C-c\C-z" 'python-switch-to-python)
976 (setq comint-input-filter #'python-input-filter))
977
978 (defcustom inferior-python-filter-regexp "\\`\\s-*\\S-?\\S-?\\s-*\\'"
979 "*Input matching this regexp is not saved on the history list.
980 Default ignores all inputs of 0, 1, or 2 non-blank characters."
981 :type 'regexp
982 :group 'python)
983
984 (defvar python-orig-start-line nil
985 "Line number at start of region sent to inferior Python.")
986
987 (defvar python-orig-file nil
988 "File name to associate with errors found in inferior Python.")
989
990 (defun python-input-filter (str)
991 "`comint-input-filter' function for inferior Python.
992 Don't save anything matching `inferior-python-filter-regexp'.
993 Also resets variables for adjusting error messages."
994 (setq python-orig-file nil
995 python-orig-start-line 1)
996 (not (string-match inferior-python-filter-regexp str)))
997
998 ;; Fixme: Loses with quoted whitespace.
999 (defun python-args-to-list (string)
1000 (let ((where (string-match "[ \t]" string)))
1001 (cond ((null where) (list string))
1002 ((not (= where 0))
1003 (cons (substring string 0 where)
1004 (python-args-to-list (substring string (+ 1 where)))))
1005 (t (let ((pos (string-match "[^ \t]" string)))
1006 (if pos (python-args-to-list (substring string pos))))))))
1007
1008 (defvar compilation-minor-mode-map)
1009 (defvar compilation-error-list)
1010 (defvar compilation-parsing-end)
1011
1012 (defconst python-compilation-regexp-alist
1013 `((,(rx (and line-start (1+ (any " \t")) "File \""
1014 (group (1+ (not (any "\"<")))) ; avoid `<stdin>' &c
1015 "\", line " (group (1+ digit))))
1016 1 python-compilation-line-number))
1017 "`compilation-error-regexp-alist' for inferior Python.")
1018
1019 (defun python-compilation-line-number (file col)
1020 "Return error descriptor of error found for FILE, column COL.
1021 Used as line-number hook function in `python-compilation-regexp-alist'."
1022 (let ((line (save-excursion
1023 (goto-char (match-beginning 2))
1024 (read (current-buffer)))))
1025 (list (point-marker) (if python-orig-file
1026 (list python-orig-file default-directory)
1027 file)
1028 (+ line (1- python-orig-start-line))
1029 nil)))
1030
1031 ;;;###autoload
1032 (defun run-python (cmd)
1033 "Run an inferior Python process, input and output via buffer *Python*.
1034 CMD is the Python command to run.
1035 If there is a process already running in `*Python*', switch to
1036 that buffer. With argument, allows you to edit the initial
1037 command line (default is the value of `python-command'); `-i' and
1038 `-c' args will be added to this to support evaluations in the
1039 REPL. Runs the hooks `inferior-python-mode-hook' \(after the
1040 `comint-mode-hook' is run). \(Type \\[describe-mode] in the
1041 process buffer for a list of commands.)"
1042 (interactive (list (if current-prefix-arg
1043 (read-string "Run Python: " python-command)
1044 python-command)))
1045 ;; Fixme: Consider making `python-buffer' buffer-local as a buffer
1046 ;; (not a name) in Python buffers from which `run-python' &c is
1047 ;; invoked. Would support multiple processes better.
1048 (if (not (comint-check-proc "*Python*"))
1049 (let ((cmdlist (append (python-args-to-list cmd)
1050 '("-i" "-c" "\
1051 from os import remove as _emacs_rem
1052 def _emacs_execfile (file):
1053 try:
1054 execfile (file)
1055 finally:
1056 _emacs_rem (file)
1057 "))))
1058 (set-buffer (apply 'make-comint "Python" (car cmdlist) nil
1059 (cdr cmdlist)))
1060 (inferior-python-mode)
1061 (setq comint-output-filter-functions nil)))
1062 (setq python-command cmd)
1063 (setq python-buffer "*Python*")
1064 (pop-to-buffer "*Python*")
1065 (compilation-minor-mode 1)
1066 (add-hook 'comint-input-filter-functions 'python-input-filter nil t)
1067 ;; Avoid clobbering comint bindings.
1068 (set (make-local-variable 'minor-mode-overriding-map-alist)
1069 `((compilation-minor-mode
1070 . ,(let ((map (make-sparse-keymap)))
1071 ;; It would be useful to put keymap properties on the
1072 ;; error lines so that we could use RET and mouse-2 on
1073 ;; them directly. These bindings will only DTRT with
1074 ;; the font-lock-style compilation mode.
1075 (define-key map [mouse-2] #'python-mouse-2-command)
1076 (define-key map "\C-m" #'python-RET-command)
1077 (if (boundp 'compilation-menu-map)
1078 (define-key map [menu-bar compilation]
1079 (cons "Errors" compilation-menu-map)))
1080 map))))
1081 (set (make-local-variable 'compilation-error-regexp-alist)
1082 python-compilation-regexp-alist))
1083
1084 (defun python-mouse-2-command (event)
1085 "Command bound to `mouse-2' in inferior Python buffer.
1086 Selects Comint or Compilation mode command as appropriate."
1087 (interactive "e")
1088 ;; This only works with the font-lock-based compilation mode.
1089 (call-interactively
1090 (lookup-key (if (save-window-excursion
1091 (save-excursion
1092 (mouse-set-point event)
1093 (consp (get-text-property (line-beginning-position)
1094 'message))))
1095 compilation-mode-map
1096 comint-mode-map)
1097 [mouse-2])))
1098
1099 (defun python-RET-command ()
1100 "Command bound to `RET' in inferior Python buffer.
1101 Selects Comint or Compilation mode command as appropriate."
1102 (interactive)
1103 ;; This only works with the font-lock-based compilation mode.
1104 (call-interactively
1105 (lookup-key (if (consp (get-text-property (line-beginning-position)
1106 'message))
1107 compilation-mode-map
1108 comint-mode-map)
1109 "\C-m")))
1110
1111 (defun python-send-region (start end)
1112 "Send the region to the inferior Python process."
1113 ;; The region is evaluated from a temporary file. This avoids
1114 ;; problems with blank lines, which have different semantics
1115 ;; interactively and in files. It also saves the inferior process
1116 ;; buffer filling up with interpreter prompts. We need a function
1117 ;; to remove the temporary file when it has been evaluated, which
1118 ;; unfortunately means using a not-quite pristine interpreter
1119 ;; initially. Unfortunately we also get tracebacks which look like:
1120 ;;
1121 ;; >>> Traceback (most recent call last):
1122 ;; File "<stdin>", line 1, in ?
1123 ;; File "<string>", line 4, in _emacs_execfile
1124 ;; File "/tmp/py7734RSB", line 11
1125 ;;
1126 ;; The compilation-minor-mode parsing takes care of relating the
1127 ;; reference to the temporary file to the source. Fixme:
1128 ;; comint-filter the first two lines of the traceback?
1129 (interactive "r")
1130 (let* ((f (make-temp-file "py"))
1131 (command (format "_emacs_execfile(%S)\n" f))
1132 (orig-file (buffer-file-name))
1133 (orig-line (save-restriction
1134 (widen)
1135 (line-number-at-pos start))))
1136 (if (save-excursion
1137 (goto-char start)
1138 (/= 0 (current-indentation))) ; need dummy block
1139 (write-region "if True:\n" nil f nil 'nomsg))
1140 (write-region start end f t 'nomsg)
1141 (when python-buffer
1142 (with-current-buffer python-buffer
1143 (let ((end (marker-position (process-mark
1144 (get-buffer-process python-buffer)))))
1145 (set (make-local-variable 'python-orig-file) orig-file)
1146 (set (make-local-variable 'python-orig-start-line) orig-line)
1147 (set (make-local-variable 'compilation-error-list) nil)
1148 ;; (set (make-local-variable 'compilation-old-error-list) nil)
1149 (let ((comint-input-filter-functions
1150 (delete 'python-input-filter comint-input-filter-functions)))
1151 (comint-send-string (python-proc) command))
1152 (set-marker compilation-parsing-end end)
1153 (setq compilation-last-buffer (current-buffer)))))))
1154
1155 (defun python-send-string (string)
1156 "Evaluate STRING in inferior Python process."
1157 (interactive "sPython command: ")
1158 (comint-send-string (python-proc) string))
1159
1160 (defun python-send-buffer ()
1161 "Send the current buffer to the inferior Python process."
1162 (interactive)
1163 (python-send-region (point-min) (point-max)))
1164
1165 (defun python-send-defun ()
1166 "Send the current defun (class or method) to the inferior Python process."
1167 (interactive)
1168 (save-excursion (python-send-region (progn (beginning-of-defun) (point))
1169 (progn (end-of-defun) (point)))))
1170
1171 (defun python-switch-to-python (eob-p)
1172 "Switch to the Python process buffer.
1173 With prefix arg, position cursor at end of buffer."
1174 (interactive "P")
1175 (if (get-buffer python-buffer)
1176 (pop-to-buffer python-buffer)
1177 (error "No current process buffer. See variable `python-buffer'"))
1178 (when eob-p
1179 (push-mark)
1180 (goto-char (point-max))))
1181
1182 (add-to-list 'debug-ignored-errors "^No current process buffer.")
1183
1184 (defun python-send-region-and-go (start end)
1185 "Send the region to the inferior Python process.
1186 Then switch to the process buffer."
1187 (interactive "r")
1188 (python-send-region start end)
1189 (python-switch-to-python t))
1190
1191 (defcustom python-source-modes '(python-mode jython-mode)
1192 "*Used to determine if a buffer contains Python source code.
1193 If it's loaded into a buffer that is in one of these major modes, it's
1194 considered a Python source file by `python-load-file'.
1195 Used by these commands to determine defaults."
1196 :type '(repeat function)
1197 :group 'python)
1198
1199 (defvar python-prev-dir/file nil
1200 "Caches (directory . file) pair used in the last `python-load-file' command.
1201 Used for determining the default in the next one.")
1202
1203 (defun python-load-file (file-name)
1204 "Load a Python file FILE-NAME into the inferior Python process.
1205 If the file has extension `.py' import or reload it as a module.
1206 Treating it as a module keeps the global namespace clean, provides
1207 function location information for debugging, and supports users of
1208 module-qualified names."
1209 (interactive (comint-get-source "Load Python file: " python-prev-dir/file
1210 python-source-modes
1211 t)) ; because execfile needs exact name
1212 (comint-check-source file-name) ; Check to see if buffer needs saved.
1213 (setq python-prev-dir/file (cons (file-name-directory file-name)
1214 (file-name-nondirectory file-name)))
1215 (comint-send-string
1216 (python-proc)
1217 (if (string-match "\\.py\\'" file-name)
1218 ;; Fixme: make sure the directory is in the path list
1219 (let ((module (file-name-sans-extension
1220 (file-name-nondirectory file-name))))
1221 (format "\
1222 if globals().has_key('%s'):
1223 reload(%s)
1224 else:
1225 import %s
1226 " module module module))
1227 (format "execfile('%s')\n" filename))))
1228
1229 ;; Fixme: Should this start a process if there isn't one? (Unlike cmuscheme.)
1230 (defun python-proc ()
1231 "Return the current Python process. See variable `python-buffer'."
1232 (let ((proc (get-buffer-process (if (eq major-mode 'inferior-python-mode)
1233 (current-buffer)
1234 python-buffer))))
1235 (or proc (error "No current process. See variable `python-buffer'"))))
1236
1237 ;;;; Context-sensitive help.
1238
1239 ;; Fixme: Investigate adapting this to eldoc.
1240
1241 (defun python-describe-symbol (symbol)
1242 "Get help on SYMBOL using `pydoc'.
1243 Interactively, prompt for symbol."
1244 (interactive
1245 (let ((symbol (current-word))
1246 (enable-recursive-minibuffers t)
1247 val)
1248 (setq val (read-string (if symbol
1249 (format "Describe variable (default %s): "
1250 symbol)
1251 "Describe variable: ")
1252 nil nil symbol))
1253 (list (or val symbol))))
1254 (if (equal symbol "") (error "No symbol"))
1255 (let* ((mod (if (string-match "\\(\\.[^.]+\\)\\'" symbol)
1256 (substring symbol 0 (match-beginning 1))))
1257 (import (when mod (concat "import " mod "\n"))))
1258 (with-output-to-temp-buffer "*Python Output*"
1259 (princ (shell-command-to-string
1260 (format "%s -c 'import pydoc %s
1261 try: pydoc.help(%S)
1262 except: print \"No help available on:\", %S'"
1263 ;; Fixme: Is this necessarily right?
1264 (car (split-string python-command))
1265 (or import "") symbol symbol))))))
1266
1267 (add-to-list 'debug-ignored-errors "^No symbol")
1268
1269 ;;;; Info-look functionality.
1270
1271 (require 'info-look)
1272 ;; We should be able to add info-lookup specs without loading the file first.
1273 ;; E.g. by setting a buffer-local var or something like that. --Stef
1274 (let ((version (let ((s (shell-command-to-string (concat python-command
1275 " -V"))))
1276 (string-match "^Python \\([0-9]+\\.[0-9]+\\>\\)" s)
1277 (match-string 1 s)))
1278 ;; Whether info files have a Python version suffix, e.g. in Debian.
1279 (versioned (save-window-excursion
1280 (condition-case ()
1281 ;; The call to `info' might create a new frame if
1282 ;; pop-up-frames or special-display-buffers are used.
1283 ;; So I disabled it until we find a better way
1284 ;; to handle this situation. Maybe Debian should just
1285 ;; fix their install somehow. --Stef
1286 ;; (progn (info "(python2.3-lib)Miscellaneous Index")
1287 ;; (Info-last)
1288 ;; (Info-exit)
1289 ;; t)
1290 nil
1291 (error nil)))))
1292 (info-lookup-maybe-add-help
1293 :mode 'python-mode
1294 :regexp "[[:alnum:]_]+"
1295 :doc-spec
1296 ;; Fixme: Add python-ref? Can this reasonably be made specific
1297 ;; to indices with different rules?
1298 (if versioned
1299 '((,(concat "(python" version "-lib)Module Index"))
1300 (,(concat "(python" version "-lib)Class-Exception-Object Index"))
1301 (,(concat "(python" version "-lib)Function-Method-Variable Index"))
1302 (,(concat "(python" version "-lib)Miscellaneous Index")))
1303 '(("(python-lib)Module Index")
1304 ("(python-lib)Class-Exception-Object Index")
1305 ("(python-lib)Function-Method-Variable Index")
1306 ("(python-lib)Miscellaneous Index")))))
1307
1308 ;;;; Miscellancy.
1309
1310 (defcustom python-jython-packages '("java" "javax" "org" "com")
1311 "Packages implying `jython-mode'.
1312 If these are imported near the beginning of the buffer, `python-mode'
1313 actually punts to `jython-mode'."
1314 :type '(repeat string)
1315 :group 'python)
1316
1317 ;; Called from `python-mode', this causes a recursive call of the
1318 ;; mode. See logic there to break out of the recursion.
1319 (defun python-maybe-jython ()
1320 "Invoke `jython-mode' if the buffer appears to contain Jython code.
1321 The criterion is either a match for `jython-mode' via
1322 `interpreter-mode-alist' or an import of a module from the list
1323 `python-jython-packages'."
1324 ;; The logic is taken from python-mode.el.
1325 (save-excursion
1326 (goto-char (point-min))
1327 (let ((interpreter (if (looking-at auto-mode-interpreter-regexp)
1328 (match-string 2))))
1329 (if (and interpreter (eq 'jython-mode
1330 (cdr (assoc (file-name-nondirectory interpreter)
1331 interpreter-mode-alist))))
1332 (jython-mode)
1333 (if (catch 'done
1334 (while (re-search-forward
1335 (rx (and line-start (or "import" "from") (1+ space)
1336 (group (1+ (not (any " \t\n."))))))
1337 (+ (point) 10000) ; Probably not worth customizing.
1338 t)
1339 (if (member (match-string 1) python-jython-packages)
1340 (throw 'done t))))
1341 (jython-mode))))))
1342
1343 (defun python-fill-paragraph (&optional justify)
1344 "Like \\[fill-paragraph], but handle comments and multi-line strings.
1345 If any of the current line is a comment, fill the comment or the
1346 paragraph of it that point is in, preserving the comment's indentation
1347 and initial comment characters."
1348 (interactive "P")
1349 (or (fill-comment-paragraph justify)
1350 (let ((paragraph-start (concat paragraph-start
1351 "\\|\\s-*\\(:?#\\s\"\\|\\s|\\|#")))
1352 (fill-paragraph justify))
1353 t))
1354
1355 (defun python-shift-left (start end &optional count)
1356 "Shift lines in region COUNT (the prefix arg) columns to the left.
1357 COUNT defaults to `python-indent'. If region isn't active, just shift
1358 current line. The region shifted includes the lines in which START and
1359 END lie. It is an error if any lines in the region are indented less than
1360 COUNT columns."
1361 (interactive (if mark-active
1362 (list (region-beginning) (region-end) current-prefix-arg)
1363 (list (point) (point) current-prefix-arg)))
1364 (if count
1365 (setq count (prefix-numeric-value count))
1366 (setq count python-indent))
1367 (when (> count 0)
1368 (save-excursion
1369 (goto-char start)
1370 (while (< (point) end)
1371 (if (and (< (current-indentation) count)
1372 (not (looking-at "[ \t]*$")))
1373 (error "Can't shift all lines enough"))
1374 (forward-line))
1375 (indent-rigidly start end (- count)))))
1376
1377 (add-to-list 'debug-ignored-errors "^Can't shift all lines enough")
1378
1379 (defun python-shift-right (start end &optional count)
1380 "Shift lines in region COUNT (the prefix arg) columns to the right.
1381 COUNT defaults to `python-indent'. If region isn't active, just shift
1382 current line. The region shifted includes the lines in which START and
1383 END lie."
1384 (interactive (if mark-active
1385 (list (region-beginning) (region-end) current-prefix-arg)
1386 (list (point) (point) current-prefix-arg)))
1387 (if count
1388 (setq count (prefix-numeric-value count))
1389 (setq count python-indent))
1390 (indent-rigidly start end count))
1391
1392 (defun python-outline-level ()
1393 "`outline-level' function for Python mode.
1394 The level is the number of `python-indent' steps of indentation."
1395 (/ (current-indentation) python-indent))
1396
1397 ;; Fixme: Consider top-level assignments, imports, &c.
1398 (defun python-current-defun ()
1399 "`add-log-current-defun-function' for Python."
1400 (save-excursion
1401 ;; Move up the tree of nested `class' and `def' blocks until we
1402 ;; get to zero indentation, accumulating the defined names.
1403 (let ((start t)
1404 accum)
1405 (while (or start (> (current-indentation) 0))
1406 (setq start nil)
1407 (python-beginning-of-block)
1408 (end-of-line)
1409 (beginning-of-defun)
1410 (if (looking-at (rx (and (0+ space) (or "def" "class") (1+ space)
1411 (group (1+ (or word (syntax symbol))))
1412 word-end)))
1413 (push (match-string 1) accum)))
1414 (if accum (mapconcat 'identity accum ".")))))
1415
1416 (defun python-mark-block ()
1417 "Mark the block around point.
1418 Uses `python-beginning-of-block', `python-end-of-block'."
1419 (interactive)
1420 (push-mark)
1421 (python-beginning-of-block)
1422 (push-mark (point) nil t)
1423 (python-end-of-block)
1424 (exchange-point-and-mark))
1425
1426 ;;;; Modes.
1427
1428 ;;;###autoload
1429 (define-derived-mode python-mode fundamental-mode "Python"
1430 "Major mode for editing Python files.
1431 Turns on Font Lock mode unconditionally since it is required for correct
1432 parsing of the source.
1433 See also `jython-mode', which is actually invoked if the buffer appears to
1434 contain Jython code.
1435
1436 The Emacs commands which work with `defun's, e.g. \\[beginning-of-defun], deal
1437 with nested `def' and `class' blocks. They take the innermost one as
1438 current without distinguishing method and class definitions.
1439 \\<python-mode-map>
1440 Colon is electric: it outdents the line if appropriate, e.g. for
1441 an else statement. \\[python-backspace] at the beginning of an indented statement
1442 deletes a level of indentation to close the current block; otherwise it
1443 deletes a charcter backward. TAB indents the current line relative to
1444 the preceding code. Successive TABs, with no intervening command, cycle
1445 through the possibilities for indentation on the basis of enclosing blocks.
1446
1447 \\{python-mode-map}"
1448 :group 'python
1449 (set (make-local-variable 'font-lock-defaults)
1450 '(python-font-lock-keywords nil nil ((?_ . "w")) nil
1451 (font-lock-syntactic-keywords
1452 . python-font-lock-syntactic-keywords)
1453 ;;; This probably isn't worth it.
1454 ;;; (font-lock-syntactic-face-function
1455 ;;; . python-font-lock-syntactic-face-function)
1456 ))
1457 (set (make-local-variable 'parse-sexp-lookup-properties) t)
1458 (set (make-local-variable 'comment-start) "# ")
1459 ;; Fixme: define a comment-indent-function?
1460 (set (make-local-variable 'indent-line-function) #'python-indent-line)
1461 (set (make-local-variable 'paragraph-start) "\\s-*$")
1462 (set (make-local-variable 'fill-paragraph-function)
1463 'python-fill-paragraph)
1464 (set (make-local-variable 'require-final-newline) t)
1465 (set (make-local-variable 'add-log-current-defun-function)
1466 #'python-current-defun)
1467 ;; Fixme: Generalize to do all blocks?
1468 (set (make-local-variable 'outline-regexp) "\\s-+\\(def\\|class\\)\\>")
1469 (set (make-local-variable 'outline-level) #'python-outline-level)
1470 (set (make-local-variable 'open-paren-in-column-0-is-defun-start) nil)
1471 (make-local-variable 'python-saved-check-command)
1472 (set (make-local-variable 'beginning-of-defun-function)
1473 'python-beginning-of-defun)
1474 (set (make-local-variable 'end-of-defun-function) 'python-end-of-defun)
1475 (setq imenu-create-index-function #'python-imenu-create-index)
1476 (unless font-lock-mode (font-lock-mode 1))
1477 (when python-guess-indent (python-guess-indent))
1478 (set (make-local-variable 'python-command) python-python-command)
1479 (unless (boundp 'python-mode-running) ; kill the recursion from jython-mode
1480 (let ((python-mode-running t))
1481 (python-maybe-jython))))
1482
1483 (custom-add-option 'python-mode-hook 'imenu-add-menubar-index)
1484 (custom-add-option 'python-mode-hook
1485 '(lambda ()
1486 "Turn on Indent Tabs mode."
1487 (set (make-local-variable 'indent-tabs-mode) t)))
1488
1489 ;;;###autoload
1490 (define-derived-mode jython-mode python-mode "Jython"
1491 "Major mode for editing Jython files.
1492 Like `python-mode', but sets up parameters for Jython subprocesses.
1493 Runs `jython-mode-hook' after `python-mode-hook'."
1494 :group 'python
1495 (set (make-local-variable 'python-command) python-jython-command))
1496
1497 (provide 'python)
1498 ;; arch-tag: 6fce1d99-a704-4de9-ba19-c6e4912b0554
1499 ;;; python.el ends here