Mercurial > dotfiles
comparison .elisp/python-mode.el @ 174:014e745b2d04
python-mode: updating to current bzr version
This is bzr revision 351, which is revision-id: barry@python.org-20090320013721-awwzwv1mfl7hicdf
author | Augie Fackler <durin42@gmail.com> |
---|---|
date | Wed, 16 Dec 2009 22:57:36 -0600 |
parents | b5d75594b356 |
children | 4741c022c7ae |
comparison
equal
deleted
inserted
replaced
173:fd92c15701ae | 174:014e745b2d04 |
---|---|
1 ;;; python-mode.el --- Major mode for editing Python programs | 1 ;;; python-mode.el --- Major mode for editing Python programs |
2 | 2 |
3 ;; Copyright (C) 1992,1993,1994 Tim Peters | 3 ;; Copyright (C) 1992,1993,1994 Tim Peters |
4 | 4 |
5 ;; Author: 2003-2004 http://sf.net/projects/python-mode | 5 ;; Author: 2003-2009 https://launchpad.net/python-mode |
6 ;; 1995-2002 Barry A. Warsaw | 6 ;; 1995-2002 Barry A. Warsaw |
7 ;; 1992-1994 Tim Peters | 7 ;; 1992-1994 Tim Peters |
8 ;; Maintainer: python-mode@python.org | 8 ;; Maintainer: python-mode@python.org |
9 ;; Created: Feb 1992 | 9 ;; Created: Feb 1992 |
10 ;; Keywords: python languages oop | 10 ;; Keywords: python languages oop |
11 | 11 |
12 (defconst py-version "$Revision: 4.75 $" | 12 (defconst py-version "5.1.0+" |
13 "`python-mode' version number.") | 13 "`python-mode' version number.") |
14 | 14 |
15 ;; This software is provided as-is, without express or implied | 15 ;; This file is part of python-mode.el. |
16 ;; warranty. Permission to use, copy, modify, distribute or sell this | 16 ;; |
17 ;; software, without fee, for any purpose and by any individual or | 17 ;; python-mode.el is free software: you can redistribute it and/or modify it |
18 ;; organization, is hereby granted, provided that the above copyright | 18 ;; under the terms of the GNU General Public License as published by the Free |
19 ;; notice and this paragraph appear in all copies. | 19 ;; Software Foundation, either version 3 of the License, or (at your option) |
20 ;; any later version. | |
21 ;; | |
22 ;; python-mode.el is distributed in the hope that it will be useful, but | |
23 ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
24 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
25 ;; for more details. | |
26 ;; | |
27 ;; You should have received a copy of the GNU General Public License along | |
28 ;; with python-mode.el. If not, see <http://www.gnu.org/licenses/>. | |
20 | 29 |
21 ;;; Commentary: | 30 ;;; Commentary: |
22 | 31 |
23 ;; This is a major mode for editing Python programs. It was developed by Tim | 32 ;; This is a major mode for editing Python programs. It was developed by Tim |
24 ;; Peters after an original idea by Michael A. Guravage. Tim subsequently | 33 ;; Peters after an original idea by Michael A. Guravage. Tim subsequently |
25 ;; left the net and in 1995, Barry Warsaw inherited the mode. Tim's now back | 34 ;; left the net and in 1995, Barry Warsaw inherited the mode. Tim came back |
26 ;; but disavows all responsibility for the mode. In fact, we suspect he | 35 ;; but disavowed all responsibility for the mode. In fact, we suspect he |
27 ;; doesn't even use Emacs any more. In 2003, python-mode.el was moved to its | 36 ;; doesn't even use Emacs any more <wink>. In 2003, python-mode.el was moved |
28 ;; own SourceForge project apart from the Python project, and now is | 37 ;; to its own SourceForge project apart from the Python project, and in 2008 |
29 ;; maintained by the volunteers at the python-mode@python.org mailing list. | 38 ;; it was moved to Launchpad for all project administration. python-mode.el |
39 ;; is maintained by the volunteers at the python-mode@python.org mailing | |
40 ;; list. | |
41 | |
42 ;; python-mode.el is different than, and pre-dates by many years, the | |
43 ;; python.el that comes with FSF Emacs. We'd like to merge the two modes but | |
44 ;; have few cycles to do so. Volunteers are welcome. | |
30 | 45 |
31 ;; pdbtrack support contributed by Ken Manheimer, April 2001. Skip Montanaro | 46 ;; pdbtrack support contributed by Ken Manheimer, April 2001. Skip Montanaro |
32 ;; has also contributed significantly to python-mode's development. | 47 ;; has also contributed significantly to python-mode's development. |
33 | 48 |
34 ;; Please use the SourceForge Python project to submit bugs or | 49 ;; Please use Launchpad to submit bugs or patches: |
35 ;; patches: | |
36 ;; | 50 ;; |
37 ;; http://sourceforge.net/projects/python | 51 ;; https://launchpad.net/python-mode |
38 | 52 |
39 ;; INSTALLATION: | 53 ;; INSTALLATION: |
40 | 54 |
41 ;; To install, just drop this file into a directory on your load-path and | 55 ;; To install, just drop this file into a directory on your load-path and |
42 ;; byte-compile it. To set up Emacs to automatically edit files ending in | 56 ;; byte-compile it. To set up Emacs to automatically edit files ending in |
50 ;; In XEmacs syntax highlighting should be enabled automatically. In GNU | 64 ;; In XEmacs syntax highlighting should be enabled automatically. In GNU |
51 ;; Emacs you may have to add these lines to your ~/.emacs file: | 65 ;; Emacs you may have to add these lines to your ~/.emacs file: |
52 ;; (global-font-lock-mode t) | 66 ;; (global-font-lock-mode t) |
53 ;; (setq font-lock-maximum-decoration t) | 67 ;; (setq font-lock-maximum-decoration t) |
54 | 68 |
55 ;; FOR MORE INFORMATION: | |
56 | |
57 ;; There is some information on python-mode.el at | |
58 | |
59 ;; http://www.python.org/emacs/python-mode/ | |
60 ;; | |
61 ;; It does contain links to other packages that you might find useful, | |
62 ;; such as pdb interfaces, OO-Browser links, etc. | |
63 | |
64 ;; BUG REPORTING: | 69 ;; BUG REPORTING: |
65 | 70 |
66 ;; As mentioned above, please use the SourceForge Python project for | 71 ;; As mentioned above, please use the Launchpad python-mode project for |
67 ;; submitting bug reports or patches. The old recommendation, to use | 72 ;; submitting bug reports or patches. The old recommendation, to use C-c C-b |
68 ;; C-c C-b will still work, but those reports have a higher chance of | 73 ;; will still work, but those reports have a higher chance of getting buried |
69 ;; getting buried in my mailbox. Please include a complete, but | 74 ;; in our inboxes. Please include a complete, but concise code sample and a |
70 ;; concise code sample and a recipe for reproducing the bug. Send | 75 ;; recipe for reproducing the bug. Send suggestions and other comments to |
71 ;; suggestions and other comments to python-mode@python.org. | 76 ;; python-mode@python.org. |
72 | 77 |
73 ;; When in a Python mode buffer, do a C-h m for more help. It's | 78 ;; When in a Python mode buffer, do a C-h m for more help. It's doubtful that |
74 ;; doubtful that a texinfo manual would be very useful, but if you | 79 ;; a texinfo manual would be very useful, but if you want to contribute one, |
75 ;; want to contribute one, I'll certainly accept it! | 80 ;; we'll certainly accept it! |
76 | 81 |
77 ;;; Code: | 82 ;;; Code: |
78 | 83 |
79 (require 'comint) | 84 (require 'comint) |
80 (require 'custom) | 85 (require 'custom) |
123 | 128 |
124 Note that this variable is consulted only the first time that a Python | 129 Note that this variable is consulted only the first time that a Python |
125 mode buffer is visited during an Emacs session. After that, use | 130 mode buffer is visited during an Emacs session. After that, use |
126 \\[py-toggle-shells] to change the interpreter shell." | 131 \\[py-toggle-shells] to change the interpreter shell." |
127 :type '(choice (const :tag "Python (a.k.a. CPython)" cpython) | 132 :type '(choice (const :tag "Python (a.k.a. CPython)" cpython) |
128 (const :tag "Jython" jython)) | 133 (const :tag "Jython" jython)) |
129 :group 'python) | 134 :group 'python) |
130 | 135 |
131 (defcustom py-python-command-args '("-i") | 136 (defcustom py-python-command-args '("-i") |
132 "*List of string arguments to be used when starting a Python shell." | 137 "*List of string arguments to be used when starting a Python shell." |
133 :type '(repeat string) | 138 :type '(repeat string) |
181 "*Flag describing how multi-line triple quoted strings are aligned. | 186 "*Flag describing how multi-line triple quoted strings are aligned. |
182 When this flag is non-nil, continuation lines are lined up under the | 187 When this flag is non-nil, continuation lines are lined up under the |
183 preceding line's indentation. When this flag is nil, continuation | 188 preceding line's indentation. When this flag is nil, continuation |
184 lines are aligned to column zero." | 189 lines are aligned to column zero." |
185 :type '(choice (const :tag "Align under preceding line" t) | 190 :type '(choice (const :tag "Align under preceding line" t) |
186 (const :tag "Align to column zero" nil)) | 191 (const :tag "Align to column zero" nil)) |
187 :group 'python) | 192 :group 'python) |
188 | 193 |
189 (defcustom py-block-comment-prefix "##" | 194 (defcustom py-block-comment-prefix "##" |
190 "*String used by \\[comment-region] to comment out a block of code. | 195 "*String used by \\[comment-region] to comment out a block of code. |
191 This should follow the convention for non-indenting comment lines so | 196 This should follow the convention for non-indenting comment lines so |
209 purposes. | 214 purposes. |
210 | 215 |
211 When not nil or t, comment lines that begin with a single `#' are used | 216 When not nil or t, comment lines that begin with a single `#' are used |
212 as indentation hints, unless the comment character is in column zero." | 217 as indentation hints, unless the comment character is in column zero." |
213 :type '(choice | 218 :type '(choice |
214 (const :tag "Skip all comment lines (fast)" nil) | 219 (const :tag "Skip all comment lines (fast)" nil) |
215 (const :tag "Single # `sets' indentation for next line" t) | 220 (const :tag "Single # `sets' indentation for next line" t) |
216 (const :tag "Single # `sets' indentation except at column zero" | 221 (const :tag "Single # `sets' indentation except at column zero" |
217 other) | 222 other) |
218 ) | 223 ) |
219 :group 'python) | 224 :group 'python) |
220 | 225 |
221 (defcustom py-temp-directory | 226 (defcustom py-temp-directory |
222 (let ((ok '(lambda (x) | 227 (let ((ok '(lambda (x) |
223 (and x | 228 (and x |
224 (setq x (expand-file-name x)) ; always true | 229 (setq x (expand-file-name x)) ; always true |
225 (file-directory-p x) | 230 (file-directory-p x) |
226 (file-writable-p x) | 231 (file-writable-p x) |
227 x)))) | 232 x)))) |
228 (or (funcall ok (getenv "TMPDIR")) | 233 (or (funcall ok (getenv "TMPDIR")) |
229 (funcall ok "/usr/tmp") | 234 (funcall ok "/usr/tmp") |
230 (funcall ok "/tmp") | 235 (funcall ok "/tmp") |
231 (funcall ok "/var/tmp") | 236 (funcall ok "/var/tmp") |
232 (funcall ok ".") | 237 (funcall ok ".") |
233 (error | 238 (error |
234 "Couldn't find a usable temp directory -- set `py-temp-directory'"))) | 239 "Couldn't find a usable temp directory -- set `py-temp-directory'"))) |
235 "*Directory used for temporary files created by a *Python* process. | 240 "*Directory used for temporary files created by a *Python* process. |
236 By default, the first directory from this list that exists and that you | 241 By default, the first directory from this list that exists and that you |
237 can write into: the value (if any) of the environment variable TMPDIR, | 242 can write into: the value (if any) of the environment variable TMPDIR, |
238 /usr/tmp, /tmp, /var/tmp, or the current directory." | 243 /usr/tmp, /tmp, /var/tmp, or the current directory." |
239 :type 'string | 244 :type 'string |
400 ;; Face for builtins | 405 ;; Face for builtins |
401 (defvar py-builtins-face 'py-builtins-face | 406 (defvar py-builtins-face 'py-builtins-face |
402 "Face for builtins like TypeError, object, open, and exec.") | 407 "Face for builtins like TypeError, object, open, and exec.") |
403 (make-face 'py-builtins-face) | 408 (make-face 'py-builtins-face) |
404 | 409 |
410 ;; XXX, TODO, and FIXME comments and such | |
411 (defvar py-XXX-tag-face 'py-XXX-tag-face | |
412 "Face for XXX, TODO, and FIXME tags") | |
413 (make-face 'py-XXX-tag-face) | |
414 | |
405 (defun py-font-lock-mode-hook () | 415 (defun py-font-lock-mode-hook () |
406 (or (face-differs-from-default-p 'py-pseudo-keyword-face) | 416 (or (face-differs-from-default-p 'py-pseudo-keyword-face) |
407 (copy-face 'font-lock-keyword-face 'py-pseudo-keyword-face)) | 417 (copy-face 'font-lock-keyword-face 'py-pseudo-keyword-face)) |
408 (or (face-differs-from-default-p 'py-builtins-face) | 418 (or (face-differs-from-default-p 'py-builtins-face) |
409 (copy-face 'font-lock-keyword-face 'py-builtins-face)) | 419 (copy-face 'font-lock-keyword-face 'py-builtins-face)) |
410 (or (face-differs-from-default-p 'py-decorators-face) | 420 (or (face-differs-from-default-p 'py-decorators-face) |
411 (copy-face 'py-pseudo-keyword-face 'py-decorators-face)) | 421 (copy-face 'py-pseudo-keyword-face 'py-decorators-face)) |
422 (or (face-differs-from-default-p 'py-XXX-tag-face) | |
423 (copy-face 'font-lock-comment-face 'py-XXX-tag-face)) | |
412 ) | 424 ) |
413 (add-hook 'font-lock-mode-hook 'py-font-lock-mode-hook) | 425 (add-hook 'font-lock-mode-hook 'py-font-lock-mode-hook) |
414 | 426 |
415 (defvar python-font-lock-keywords | 427 (defvar python-font-lock-keywords |
416 (let ((kw1 (mapconcat 'identity | 428 (let ((kw1 (mapconcat 'identity |
417 '("and" "assert" "break" "class" | 429 '("and" "assert" "break" "class" |
418 "continue" "def" "del" "elif" | 430 "continue" "def" "del" "elif" |
419 "else" "except" "exec" "for" | 431 "else" "except" "for" "from" |
420 "from" "global" "if" "import" | 432 "global" "if" "import" "in" |
421 "in" "is" "lambda" "not" | 433 "is" "lambda" "not" "or" |
422 "or" "pass" "print" "raise" | 434 "pass" "raise" "as" "return" |
423 "return" "while" "yield" | 435 "while" "with" "yield" |
424 ) | 436 ) |
425 "\\|")) | 437 "\\|")) |
426 (kw2 (mapconcat 'identity | 438 (kw2 (mapconcat 'identity |
427 '("else:" "except:" "finally:" "try:") | 439 '("else:" "except:" "finally:" "try:") |
428 "\\|")) | 440 "\\|")) |
429 (kw3 (mapconcat 'identity | 441 (kw3 (mapconcat 'identity |
430 ;; Don't include True, False, None, or | 442 ;; Don't include Ellipsis in this list, since it is |
431 ;; Ellipsis in this list, since they are | 443 ;; already defined as a pseudo keyword. |
432 ;; already defined as pseudo keywords. | 444 '("__debug__" |
433 '("__debug__" | 445 "__import__" "__name__" "abs" "all" "any" "apply" |
434 "__import__" "__name__" "abs" "apply" "basestring" | 446 "basestring" "bin" "bool" "buffer" "bytearray" |
435 "bool" "buffer" "callable" "chr" "classmethod" | 447 "callable" "chr" "classmethod" "cmp" "coerce" |
436 "cmp" "coerce" "compile" "complex" "copyright" | 448 "compile" "complex" "copyright" "credits" |
437 "delattr" "dict" "dir" "divmod" | 449 "delattr" "dict" "dir" "divmod" "enumerate" "eval" |
438 "enumerate" "eval" "execfile" "exit" "file" | 450 "exec" "execfile" "exit" "file" "filter" "float" |
439 "filter" "float" "getattr" "globals" "hasattr" | 451 "format" "getattr" "globals" "hasattr" "hash" "help" |
440 "hash" "hex" "id" "input" "int" "intern" | 452 "hex" "id" "input" "int" "intern" "isinstance" |
441 "isinstance" "issubclass" "iter" "len" "license" | 453 "issubclass" "iter" "len" "license" "list" "locals" |
442 "list" "locals" "long" "map" "max" "min" "object" | 454 "long" "map" "max" "memoryview" "min" "next" |
443 "oct" "open" "ord" "pow" "property" "range" | 455 "object" "oct" "open" "ord" "pow" "print" "property" |
444 "raw_input" "reduce" "reload" "repr" "round" | 456 "quit" "range" "raw_input" "reduce" "reload" "repr" |
445 "setattr" "slice" "staticmethod" "str" "sum" | 457 "round" "set" "setattr" "slice" "sorted" |
446 "super" "tuple" "type" "unichr" "unicode" "vars" | 458 "staticmethod" "str" "sum" "super" "tuple" "type" |
447 "xrange" "zip") | 459 "unichr" "unicode" "vars" "xrange" "zip") |
448 "\\|")) | 460 "\\|")) |
449 (kw4 (mapconcat 'identity | 461 (kw4 (mapconcat 'identity |
450 ;; Exceptions and warnings | 462 ;; Exceptions and warnings |
451 '("ArithmeticError" "AssertionError" | 463 '("ArithmeticError" "AssertionError" |
452 "AttributeError" "DeprecationWarning" "EOFError" | 464 "AttributeError" "BaseException" "BufferError" |
453 "EnvironmentError" "Exception" | 465 "BytesWarning" "DeprecationWarning" "EOFError" |
454 "FloatingPointError" "FutureWarning" "IOError" | 466 "EnvironmentError" "Exception" |
455 "ImportError" "IndentationError" "IndexError" | 467 "FloatingPointError" "FutureWarning" "GeneratorExit" |
456 "KeyError" "KeyboardInterrupt" "LookupError" | 468 "IOError" "ImportError" "ImportWarning" |
457 "MemoryError" "NameError" "NotImplemented" | 469 "IndentationError" "IndexError" |
458 "NotImplementedError" "OSError" "OverflowError" | 470 "KeyError" "KeyboardInterrupt" "LookupError" |
459 "OverflowWarning" "PendingDeprecationWarning" | 471 "MemoryError" "NameError" "NotImplemented" |
460 "ReferenceError" "RuntimeError" "RuntimeWarning" | 472 "NotImplementedError" "OSError" "OverflowError" |
461 "StandardError" "StopIteration" "SyntaxError" | 473 "PendingDeprecationWarning" "ReferenceError" |
462 "SyntaxWarning" "SystemError" "SystemExit" | 474 "RuntimeError" "RuntimeWarning" "StandardError" |
463 "TabError" "TypeError" "UnboundLocalError" | 475 "StopIteration" "SyntaxError" "SyntaxWarning" |
464 "UnicodeDecodeError" "UnicodeEncodeError" | 476 "SystemError" "SystemExit" "TabError" "TypeError" |
465 "UnicodeError" "UnicodeTranslateError" | 477 "UnboundLocalError" "UnicodeDecodeError" |
466 "UserWarning" "ValueError" "Warning" | 478 "UnicodeEncodeError" "UnicodeError" |
467 "ZeroDivisionError") | 479 "UnicodeTranslateError" "UnicodeWarning" |
468 "\\|")) | 480 "UserWarning" "ValueError" "Warning" |
469 ) | 481 "ZeroDivisionError") |
482 "\\|")) | |
483 ) | |
470 (list | 484 (list |
471 '("^[ \t]*\\(@.+\\)" 1 'py-decorators-face) | 485 '("^[ \t]*\\(@.+\\)" 1 'py-decorators-face) |
472 ;; keywords | 486 ;; keywords |
473 (cons (concat "\\<\\(" kw1 "\\)\\>[ \n\t(]") 1) | 487 (cons (concat "\\<\\(" kw1 "\\)\\>[ \n\t(]") 1) |
474 ;; builtins when they don't appear as object attributes | 488 ;; builtins when they don't appear as object attributes |
475 (list (concat "\\([^. \t]\\|^\\)[ \t]*\\<\\(" kw3 "\\)\\>[ \n\t(]") 2 | 489 (list (concat "\\([^. \t]\\|^\\)[ \t]*\\<\\(" kw3 "\\)\\>[ \n\t(]") 2 |
476 'py-builtins-face) | 490 'py-builtins-face) |
477 ;; block introducing keywords with immediately following colons. | 491 ;; block introducing keywords with immediately following colons. |
478 ;; Yes "except" is in both lists. | 492 ;; Yes "except" is in both lists. |
479 (cons (concat "\\<\\(" kw2 "\\)[ \n\t(]") 1) | 493 (cons (concat "\\<\\(" kw2 "\\)[ \n\t(]") 1) |
480 ;; Exceptions | 494 ;; Exceptions |
481 (list (concat "\\<\\(" kw4 "\\)[ \n\t:,(]") 1 'py-builtins-face) | 495 (list (concat "\\<\\(" kw4 "\\)[ \n\t:,(]") 1 'py-builtins-face) |
482 ;; `as' but only in "import foo as bar" | |
483 '("[ \t]*\\(\\<from\\>.*\\)?\\<import\\>.*\\<\\(as\\)\\>" . 2) | |
484 | |
485 ;; classes | 496 ;; classes |
486 '("\\<class[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)" 1 font-lock-type-face) | 497 '("\\<class[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)" 1 font-lock-type-face) |
487 ;; functions | 498 ;; functions |
488 '("\\<def[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)" | 499 '("\\<def[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)" |
489 1 font-lock-function-name-face) | 500 1 font-lock-function-name-face) |
490 ;; pseudo-keywords | 501 ;; pseudo-keywords |
491 '("\\<\\(self\\|None\\|True\\|False\\|Ellipsis\\)\\>" | 502 '("\\<\\(self\\|Ellipsis\\|True\\|False\\|None\\)\\>" |
492 1 py-pseudo-keyword-face) | 503 1 py-pseudo-keyword-face) |
504 ;; XXX, TODO, and FIXME tags | |
505 '("XXX\\|TODO\\|FIXME" 0 py-XXX-tag-face t) | |
493 )) | 506 )) |
494 "Additional expressions to highlight in Python mode.") | 507 "Additional expressions to highlight in Python mode.") |
495 (put 'python-mode 'font-lock-defaults '(python-font-lock-keywords)) | 508 (put 'python-mode 'font-lock-defaults '(python-font-lock-keywords)) |
496 | 509 |
497 ;; have to bind py-file-queue before installing the kill-emacs-hook | 510 ;; have to bind py-file-queue before installing the kill-emacs-hook |
519 "\\|" | 532 "\\|" |
520 ;; (maybe raw), long double quoted triple quoted strings (DQTQ), | 533 ;; (maybe raw), long double quoted triple quoted strings (DQTQ), |
521 ;; with potential embedded double quotes | 534 ;; with potential embedded double quotes |
522 "[rR]?\"\"\"[^\"]*\\(\\(\"[^\"]\\|\"\"[^\"]\\)[^\"]*\\)*\"\"\"" | 535 "[rR]?\"\"\"[^\"]*\\(\\(\"[^\"]\\|\"\"[^\"]\\)[^\"]*\\)*\"\"\"" |
523 "\\|" | 536 "\\|" |
524 "[rR]?'\\([^'\n\\]\\|\\\\.\\)*'" ; single-quoted | 537 "[rR]?'\\([^'\n\\]\\|\\\\.\\)*'" ; single-quoted |
525 "\\|" ; or | 538 "\\|" ; or |
526 "[rR]?\"\\([^\"\n\\]\\|\\\\.\\)*\"" ; double-quoted | 539 "[rR]?\"\\([^\"\n\\]\\|\\\\.\\)*\"" ; double-quoted |
527 ) | 540 ) |
528 "Regular expression matching a Python string literal.") | 541 "Regular expression matching a Python string literal.") |
529 | 542 |
530 (defconst py-continued-re | 543 (defconst py-continued-re |
531 ;; This is tricky because a trailing backslash does not mean | 544 ;; This is tricky because a trailing backslash does not mean |
538 (defconst py-blank-or-comment-re "[ \t]*\\($\\|#\\)" | 551 (defconst py-blank-or-comment-re "[ \t]*\\($\\|#\\)" |
539 "Regular expression matching a blank or comment line.") | 552 "Regular expression matching a blank or comment line.") |
540 | 553 |
541 (defconst py-outdent-re | 554 (defconst py-outdent-re |
542 (concat "\\(" (mapconcat 'identity | 555 (concat "\\(" (mapconcat 'identity |
543 '("else:" | 556 '("else:" |
544 "except\\(\\s +.*\\)?:" | 557 "except\\(\\s +.*\\)?:" |
545 "finally:" | 558 "finally:" |
546 "elif\\s +.*:") | 559 "elif\\s +.*:") |
547 "\\|") | 560 "\\|") |
548 "\\)") | 561 "\\)") |
549 "Regular expression matching statements to be dedented one level.") | 562 "Regular expression matching statements to be dedented one level.") |
550 | 563 |
551 (defconst py-block-closing-keywords-re | 564 (defconst py-block-closing-keywords-re |
552 "\\(return\\|raise\\|break\\|continue\\|pass\\)" | 565 "\\(return\\|raise\\|break\\|continue\\|pass\\)" |
553 "Regular expression matching keywords which typically close a block.") | 566 "Regular expression matching keywords which typically close a block.") |
554 | 567 |
555 (defconst py-no-outdent-re | 568 (defconst py-no-outdent-re |
556 (concat | 569 (concat |
557 "\\(" | 570 "\\(" |
558 (mapconcat 'identity | 571 (mapconcat 'identity |
559 (list "try:" | 572 (list "try:" |
560 "except\\(\\s +.*\\)?:" | 573 "except\\(\\s +.*\\)?:" |
561 "while\\s +.*:" | 574 "while\\s +.*:" |
562 "for\\s +.*:" | 575 "for\\s +.*:" |
563 "if\\s +.*:" | 576 "if\\s +.*:" |
564 "elif\\s +.*:" | 577 "elif\\s +.*:" |
565 (concat py-block-closing-keywords-re "[ \t\n]") | 578 (concat py-block-closing-keywords-re "[ \t\n]") |
566 ) | 579 ) |
567 "\\|") | 580 "\\|") |
568 "\\)") | 581 "\\)") |
569 "Regular expression matching lines not to dedent after.") | 582 "Regular expression matching lines not to dedent after.") |
570 | 583 |
571 (defvar py-traceback-line-re | 584 (defvar py-traceback-line-re |
572 "[ \t]+File \"\\([^\"]+\\)\", line \\([0-9]+\\)" | 585 "[ \t]+File \"\\([^\"]+\\)\", line \\([0-9]+\\)" |
573 "Regular expression that describes tracebacks.") | 586 "Regular expression that describes tracebacks.") |
652 (define-key py-mode-map "\C-c\C-k" 'py-mark-block) | 665 (define-key py-mode-map "\C-c\C-k" 'py-mark-block) |
653 ;; Miscellaneous | 666 ;; Miscellaneous |
654 (define-key py-mode-map "\C-c:" 'py-guess-indent-offset) | 667 (define-key py-mode-map "\C-c:" 'py-guess-indent-offset) |
655 (define-key py-mode-map "\C-c\t" 'py-indent-region) | 668 (define-key py-mode-map "\C-c\t" 'py-indent-region) |
656 (define-key py-mode-map "\C-c\C-d" 'py-pdbtrack-toggle-stack-tracking) | 669 (define-key py-mode-map "\C-c\C-d" 'py-pdbtrack-toggle-stack-tracking) |
670 (define-key py-mode-map "\C-c\C-f" 'py-sort-imports) | |
657 (define-key py-mode-map "\C-c\C-n" 'py-next-statement) | 671 (define-key py-mode-map "\C-c\C-n" 'py-next-statement) |
658 (define-key py-mode-map "\C-c\C-p" 'py-previous-statement) | 672 (define-key py-mode-map "\C-c\C-p" 'py-previous-statement) |
659 (define-key py-mode-map "\C-c\C-u" 'py-goto-block-up) | 673 (define-key py-mode-map "\C-c\C-u" 'py-goto-block-up) |
660 (define-key py-mode-map "\C-c#" 'py-comment-region) | 674 (define-key py-mode-map "\C-c#" 'py-comment-region) |
661 (define-key py-mode-map "\C-c?" 'py-describe-mode) | 675 (define-key py-mode-map "\C-c?" 'py-describe-mode) |
672 (define-key py-mode-map "\C-c\C-v" 'py-version) | 686 (define-key py-mode-map "\C-c\C-v" 'py-version) |
673 (define-key py-mode-map "\C-c\C-w" 'py-pychecker-run) | 687 (define-key py-mode-map "\C-c\C-w" 'py-pychecker-run) |
674 ;; shadow global bindings for newline-and-indent w/ the py- version. | 688 ;; shadow global bindings for newline-and-indent w/ the py- version. |
675 ;; BAW - this is extremely bad form, but I'm not going to change it | 689 ;; BAW - this is extremely bad form, but I'm not going to change it |
676 ;; for now. | 690 ;; for now. |
677 (mapcar #'(lambda (key) | 691 (mapc #'(lambda (key) |
678 (define-key py-mode-map key 'py-newline-and-indent)) | 692 (define-key py-mode-map key 'py-newline-and-indent)) |
679 (where-is-internal 'newline-and-indent)) | 693 (where-is-internal 'newline-and-indent)) |
680 ;; Force RET to be py-newline-and-indent even if it didn't get | 694 ;; Force RET to be py-newline-and-indent even if it didn't get |
681 ;; mapped by the above code. motivation: Emacs' default binding for | 695 ;; mapped by the above code. motivation: Emacs' default binding for |
682 ;; RET is `newline' and C-j is `newline-and-indent'. Most Pythoneers | 696 ;; RET is `newline' and C-j is `newline-and-indent'. Most Pythoneers |
683 ;; expect RET to do a `py-newline-and-indent' and any Emacsers who | 697 ;; expect RET to do a `py-newline-and-indent' and any Emacsers who |
684 ;; dislike this are probably knowledgeable enough to do a rebind. | 698 ;; dislike this are probably knowledgeable enough to do a rebind. |
695 (setq py-mode-output-map (make-sparse-keymap)) | 709 (setq py-mode-output-map (make-sparse-keymap)) |
696 (define-key py-mode-output-map [button2] 'py-mouseto-exception) | 710 (define-key py-mode-output-map [button2] 'py-mouseto-exception) |
697 (define-key py-mode-output-map "\C-c\C-c" 'py-goto-exception) | 711 (define-key py-mode-output-map "\C-c\C-c" 'py-goto-exception) |
698 ;; TBD: Disable all self-inserting keys. This is bogus, we should | 712 ;; TBD: Disable all self-inserting keys. This is bogus, we should |
699 ;; really implement this as *Python Output* buffer being read-only | 713 ;; really implement this as *Python Output* buffer being read-only |
700 (mapcar #' (lambda (key) | 714 (mapc #' (lambda (key) |
701 (define-key py-mode-output-map key | 715 (define-key py-mode-output-map key |
702 #'(lambda () (interactive) (beep)))) | 716 #'(lambda () (interactive) (beep)))) |
703 (where-is-internal 'self-insert-command)) | 717 (where-is-internal 'self-insert-command)) |
704 ) | 718 ) |
705 | 719 |
706 (defvar py-shell-map nil | 720 (defvar py-shell-map nil |
707 "Keymap used in *Python* shell buffers.") | 721 "Keymap used in *Python* shell buffers.") |
708 (if py-shell-map | 722 (if py-shell-map |
760 ;; symbol class for simplicity | 774 ;; symbol class for simplicity |
761 (defvar py-dotted-expression-syntax-table nil | 775 (defvar py-dotted-expression-syntax-table nil |
762 "Syntax table used to identify Python dotted expressions.") | 776 "Syntax table used to identify Python dotted expressions.") |
763 (when (not py-dotted-expression-syntax-table) | 777 (when (not py-dotted-expression-syntax-table) |
764 (setq py-dotted-expression-syntax-table | 778 (setq py-dotted-expression-syntax-table |
765 (copy-syntax-table py-mode-syntax-table)) | 779 (copy-syntax-table py-mode-syntax-table)) |
766 (modify-syntax-entry ?_ "_" py-dotted-expression-syntax-table) | 780 (modify-syntax-entry ?_ "_" py-dotted-expression-syntax-table) |
767 (modify-syntax-entry ?. "_" py-dotted-expression-syntax-table)) | 781 (modify-syntax-entry ?. "_" py-dotted-expression-syntax-table)) |
768 | 782 |
769 | 783 |
770 | 784 |
771 ;; Utilities | 785 ;; Utilities |
772 (defmacro py-safe (&rest body) | 786 (defmacro py-safe (&rest body) |
773 "Safely execute BODY, return nil if an error occurred." | 787 "Safely execute BODY, return nil if an error occurred." |
774 (` (condition-case nil | 788 `(condition-case nil |
775 (progn (,@ body)) | 789 (progn ,@ body) |
776 (error nil)))) | 790 (error nil))) |
777 | 791 |
778 (defsubst py-keep-region-active () | 792 (defsubst py-keep-region-active () |
779 "Keep the region active in XEmacs." | 793 "Keep the region active in XEmacs." |
780 ;; Ignore byte-compiler warnings you might see. Also note that | 794 ;; Ignore byte-compiler warnings you might see. Also note that |
781 ;; FSF's Emacs 19 does it differently; its policy doesn't require us | 795 ;; FSF's Emacs 19 does it differently; its policy doesn't require us |
802 ((eq position 'bol) (beginning-of-line)) | 816 ((eq position 'bol) (beginning-of-line)) |
803 ((eq position 'eol) (end-of-line)) | 817 ((eq position 'eol) (end-of-line)) |
804 ((eq position 'bod) (py-beginning-of-def-or-class 'either)) | 818 ((eq position 'bod) (py-beginning-of-def-or-class 'either)) |
805 ((eq position 'eod) (py-end-of-def-or-class 'either)) | 819 ((eq position 'eod) (py-end-of-def-or-class 'either)) |
806 ;; Kind of funny, I know, but useful for py-up-exception. | 820 ;; Kind of funny, I know, but useful for py-up-exception. |
807 ((eq position 'bob) (beginning-of-buffer)) | 821 ((eq position 'bob) (goto-char (point-min))) |
808 ((eq position 'eob) (end-of-buffer)) | 822 ((eq position 'eob) (goto-char (point-max))) |
809 ((eq position 'boi) (back-to-indentation)) | 823 ((eq position 'boi) (back-to-indentation)) |
810 ((eq position 'bos) (py-goto-initial-line)) | 824 ((eq position 'bos) (py-goto-initial-line)) |
811 (t (error "Unknown buffer position requested: %s" position)) | 825 (t (error "Unknown buffer position requested: %s" position)) |
812 ) | 826 ) |
813 (prog1 | 827 (prog1 |
814 (point) | 828 (point) |
815 (goto-char here)))) | 829 (goto-char here)))) |
816 | 830 |
817 (defsubst py-highlight-line (from to file line) | 831 (defsubst py-highlight-line (from to file line) |
818 (cond | 832 (cond |
819 ((fboundp 'make-extent) | 833 ((fboundp 'make-extent) |
834 ;; This is the version used for non-XEmacs, which has a nicer | 848 ;; This is the version used for non-XEmacs, which has a nicer |
835 ;; interface. | 849 ;; interface. |
836 ;; | 850 ;; |
837 ;; WARNING: Watch out for infinite recursion. | 851 ;; WARNING: Watch out for infinite recursion. |
838 (let* ((lim (or lim (py-point 'bod))) | 852 (let* ((lim (or lim (py-point 'bod))) |
839 (state (parse-partial-sexp lim (point)))) | 853 (state (parse-partial-sexp lim (point)))) |
840 (cond | 854 (cond |
841 ((nth 3 state) 'string) | 855 ((nth 3 state) 'string) |
842 ((nth 4 state) 'comment) | 856 ((nth 4 state) 'comment) |
843 (t nil)))) | 857 (t nil)))) |
844 | 858 |
864 | 878 |
865 (and (py-safe (require 'easymenu) t) | 879 (and (py-safe (require 'easymenu) t) |
866 (easy-menu-define | 880 (easy-menu-define |
867 py-menu py-mode-map "Python Mode menu" | 881 py-menu py-mode-map "Python Mode menu" |
868 '("Python" | 882 '("Python" |
869 ["Comment Out Region" py-comment-region (mark)] | 883 ["Comment Out Region" py-comment-region (mark)] |
870 ["Uncomment Region" (py-comment-region (point) (mark) '(4)) (mark)] | 884 ["Uncomment Region" (py-comment-region (point) (mark) '(4)) (mark)] |
871 "-" | 885 "-" |
872 ["Mark current block" py-mark-block t] | 886 ["Mark current block" py-mark-block t] |
873 ["Mark current def" py-mark-def-or-class t] | 887 ["Mark current def" py-mark-def-or-class t] |
874 ["Mark current class" (py-mark-def-or-class t) t] | 888 ["Mark current class" (py-mark-def-or-class t) t] |
875 "-" | 889 "-" |
876 ["Shift region left" py-shift-region-left (mark)] | 890 ["Shift region left" py-shift-region-left (mark)] |
877 ["Shift region right" py-shift-region-right (mark)] | 891 ["Shift region right" py-shift-region-right (mark)] |
878 "-" | 892 "-" |
879 ["Import/reload file" py-execute-import-or-reload t] | 893 ["Import/reload file" py-execute-import-or-reload t] |
880 ["Execute buffer" py-execute-buffer t] | 894 ["Execute buffer" py-execute-buffer t] |
881 ["Execute region" py-execute-region (mark)] | 895 ["Execute region" py-execute-region (mark)] |
882 ["Execute def or class" py-execute-def-or-class (mark)] | 896 ["Execute def or class" py-execute-def-or-class (mark)] |
883 ["Execute string" py-execute-string t] | 897 ["Execute string" py-execute-string t] |
884 ["Start interpreter..." py-shell t] | 898 ["Start interpreter..." py-shell t] |
885 "-" | 899 "-" |
886 ["Go to start of block" py-goto-block-up t] | 900 ["Go to start of block" py-goto-block-up t] |
887 ["Go to start of class" (py-beginning-of-def-or-class t) t] | 901 ["Go to start of class" (py-beginning-of-def-or-class t) t] |
888 ["Move to end of class" (py-end-of-def-or-class t) t] | 902 ["Move to end of class" (py-end-of-def-or-class t) t] |
889 ["Move to start of def" py-beginning-of-def-or-class t] | 903 ["Move to start of def" py-beginning-of-def-or-class t] |
890 ["Move to end of def" py-end-of-def-or-class t] | 904 ["Move to end of def" py-end-of-def-or-class t] |
891 "-" | 905 "-" |
892 ["Describe mode" py-describe-mode t] | 906 ["Describe mode" py-describe-mode t] |
893 ))) | 907 ))) |
894 | 908 |
895 | 909 |
896 | 910 |
897 ;; Imenu definitions | 911 ;; Imenu definitions |
898 (defvar py-imenu-class-regexp | 912 (defvar py-imenu-class-regexp |
899 (concat ; <<classes>> | 913 (concat ; <<classes>> |
900 "\\(" ; | 914 "\\(" ; |
901 "^[ \t]*" ; newline and maybe whitespace | 915 "^[ \t]*" ; newline and maybe whitespace |
902 "\\(class[ \t]+[a-zA-Z0-9_]+\\)" ; class name | 916 "\\(class[ \t]+[a-zA-Z0-9_]+\\)" ; class name |
903 ; possibly multiple superclasses | 917 ; possibly multiple superclasses |
904 "\\([ \t]*\\((\\([a-zA-Z0-9_,. \t\n]\\)*)\\)?\\)" | 918 "\\([ \t]*\\((\\([a-zA-Z0-9_,. \t\n]\\)*)\\)?\\)" |
905 "[ \t]*:" ; and the final : | 919 "[ \t]*:" ; and the final : |
906 "\\)" ; >>classes<< | 920 "\\)" ; >>classes<< |
907 ) | 921 ) |
908 "Regexp for Python classes for use with the Imenu package." | 922 "Regexp for Python classes for use with the Imenu package." |
909 ) | 923 ) |
910 | 924 |
911 (defvar py-imenu-method-regexp | 925 (defvar py-imenu-method-regexp |
912 (concat ; <<methods and functions>> | 926 (concat ; <<methods and functions>> |
913 "\\(" ; | 927 "\\(" ; |
914 "^[ \t]*" ; new line and maybe whitespace | 928 "^[ \t]*" ; new line and maybe whitespace |
915 "\\(def[ \t]+" ; function definitions start with def | 929 "\\(def[ \t]+" ; function definitions start with def |
916 "\\([a-zA-Z0-9_]+\\)" ; name is here | 930 "\\([a-zA-Z0-9_]+\\)" ; name is here |
917 ; function arguments... | 931 ; function arguments... |
918 ;; "[ \t]*(\\([-+/a-zA-Z0-9_=,\* \t\n.()\"'#]*\\))" | 932 ;; "[ \t]*(\\([-+/a-zA-Z0-9_=,\* \t\n.()\"'#]*\\))" |
919 "[ \t]*(\\([^:#]*\\))" | 933 "[ \t]*(\\([^:#]*\\))" |
920 "\\)" ; end of def | 934 "\\)" ; end of def |
921 "[ \t]*:" ; and then the : | 935 "[ \t]*:" ; and then the : |
922 "\\)" ; >>methods and functions<< | 936 "\\)" ; >>methods and functions<< |
946 ;; it. | 960 ;; it. |
947 (defvar py-imenu-generic-expression | 961 (defvar py-imenu-generic-expression |
948 (cons | 962 (cons |
949 (concat | 963 (concat |
950 py-imenu-class-regexp | 964 py-imenu-class-regexp |
951 "\\|" ; or... | 965 "\\|" ; or... |
952 py-imenu-method-regexp | 966 py-imenu-method-regexp |
953 ) | 967 ) |
954 py-imenu-method-no-arg-parens) | 968 py-imenu-method-no-arg-parens) |
955 "Generic Python expression which may be used directly with Imenu. | 969 "Generic Python expression which may be used directly with Imenu. |
956 Used by setting the variable `imenu-generic-expression' to this value. | 970 Used by setting the variable `imenu-generic-expression' to this value. |
968 "Python interface function for the Imenu package. | 982 "Python interface function for the Imenu package. |
969 Finds all Python classes and functions/methods. Calls function | 983 Finds all Python classes and functions/methods. Calls function |
970 \\[py-imenu-create-index-engine]. See that function for the details | 984 \\[py-imenu-create-index-engine]. See that function for the details |
971 of how this works." | 985 of how this works." |
972 (setq py-imenu-generic-regexp (car py-imenu-generic-expression) | 986 (setq py-imenu-generic-regexp (car py-imenu-generic-expression) |
973 py-imenu-generic-parens (if py-imenu-show-method-args-p | 987 py-imenu-generic-parens (if py-imenu-show-method-args-p |
974 py-imenu-method-arg-parens | 988 py-imenu-method-arg-parens |
975 py-imenu-method-no-arg-parens)) | 989 py-imenu-method-no-arg-parens)) |
976 (goto-char (point-min)) | 990 (goto-char (point-min)) |
977 ;; Warning: When the buffer has no classes or functions, this will | 991 ;; Warning: When the buffer has no classes or functions, this will |
978 ;; return nil, which seems proper according to the Imenu API, but | 992 ;; return nil, which seems proper according to the Imenu API, but |
979 ;; causes an error in the XEmacs port of Imenu. Sigh. | 993 ;; causes an error in the XEmacs port of Imenu. Sigh. |
980 (py-imenu-create-index-engine nil)) | 994 (py-imenu-create-index-engine nil)) |
985 Finds all definitions (classes, methods, or functions) in a Python | 999 Finds all definitions (classes, methods, or functions) in a Python |
986 file for the Imenu package. | 1000 file for the Imenu package. |
987 | 1001 |
988 Returns a possibly nested alist of the form | 1002 Returns a possibly nested alist of the form |
989 | 1003 |
990 (INDEX-NAME . INDEX-POSITION) | 1004 (INDEX-NAME . INDEX-POSITION) |
991 | 1005 |
992 The second element of the alist may be an alist, producing a nested | 1006 The second element of the alist may be an alist, producing a nested |
993 list as in | 1007 list as in |
994 | 1008 |
995 (INDEX-NAME . INDEX-ALIST) | 1009 (INDEX-NAME . INDEX-ALIST) |
996 | 1010 |
997 This function should not be called directly, as it calls itself | 1011 This function should not be called directly, as it calls itself |
998 recursively and requires some setup. Rather this is the engine for | 1012 recursively and requires some setup. Rather this is the engine for |
999 the function \\[py-imenu-create-index-function]. | 1013 the function \\[py-imenu-create-index-function]. |
1000 | 1014 |
1009 The optional argument START-INDENT indicates the starting indentation | 1023 The optional argument START-INDENT indicates the starting indentation |
1010 at which to continue looking for Python classes, methods, or | 1024 at which to continue looking for Python classes, methods, or |
1011 functions. If this is not supplied, the function uses the indentation | 1025 functions. If this is not supplied, the function uses the indentation |
1012 of the first definition found." | 1026 of the first definition found." |
1013 (let (index-alist | 1027 (let (index-alist |
1014 sub-method-alist | 1028 sub-method-alist |
1015 looking-p | 1029 looking-p |
1016 def-name prev-name | 1030 def-name prev-name |
1017 cur-indent def-pos | 1031 cur-indent def-pos |
1018 (class-paren (first py-imenu-generic-parens)) | 1032 (class-paren (first py-imenu-generic-parens)) |
1019 (def-paren (second py-imenu-generic-parens))) | 1033 (def-paren (second py-imenu-generic-parens))) |
1020 (setq looking-p | 1034 (setq looking-p |
1021 (re-search-forward py-imenu-generic-regexp (point-max) t)) | 1035 (re-search-forward py-imenu-generic-regexp (point-max) t)) |
1022 (while looking-p | 1036 (while looking-p |
1023 (save-excursion | 1037 (save-excursion |
1024 ;; used to set def-name to this value but generic-extract-name | 1038 ;; used to set def-name to this value but generic-extract-name |
1025 ;; is new to imenu-1.14. this way it still works with | 1039 ;; is new to imenu-1.14. this way it still works with |
1026 ;; imenu-1.11 | 1040 ;; imenu-1.11 |
1027 ;;(imenu--generic-extract-name py-imenu-generic-parens)) | 1041 ;;(imenu--generic-extract-name py-imenu-generic-parens)) |
1028 (let ((cur-paren (if (match-beginning class-paren) | 1042 (let ((cur-paren (if (match-beginning class-paren) |
1029 class-paren def-paren))) | 1043 class-paren def-paren))) |
1030 (setq def-name | 1044 (setq def-name |
1031 (buffer-substring-no-properties (match-beginning cur-paren) | 1045 (buffer-substring-no-properties (match-beginning cur-paren) |
1032 (match-end cur-paren)))) | 1046 (match-end cur-paren)))) |
1033 (save-match-data | 1047 (save-match-data |
1034 (py-beginning-of-def-or-class 'either)) | 1048 (py-beginning-of-def-or-class 'either)) |
1035 (beginning-of-line) | 1049 (beginning-of-line) |
1036 (setq cur-indent (current-indentation))) | 1050 (setq cur-indent (current-indentation))) |
1037 ;; HACK: want to go to the next correct definition location. We | 1051 ;; HACK: want to go to the next correct definition location. We |
1038 ;; explicitly list them here but it would be better to have them | 1052 ;; explicitly list them here but it would be better to have them |
1039 ;; in a list. | 1053 ;; in a list. |
1040 (setq def-pos | 1054 (setq def-pos |
1041 (or (match-beginning class-paren) | 1055 (or (match-beginning class-paren) |
1042 (match-beginning def-paren))) | 1056 (match-beginning def-paren))) |
1043 ;; if we don't have a starting indent level, take this one | 1057 ;; if we don't have a starting indent level, take this one |
1044 (or start-indent | 1058 (or start-indent |
1045 (setq start-indent cur-indent)) | 1059 (setq start-indent cur-indent)) |
1046 ;; if we don't have class name yet, take this one | 1060 ;; if we don't have class name yet, take this one |
1047 (or prev-name | 1061 (or prev-name |
1048 (setq prev-name def-name)) | 1062 (setq prev-name def-name)) |
1049 ;; what level is the next definition on? must be same, deeper | 1063 ;; what level is the next definition on? must be same, deeper |
1050 ;; or shallower indentation | 1064 ;; or shallower indentation |
1051 (cond | 1065 (cond |
1052 ;; Skip code in comments and strings | 1066 ;; Skip code in comments and strings |
1053 ((py-in-literal)) | 1067 ((py-in-literal)) |
1054 ;; at the same indent level, add it to the list... | 1068 ;; at the same indent level, add it to the list... |
1055 ((= start-indent cur-indent) | 1069 ((= start-indent cur-indent) |
1056 (push (cons def-name def-pos) index-alist)) | 1070 (push (cons def-name def-pos) index-alist)) |
1057 ;; deeper indented expression, recurse | 1071 ;; deeper indented expression, recurse |
1058 ((< start-indent cur-indent) | 1072 ((< start-indent cur-indent) |
1059 ;; the point is currently on the expression we're supposed to | 1073 ;; the point is currently on the expression we're supposed to |
1060 ;; start on, so go back to the last expression. The recursive | 1074 ;; start on, so go back to the last expression. The recursive |
1061 ;; call will find this place again and add it to the correct | 1075 ;; call will find this place again and add it to the correct |
1062 ;; list | 1076 ;; list |
1063 (re-search-backward py-imenu-generic-regexp (point-min) 'move) | 1077 (re-search-backward py-imenu-generic-regexp (point-min) 'move) |
1064 (setq sub-method-alist (py-imenu-create-index-engine cur-indent)) | 1078 (setq sub-method-alist (py-imenu-create-index-engine cur-indent)) |
1065 (if sub-method-alist | 1079 (if sub-method-alist |
1066 ;; we put the last element on the index-alist on the start | 1080 ;; we put the last element on the index-alist on the start |
1067 ;; of the submethod alist so the user can still get to it. | 1081 ;; of the submethod alist so the user can still get to it. |
1068 (let ((save-elmt (pop index-alist))) | 1082 (let ((save-elmt (pop index-alist))) |
1069 (push (cons prev-name | 1083 (push (cons prev-name |
1070 (cons save-elmt sub-method-alist)) | 1084 (cons save-elmt sub-method-alist)) |
1071 index-alist)))) | 1085 index-alist)))) |
1072 ;; found less indented expression, we're done. | 1086 ;; found less indented expression, we're done. |
1073 (t | 1087 (t |
1074 (setq looking-p nil) | 1088 (setq looking-p nil) |
1075 (re-search-backward py-imenu-generic-regexp (point-min) t))) | 1089 (re-search-backward py-imenu-generic-regexp (point-min) t))) |
1076 ;; end-cond | 1090 ;; end-cond |
1077 (setq prev-name def-name) | 1091 (setq prev-name def-name) |
1078 (and looking-p | 1092 (and looking-p |
1079 (setq looking-p | 1093 (setq looking-p |
1080 (re-search-forward py-imenu-generic-regexp | 1094 (re-search-forward py-imenu-generic-regexp |
1081 (point-max) 'move)))) | 1095 (point-max) 'move)))) |
1082 (nreverse index-alist))) | 1096 (nreverse index-alist))) |
1083 | 1097 |
1084 | 1098 |
1085 | 1099 |
1086 (defun py-choose-shell-by-shebang () | 1100 (defun py-choose-shell-by-shebang () |
1089 Used by `py-choose-shell', and similar to but distinct from | 1103 Used by `py-choose-shell', and similar to but distinct from |
1090 `set-auto-mode', though it uses `auto-mode-interpreter-regexp' (if available)." | 1104 `set-auto-mode', though it uses `auto-mode-interpreter-regexp' (if available)." |
1091 ;; look for an interpreter specified in the first line | 1105 ;; look for an interpreter specified in the first line |
1092 ;; similar to set-auto-mode (files.el) | 1106 ;; similar to set-auto-mode (files.el) |
1093 (let* ((re (if (boundp 'auto-mode-interpreter-regexp) | 1107 (let* ((re (if (boundp 'auto-mode-interpreter-regexp) |
1094 auto-mode-interpreter-regexp | 1108 auto-mode-interpreter-regexp |
1095 ;; stolen from Emacs 21.2 | 1109 ;; stolen from Emacs 21.2 |
1096 "#![ \t]?\\([^ \t\n]*/bin/env[ \t]\\)?\\([^ \t\n]+\\)")) | 1110 "#![ \t]?\\([^ \t\n]*/bin/env[ \t]\\)?\\([^ \t\n]+\\)")) |
1097 (interpreter (save-excursion | 1111 (interpreter (save-excursion |
1098 (goto-char (point-min)) | 1112 (goto-char (point-min)) |
1099 (if (looking-at re) | 1113 (if (looking-at re) |
1100 (match-string 2) | 1114 (match-string 2) |
1101 ""))) | 1115 ""))) |
1102 elt) | 1116 elt) |
1103 ;; Map interpreter name to a mode. | 1117 ;; Map interpreter name to a mode. |
1104 (setq elt (assoc (file-name-nondirectory interpreter) | 1118 (setq elt (assoc (file-name-nondirectory interpreter) |
1105 py-shell-alist)) | 1119 py-shell-alist)) |
1106 (and elt (caddr elt)))) | 1120 (and elt (caddr elt)))) |
1107 | 1121 |
1108 | 1122 |
1109 | 1123 |
1110 (defun py-choose-shell-by-import () | 1124 (defun py-choose-shell-by-import () |
1114 return `jython', otherwise return nil." | 1128 return `jython', otherwise return nil." |
1115 (let (mode) | 1129 (let (mode) |
1116 (save-excursion | 1130 (save-excursion |
1117 (goto-char (point-min)) | 1131 (goto-char (point-min)) |
1118 (while (and (not mode) | 1132 (while (and (not mode) |
1119 (search-forward-regexp | 1133 (search-forward-regexp |
1120 "^\\(\\(from\\)\\|\\(import\\)\\) \\([^ \t\n.]+\\)" | 1134 "^\\(\\(from\\)\\|\\(import\\)\\) \\([^ \t\n.]+\\)" |
1121 py-import-check-point-max t)) | 1135 py-import-check-point-max t)) |
1122 (setq mode (and (member (match-string 4) py-jython-packages) | 1136 (setq mode (and (member (match-string 4) py-jython-packages) |
1123 'jython | 1137 'jython |
1124 )))) | 1138 )))) |
1125 mode)) | 1139 mode)) |
1126 | 1140 |
1127 | 1141 |
1128 (defun py-choose-shell () | 1142 (defun py-choose-shell () |
1129 "Choose CPython or Jython mode. Returns the appropriate mode function. | 1143 "Choose CPython or Jython mode. Returns the appropriate mode function. |
1177 (make-local-variable 'add-log-current-defun-function) | 1191 (make-local-variable 'add-log-current-defun-function) |
1178 (make-local-variable 'fill-paragraph-function) | 1192 (make-local-variable 'fill-paragraph-function) |
1179 ;; | 1193 ;; |
1180 (set-syntax-table py-mode-syntax-table) | 1194 (set-syntax-table py-mode-syntax-table) |
1181 (setq major-mode 'python-mode | 1195 (setq major-mode 'python-mode |
1182 mode-name "Python" | 1196 mode-name "Python" |
1183 local-abbrev-table python-mode-abbrev-table | 1197 local-abbrev-table python-mode-abbrev-table |
1184 font-lock-defaults '(python-font-lock-keywords) | 1198 font-lock-defaults '(python-font-lock-keywords) |
1185 paragraph-separate "^[ \t]*$" | 1199 paragraph-separate "^[ \t]*$" |
1186 paragraph-start "^[ \t]*$" | 1200 paragraph-start "^[ \t]*$" |
1187 require-final-newline t | 1201 require-final-newline t |
1188 comment-start "# " | 1202 comment-start "# " |
1189 comment-end "" | 1203 comment-end "" |
1190 comment-start-skip "# *" | 1204 comment-start-skip "# *" |
1191 comment-column 40 | 1205 comment-column 40 |
1192 comment-indent-function 'py-comment-indent-function | 1206 comment-indent-function 'py-comment-indent-function |
1193 indent-region-function 'py-indent-region | 1207 indent-region-function 'py-indent-region |
1194 indent-line-function 'py-indent-line | 1208 indent-line-function 'py-indent-line |
1195 ;; tell add-log.el how to find the current function/method/variable | 1209 ;; tell add-log.el how to find the current function/method/variable |
1196 add-log-current-defun-function 'py-current-defun | 1210 add-log-current-defun-function 'py-current-defun |
1197 | 1211 |
1198 fill-paragraph-function 'py-fill-paragraph | 1212 fill-paragraph-function 'py-fill-paragraph |
1199 ) | 1213 ) |
1200 (use-local-map py-mode-map) | 1214 (use-local-map py-mode-map) |
1201 ;; add the menu | 1215 ;; add the menu |
1202 (if py-menu | 1216 (if py-menu |
1203 (easy-menu-add py-menu)) | 1217 (easy-menu-add py-menu)) |
1204 ;; Emacs 19 requires this | 1218 ;; Emacs 19 requires this |
1207 ;; Install Imenu if available | 1221 ;; Install Imenu if available |
1208 (when (py-safe (require 'imenu)) | 1222 (when (py-safe (require 'imenu)) |
1209 (setq imenu-create-index-function #'py-imenu-create-index-function) | 1223 (setq imenu-create-index-function #'py-imenu-create-index-function) |
1210 (setq imenu-generic-expression py-imenu-generic-expression) | 1224 (setq imenu-generic-expression py-imenu-generic-expression) |
1211 (if (fboundp 'imenu-add-to-menubar) | 1225 (if (fboundp 'imenu-add-to-menubar) |
1212 (imenu-add-to-menubar (format "%s-%s" "IM" mode-name))) | 1226 (imenu-add-to-menubar (format "%s-%s" "IM" mode-name))) |
1213 ) | 1227 ) |
1214 ;; Run the mode hook. Note that py-mode-hook is deprecated. | 1228 ;; Run the mode hook. Note that py-mode-hook is deprecated. |
1215 (if python-mode-hook | 1229 (if python-mode-hook |
1216 (run-hooks 'python-mode-hook) | 1230 (run-hooks 'python-mode-hook) |
1217 (run-hooks 'py-mode-hook)) | 1231 (run-hooks 'py-mode-hook)) |
1218 ;; Now do the automagical guessing | 1232 ;; Now do the automagical guessing |
1219 (if py-smart-indentation | 1233 (if py-smart-indentation |
1220 (let ((offset py-indent-offset)) | 1234 (let ((offset py-indent-offset)) |
1221 ;; It's okay if this fails to guess a good value | 1235 ;; It's okay if this fails to guess a good value |
1222 (if (and (py-safe (py-guess-indent-offset)) | 1236 (if (and (py-safe (py-guess-indent-offset)) |
1223 (<= py-indent-offset 8) | 1237 (<= py-indent-offset 8) |
1224 (>= py-indent-offset 2)) | 1238 (>= py-indent-offset 2)) |
1225 (setq offset py-indent-offset)) | 1239 (setq offset py-indent-offset)) |
1226 (setq py-indent-offset offset) | 1240 (setq py-indent-offset offset) |
1227 ;; Only turn indent-tabs-mode off if tab-width != | 1241 ;; Only turn indent-tabs-mode off if tab-width != |
1228 ;; py-indent-offset. Never turn it on, because the user must | 1242 ;; py-indent-offset. Never turn it on, because the user must |
1229 ;; have explicitly turned it off. | 1243 ;; have explicitly turned it off. |
1230 (if (/= tab-width py-indent-offset) | 1244 (if (/= tab-width py-indent-offset) |
1231 (setq indent-tabs-mode nil)) | 1245 (setq indent-tabs-mode nil)) |
1232 )) | 1246 )) |
1233 ;; Set the default shell if not already set | 1247 ;; Set the default shell if not already set |
1234 (when (null py-which-shell) | 1248 (when (null py-which-shell) |
1235 (py-toggle-shells (py-choose-shell)))) | 1249 (py-toggle-shells (py-choose-shell)))) |
1236 | 1250 |
1254 ;; can specify different `derived-modes' based on the #! line, but | 1268 ;; can specify different `derived-modes' based on the #! line, but |
1255 ;; with the latter, we can't. So we just won't add them if they're | 1269 ;; with the latter, we can't. So we just won't add them if they're |
1256 ;; already added. | 1270 ;; already added. |
1257 ;;;###autoload | 1271 ;;;###autoload |
1258 (let ((modes '(("jython" . jython-mode) | 1272 (let ((modes '(("jython" . jython-mode) |
1259 ("python" . python-mode)))) | 1273 ("python" . python-mode)))) |
1260 (while modes | 1274 (while modes |
1261 (when (not (assoc (car modes) interpreter-mode-alist)) | 1275 (when (not (assoc (car modes) interpreter-mode-alist)) |
1262 (push (car modes) interpreter-mode-alist)) | 1276 (push (car modes) interpreter-mode-alist)) |
1263 (setq modes (cdr modes)))) | 1277 (setq modes (cdr modes)))) |
1264 ;;;###autoload | 1278 ;;;###autoload |
1265 (when (not (or (rassq 'python-mode auto-mode-alist) | 1279 (when (not (or (rassq 'python-mode auto-mode-alist) |
1266 (rassq 'jython-mode auto-mode-alist))) | 1280 (rassq 'jython-mode auto-mode-alist))) |
1267 (push '("\\.py$" . python-mode) auto-mode-alist)) | 1281 (push '("\\.py$" . python-mode) auto-mode-alist)) |
1268 | 1282 |
1269 | 1283 |
1270 | 1284 |
1271 ;; electric characters | 1285 ;; electric characters |
1272 (defun py-outdent-p () | 1286 (defun py-outdent-p () |
1273 "Returns non-nil if the current line should dedent one level." | 1287 "Returns non-nil if the current line should dedent one level." |
1274 (save-excursion | 1288 (save-excursion |
1275 (and (progn (back-to-indentation) | 1289 (and (progn (back-to-indentation) |
1276 (looking-at py-outdent-re)) | 1290 (looking-at py-outdent-re)) |
1277 ;; short circuit infloop on illegal construct | 1291 ;; short circuit infloop on illegal construct |
1278 (not (bobp)) | 1292 (not (bobp)) |
1279 (progn (forward-line -1) | 1293 (progn (forward-line -1) |
1280 (py-goto-initial-line) | 1294 (py-goto-initial-line) |
1281 (back-to-indentation) | 1295 (back-to-indentation) |
1282 (while (or (looking-at py-blank-or-comment-re) | 1296 (while (or (looking-at py-blank-or-comment-re) |
1283 (bobp)) | 1297 (bobp)) |
1284 (backward-to-indentation 1)) | 1298 (backward-to-indentation 1)) |
1285 (not (looking-at py-no-outdent-re))) | 1299 (not (looking-at py-no-outdent-re))) |
1286 ))) | 1300 ))) |
1287 | 1301 |
1288 (defun py-electric-colon (arg) | 1302 (defun py-electric-colon (arg) |
1289 "Insert a colon. | 1303 "Insert a colon. |
1290 In certain cases the line is dedented appropriately. If a numeric | 1304 In certain cases the line is dedented appropriately. If a numeric |
1291 argument ARG is provided, that many colons are inserted | 1305 argument ARG is provided, that many colons are inserted |
1293 comment." | 1307 comment." |
1294 (interactive "*P") | 1308 (interactive "*P") |
1295 (self-insert-command (prefix-numeric-value arg)) | 1309 (self-insert-command (prefix-numeric-value arg)) |
1296 ;; are we in a string or comment? | 1310 ;; are we in a string or comment? |
1297 (if (save-excursion | 1311 (if (save-excursion |
1298 (let ((pps (parse-partial-sexp (save-excursion | 1312 (let ((pps (parse-partial-sexp (save-excursion |
1299 (py-beginning-of-def-or-class) | 1313 (py-beginning-of-def-or-class) |
1300 (point)) | 1314 (point)) |
1301 (point)))) | 1315 (point)))) |
1302 (not (or (nth 3 pps) (nth 4 pps))))) | 1316 (not (or (nth 3 pps) (nth 4 pps))))) |
1303 (save-excursion | 1317 (save-excursion |
1304 (let ((here (point)) | 1318 (let ((here (point)) |
1305 (outdent 0) | 1319 (outdent 0) |
1306 (indent (py-compute-indentation t))) | 1320 (indent (py-compute-indentation t))) |
1307 (if (and (not arg) | 1321 (if (and (not arg) |
1308 (py-outdent-p) | 1322 (py-outdent-p) |
1309 (= indent (save-excursion | 1323 (= indent (save-excursion |
1310 (py-next-statement -1) | 1324 (py-next-statement -1) |
1311 (py-compute-indentation t))) | 1325 (py-compute-indentation t))) |
1312 ) | 1326 ) |
1313 (setq outdent py-indent-offset)) | 1327 (setq outdent py-indent-offset)) |
1314 ;; Don't indent, only dedent. This assumes that any lines | 1328 ;; Don't indent, only dedent. This assumes that any lines |
1315 ;; that are already dedented relative to | 1329 ;; that are already dedented relative to |
1316 ;; py-compute-indentation were put there on purpose. It's | 1330 ;; py-compute-indentation were put there on purpose. It's |
1317 ;; highly annoying to have `:' indent for you. Use TAB, C-c | 1331 ;; highly annoying to have `:' indent for you. Use TAB, C-c |
1318 ;; C-l or C-c C-r to adjust. TBD: Is there a better way to | 1332 ;; C-l or C-c C-r to adjust. TBD: Is there a better way to |
1319 ;; determine this??? | 1333 ;; determine this??? |
1320 (if (< (current-indentation) indent) nil | 1334 (if (< (current-indentation) indent) nil |
1321 (goto-char here) | 1335 (goto-char here) |
1322 (beginning-of-line) | 1336 (beginning-of-line) |
1323 (delete-horizontal-space) | 1337 (delete-horizontal-space) |
1324 (indent-to (- indent outdent)) | 1338 (indent-to (- indent outdent)) |
1325 ))))) | 1339 ))))) |
1326 | 1340 |
1327 | 1341 |
1328 ;; Python subprocess utilities and filters | 1342 ;; Python subprocess utilities and filters |
1329 (defun py-execute-file (proc filename) | 1343 (defun py-execute-file (proc filename) |
1330 "Send to Python interpreter process PROC \"execfile('FILENAME')\". | 1344 "Send to Python interpreter process PROC \"execfile('FILENAME')\". |
1331 Make that process's buffer visible and force display. Also make | 1345 Make that process's buffer visible and force display. Also make |
1332 comint believe the user typed this string so that | 1346 comint believe the user typed this string so that |
1333 `kill-output-from-shell' does The Right Thing." | 1347 `kill-output-from-shell' does The Right Thing." |
1334 (let ((curbuf (current-buffer)) | 1348 (let ((curbuf (current-buffer)) |
1335 (procbuf (process-buffer proc)) | 1349 (procbuf (process-buffer proc)) |
1336 ; (comint-scroll-to-bottom-on-output t) | 1350 ; (comint-scroll-to-bottom-on-output t) |
1337 (msg (format "## working on region in file %s...\n" filename)) | 1351 (msg (format "## working on region in file %s...\n" filename)) |
1338 ;; add some comment, so that we can filter it out of history | 1352 ;; add some comment, so that we can filter it out of history |
1339 (cmd (format "execfile(r'%s') # PYTHON-MODE\n" filename))) | 1353 (cmd (format "execfile(r'%s') # PYTHON-MODE\n" filename))) |
1340 (unwind-protect | 1354 (unwind-protect |
1341 (save-excursion | 1355 (save-excursion |
1342 (set-buffer procbuf) | 1356 (set-buffer procbuf) |
1343 (goto-char (point-max)) | 1357 (goto-char (point-max)) |
1344 (move-marker (process-mark proc) (point)) | 1358 (move-marker (process-mark proc) (point)) |
1345 (funcall (process-filter proc) proc msg)) | 1359 (funcall (process-filter proc) proc msg)) |
1346 (set-buffer curbuf)) | 1360 (set-buffer curbuf)) |
1347 (process-send-string proc cmd))) | 1361 (process-send-string proc cmd))) |
1348 | 1362 |
1349 (defun py-comint-output-filter-function (string) | 1363 (defun py-comint-output-filter-function (string) |
1350 "Watch output for Python prompt and exec next file waiting in queue. | 1364 "Watch output for Python prompt and exec next file waiting in queue. |
1357 (if py-shell-switch-buffers-on-execute | 1371 (if py-shell-switch-buffers-on-execute |
1358 (pop-to-buffer (current-buffer))) | 1372 (pop-to-buffer (current-buffer))) |
1359 (py-safe (delete-file (car py-file-queue))) | 1373 (py-safe (delete-file (car py-file-queue))) |
1360 (setq py-file-queue (cdr py-file-queue)) | 1374 (setq py-file-queue (cdr py-file-queue)) |
1361 (if py-file-queue | 1375 (if py-file-queue |
1362 (let ((pyproc (get-buffer-process (current-buffer)))) | 1376 (let ((pyproc (get-buffer-process (current-buffer)))) |
1363 (py-execute-file pyproc (car py-file-queue)))) | 1377 (py-execute-file pyproc (car py-file-queue)))) |
1364 )) | 1378 )) |
1365 | 1379 |
1366 (defun py-pdbtrack-overlay-arrow (activation) | 1380 (defun py-pdbtrack-overlay-arrow (activation) |
1367 "Activate or de arrow at beginning-of-line in current buffer." | 1381 "Activate or de arrow at beginning-of-line in current buffer." |
1368 ;; This was derived/simplified from edebug-overlay-arrow | 1382 ;; This was derived/simplified from edebug-overlay-arrow |
1369 (cond (activation | 1383 (cond (activation |
1370 (setq overlay-arrow-position (make-marker)) | 1384 (setq overlay-arrow-position (make-marker)) |
1371 (setq overlay-arrow-string "=>") | 1385 (setq overlay-arrow-string "=>") |
1372 (set-marker overlay-arrow-position (py-point 'bol) (current-buffer)) | 1386 (set-marker overlay-arrow-position (py-point 'bol) (current-buffer)) |
1373 (setq py-pdbtrack-is-tracking-p t)) | 1387 (setq py-pdbtrack-is-tracking-p t)) |
1374 (overlay-arrow-position | 1388 (overlay-arrow-position |
1375 (setq overlay-arrow-position nil) | 1389 (setq overlay-arrow-position nil) |
1376 (setq py-pdbtrack-is-tracking-p nil)) | 1390 (setq py-pdbtrack-is-tracking-p nil)) |
1377 )) | 1391 )) |
1378 | 1392 |
1379 (defun py-pdbtrack-track-stack-file (text) | 1393 (defun py-pdbtrack-track-stack-file (text) |
1380 "Show the file indicated by the pdb stack entry line, in a separate window. | 1394 "Show the file indicated by the pdb stack entry line, in a separate window. |
1381 | 1395 |
1382 Activity is disabled if the buffer-local variable | 1396 Activity is disabled if the buffer-local variable |
1399 ;; Also, we're very conservative about clearing the overlay arrow, | 1413 ;; Also, we're very conservative about clearing the overlay arrow, |
1400 ;; to minimize residue. This means, for instance, that executing | 1414 ;; to minimize residue. This means, for instance, that executing |
1401 ;; other pdb commands wipe out the highlight. You can always do a | 1415 ;; other pdb commands wipe out the highlight. You can always do a |
1402 ;; 'where' (aka 'w') command to reveal the overlay arrow. | 1416 ;; 'where' (aka 'w') command to reveal the overlay arrow. |
1403 (let* ((origbuf (current-buffer)) | 1417 (let* ((origbuf (current-buffer)) |
1404 (currproc (get-buffer-process origbuf))) | 1418 (currproc (get-buffer-process origbuf))) |
1405 | 1419 |
1406 (if (not (and currproc py-pdbtrack-do-tracking-p)) | 1420 (if (not (and currproc py-pdbtrack-do-tracking-p)) |
1407 (py-pdbtrack-overlay-arrow nil) | 1421 (py-pdbtrack-overlay-arrow nil) |
1408 | 1422 |
1409 (let* ((procmark (process-mark currproc)) | 1423 (let* ((procmark (process-mark currproc)) |
1447 (if (not (string-match py-pdbtrack-stack-entry-regexp block)) | 1461 (if (not (string-match py-pdbtrack-stack-entry-regexp block)) |
1448 | 1462 |
1449 "Traceback cue not found" | 1463 "Traceback cue not found" |
1450 | 1464 |
1451 (let* ((filename (match-string 1 block)) | 1465 (let* ((filename (match-string 1 block)) |
1452 (lineno (string-to-int (match-string 2 block))) | 1466 (lineno (string-to-number (match-string 2 block))) |
1453 (funcname (match-string 3 block)) | 1467 (funcname (match-string 3 block)) |
1454 funcbuffer) | 1468 funcbuffer) |
1455 | 1469 |
1456 (cond ((file-exists-p filename) | 1470 (cond ((file-exists-p filename) |
1457 (list lineno (find-file-noselect filename))) | 1471 (list lineno (find-file-noselect filename))) |
1507 "Highlight exceptions found in BUF. | 1521 "Highlight exceptions found in BUF. |
1508 If an exception occurred return t, otherwise return nil. BUF must exist." | 1522 If an exception occurred return t, otherwise return nil. BUF must exist." |
1509 (let (line file bol err-p) | 1523 (let (line file bol err-p) |
1510 (save-excursion | 1524 (save-excursion |
1511 (set-buffer buf) | 1525 (set-buffer buf) |
1512 (beginning-of-buffer) | 1526 (goto-char (point-min)) |
1513 (while (re-search-forward py-traceback-line-re nil t) | 1527 (while (re-search-forward py-traceback-line-re nil t) |
1514 (setq file (match-string 1) | 1528 (setq file (match-string 1) |
1515 line (string-to-int (match-string 2)) | 1529 line (string-to-number (match-string 2)) |
1516 bol (py-point 'bol)) | 1530 bol (py-point 'bol)) |
1517 (py-highlight-line bol (py-point 'eol) file line))) | 1531 (py-highlight-line bol (py-point 'eol) file line))) |
1518 (when (and py-jump-on-exception line) | 1532 (when (and py-jump-on-exception line) |
1519 (beep) | 1533 (beep) |
1520 (py-jump-to-exception file line) | 1534 (py-jump-to-exception file line) |
1521 (setq err-p t)) | 1535 (setq err-p t)) |
1522 err-p)) | 1536 err-p)) |
1526 ;;; Subprocess commands | 1540 ;;; Subprocess commands |
1527 | 1541 |
1528 ;; only used when (memq 'broken-temp-names py-emacs-features) | 1542 ;; only used when (memq 'broken-temp-names py-emacs-features) |
1529 (defvar py-serial-number 0) | 1543 (defvar py-serial-number 0) |
1530 (defvar py-exception-buffer nil) | 1544 (defvar py-exception-buffer nil) |
1531 (defconst py-output-buffer "*Python Output*") | 1545 (defvar py-output-buffer "*Python Output*") |
1532 (make-variable-buffer-local 'py-output-buffer) | 1546 (make-variable-buffer-local 'py-output-buffer) |
1533 | 1547 |
1534 ;; for toggling between CPython and Jython | 1548 ;; for toggling between CPython and Jython |
1535 (defvar py-which-shell nil) | 1549 (defvar py-which-shell nil) |
1536 (defvar py-which-args py-python-command-args) | 1550 (defvar py-which-args py-python-command-args) |
1555 ;; preprocess arg | 1569 ;; preprocess arg |
1556 (cond | 1570 (cond |
1557 ((equal arg 0) | 1571 ((equal arg 0) |
1558 ;; toggle | 1572 ;; toggle |
1559 (if (string-equal py-which-bufname "Python") | 1573 (if (string-equal py-which-bufname "Python") |
1560 (setq arg -1) | 1574 (setq arg -1) |
1561 (setq arg 1))) | 1575 (setq arg 1))) |
1562 ((equal arg 'cpython) (setq arg 1)) | 1576 ((equal arg 'cpython) (setq arg 1)) |
1563 ((equal arg 'jython) (setq arg -1))) | 1577 ((equal arg 'jython) (setq arg -1))) |
1564 (let (msg) | 1578 (let (msg) |
1565 (cond | 1579 (cond |
1566 ((< 0 arg) | 1580 ((< 0 arg) |
1567 ;; set to CPython | 1581 ;; set to CPython |
1568 (setq py-which-shell py-python-command | 1582 (setq py-which-shell py-python-command |
1569 py-which-args py-python-command-args | 1583 py-which-args py-python-command-args |
1570 py-which-bufname "Python" | 1584 py-which-bufname "Python" |
1571 msg "CPython") | 1585 msg "CPython") |
1572 (if (string-equal py-which-bufname "Jython") | 1586 (if (string-equal py-which-bufname "Jython") |
1573 (setq mode-name "Python"))) | 1587 (setq mode-name "Python"))) |
1574 ((> 0 arg) | 1588 ((> 0 arg) |
1575 (setq py-which-shell py-jython-command | 1589 (setq py-which-shell py-jython-command |
1576 py-which-args py-jython-command-args | 1590 py-which-args py-jython-command-args |
1577 py-which-bufname "Jython" | 1591 py-which-bufname "Jython" |
1578 msg "Jython") | 1592 msg "Jython") |
1579 (if (string-equal py-which-bufname "Python") | 1593 (if (string-equal py-which-bufname "Python") |
1580 (setq mode-name "Jython"))) | 1594 (setq mode-name "Jython"))) |
1581 ) | 1595 ) |
1582 (message "Using the %s shell" msg) | 1596 (message "Using the %s shell" msg) |
1583 (setq py-output-buffer (format "*%s Output*" py-which-bufname)))) | 1597 (setq py-output-buffer (format "*%s Output*" py-which-bufname)))) |
1584 | 1598 |
1585 ;;;###autoload | 1599 ;;;###autoload |
1624 ;; Set the default shell if not already set | 1638 ;; Set the default shell if not already set |
1625 (when (null py-which-shell) | 1639 (when (null py-which-shell) |
1626 (py-toggle-shells py-default-interpreter)) | 1640 (py-toggle-shells py-default-interpreter)) |
1627 (let ((args py-which-args)) | 1641 (let ((args py-which-args)) |
1628 (when (and argprompt | 1642 (when (and argprompt |
1629 (interactive-p) | 1643 (interactive-p) |
1630 (fboundp 'split-string)) | 1644 (fboundp 'split-string)) |
1631 ;; TBD: Perhaps force "-i" in the final list? | 1645 ;; TBD: Perhaps force "-i" in the final list? |
1632 (setq args (split-string | 1646 (setq args (split-string |
1633 (read-string (concat py-which-bufname | 1647 (read-string (concat py-which-bufname |
1634 " arguments: ") | 1648 " arguments: ") |
1635 (concat | 1649 (concat |
1636 (mapconcat 'identity py-which-args " ") " ") | 1650 (mapconcat 'identity py-which-args " ") " ") |
1637 )))) | 1651 )))) |
1638 (if (not (equal (buffer-name) "*Python*")) | 1652 (if (not (equal (buffer-name) "*Python*")) |
1639 (switch-to-buffer-other-window | 1653 (switch-to-buffer-other-window |
1640 (apply 'make-comint py-which-bufname py-which-shell nil args)) | 1654 (apply 'make-comint py-which-bufname py-which-shell nil args)) |
1641 (apply 'make-comint py-which-bufname py-which-shell nil args)) | 1655 (apply 'make-comint py-which-bufname py-which-shell nil args)) |
1642 (make-local-variable 'comint-prompt-regexp) | 1656 (make-local-variable 'comint-prompt-regexp) |
1643 (setq comint-prompt-regexp (concat py-shell-input-prompt-1-regexp "\\|" | 1657 (setq comint-prompt-regexp (concat py-shell-input-prompt-1-regexp "\\|" |
1644 py-shell-input-prompt-2-regexp "\\|" | 1658 py-shell-input-prompt-2-regexp "\\|" |
1645 "^([Pp]db) ")) | 1659 "^([Pp]db) ")) |
1646 (add-hook 'comint-output-filter-functions | 1660 (add-hook 'comint-output-filter-functions |
1647 'py-comint-output-filter-function) | 1661 'py-comint-output-filter-function) |
1648 ;; pdbtrack | 1662 ;; pdbtrack |
1649 (add-hook 'comint-output-filter-functions 'py-pdbtrack-track-stack-file) | 1663 (add-hook 'comint-output-filter-functions 'py-pdbtrack-track-stack-file) |
1650 (setq py-pdbtrack-do-tracking-p t) | 1664 (setq py-pdbtrack-do-tracking-p t) |
1651 (set-syntax-table py-mode-syntax-table) | 1665 (set-syntax-table py-mode-syntax-table) |
1652 (use-local-map py-shell-map) | 1666 (use-local-map py-shell-map) |
1655 | 1669 |
1656 (defun py-clear-queue () | 1670 (defun py-clear-queue () |
1657 "Clear the queue of temporary files waiting to execute." | 1671 "Clear the queue of temporary files waiting to execute." |
1658 (interactive) | 1672 (interactive) |
1659 (let ((n (length py-file-queue))) | 1673 (let ((n (length py-file-queue))) |
1660 (mapcar 'delete-file py-file-queue) | 1674 (mapc 'delete-file py-file-queue) |
1661 (setq py-file-queue nil) | 1675 (setq py-file-queue nil) |
1662 (message "%d pending files de-queued." n))) | 1676 (message "%d pending files de-queued." n))) |
1663 | 1677 |
1664 | 1678 |
1665 (defun py-execute-region (start end &optional async) | 1679 (defun py-execute-region (start end &optional async) |
1688 | 1702 |
1689 is inserted at the end. See also the command `py-clear-queue'." | 1703 is inserted at the end. See also the command `py-clear-queue'." |
1690 (interactive "r\nP") | 1704 (interactive "r\nP") |
1691 ;; Skip ahead to the first non-blank line | 1705 ;; Skip ahead to the first non-blank line |
1692 (let* ((proc (get-process py-which-bufname)) | 1706 (let* ((proc (get-process py-which-bufname)) |
1693 (temp (if (memq 'broken-temp-names py-emacs-features) | 1707 (temp (if (memq 'broken-temp-names py-emacs-features) |
1694 (let | 1708 (let |
1695 ((sn py-serial-number) | 1709 ((sn py-serial-number) |
1696 (pid (and (fboundp 'emacs-pid) (emacs-pid)))) | 1710 (pid (and (fboundp 'emacs-pid) (emacs-pid)))) |
1697 (setq py-serial-number (1+ py-serial-number)) | 1711 (setq py-serial-number (1+ py-serial-number)) |
1698 (if pid | 1712 (if pid |
1699 (format "python-%d-%d" sn pid) | 1713 (format "python-%d-%d" sn pid) |
1700 (format "python-%d" sn))) | 1714 (format "python-%d" sn))) |
1701 (make-temp-name "python-"))) | 1715 (make-temp-name "python-"))) |
1702 (file (concat (expand-file-name temp py-temp-directory) ".py")) | 1716 (file (concat (expand-file-name temp py-temp-directory) ".py")) |
1703 (cur (current-buffer)) | 1717 (cur (current-buffer)) |
1704 (buf (get-buffer-create file)) | 1718 (buf (get-buffer-create file)) |
1705 shell) | 1719 shell) |
1706 ;; Write the contents of the buffer, watching out for indented regions. | 1720 ;; Write the contents of the buffer, watching out for indented regions. |
1707 (save-excursion | 1721 (save-excursion |
1708 (goto-char start) | 1722 (goto-char start) |
1709 (beginning-of-line) | 1723 (beginning-of-line) |
1710 (while (and (looking-at "\\s *$") | 1724 (while (and (looking-at "\\s *$") |
1711 (< (point) end)) | 1725 (< (point) end)) |
1712 (forward-line 1)) | 1726 (forward-line 1)) |
1713 (setq start (point)) | 1727 (setq start (point)) |
1714 (or (< start end) | 1728 (or (< start end) |
1715 (error "Region is empty")) | 1729 (error "Region is empty")) |
1716 (setq py-line-number-offset (count-lines 1 start)) | 1730 (setq py-line-number-offset (count-lines 1 start)) |
1717 (let ((needs-if (/= (py-point 'bol) (py-point 'boi)))) | 1731 (let ((needs-if (/= (py-point 'bol) (py-point 'boi)))) |
1718 (set-buffer buf) | 1732 (set-buffer buf) |
1719 (python-mode) | 1733 (python-mode) |
1720 (when needs-if | 1734 (when needs-if |
1721 (insert "if 1:\n") | 1735 (insert "if 1:\n") |
1722 (setq py-line-number-offset (- py-line-number-offset 1))) | 1736 (setq py-line-number-offset (- py-line-number-offset 1))) |
1723 (insert-buffer-substring cur start end) | 1737 (insert-buffer-substring cur start end) |
1724 ;; Set the shell either to the #! line command, or to the | 1738 ;; Set the shell either to the #! line command, or to the |
1725 ;; py-which-shell buffer local variable. | 1739 ;; py-which-shell buffer local variable. |
1726 (setq shell (or (py-choose-shell-by-shebang) | 1740 (setq shell (or (py-choose-shell-by-shebang) |
1727 (py-choose-shell-by-import) | 1741 (py-choose-shell-by-import) |
1728 py-which-shell)))) | 1742 py-which-shell)))) |
1729 (cond | 1743 (cond |
1730 ;; always run the code in its own asynchronous subprocess | 1744 ;; always run the code in its own asynchronous subprocess |
1731 (async | 1745 (async |
1732 ;; User explicitly wants this to run in its own async subprocess | 1746 ;; User explicitly wants this to run in its own async subprocess |
1733 (save-excursion | 1747 (save-excursion |
1734 (set-buffer buf) | 1748 (set-buffer buf) |
1735 (write-region (point-min) (point-max) file nil 'nomsg)) | 1749 (write-region (point-min) (point-max) file nil 'nomsg)) |
1736 (let* ((buf (generate-new-buffer-name py-output-buffer)) | 1750 (let* ((buf (generate-new-buffer-name py-output-buffer)) |
1737 ;; TBD: a horrible hack, but why create new Custom variables? | 1751 ;; TBD: a horrible hack, but why create new Custom variables? |
1738 (arg (if (string-equal py-which-bufname "Python") | 1752 (arg (if (string-equal py-which-bufname "Python") |
1739 "-u" ""))) | 1753 "-u" ""))) |
1740 (start-process py-which-bufname buf shell arg file) | 1754 (start-process py-which-bufname buf shell arg file) |
1741 (pop-to-buffer buf) | 1755 (pop-to-buffer buf) |
1742 (py-postprocess-output-buffer buf) | 1756 (py-postprocess-output-buffer buf) |
1743 ;; TBD: clean up the temporary file! | 1757 ;; TBD: clean up the temporary file! |
1744 )) | 1758 )) |
1745 ;; if the Python interpreter shell is running, queue it up for | 1759 ;; if the Python interpreter shell is running, queue it up for |
1746 ;; execution there. | 1760 ;; execution there. |
1747 (proc | 1761 (proc |
1748 ;; use the existing python shell | 1762 ;; use the existing python shell |
1749 (save-excursion | 1763 (save-excursion |
1750 (set-buffer buf) | 1764 (set-buffer buf) |
1751 (write-region (point-min) (point-max) file nil 'nomsg)) | 1765 (write-region (point-min) (point-max) file nil 'nomsg)) |
1752 (if (not py-file-queue) | 1766 (if (not py-file-queue) |
1753 (py-execute-file proc file) | 1767 (py-execute-file proc file) |
1754 (message "File %s queued for execution" file)) | 1768 (message "File %s queued for execution" file)) |
1755 (setq py-file-queue (append py-file-queue (list file))) | 1769 (setq py-file-queue (append py-file-queue (list file))) |
1756 (setq py-exception-buffer (cons file (current-buffer)))) | 1770 (setq py-exception-buffer (cons file (current-buffer)))) |
1757 (t | 1771 (t |
1758 ;; TBD: a horrible hack, but why create new Custom variables? | 1772 ;; TBD: a horrible hack, but why create new Custom variables? |
1759 (let ((cmd (concat py-which-shell (if (string-equal py-which-bufname | 1773 (let ((cmd (concat py-which-shell (if (string-equal py-which-bufname |
1760 "Jython") | 1774 "Jython") |
1761 " -" "")))) | 1775 " -" "")))) |
1762 ;; otherwise either run it synchronously in a subprocess | 1776 ;; otherwise either run it synchronously in a subprocess |
1763 (save-excursion | 1777 (save-excursion |
1764 (set-buffer buf) | 1778 (set-buffer buf) |
1765 (shell-command-on-region (point-min) (point-max) | 1779 (shell-command-on-region (point-min) (point-max) |
1766 cmd py-output-buffer)) | 1780 cmd py-output-buffer)) |
1767 ;; shell-command-on-region kills the output buffer if it never | 1781 ;; shell-command-on-region kills the output buffer if it never |
1768 ;; existed and there's no output from the command | 1782 ;; existed and there's no output from the command |
1769 (if (not (get-buffer py-output-buffer)) | 1783 (if (not (get-buffer py-output-buffer)) |
1770 (message "No output.") | 1784 (message "No output.") |
1771 (setq py-exception-buffer (current-buffer)) | 1785 (setq py-exception-buffer (current-buffer)) |
1772 (let ((err-p (py-postprocess-output-buffer py-output-buffer))) | 1786 (let ((err-p (py-postprocess-output-buffer py-output-buffer))) |
1773 (pop-to-buffer py-output-buffer) | 1787 (pop-to-buffer py-output-buffer) |
1774 (if err-p | 1788 (if err-p |
1775 (pop-to-buffer py-exception-buffer))) | 1789 (pop-to-buffer py-exception-buffer))) |
1776 )) | 1790 )) |
1777 )) | 1791 )) |
1778 ;; Clean up after ourselves. | 1792 ;; Clean up after ourselves. |
1779 (kill-buffer buf))) | 1793 (kill-buffer buf))) |
1780 | 1794 |
1781 | 1795 |
1834 (find-file-noselect filename)))) | 1848 (find-file-noselect filename)))) |
1835 (set-buffer buffer))) | 1849 (set-buffer buffer))) |
1836 (let ((file (buffer-file-name (current-buffer)))) | 1850 (let ((file (buffer-file-name (current-buffer)))) |
1837 (if file | 1851 (if file |
1838 (progn | 1852 (progn |
1839 ;; Maybe save some buffers | 1853 ;; Maybe save some buffers |
1840 (save-some-buffers (not py-ask-about-save) nil) | 1854 (save-some-buffers (not py-ask-about-save) nil) |
1841 (py-execute-string | 1855 (py-execute-string |
1842 (if (string-match "\\.py$" file) | 1856 (if (string-match "\\.py$" file) |
1843 (let ((f (file-name-sans-extension | 1857 (let ((f (file-name-sans-extension |
1844 (file-name-nondirectory file)))) | 1858 (file-name-nondirectory file)))) |
1845 (format "if globals().has_key('%s'):\n reload(%s)\nelse:\n import %s\n" | 1859 (format "if globals().has_key('%s'):\n reload(%s)\nelse:\n import %s\n" |
1846 f f f)) | 1860 f f f)) |
1847 (format "execfile(r'%s')\n" file)) | 1861 (format "execfile(r'%s')\n" file)) |
1848 async)) | 1862 async)) |
1849 ;; else | 1863 ;; else |
1881 | 1895 |
1882 | 1896 |
1883 (defun py-jump-to-exception (file line) | 1897 (defun py-jump-to-exception (file line) |
1884 "Jump to the Python code in FILE at LINE." | 1898 "Jump to the Python code in FILE at LINE." |
1885 (let ((buffer (cond ((string-equal file "<stdin>") | 1899 (let ((buffer (cond ((string-equal file "<stdin>") |
1886 (if (consp py-exception-buffer) | 1900 (if (consp py-exception-buffer) |
1887 (cdr py-exception-buffer) | 1901 (cdr py-exception-buffer) |
1888 py-exception-buffer)) | 1902 py-exception-buffer)) |
1889 ((and (consp py-exception-buffer) | 1903 ((and (consp py-exception-buffer) |
1890 (string-equal file (car py-exception-buffer))) | 1904 (string-equal file (car py-exception-buffer))) |
1891 (cdr py-exception-buffer)) | 1905 (cdr py-exception-buffer)) |
1892 ((py-safe (find-file-noselect file))) | 1906 ((py-safe (find-file-noselect file))) |
1893 ;; could not figure out what file the exception | 1907 ;; could not figure out what file the exception |
1894 ;; is pointing to, so prompt for it | 1908 ;; is pointing to, so prompt for it |
1895 (t (find-file (read-file-name "Exception file: " | 1909 (t (find-file (read-file-name "Exception file: " |
1896 nil | 1910 nil |
1897 file t)))))) | 1911 file t)))))) |
1898 ;; Fiddle about with line number | 1912 ;; Fiddle about with line number |
1899 (setq line (+ py-line-number-offset line)) | 1913 (setq line (+ py-line-number-offset line)) |
1900 | 1914 |
1901 (pop-to-buffer buffer) | 1915 (pop-to-buffer buffer) |
1902 ;; Force Python mode | 1916 ;; Force Python mode |
1903 (if (not (eq major-mode 'python-mode)) | 1917 (if (not (eq major-mode 'python-mode)) |
1904 (python-mode)) | 1918 (python-mode)) |
1905 (goto-line line) | 1919 (goto-line line) |
1906 (message "Jumping to exception in file %s on line %d" file line))) | 1920 (message "Jumping to exception in file %s on line %d" file line))) |
1907 | 1921 |
1908 (defun py-mouseto-exception (event) | 1922 (defun py-mouseto-exception (event) |
1909 "Jump to the code which caused the Python exception at EVENT. | 1923 "Jump to the code which caused the Python exception at EVENT. |
1911 (interactive "e") | 1925 (interactive "e") |
1912 (cond | 1926 (cond |
1913 ((fboundp 'event-point) | 1927 ((fboundp 'event-point) |
1914 ;; XEmacs | 1928 ;; XEmacs |
1915 (let* ((point (event-point event)) | 1929 (let* ((point (event-point event)) |
1916 (buffer (event-buffer event)) | 1930 (buffer (event-buffer event)) |
1917 (e (and point buffer (extent-at point buffer 'py-exc-info))) | 1931 (e (and point buffer (extent-at point buffer 'py-exc-info))) |
1918 (info (and e (extent-property e 'py-exc-info)))) | 1932 (info (and e (extent-property e 'py-exc-info)))) |
1919 (message "Event point: %d, info: %s" point info) | 1933 (message "Event point: %d, info: %s" point info) |
1920 (and info | 1934 (and info |
1921 (py-jump-to-exception (car info) (cdr info))) | 1935 (py-jump-to-exception (car info) (cdr info))) |
1922 )) | 1936 )) |
1923 ;; Emacs -- Please port this! | 1937 ;; Emacs -- Please port this! |
1924 )) | 1938 )) |
1925 | 1939 |
1926 (defun py-goto-exception () | 1940 (defun py-goto-exception () |
1928 (interactive) | 1942 (interactive) |
1929 (let (file line) | 1943 (let (file line) |
1930 (save-excursion | 1944 (save-excursion |
1931 (beginning-of-line) | 1945 (beginning-of-line) |
1932 (if (looking-at py-traceback-line-re) | 1946 (if (looking-at py-traceback-line-re) |
1933 (setq file (match-string 1) | 1947 (setq file (match-string 1) |
1934 line (string-to-int (match-string 2))))) | 1948 line (string-to-number (match-string 2))))) |
1935 (if (not file) | 1949 (if (not file) |
1936 (error "Not on a traceback line")) | 1950 (error "Not on a traceback line")) |
1937 (py-jump-to-exception file line))) | 1951 (py-jump-to-exception file line))) |
1938 | 1952 |
1939 (defun py-find-next-exception (start buffer searchdir errwhere) | 1953 (defun py-find-next-exception (start buffer searchdir errwhere) |
1940 "Find the next Python exception and jump to the code that caused it. | 1954 "Find the next Python exception and jump to the code that caused it. |
1941 START is the buffer position in BUFFER from which to begin searching | 1955 START is the buffer position in BUFFER from which to begin searching |
1946 (let (file line) | 1960 (let (file line) |
1947 (save-excursion | 1961 (save-excursion |
1948 (set-buffer buffer) | 1962 (set-buffer buffer) |
1949 (goto-char (py-point start)) | 1963 (goto-char (py-point start)) |
1950 (if (funcall searchdir py-traceback-line-re nil t) | 1964 (if (funcall searchdir py-traceback-line-re nil t) |
1951 (setq file (match-string 1) | 1965 (setq file (match-string 1) |
1952 line (string-to-int (match-string 2))))) | 1966 line (string-to-number (match-string 2))))) |
1953 (if (and file line) | 1967 (if (and file line) |
1954 (py-jump-to-exception file line) | 1968 (py-jump-to-exception file line) |
1955 (error "%s of traceback" errwhere)))) | 1969 (error "%s of traceback" errwhere)))) |
1956 | 1970 |
1957 (defun py-down-exception (&optional bottom) | 1971 (defun py-down-exception (&optional bottom) |
1958 "Go to the next line down in the traceback. | 1972 "Go to the next line down in the traceback. |
1959 With \\[univeral-argument] (programmatically, optional argument | 1973 With \\[univeral-argument] (programmatically, optional argument |
1960 BOTTOM), jump to the bottom (innermost) exception in the exception | 1974 BOTTOM), jump to the bottom (innermost) exception in the exception |
1961 stack." | 1975 stack." |
1962 (interactive "P") | 1976 (interactive "P") |
1963 (let* ((proc (get-process "Python")) | 1977 (let* ((proc (get-process "Python")) |
1964 (buffer (if proc "*Python*" py-output-buffer))) | 1978 (buffer (if proc "*Python*" py-output-buffer))) |
1965 (if bottom | 1979 (if bottom |
1966 (py-find-next-exception 'eob buffer 're-search-backward "Bottom") | 1980 (py-find-next-exception 'eob buffer 're-search-backward "Bottom") |
1967 (py-find-next-exception 'eol buffer 're-search-forward "Bottom")))) | 1981 (py-find-next-exception 'eol buffer 're-search-forward "Bottom")))) |
1968 | 1982 |
1969 (defun py-up-exception (&optional top) | 1983 (defun py-up-exception (&optional top) |
1970 "Go to the previous line up in the traceback. | 1984 "Go to the previous line up in the traceback. |
1971 With \\[universal-argument] (programmatically, optional argument TOP) | 1985 With \\[universal-argument] (programmatically, optional argument TOP) |
1972 jump to the top (outermost) exception in the exception stack." | 1986 jump to the top (outermost) exception in the exception stack." |
1973 (interactive "P") | 1987 (interactive "P") |
1974 (let* ((proc (get-process "Python")) | 1988 (let* ((proc (get-process "Python")) |
1975 (buffer (if proc "*Python*" py-output-buffer))) | 1989 (buffer (if proc "*Python*" py-output-buffer))) |
1976 (if top | 1990 (if top |
1977 (py-find-next-exception 'bob buffer 're-search-forward "Top") | 1991 (py-find-next-exception 'bob buffer 're-search-forward "Top") |
1978 (py-find-next-exception 'bol buffer 're-search-backward "Top")))) | 1992 (py-find-next-exception 'bol buffer 're-search-backward "Top")))) |
1979 | 1993 |
1980 | 1994 |
1981 ;; Electric deletion | 1995 ;; Electric deletion |
1982 (defun py-electric-backspace (arg) | 1996 (defun py-electric-backspace (arg) |
2003 When used programmatically, argument ARG specifies the number of | 2017 When used programmatically, argument ARG specifies the number of |
2004 blocks to dedent, or the number of characters to delete, as indicated | 2018 blocks to dedent, or the number of characters to delete, as indicated |
2005 above." | 2019 above." |
2006 (interactive "*p") | 2020 (interactive "*p") |
2007 (if (or (/= (current-indentation) (current-column)) | 2021 (if (or (/= (current-indentation) (current-column)) |
2008 (bolp) | 2022 (bolp) |
2009 (py-continuation-line-p) | 2023 (py-continuation-line-p) |
2010 ; (not py-honor-comment-indentation) | 2024 ; (not py-honor-comment-indentation) |
2011 ; (looking-at "#[^ \t\n]") ; non-indenting # | 2025 ; (looking-at "#[^ \t\n]") ; non-indenting # |
2012 ) | 2026 ) |
2013 (funcall py-backspace-function arg) | 2027 (funcall py-backspace-function arg) |
2014 ;; else indent the same as the colon line that opened the block | 2028 ;; else indent the same as the colon line that opened the block |
2015 ;; force non-blank so py-goto-block-up doesn't ignore it | 2029 ;; force non-blank so py-goto-block-up doesn't ignore it |
2016 (insert-char ?* 1) | 2030 (insert-char ?* 1) |
2017 (backward-char) | 2031 (backward-char) |
2018 (let ((base-indent 0) ; indentation of base line | 2032 (let ((base-indent 0) ; indentation of base line |
2019 (base-text "") ; and text of base line | 2033 (base-text "") ; and text of base line |
2020 (base-found-p nil)) | 2034 (base-found-p nil)) |
2021 (save-excursion | 2035 (save-excursion |
2022 (while (< 0 arg) | 2036 (while (< 0 arg) |
2023 (condition-case nil ; in case no enclosing block | 2037 (condition-case nil ; in case no enclosing block |
2024 (progn | 2038 (progn |
2025 (py-goto-block-up 'no-mark) | 2039 (py-goto-block-up 'no-mark) |
2026 (setq base-indent (current-indentation) | 2040 (setq base-indent (current-indentation) |
2027 base-text (py-suck-up-leading-text) | 2041 base-text (py-suck-up-leading-text) |
2028 base-found-p t)) | 2042 base-found-p t)) |
2029 (error nil)) | 2043 (error nil)) |
2030 (setq arg (1- arg)))) | 2044 (setq arg (1- arg)))) |
2031 (delete-char 1) ; toss the dummy character | 2045 (delete-char 1) ; toss the dummy character |
2032 (delete-horizontal-space) | 2046 (delete-horizontal-space) |
2033 (indent-to base-indent) | 2047 (indent-to base-indent) |
2034 (if base-found-p | 2048 (if base-found-p |
2035 (message "Closes block: %s" base-text))))) | 2049 (message "Closes block: %s" base-text))))) |
2036 | 2050 |
2037 | 2051 |
2038 (defun py-electric-delete (arg) | 2052 (defun py-electric-delete (arg) |
2039 "Delete preceding or following character or levels of whitespace. | 2053 "Delete preceding or following character or levels of whitespace. |
2040 | 2054 |
2049 | 2063 |
2050 \\[universal-argument] (programmatically, argument ARG) specifies the | 2064 \\[universal-argument] (programmatically, argument ARG) specifies the |
2051 number of characters to delete (default is 1)." | 2065 number of characters to delete (default is 1)." |
2052 (interactive "*p") | 2066 (interactive "*p") |
2053 (if (or (and (fboundp 'delete-forward-p) ;XEmacs 21 | 2067 (if (or (and (fboundp 'delete-forward-p) ;XEmacs 21 |
2054 (delete-forward-p)) | 2068 (delete-forward-p)) |
2055 (and (boundp 'delete-key-deletes-forward) ;XEmacs 20 | 2069 (and (boundp 'delete-key-deletes-forward) ;XEmacs 20 |
2056 delete-key-deletes-forward)) | 2070 delete-key-deletes-forward)) |
2057 (funcall py-delete-function arg) | 2071 (funcall py-delete-function arg) |
2058 (py-electric-backspace arg))) | 2072 (py-electric-backspace arg))) |
2059 | 2073 |
2060 ;; required for pending-del and delsel modes | 2074 ;; required for pending-del and delsel modes |
2061 (put 'py-electric-colon 'delete-selection t) ;delsel | 2075 (put 'py-electric-colon 'delete-selection t) ;delsel |
2075 | 2089 |
2076 This function is normally bound to `indent-line-function' so | 2090 This function is normally bound to `indent-line-function' so |
2077 \\[indent-for-tab-command] will call it." | 2091 \\[indent-for-tab-command] will call it." |
2078 (interactive "P") | 2092 (interactive "P") |
2079 (let* ((ci (current-indentation)) | 2093 (let* ((ci (current-indentation)) |
2080 (move-to-indentation-p (<= (current-column) ci)) | 2094 (move-to-indentation-p (<= (current-column) ci)) |
2081 (need (py-compute-indentation (not arg))) | 2095 (need (py-compute-indentation (not arg))) |
2082 (cc (current-column))) | 2096 (cc (current-column))) |
2083 ;; dedent out a level if previous command was the same unless we're in | 2097 ;; dedent out a level if previous command was the same unless we're in |
2084 ;; column 1 | 2098 ;; column 1 |
2085 (if (and (equal last-command this-command) | 2099 (if (and (equal last-command this-command) |
2086 (/= cc 0)) | 2100 (/= cc 0)) |
2087 (progn | 2101 (progn |
2088 (beginning-of-line) | 2102 (beginning-of-line) |
2089 (delete-horizontal-space) | 2103 (delete-horizontal-space) |
2090 (indent-to (* (/ (- cc 1) py-indent-offset) py-indent-offset))) | 2104 (indent-to (* (/ (- cc 1) py-indent-offset) py-indent-offset))) |
2091 (progn | 2105 (progn |
2092 ;; see if we need to dedent | 2106 ;; see if we need to dedent |
2093 (if (py-outdent-p) | 2107 (if (py-outdent-p) |
2094 (setq need (- need py-indent-offset))) | 2108 (setq need (- need py-indent-offset))) |
2095 (if (or py-tab-always-indent | 2109 (if (or py-tab-always-indent |
2096 move-to-indentation-p) | 2110 move-to-indentation-p) |
2097 (progn (if (/= ci need) | 2111 (progn (if (/= ci need) |
2098 (save-excursion | 2112 (save-excursion |
2099 (beginning-of-line) | 2113 (beginning-of-line) |
2100 (delete-horizontal-space) | 2114 (delete-horizontal-space) |
2101 (indent-to need))) | 2115 (indent-to need))) |
2102 (if move-to-indentation-p (back-to-indentation))) | 2116 (if move-to-indentation-p (back-to-indentation))) |
2103 (insert-tab)))))) | 2117 (insert-tab)))))) |
2104 | 2118 |
2105 (defun py-newline-and-indent () | 2119 (defun py-newline-and-indent () |
2106 "Strives to act like the Emacs `newline-and-indent'. | 2120 "Strives to act like the Emacs `newline-and-indent'. |
2107 This is just `strives to' because correct indentation can't be computed | 2121 This is just `strives to' because correct indentation can't be computed |
2108 from scratch for Python code. In general, deletes the whitespace before | 2122 from scratch for Python code. In general, deletes the whitespace before |
2109 point, inserts a newline, and takes an educated guess as to how you want | 2123 point, inserts a newline, and takes an educated guess as to how you want |
2110 the new line indented." | 2124 the new line indented." |
2111 (interactive) | 2125 (interactive) |
2112 (let ((ci (current-indentation))) | 2126 (let ((ci (current-indentation))) |
2113 (if (< ci (current-column)) ; if point beyond indentation | 2127 (if (< ci (current-column)) ; if point beyond indentation |
2114 (newline-and-indent) | 2128 (newline-and-indent) |
2115 ;; else try to act like newline-and-indent "normally" acts | 2129 ;; else try to act like newline-and-indent "normally" acts |
2116 (beginning-of-line) | 2130 (beginning-of-line) |
2117 (insert-char ?\n 1) | 2131 (insert-char ?\n 1) |
2118 (move-to-column ci)))) | 2132 (move-to-column ci)))) |
2119 | 2133 |
2123 `raise', `break', `continue', and `pass' force one level of | 2137 `raise', `break', `continue', and `pass' force one level of |
2124 dedenting." | 2138 dedenting." |
2125 (save-excursion | 2139 (save-excursion |
2126 (beginning-of-line) | 2140 (beginning-of-line) |
2127 (let* ((bod (py-point 'bod)) | 2141 (let* ((bod (py-point 'bod)) |
2128 (pps (parse-partial-sexp bod (point))) | 2142 (pps (parse-partial-sexp bod (point))) |
2129 (boipps (parse-partial-sexp bod (py-point 'boi))) | 2143 (boipps (parse-partial-sexp bod (py-point 'boi))) |
2130 placeholder) | 2144 placeholder) |
2131 (cond | 2145 (cond |
2132 ;; are we inside a multi-line string or comment? | 2146 ;; are we inside a multi-line string or comment? |
2133 ((or (and (nth 3 pps) (nth 3 boipps)) | 2147 ((or (and (nth 3 pps) (nth 3 boipps)) |
2134 (and (nth 4 pps) (nth 4 boipps))) | 2148 (and (nth 4 pps) (nth 4 boipps))) |
2135 (save-excursion | 2149 (save-excursion |
2136 (if (not py-align-multiline-strings-p) 0 | 2150 (if (not py-align-multiline-strings-p) 0 |
2137 ;; skip back over blank & non-indenting comment lines | 2151 ;; skip back over blank & non-indenting comment lines |
2138 ;; note: will skip a blank or non-indenting comment line | 2152 ;; note: will skip a blank or non-indenting comment line |
2139 ;; that happens to be a continuation line too | 2153 ;; that happens to be a continuation line too |
2140 (re-search-backward "^[ \t]*\\([^ \t\n#]\\|#[ \t\n]\\)" nil 'move) | 2154 (re-search-backward "^[ \t]*\\([^ \t\n#]\\|#[ \t\n]\\)" nil 'move) |
2141 (back-to-indentation) | 2155 (back-to-indentation) |
2142 (current-column)))) | 2156 (current-column)))) |
2143 ;; are we on a continuation line? | 2157 ;; are we on a continuation line? |
2144 ((py-continuation-line-p) | 2158 ((py-continuation-line-p) |
2145 (let ((startpos (point)) | 2159 (let ((startpos (point)) |
2146 (open-bracket-pos (py-nesting-level)) | 2160 (open-bracket-pos (py-nesting-level)) |
2147 endpos searching found state) | 2161 endpos searching found state cind cline) |
2148 (if open-bracket-pos | 2162 (if open-bracket-pos |
2149 (progn | 2163 (progn |
2150 ;; align with first item in list; else a normal | 2164 (setq endpos (py-point 'bol)) |
2151 ;; indent beyond the line with the open bracket | 2165 (py-goto-initial-line) |
2152 (goto-char (1+ open-bracket-pos)) ; just beyond bracket | 2166 (setq cind (current-indentation)) |
2153 ;; is the first list item on the same line? | 2167 (setq cline cind) |
2154 (skip-chars-forward " \t") | 2168 (dolist (bp |
2155 (if (null (memq (following-char) '(?\n ?# ?\\))) | 2169 (nth 9 (save-excursion |
2156 ; yes, so line up with it | 2170 (parse-partial-sexp (point) endpos))) |
2157 (current-column) | 2171 cind) |
2158 ;; first list item on another line, or doesn't exist yet | 2172 (if (search-forward "\n" bp t) (setq cline cind)) |
2159 (forward-line 1) | 2173 (goto-char (1+ bp)) |
2160 (while (and (< (point) startpos) | 2174 (skip-chars-forward " \t") |
2161 (looking-at "[ \t]*[#\n\\\\]")) ; skip noise | 2175 (setq cind (if (memq (following-char) '(?\n ?# ?\\)) |
2162 (forward-line 1)) | 2176 (+ cline py-indent-offset) |
2163 (if (and (< (point) startpos) | 2177 (current-column))))) |
2164 (/= startpos | 2178 ;; else on backslash continuation line |
2165 (save-excursion | 2179 (forward-line -1) |
2166 (goto-char (1+ open-bracket-pos)) | 2180 (if (py-continuation-line-p) ; on at least 3rd line in block |
2167 (forward-comment (point-max)) | 2181 (current-indentation) ; so just continue the pattern |
2168 (point)))) | 2182 ;; else started on 2nd line in block, so indent more. |
2169 ;; again mimic the first list item | 2183 ;; if base line is an assignment with a start on a RHS, |
2170 (current-indentation) | 2184 ;; indent to 2 beyond the leftmost "="; else skip first |
2171 ;; else they're about to enter the first item | 2185 ;; chunk of non-whitespace characters on base line, + 1 more |
2172 (goto-char open-bracket-pos) | 2186 ;; column |
2173 (setq placeholder (point)) | 2187 (end-of-line) |
2174 (py-goto-initial-line) | 2188 (setq endpos (point) |
2175 (py-goto-beginning-of-tqs | 2189 searching t) |
2176 (save-excursion (nth 3 (parse-partial-sexp | 2190 (back-to-indentation) |
2177 placeholder (point))))) | 2191 (setq startpos (point)) |
2178 (+ (current-indentation) py-indent-offset)))) | 2192 ;; look at all "=" from left to right, stopping at first |
2179 | 2193 ;; one not nested in a list or string |
2180 ;; else on backslash continuation line | 2194 (while searching |
2181 (forward-line -1) | 2195 (skip-chars-forward "^=" endpos) |
2182 (if (py-continuation-line-p) ; on at least 3rd line in block | 2196 (if (= (point) endpos) |
2183 (current-indentation) ; so just continue the pattern | 2197 (setq searching nil) |
2184 ;; else started on 2nd line in block, so indent more. | 2198 (forward-char 1) |
2185 ;; if base line is an assignment with a start on a RHS, | 2199 (setq state (parse-partial-sexp startpos (point))) |
2186 ;; indent to 2 beyond the leftmost "="; else skip first | 2200 (if (and (zerop (car state)) ; not in a bracket |
2187 ;; chunk of non-whitespace characters on base line, + 1 more | 2201 (null (nth 3 state))) ; & not in a string |
2188 ;; column | 2202 (progn |
2189 (end-of-line) | 2203 (setq searching nil) ; done searching in any case |
2190 (setq endpos (point) | 2204 (setq found |
2191 searching t) | 2205 (not (or |
2192 (back-to-indentation) | 2206 (eq (following-char) ?=) |
2193 (setq startpos (point)) | 2207 (memq (char-after (- (point) 2)) |
2194 ;; look at all "=" from left to right, stopping at first | 2208 '(?< ?> ?!))))))))) |
2195 ;; one not nested in a list or string | 2209 (if (or (not found) ; not an assignment |
2196 (while searching | 2210 (looking-at "[ \t]*\\\\")) ; <=><spaces><backslash> |
2197 (skip-chars-forward "^=" endpos) | 2211 (progn |
2198 (if (= (point) endpos) | 2212 (goto-char startpos) |
2199 (setq searching nil) | 2213 (skip-chars-forward "^ \t\n"))) |
2200 (forward-char 1) | 2214 ;; if this is a continuation for a block opening |
2201 (setq state (parse-partial-sexp startpos (point))) | 2215 ;; statement, add some extra offset. |
2202 (if (and (zerop (car state)) ; not in a bracket | 2216 (+ (current-column) (if (py-statement-opens-block-p) |
2203 (null (nth 3 state))) ; & not in a string | 2217 py-continuation-offset 0) |
2204 (progn | 2218 1) |
2205 (setq searching nil) ; done searching in any case | 2219 )))) |
2206 (setq found | |
2207 (not (or | |
2208 (eq (following-char) ?=) | |
2209 (memq (char-after (- (point) 2)) | |
2210 '(?< ?> ?!))))))))) | |
2211 (if (or (not found) ; not an assignment | |
2212 (looking-at "[ \t]*\\\\")) ; <=><spaces><backslash> | |
2213 (progn | |
2214 (goto-char startpos) | |
2215 (skip-chars-forward "^ \t\n"))) | |
2216 ;; if this is a continuation for a block opening | |
2217 ;; statement, add some extra offset. | |
2218 (+ (current-column) (if (py-statement-opens-block-p) | |
2219 py-continuation-offset 0) | |
2220 1) | |
2221 )))) | |
2222 | 2220 |
2223 ;; not on a continuation line | 2221 ;; not on a continuation line |
2224 ((bobp) (current-indentation)) | 2222 ((bobp) (current-indentation)) |
2225 | 2223 |
2226 ;; Dfn: "Indenting comment line". A line containing only a | 2224 ;; Dfn: "Indenting comment line". A line containing only a |
2246 ;; indenting comment line? If so, we assume that it's been | 2244 ;; indenting comment line? If so, we assume that it's been |
2247 ;; placed at the desired indentation, so leave it alone. | 2245 ;; placed at the desired indentation, so leave it alone. |
2248 ;; Indenting comment lines are aligned as statements down | 2246 ;; Indenting comment lines are aligned as statements down |
2249 ;; below. | 2247 ;; below. |
2250 ((and (looking-at "[ \t]*#[^ \t\n]") | 2248 ((and (looking-at "[ \t]*#[^ \t\n]") |
2251 ;; NOTE: this test will not be performed in older Emacsen | 2249 ;; NOTE: this test will not be performed in older Emacsen |
2252 (fboundp 'forward-comment) | 2250 (fboundp 'forward-comment) |
2253 (<= (current-indentation) | 2251 (<= (current-indentation) |
2254 (save-excursion | 2252 (save-excursion |
2255 (forward-comment (- (point-max))) | 2253 (forward-comment (- (point-max))) |
2256 (current-indentation)))) | 2254 (current-indentation)))) |
2257 (current-indentation)) | 2255 (current-indentation)) |
2258 | 2256 |
2259 ;; else indentation based on that of the statement that | 2257 ;; else indentation based on that of the statement that |
2260 ;; precedes us; use the first line of that statement to | 2258 ;; precedes us; use the first line of that statement to |
2261 ;; establish the base, in case the user forced a non-std | 2259 ;; establish the base, in case the user forced a non-std |
2262 ;; indentation for the continuation lines (if any) | 2260 ;; indentation for the continuation lines (if any) |
2263 (t | 2261 (t |
2264 ;; skip back over blank & non-indenting comment lines note: | 2262 ;; skip back over blank & non-indenting comment lines note: |
2265 ;; will skip a blank or non-indenting comment line that | 2263 ;; will skip a blank or non-indenting comment line that |
2266 ;; happens to be a continuation line too. use fast Emacs 19 | 2264 ;; happens to be a continuation line too. use fast Emacs 19 |
2267 ;; function if it's there. | 2265 ;; function if it's there. |
2268 (if (and (eq py-honor-comment-indentation nil) | 2266 (if (and (eq py-honor-comment-indentation nil) |
2269 (fboundp 'forward-comment)) | 2267 (fboundp 'forward-comment)) |
2270 (forward-comment (- (point-max))) | 2268 (forward-comment (- (point-max))) |
2271 (let ((prefix-re (concat py-block-comment-prefix "[ \t]*")) | 2269 (let ((prefix-re (concat py-block-comment-prefix "[ \t]*")) |
2272 done) | 2270 done) |
2273 (while (not done) | 2271 (while (not done) |
2274 (re-search-backward "^[ \t]*\\([^ \t\n#]\\|#\\)" nil 'move) | 2272 (re-search-backward "^[ \t]*\\([^ \t\n#]\\|#\\)" nil 'move) |
2275 (setq done (or (bobp) | 2273 (setq done (or (bobp) |
2276 (and (eq py-honor-comment-indentation t) | 2274 (and (eq py-honor-comment-indentation t) |
2277 (save-excursion | 2275 (save-excursion |
2278 (back-to-indentation) | 2276 (back-to-indentation) |
2279 (not (looking-at prefix-re)) | 2277 (not (looking-at prefix-re)) |
2280 )) | 2278 )) |
2281 (and (not (eq py-honor-comment-indentation t)) | 2279 (and (not (eq py-honor-comment-indentation t)) |
2282 (save-excursion | 2280 (save-excursion |
2283 (back-to-indentation) | 2281 (back-to-indentation) |
2284 (and (not (looking-at prefix-re)) | 2282 (and (not (looking-at prefix-re)) |
2285 (or (looking-at "[^#]") | 2283 (or (looking-at "[^#]") |
2286 (not (zerop (current-column))) | 2284 (not (zerop (current-column))) |
2287 )) | 2285 )) |
2288 )) | 2286 )) |
2289 )) | 2287 )) |
2290 ))) | 2288 ))) |
2291 ;; if we landed inside a string, go to the beginning of that | 2289 ;; if we landed inside a string, go to the beginning of that |
2292 ;; string. this handles triple quoted, multi-line spanning | 2290 ;; string. this handles triple quoted, multi-line spanning |
2293 ;; strings. | 2291 ;; strings. |
2294 (py-goto-beginning-of-tqs (nth 3 (parse-partial-sexp bod (point)))) | 2292 (py-goto-beginning-of-tqs (nth 3 (parse-partial-sexp bod (point)))) |
2295 ;; now skip backward over continued lines | 2293 ;; now skip backward over continued lines |
2296 (setq placeholder (point)) | 2294 (setq placeholder (point)) |
2297 (py-goto-initial-line) | 2295 (py-goto-initial-line) |
2298 ;; we may *now* have landed in a TQS, so find the beginning of | 2296 ;; we may *now* have landed in a TQS, so find the beginning of |
2299 ;; this string. | 2297 ;; this string. |
2300 (py-goto-beginning-of-tqs | 2298 (py-goto-beginning-of-tqs |
2301 (save-excursion (nth 3 (parse-partial-sexp | 2299 (save-excursion (nth 3 (parse-partial-sexp |
2302 placeholder (point))))) | 2300 placeholder (point))))) |
2303 (+ (current-indentation) | 2301 (+ (current-indentation) |
2304 (if (py-statement-opens-block-p) | 2302 (if (py-statement-opens-block-p) |
2305 py-indent-offset | 2303 py-indent-offset |
2306 (if (and honor-block-close-p (py-statement-closes-block-p)) | 2304 (if (and honor-block-close-p (py-statement-closes-block-p)) |
2307 (- py-indent-offset) | 2305 (- py-indent-offset) |
2308 0))) | 2306 0))) |
2309 ))))) | 2307 ))))) |
2310 | 2308 |
2311 (defun py-guess-indent-offset (&optional global) | 2309 (defun py-guess-indent-offset (&optional global) |
2312 "Guess a good value for, and change, `py-indent-offset'. | 2310 "Guess a good value for, and change, `py-indent-offset'. |
2313 | 2311 |
2314 By default, make a buffer-local copy of `py-indent-offset' with the | 2312 By default, make a buffer-local copy of `py-indent-offset' with the |
2327 Specifically, it searches forward from the statement containing point, | 2325 Specifically, it searches forward from the statement containing point, |
2328 looking for a line that opens a block of code. `py-indent-offset' is | 2326 looking for a line that opens a block of code. `py-indent-offset' is |
2329 set to the difference in indentation between that line and the Python | 2327 set to the difference in indentation between that line and the Python |
2330 statement following it. If the search doesn't succeed going forward, | 2328 statement following it. If the search doesn't succeed going forward, |
2331 it's tried again going backward." | 2329 it's tried again going backward." |
2332 (interactive "P") ; raw prefix arg | 2330 (interactive "P") ; raw prefix arg |
2333 (let (new-value | 2331 (let (new-value |
2334 (start (point)) | 2332 (start (point)) |
2335 (restart (point)) | 2333 (restart (point)) |
2336 (found nil) | 2334 (found nil) |
2337 colon-indent) | 2335 colon-indent) |
2338 (py-goto-initial-line) | 2336 (py-goto-initial-line) |
2339 (while (not (or found (eobp))) | 2337 (while (not (or found (eobp))) |
2340 (when (and (re-search-forward ":[ \t]*\\($\\|[#\\]\\)" nil 'move) | 2338 (when (and (re-search-forward ":[ \t]*\\($\\|[#\\]\\)" nil 'move) |
2341 (not (py-in-literal restart))) | 2339 (not (py-in-literal restart))) |
2342 (setq restart (point)) | 2340 (setq restart (point)) |
2343 (py-goto-initial-line) | 2341 (py-goto-initial-line) |
2344 (if (py-statement-opens-block-p) | 2342 (if (py-statement-opens-block-p) |
2345 (setq found t) | 2343 (setq found t) |
2346 (goto-char restart)))) | 2344 (goto-char restart)))) |
2347 (unless found | 2345 (unless found |
2348 (goto-char start) | 2346 (goto-char start) |
2349 (py-goto-initial-line) | 2347 (py-goto-initial-line) |
2350 (while (not (or found (bobp))) | 2348 (while (not (or found (bobp))) |
2351 (setq found (and | 2349 (setq found (and |
2352 (re-search-backward ":[ \t]*\\($\\|[#\\]\\)" nil 'move) | 2350 (re-search-backward ":[ \t]*\\($\\|[#\\]\\)" nil 'move) |
2353 (or (py-goto-initial-line) t) ; always true -- side effect | 2351 (or (py-goto-initial-line) t) ; always true -- side effect |
2354 (py-statement-opens-block-p))))) | 2352 (py-statement-opens-block-p))))) |
2355 (setq colon-indent (current-indentation) | 2353 (setq colon-indent (current-indentation) |
2356 found (and found (zerop (py-next-statement 1))) | 2354 found (and found (zerop (py-next-statement 1))) |
2357 new-value (- (current-indentation) colon-indent)) | 2355 new-value (- (current-indentation) colon-indent)) |
2358 (goto-char start) | 2356 (goto-char start) |
2359 (if (not found) | 2357 (if (not found) |
2360 (error "Sorry, couldn't guess a value for py-indent-offset") | 2358 (error "Sorry, couldn't guess a value for py-indent-offset") |
2361 (funcall (if global 'kill-local-variable 'make-local-variable) | 2359 (funcall (if global 'kill-local-variable 'make-local-variable) |
2362 'py-indent-offset) | 2360 'py-indent-offset) |
2363 (setq py-indent-offset new-value) | 2361 (setq py-indent-offset new-value) |
2364 (or noninteractive | 2362 (or noninteractive |
2365 (message "%s value of py-indent-offset set to %d" | 2363 (message "%s value of py-indent-offset set to %d" |
2366 (if global "Global" "Local") | 2364 (if global "Global" "Local") |
2367 py-indent-offset))) | 2365 py-indent-offset))) |
2368 )) | 2366 )) |
2369 | 2367 |
2370 (defun py-comment-indent-function () | 2368 (defun py-comment-indent-function () |
2371 "Python version of `comment-indent-function'." | 2369 "Python version of `comment-indent-function'." |
2372 ;; This is required when filladapt is turned off. Without it, when | 2370 ;; This is required when filladapt is turned off. Without it, when |
2374 ;; cascade one character to the right | 2372 ;; cascade one character to the right |
2375 (save-excursion | 2373 (save-excursion |
2376 (beginning-of-line) | 2374 (beginning-of-line) |
2377 (let ((eol (py-point 'eol))) | 2375 (let ((eol (py-point 'eol))) |
2378 (and comment-start-skip | 2376 (and comment-start-skip |
2379 (re-search-forward comment-start-skip eol t) | 2377 (re-search-forward comment-start-skip eol t) |
2380 (setq eol (match-beginning 0))) | 2378 (setq eol (match-beginning 0))) |
2381 (goto-char eol) | 2379 (goto-char eol) |
2382 (skip-chars-backward " \t") | 2380 (skip-chars-backward " \t") |
2383 (max comment-column (+ (current-column) (if (bolp) 0 1))) | 2381 (max comment-column (+ (current-column) (if (bolp) 0 1))) |
2384 ))) | 2382 ))) |
2385 | 2383 |
2403 (beginning-of-line) | 2401 (beginning-of-line) |
2404 (setq end (point)) | 2402 (setq end (point)) |
2405 (goto-char start) | 2403 (goto-char start) |
2406 (beginning-of-line) | 2404 (beginning-of-line) |
2407 (setq start (point)) | 2405 (setq start (point)) |
2408 (indent-rigidly start end count))) | 2406 (let (deactivate-mark) |
2407 (indent-rigidly start end count)))) | |
2409 | 2408 |
2410 (defun py-shift-region-left (start end &optional count) | 2409 (defun py-shift-region-left (start end &optional count) |
2411 "Shift region of Python code to the left. | 2410 "Shift region of Python code to the left. |
2412 The lines from the line containing the start of the current region up | 2411 The lines from the line containing the start of the current region up |
2413 to (but not including) the line containing the end of the region are | 2412 to (but not including) the line containing the end of the region are |
2416 If a prefix argument is given, the region is instead shifted by that | 2415 If a prefix argument is given, the region is instead shifted by that |
2417 many columns. With no active region, dedent only the current line. | 2416 many columns. With no active region, dedent only the current line. |
2418 You cannot dedent the region if any line is already at column zero." | 2417 You cannot dedent the region if any line is already at column zero." |
2419 (interactive | 2418 (interactive |
2420 (let ((p (point)) | 2419 (let ((p (point)) |
2421 (m (mark)) | 2420 (m (condition-case nil (mark) (mark-inactive nil))) |
2422 (arg current-prefix-arg)) | 2421 (arg current-prefix-arg)) |
2423 (if m | 2422 (if m |
2424 (list (min p m) (max p m) arg) | 2423 (list (min p m) (max p m) arg) |
2425 (list p (save-excursion (forward-line 1) (point)) arg)))) | 2424 (list p (save-excursion (forward-line 1) (point)) arg)))) |
2426 ;; if any line is at column zero, don't shift the region | 2425 ;; if any line is at column zero, don't shift the region |
2427 (save-excursion | 2426 (save-excursion |
2428 (goto-char start) | 2427 (goto-char start) |
2429 (while (< (point) end) | 2428 (while (< (point) end) |
2430 (back-to-indentation) | 2429 (back-to-indentation) |
2431 (if (and (zerop (current-column)) | 2430 (if (and (zerop (current-column)) |
2432 (not (looking-at "\\s *$"))) | 2431 (not (looking-at "\\s *$"))) |
2433 (error "Region is at left edge")) | 2432 (error "Region is at left edge")) |
2434 (forward-line 1))) | 2433 (forward-line 1))) |
2435 (py-shift-region start end (- (prefix-numeric-value | 2434 (py-shift-region start end (- (prefix-numeric-value |
2436 (or count py-indent-offset)))) | 2435 (or count py-indent-offset)))) |
2437 (py-keep-region-active)) | 2436 (py-keep-region-active)) |
2438 | 2437 |
2439 (defun py-shift-region-right (start end &optional count) | 2438 (defun py-shift-region-right (start end &optional count) |
2440 "Shift region of Python code to the right. | 2439 "Shift region of Python code to the right. |
2441 The lines from the line containing the start of the current region up | 2440 The lines from the line containing the start of the current region up |
2444 | 2443 |
2445 If a prefix argument is given, the region is instead shifted by that | 2444 If a prefix argument is given, the region is instead shifted by that |
2446 many columns. With no active region, indent only the current line." | 2445 many columns. With no active region, indent only the current line." |
2447 (interactive | 2446 (interactive |
2448 (let ((p (point)) | 2447 (let ((p (point)) |
2449 (m (mark)) | 2448 (m (condition-case nil (mark) (mark-inactive nil))) |
2450 (arg current-prefix-arg)) | 2449 (arg current-prefix-arg)) |
2451 (if m | 2450 (if m |
2452 (list (min p m) (max p m) arg) | 2451 (list (min p m) (max p m) arg) |
2453 (list p (save-excursion (forward-line 1) (point)) arg)))) | 2452 (list p (save-excursion (forward-line 1) (point)) arg)))) |
2454 (py-shift-region start end (prefix-numeric-value | 2453 (py-shift-region start end (prefix-numeric-value |
2455 (or count py-indent-offset))) | 2454 (or count py-indent-offset))) |
2456 (py-keep-region-active)) | 2455 (py-keep-region-active)) |
2457 | 2456 |
2458 (defun py-indent-region (start end &optional indent-offset) | 2457 (defun py-indent-region (start end &optional indent-offset) |
2459 "Reindent a region of Python code. | 2458 "Reindent a region of Python code. |
2460 | 2459 |
2485 | 2484 |
2486 Special cases: whitespace is deleted from blank lines; continuation | 2485 Special cases: whitespace is deleted from blank lines; continuation |
2487 lines are shifted by the same amount their initial line was shifted, | 2486 lines are shifted by the same amount their initial line was shifted, |
2488 in order to preserve their relative indentation with respect to their | 2487 in order to preserve their relative indentation with respect to their |
2489 initial line; and comment lines beginning in column 1 are ignored." | 2488 initial line; and comment lines beginning in column 1 are ignored." |
2490 (interactive "*r\nP") ; region; raw prefix arg | 2489 (interactive "*r\nP") ; region; raw prefix arg |
2491 (save-excursion | 2490 (save-excursion |
2492 (goto-char end) (beginning-of-line) (setq end (point-marker)) | 2491 (goto-char end) (beginning-of-line) (setq end (point-marker)) |
2493 (goto-char start) (beginning-of-line) | 2492 (goto-char start) (beginning-of-line) |
2494 (let ((py-indent-offset (prefix-numeric-value | 2493 (let ((py-indent-offset (prefix-numeric-value |
2495 (or indent-offset py-indent-offset))) | 2494 (or indent-offset py-indent-offset))) |
2496 (indents '(-1)) ; stack of active indent levels | 2495 (indents '(-1)) ; stack of active indent levels |
2497 (target-column 0) ; column to which to indent | 2496 (target-column 0) ; column to which to indent |
2498 (base-shifted-by 0) ; amount last base line was shifted | 2497 (base-shifted-by 0) ; amount last base line was shifted |
2499 (indent-base (if (looking-at "[ \t\n]") | 2498 (indent-base (if (looking-at "[ \t\n]") |
2500 (py-compute-indentation t) | 2499 (py-compute-indentation t) |
2501 0)) | 2500 0)) |
2502 ci) | 2501 ci) |
2503 (while (< (point) end) | 2502 (while (< (point) end) |
2504 (setq ci (current-indentation)) | 2503 (setq ci (current-indentation)) |
2505 ;; figure out appropriate target column | 2504 ;; figure out appropriate target column |
2506 (cond | 2505 (cond |
2507 ((or (eq (following-char) ?#) ; comment in column 1 | 2506 ((or (eq (following-char) ?#) ; comment in column 1 |
2508 (looking-at "[ \t]*$")) ; entirely blank | 2507 (looking-at "[ \t]*$")) ; entirely blank |
2509 (setq target-column 0)) | 2508 (setq target-column 0)) |
2510 ((py-continuation-line-p) ; shift relative to base line | 2509 ((py-continuation-line-p) ; shift relative to base line |
2511 (setq target-column (+ ci base-shifted-by))) | 2510 (setq target-column (+ ci base-shifted-by))) |
2512 (t ; new base line | 2511 (t ; new base line |
2513 (if (> ci (car indents)) ; going deeper; push it | 2512 (if (> ci (car indents)) ; going deeper; push it |
2514 (setq indents (cons ci indents)) | 2513 (setq indents (cons ci indents)) |
2515 ;; else we should have seen this indent before | 2514 ;; else we should have seen this indent before |
2516 (setq indents (memq ci indents)) ; pop deeper indents | 2515 (setq indents (memq ci indents)) ; pop deeper indents |
2517 (if (null indents) | 2516 (if (null indents) |
2518 (error "Bad indentation in region, at line %d" | 2517 (error "Bad indentation in region, at line %d" |
2519 (save-restriction | 2518 (save-restriction |
2520 (widen) | 2519 (widen) |
2521 (1+ (count-lines 1 (point))))))) | 2520 (1+ (count-lines 1 (point))))))) |
2522 (setq target-column (+ indent-base | 2521 (setq target-column (+ indent-base |
2523 (* py-indent-offset | 2522 (* py-indent-offset |
2524 (- (length indents) 2)))) | 2523 (- (length indents) 2)))) |
2525 (setq base-shifted-by (- target-column ci)))) | 2524 (setq base-shifted-by (- target-column ci)))) |
2526 ;; shift as needed | 2525 ;; shift as needed |
2527 (if (/= ci target-column) | 2526 (if (/= ci target-column) |
2528 (progn | 2527 (progn |
2529 (delete-horizontal-space) | 2528 (delete-horizontal-space) |
2530 (indent-to target-column))) | 2529 (indent-to target-column))) |
2531 (forward-line 1)))) | 2530 (forward-line 1)))) |
2532 (set-marker end nil)) | 2531 (set-marker end nil)) |
2533 | 2532 |
2534 (defun py-comment-region (beg end &optional arg) | 2533 (defun py-comment-region (beg end &optional arg) |
2535 "Like `comment-region' but uses double hash (`#') comment starter." | 2534 "Like `comment-region' but uses double hash (`#') comment starter." |
2536 (interactive "r\nP") | 2535 (interactive "r\nP") |
2537 (let ((comment-start py-block-comment-prefix)) | 2536 (let ((comment-start py-block-comment-prefix)) |
2538 (comment-region beg end arg))) | 2537 (comment-region beg end arg))) |
2538 | |
2539 (defun py-join-words-wrapping (words separator line-prefix line-length) | |
2540 (let ((lines ()) | |
2541 (current-line line-prefix)) | |
2542 (while words | |
2543 (let* ((word (car words)) | |
2544 (maybe-line (concat current-line word separator))) | |
2545 (if (> (length maybe-line) line-length) | |
2546 (setq lines (cons (substring current-line 0 -1) lines) | |
2547 current-line (concat line-prefix word separator " ")) | |
2548 (setq current-line (concat maybe-line " ")))) | |
2549 (setq words (cdr words))) | |
2550 (setq lines (cons (substring | |
2551 current-line 0 (- 0 (length separator) 1)) lines)) | |
2552 (mapconcat 'identity (nreverse lines) "\n"))) | |
2553 | |
2554 (defun py-sort-imports () | |
2555 "Sort multiline imports. | |
2556 Put point inside the parentheses of a multiline import and hit | |
2557 \\[py-sort-imports] to sort the imports lexicographically" | |
2558 (interactive) | |
2559 (save-excursion | |
2560 (let ((open-paren (save-excursion (progn (up-list -1) (point)))) | |
2561 (close-paren (save-excursion (progn (up-list 1) (point)))) | |
2562 sorted-imports) | |
2563 (goto-char (1+ open-paren)) | |
2564 (skip-chars-forward " \n\t") | |
2565 (setq sorted-imports | |
2566 (sort | |
2567 (delete-dups | |
2568 (split-string (buffer-substring | |
2569 (point) | |
2570 (save-excursion (goto-char (1- close-paren)) | |
2571 (skip-chars-backward " \n\t") | |
2572 (point))) | |
2573 ", *\\(\n *\\)?")) | |
2574 ;; XXX Should this sort case insensitively? | |
2575 'string-lessp)) | |
2576 ;; Remove empty strings. | |
2577 (delete-region open-paren close-paren) | |
2578 (goto-char open-paren) | |
2579 (insert "(\n") | |
2580 (insert (py-join-words-wrapping (remove "" sorted-imports) "," " " 78)) | |
2581 (insert ")") | |
2582 ))) | |
2583 | |
2539 | 2584 |
2540 | 2585 |
2541 ;; Functions for moving point | 2586 ;; Functions for moving point |
2542 (defun py-previous-statement (count) | 2587 (defun py-previous-statement (count) |
2543 "Go to the start of the COUNTth preceding Python statement. | 2588 "Go to the start of the COUNTth preceding Python statement. |
2544 By default, goes to the previous statement. If there is no such | 2589 By default, goes to the previous statement. If there is no such |
2545 statement, goes to the first statement. Return count of statements | 2590 statement, goes to the first statement. Return count of statements |
2546 left to move. `Statements' do not include blank, comment, or | 2591 left to move. `Statements' do not include blank, comment, or |
2547 continuation lines." | 2592 continuation lines." |
2548 (interactive "p") ; numeric prefix arg | 2593 (interactive "p") ; numeric prefix arg |
2549 (if (< count 0) (py-next-statement (- count)) | 2594 (if (< count 0) (py-next-statement (- count)) |
2550 (py-goto-initial-line) | 2595 (py-goto-initial-line) |
2551 (let (start) | 2596 (let (start) |
2552 (while (and | 2597 (while (and |
2553 (setq start (point)) ; always true -- side effect | 2598 (setq start (point)) ; always true -- side effect |
2554 (> count 0) | 2599 (> count 0) |
2555 (zerop (forward-line -1)) | 2600 (zerop (forward-line -1)) |
2556 (py-goto-statement-at-or-above)) | 2601 (py-goto-statement-at-or-above)) |
2557 (setq count (1- count))) | 2602 (setq count (1- count))) |
2558 (if (> count 0) (goto-char start))) | 2603 (if (> count 0) (goto-char start))) |
2559 count)) | 2604 count)) |
2560 | 2605 |
2561 (defun py-next-statement (count) | 2606 (defun py-next-statement (count) |
2562 "Go to the start of next Python statement. | 2607 "Go to the start of next Python statement. |
2563 If the statement at point is the i'th Python statement, goes to the | 2608 If the statement at point is the i'th Python statement, goes to the |
2564 start of statement i+COUNT. If there is no such statement, goes to the | 2609 start of statement i+COUNT. If there is no such statement, goes to the |
2565 last statement. Returns count of statements left to move. `Statements' | 2610 last statement. Returns count of statements left to move. `Statements' |
2566 do not include blank, comment, or continuation lines." | 2611 do not include blank, comment, or continuation lines." |
2567 (interactive "p") ; numeric prefix arg | 2612 (interactive "p") ; numeric prefix arg |
2568 (if (< count 0) (py-previous-statement (- count)) | 2613 (if (< count 0) (py-previous-statement (- count)) |
2569 (beginning-of-line) | 2614 (beginning-of-line) |
2570 (let (start) | 2615 (let (start) |
2571 (while (and | 2616 (while (and |
2572 (setq start (point)) ; always true -- side effect | 2617 (setq start (point)) ; always true -- side effect |
2573 (> count 0) | 2618 (> count 0) |
2574 (py-goto-statement-below)) | 2619 (py-goto-statement-below)) |
2575 (setq count (1- count))) | 2620 (setq count (1- count))) |
2576 (if (> count 0) (goto-char start))) | 2621 (if (> count 0) (goto-char start))) |
2577 count)) | 2622 count)) |
2578 | 2623 |
2579 (defun py-goto-block-up (&optional nomark) | 2624 (defun py-goto-block-up (&optional nomark) |
2580 "Move up to start of current block. | 2625 "Move up to start of current block. |
2588 | 2633 |
2589 If called from a program, the mark will not be set if optional argument | 2634 If called from a program, the mark will not be set if optional argument |
2590 NOMARK is not nil." | 2635 NOMARK is not nil." |
2591 (interactive) | 2636 (interactive) |
2592 (let ((start (point)) | 2637 (let ((start (point)) |
2593 (found nil) | 2638 (found nil) |
2594 initial-indent) | 2639 initial-indent) |
2595 (py-goto-initial-line) | 2640 (py-goto-initial-line) |
2596 ;; if on blank or non-indenting comment line, use the preceding stmt | 2641 ;; if on blank or non-indenting comment line, use the preceding stmt |
2597 (if (looking-at "[ \t]*\\($\\|#[^ \t\n]\\)") | 2642 (if (looking-at "[ \t]*\\($\\|#[^ \t\n]\\)") |
2598 (progn | 2643 (progn |
2599 (py-goto-statement-at-or-above) | 2644 (py-goto-statement-at-or-above) |
2600 (setq found (py-statement-opens-block-p)))) | 2645 (setq found (py-statement-opens-block-p)))) |
2601 ;; search back for colon line indented less | 2646 ;; search back for colon line indented less |
2602 (setq initial-indent (current-indentation)) | 2647 (setq initial-indent (current-indentation)) |
2603 (if (zerop initial-indent) | 2648 (if (zerop initial-indent) |
2604 ;; force fast exit | 2649 ;; force fast exit |
2605 (goto-char (point-min))) | 2650 (goto-char (point-min))) |
2606 (while (not (or found (bobp))) | 2651 (while (not (or found (bobp))) |
2607 (setq found | 2652 (setq found |
2608 (and | 2653 (and |
2609 (re-search-backward ":[ \t]*\\($\\|[#\\]\\)" nil 'move) | 2654 (re-search-backward ":[ \t]*\\($\\|[#\\]\\)" nil 'move) |
2610 (or (py-goto-initial-line) t) ; always true -- side effect | 2655 (or (py-goto-initial-line) t) ; always true -- side effect |
2611 (< (current-indentation) initial-indent) | 2656 (< (current-indentation) initial-indent) |
2612 (py-statement-opens-block-p)))) | 2657 (py-statement-opens-block-p)))) |
2613 (if found | 2658 (if found |
2614 (progn | 2659 (progn |
2615 (or nomark (push-mark start)) | 2660 (or nomark (push-mark start)) |
2616 (back-to-indentation)) | 2661 (back-to-indentation)) |
2617 (goto-char start) | 2662 (goto-char start) |
2618 (error "Enclosing block not found")))) | 2663 (error "Enclosing block not found")))) |
2619 | 2664 |
2620 (defun py-beginning-of-def-or-class (&optional class count) | 2665 (defun py-beginning-of-def-or-class (&optional class count) |
2621 "Move point to start of `def' or `class'. | 2666 "Move point to start of `def' or `class'. |
2641 | 2686 |
2642 Note that doing this command repeatedly will take you closer to the | 2687 Note that doing this command repeatedly will take you closer to the |
2643 start of the buffer each time. | 2688 start of the buffer each time. |
2644 | 2689 |
2645 To mark the current `def', see `\\[py-mark-def-or-class]'." | 2690 To mark the current `def', see `\\[py-mark-def-or-class]'." |
2646 (interactive "P") ; raw prefix arg | 2691 (interactive "P") ; raw prefix arg |
2647 (setq count (or count 1)) | 2692 (setq count (or count 1)) |
2648 (let ((at-or-before-p (<= (current-column) (current-indentation))) | 2693 (let ((at-or-before-p (<= (current-column) (current-indentation))) |
2649 (start-of-line (goto-char (py-point 'bol))) | 2694 (start-of-line (goto-char (py-point 'bol))) |
2650 (start-of-stmt (goto-char (py-point 'bos))) | 2695 (start-of-stmt (goto-char (py-point 'bos))) |
2651 (start-re (cond ((eq class 'either) "^[ \t]*\\(class\\|def\\)\\>") | 2696 (start-re (cond ((eq class 'either) "^[ \t]*\\(class\\|def\\)\\>") |
2652 (class "^[ \t]*class\\>") | 2697 (class "^[ \t]*class\\>") |
2653 (t "^[ \t]*def\\>"))) | 2698 (t "^[ \t]*def\\>"))) |
2654 ) | 2699 ) |
2655 ;; searching backward | 2700 ;; searching backward |
2656 (if (and (< 0 count) | 2701 (if (and (< 0 count) |
2657 (or (/= start-of-stmt start-of-line) | 2702 (or (/= start-of-stmt start-of-line) |
2658 (not at-or-before-p))) | 2703 (not at-or-before-p))) |
2659 (end-of-line)) | 2704 (end-of-line)) |
2660 ;; search forward | 2705 ;; search forward |
2661 (if (and (> 0 count) | 2706 (if (and (> 0 count) |
2662 (zerop (current-column)) | 2707 (zerop (current-column)) |
2663 (looking-at start-re)) | 2708 (looking-at start-re)) |
2664 (end-of-line)) | 2709 (end-of-line)) |
2665 (if (re-search-backward start-re nil 'move count) | 2710 (if (re-search-backward start-re nil 'move count) |
2666 (goto-char (match-beginning 0))))) | 2711 (goto-char (match-beginning 0))))) |
2667 | 2712 |
2668 ;; Backwards compatibility | 2713 ;; Backwards compatibility |
2669 (defalias 'beginning-of-python-def-or-class 'py-beginning-of-def-or-class) | 2714 (defalias 'beginning-of-python-def-or-class 'py-beginning-of-def-or-class) |
2670 | 2715 |
2671 (defun py-end-of-def-or-class (&optional class count) | 2716 (defun py-end-of-def-or-class (&optional class count) |
2695 | 2740 |
2696 Note that doing this command repeatedly will take you closer to the | 2741 Note that doing this command repeatedly will take you closer to the |
2697 end of the buffer each time. | 2742 end of the buffer each time. |
2698 | 2743 |
2699 To mark the current `def', see `\\[py-mark-def-or-class]'." | 2744 To mark the current `def', see `\\[py-mark-def-or-class]'." |
2700 (interactive "P") ; raw prefix arg | 2745 (interactive "P") ; raw prefix arg |
2701 (if (and count (/= count 1)) | 2746 (if (and count (/= count 1)) |
2702 (py-beginning-of-def-or-class (- 1 count))) | 2747 (py-beginning-of-def-or-class (- 1 count))) |
2703 (let ((start (progn (py-goto-initial-line) (point))) | 2748 (let ((start (progn (py-goto-initial-line) (point))) |
2704 (which (cond ((eq class 'either) "\\(class\\|def\\)") | 2749 (which (cond ((eq class 'either) "\\(class\\|def\\)") |
2705 (class "class") | 2750 (class "class") |
2706 (t "def"))) | 2751 (t "def"))) |
2707 (state 'not-found)) | 2752 (state 'not-found)) |
2708 ;; move point to start of appropriate def/class | 2753 ;; move point to start of appropriate def/class |
2709 (if (looking-at (concat "[ \t]*" which "\\>")) ; already on one | 2754 (if (looking-at (concat "[ \t]*" which "\\>")) ; already on one |
2710 (setq state 'at-beginning) | 2755 (setq state 'at-beginning) |
2711 ;; else see if py-beginning-of-def-or-class hits container | 2756 ;; else see if py-beginning-of-def-or-class hits container |
2712 (if (and (py-beginning-of-def-or-class class) | 2757 (if (and (py-beginning-of-def-or-class class) |
2713 (progn (py-goto-beyond-block) | 2758 (progn (py-goto-beyond-block) |
2714 (> (point) start))) | 2759 (> (point) start))) |
2715 (setq state 'at-end) | 2760 (setq state 'at-end) |
2716 ;; else search forward | 2761 ;; else search forward |
2717 (goto-char start) | 2762 (goto-char start) |
2718 (if (re-search-forward (concat "^[ \t]*" which "\\>") nil 'move) | 2763 (if (re-search-forward (concat "^[ \t]*" which "\\>") nil 'move) |
2719 (progn (setq state 'at-beginning) | 2764 (progn (setq state 'at-beginning) |
2720 (beginning-of-line))))) | 2765 (beginning-of-line))))) |
2721 (cond | 2766 (cond |
2722 ((eq state 'at-beginning) (py-goto-beyond-block) t) | 2767 ((eq state 'at-beginning) (py-goto-beyond-block) t) |
2723 ((eq state 'at-end) t) | 2768 ((eq state 'at-end) t) |
2724 ((eq state 'not-found) nil) | 2769 ((eq state 'not-found) nil) |
2725 (t (error "Internal error in `py-end-of-def-or-class'"))))) | 2770 (t (error "Internal error in `py-end-of-def-or-class'"))))) |
2773 area; or do `\\[exchange-point-and-mark]' to flip down to the end. | 2818 area; or do `\\[exchange-point-and-mark]' to flip down to the end. |
2774 | 2819 |
2775 If called from a program, optional argument EXTEND plays the role of | 2820 If called from a program, optional argument EXTEND plays the role of |
2776 the prefix arg, and if optional argument JUST-MOVE is not nil, just | 2821 the prefix arg, and if optional argument JUST-MOVE is not nil, just |
2777 moves to the end of the block (& does not set mark or display a msg)." | 2822 moves to the end of the block (& does not set mark or display a msg)." |
2778 (interactive "P") ; raw prefix arg | 2823 (interactive "P") ; raw prefix arg |
2779 (py-goto-initial-line) | 2824 (py-goto-initial-line) |
2780 ;; skip over blank lines | 2825 ;; skip over blank lines |
2781 (while (and | 2826 (while (and |
2782 (looking-at "[ \t]*$") ; while blank line | 2827 (looking-at "[ \t]*$") ; while blank line |
2783 (not (eobp))) ; & somewhere to go | 2828 (not (eobp))) ; & somewhere to go |
2784 (forward-line 1)) | 2829 (forward-line 1)) |
2785 (if (eobp) | 2830 (if (eobp) |
2786 (error "Hit end of buffer without finding a non-blank stmt")) | 2831 (error "Hit end of buffer without finding a non-blank stmt")) |
2787 (let ((initial-pos (point)) | 2832 (let ((initial-pos (point)) |
2788 (initial-indent (current-indentation)) | 2833 (initial-indent (current-indentation)) |
2789 last-pos ; position of last stmt in region | 2834 last-pos ; position of last stmt in region |
2790 (followers | 2835 (followers |
2791 '((if elif else) (elif elif else) (else) | 2836 '((if elif else) (elif elif else) (else) |
2792 (try except finally) (except except) (finally) | 2837 (try except finally) (except except) (finally) |
2793 (for else) (while else) | 2838 (for else) (while else) |
2794 (def) (class) ) ) | 2839 (def) (class) ) ) |
2795 first-symbol next-symbol) | 2840 first-symbol next-symbol) |
2796 | 2841 |
2797 (cond | 2842 (cond |
2798 ;; if comment line, suck up the following comment lines | 2843 ;; if comment line, suck up the following comment lines |
2799 ((looking-at "[ \t]*#") | 2844 ((looking-at "[ \t]*#") |
2800 (re-search-forward "^[ \t]*[^ \t#]" nil 'move) ; look for non-comment | 2845 (re-search-forward "^[ \t]*[^ \t#]" nil 'move) ; look for non-comment |
2801 (re-search-backward "^[ \t]*#") ; and back to last comment in block | 2846 (re-search-backward "^[ \t]*#") ; and back to last comment in block |
2802 (setq last-pos (point))) | 2847 (setq last-pos (point))) |
2803 | 2848 |
2804 ;; else if line is a block line and EXTEND given, suck up | 2849 ;; else if line is a block line and EXTEND given, suck up |
2805 ;; the whole structure | 2850 ;; the whole structure |
2806 ((and extend | 2851 ((and extend |
2807 (setq first-symbol (py-suck-up-first-keyword) ) | 2852 (setq first-symbol (py-suck-up-first-keyword) ) |
2808 (assq first-symbol followers)) | 2853 (assq first-symbol followers)) |
2809 (while (and | 2854 (while (and |
2810 (or (py-goto-beyond-block) t) ; side effect | 2855 (or (py-goto-beyond-block) t) ; side effect |
2811 (forward-line -1) ; side effect | 2856 (forward-line -1) ; side effect |
2812 (setq last-pos (point)) ; side effect | 2857 (setq last-pos (point)) ; side effect |
2813 (py-goto-statement-below) | 2858 (py-goto-statement-below) |
2814 (= (current-indentation) initial-indent) | 2859 (= (current-indentation) initial-indent) |
2815 (setq next-symbol (py-suck-up-first-keyword)) | 2860 (setq next-symbol (py-suck-up-first-keyword)) |
2816 (memq next-symbol (cdr (assq first-symbol followers)))) | 2861 (memq next-symbol (cdr (assq first-symbol followers)))) |
2817 (setq first-symbol next-symbol))) | 2862 (setq first-symbol next-symbol))) |
2818 | 2863 |
2819 ;; else if line *opens* a block, search for next stmt indented <= | 2864 ;; else if line *opens* a block, search for next stmt indented <= |
2820 ((py-statement-opens-block-p) | 2865 ((py-statement-opens-block-p) |
2821 (while (and | 2866 (while (and |
2822 (setq last-pos (point)) ; always true -- side effect | 2867 (setq last-pos (point)) ; always true -- side effect |
2823 (py-goto-statement-below) | 2868 (py-goto-statement-below) |
2824 (> (current-indentation) initial-indent) | 2869 (> (current-indentation) initial-indent) |
2825 ))) | 2870 ))) |
2826 | 2871 |
2827 ;; else plain code line; stop at next blank line, or stmt or | 2872 ;; else plain code line; stop at next blank line, or stmt or |
2828 ;; indenting comment line indented < | 2873 ;; indenting comment line indented < |
2829 (t | 2874 (t |
2830 (while (and | 2875 (while (and |
2831 (setq last-pos (point)) ; always true -- side effect | 2876 (setq last-pos (point)) ; always true -- side effect |
2832 (or (py-goto-beyond-final-line) t) | 2877 (or (py-goto-beyond-final-line) t) |
2833 (not (looking-at "[ \t]*$")) ; stop at blank line | 2878 (not (looking-at "[ \t]*$")) ; stop at blank line |
2834 (or | 2879 (or |
2835 (>= (current-indentation) initial-indent) | 2880 (>= (current-indentation) initial-indent) |
2836 (looking-at "[ \t]*#[^ \t\n]"))) ; ignore non-indenting # | 2881 (looking-at "[ \t]*#[^ \t\n]"))) ; ignore non-indenting # |
2837 nil))) | 2882 nil))) |
2838 | 2883 |
2839 ;; skip to end of last stmt | 2884 ;; skip to end of last stmt |
2840 (goto-char last-pos) | 2885 (goto-char last-pos) |
2841 (py-goto-beyond-final-line) | 2886 (py-goto-beyond-final-line) |
2842 | 2887 |
2843 ;; set mark & display | 2888 ;; set mark & display |
2844 (if just-move | 2889 (if just-move |
2845 () ; just return | 2890 () ; just return |
2846 (push-mark (point) 'no-msg) | 2891 (push-mark (point) 'no-msg) |
2847 (forward-line -1) | 2892 (forward-line -1) |
2848 (message "Mark set after: %s" (py-suck-up-leading-text)) | 2893 (message "Mark set after: %s" (py-suck-up-leading-text)) |
2849 (goto-char initial-pos)))) | 2894 (goto-char initial-pos)))) |
2850 | 2895 |
2884 point is left at its start. | 2929 point is left at its start. |
2885 | 2930 |
2886 The intent is to mark the containing def/class and its associated | 2931 The intent is to mark the containing def/class and its associated |
2887 documentation, to make moving and duplicating functions and classes | 2932 documentation, to make moving and duplicating functions and classes |
2888 pleasant." | 2933 pleasant." |
2889 (interactive "P") ; raw prefix arg | 2934 (interactive "P") ; raw prefix arg |
2890 (let ((start (point)) | 2935 (let ((start (point)) |
2891 (which (cond ((eq class 'either) "\\(class\\|def\\)") | 2936 (which (cond ((eq class 'either) "\\(class\\|def\\)") |
2892 (class "class") | 2937 (class "class") |
2893 (t "def")))) | 2938 (t "def")))) |
2894 (push-mark start) | 2939 (push-mark start) |
2895 (if (not (py-go-up-tree-to-keyword which)) | 2940 (if (not (py-go-up-tree-to-keyword which)) |
2896 (progn (goto-char start) | 2941 (progn (goto-char start) |
2897 (error "Enclosing %s not found" | 2942 (error "Enclosing %s not found" |
2898 (if (eq class 'either) | 2943 (if (eq class 'either) |
2899 "def or class" | 2944 "def or class" |
2900 which))) | 2945 which))) |
2901 ;; else enclosing def/class found | 2946 ;; else enclosing def/class found |
2902 (setq start (point)) | 2947 (setq start (point)) |
2903 (py-goto-beyond-block) | 2948 (py-goto-beyond-block) |
2904 (push-mark (point)) | 2949 (push-mark (point)) |
2905 (goto-char start) | 2950 (goto-char start) |
2906 (if (zerop (forward-line -1)) ; if there is a preceding line | 2951 (if (zerop (forward-line -1)) ; if there is a preceding line |
2907 (progn | 2952 (progn |
2908 (if (looking-at "[ \t]*$") ; it's blank | 2953 (if (looking-at "[ \t]*$") ; it's blank |
2909 (setq start (point)) ; so reset start point | 2954 (setq start (point)) ; so reset start point |
2910 (goto-char start)) ; else try again | 2955 (goto-char start)) ; else try again |
2911 (if (zerop (forward-line -1)) | 2956 (if (zerop (forward-line -1)) |
2912 (if (looking-at "[ \t]*#") ; a comment | 2957 (if (looking-at "[ \t]*#") ; a comment |
2913 ;; look back for non-comment line | 2958 ;; look back for non-comment line |
2914 ;; tricky: note that the regexp matches a blank | 2959 ;; tricky: note that the regexp matches a blank |
2915 ;; line, cuz \n is in the 2nd character class | 2960 ;; line, cuz \n is in the 2nd character class |
2916 (and | 2961 (and |
2917 (re-search-backward "^[ \t]*[^ \t#]" nil 'move) | 2962 (re-search-backward "^[ \t]*[^ \t#]" nil 'move) |
2918 (forward-line 1)) | 2963 (forward-line 1)) |
2919 ;; no comment, so go back | 2964 ;; no comment, so go back |
2920 (goto-char start))))))) | 2965 (goto-char start))))))) |
2921 (exchange-point-and-mark) | 2966 (exchange-point-and-mark) |
2922 (py-keep-region-active)) | 2967 (py-keep-region-active)) |
2923 | 2968 |
2924 ;; ripped from cc-mode | 2969 ;; ripped from cc-mode |
2925 (defun py-forward-into-nomenclature (&optional arg) | 2970 (defun py-forward-into-nomenclature (&optional arg) |
2929 | 2974 |
2930 A `nomenclature' is a fancy way of saying AWordWithMixedCaseNotUnderscores." | 2975 A `nomenclature' is a fancy way of saying AWordWithMixedCaseNotUnderscores." |
2931 (interactive "p") | 2976 (interactive "p") |
2932 (let ((case-fold-search nil)) | 2977 (let ((case-fold-search nil)) |
2933 (if (> arg 0) | 2978 (if (> arg 0) |
2934 (re-search-forward | 2979 (re-search-forward |
2935 "\\(\\W\\|[_]\\)*\\([A-Z]*[a-z0-9]*\\)" | 2980 "\\(\\W\\|[_]\\)*\\([A-Z]*[a-z0-9]*\\)" |
2936 (point-max) t arg) | 2981 (point-max) t arg) |
2937 (while (and (< arg 0) | 2982 (while (and (< arg 0) |
2938 (re-search-backward | 2983 (re-search-backward |
2939 "\\(\\W\\|[a-z0-9]\\)[A-Z]+\\|\\(\\W\\|[_]\\)\\w+" | 2984 "\\(\\W\\|[a-z0-9]\\)[A-Z]+\\|\\(\\W\\|[_]\\)\\w+" |
2940 (point-min) 0)) | 2985 (point-min) 0)) |
2941 (forward-char 1) | 2986 (forward-char 1) |
2942 (setq arg (1+ arg))))) | 2987 (setq arg (1+ arg))))) |
2943 (py-keep-region-active)) | 2988 (py-keep-region-active)) |
2944 | 2989 |
2945 (defun py-backward-into-nomenclature (&optional arg) | 2990 (defun py-backward-into-nomenclature (&optional arg) |
2946 "Move backward to beginning of a nomenclature section or word. | 2991 "Move backward to beginning of a nomenclature section or word. |
2947 With optional ARG, move that many times. If ARG is negative, move | 2992 With optional ARG, move that many times. If ARG is negative, move |
2959 (interactive "P") | 3004 (interactive "P") |
2960 (if (not (get-buffer-process (current-buffer))) | 3005 (if (not (get-buffer-process (current-buffer))) |
2961 (error "No process associated with buffer '%s'" (current-buffer))) | 3006 (error "No process associated with buffer '%s'" (current-buffer))) |
2962 ;; missing or 0 is toggle, >0 turn on, <0 turn off | 3007 ;; missing or 0 is toggle, >0 turn on, <0 turn off |
2963 (if (or (not arg) | 3008 (if (or (not arg) |
2964 (zerop (setq arg (prefix-numeric-value arg)))) | 3009 (zerop (setq arg (prefix-numeric-value arg)))) |
2965 (setq py-pdbtrack-do-tracking-p (not py-pdbtrack-do-tracking-p)) | 3010 (setq py-pdbtrack-do-tracking-p (not py-pdbtrack-do-tracking-p)) |
2966 (setq py-pdbtrack-do-tracking-p (> arg 0))) | 3011 (setq py-pdbtrack-do-tracking-p (> arg 0))) |
2967 (message "%sabled Python's pdbtrack" | 3012 (message "%sabled Python's pdbtrack" |
2968 (if py-pdbtrack-do-tracking-p "En" "Dis"))) | 3013 (if py-pdbtrack-do-tracking-p "En" "Dis"))) |
2969 | 3014 |
2986 (defun py-pychecker-run (command) | 3031 (defun py-pychecker-run (command) |
2987 "*Run pychecker (default on the file currently visited)." | 3032 "*Run pychecker (default on the file currently visited)." |
2988 (interactive | 3033 (interactive |
2989 (let ((default | 3034 (let ((default |
2990 (format "%s %s %s" py-pychecker-command | 3035 (format "%s %s %s" py-pychecker-command |
2991 (mapconcat 'identity py-pychecker-command-args " ") | 3036 (mapconcat 'identity py-pychecker-command-args " ") |
2992 (buffer-file-name))) | 3037 (buffer-file-name))) |
2993 (last (when py-pychecker-history | 3038 (last (when py-pychecker-history |
2994 (let* ((lastcmd (car py-pychecker-history)) | 3039 (let* ((lastcmd (car py-pychecker-history)) |
2995 (cmd (cdr (reverse (split-string lastcmd)))) | 3040 (cmd (cdr (reverse (split-string lastcmd)))) |
2996 (newcmd (reverse (cons (buffer-file-name) cmd)))) | 3041 (newcmd (reverse (cons (buffer-file-name) cmd)))) |
2997 (mapconcat 'identity newcmd " "))))) | 3042 (mapconcat 'identity newcmd " "))))) |
2998 | 3043 |
2999 (list | 3044 (list |
3000 (if (fboundp 'read-shell-command) | 3045 (if (fboundp 'read-shell-command) |
3001 (read-shell-command "Run pychecker like this: " | 3046 (read-shell-command "Run pychecker like this: " |
3002 (if last | 3047 (if last |
3003 last | 3048 last |
3004 default) | 3049 default) |
3005 'py-pychecker-history) | 3050 'py-pychecker-history) |
3006 (read-string "Run pychecker like this: " | 3051 (read-string "Run pychecker like this: " |
3007 (if last | 3052 (if last |
3008 last | 3053 last |
3009 default) | 3054 default) |
3010 'py-pychecker-history)) | 3055 'py-pychecker-history)) |
3011 ))) | 3056 ))) |
3012 (save-some-buffers (not py-ask-about-save) nil) | 3057 (save-some-buffers (not py-ask-about-save) nil) |
3013 (compile-internal command "No more errors")) | 3058 (if (fboundp 'compilation-start) |
3059 ;; Emacs. | |
3060 (compilation-start command) | |
3061 ;; XEmacs. | |
3062 (compile-internal command "No more errors"))) | |
3014 | 3063 |
3015 | 3064 |
3016 | 3065 |
3017 ;; pydoc commands. The guts of this function is stolen from XEmacs's | 3066 ;; pydoc commands. The guts of this function is stolen from XEmacs's |
3018 ;; symbol-near-point, but without the useless regexp-quote call on the | 3067 ;; symbol-near-point, but without the useless regexp-quote call on the |
3024 "Return the first textual item to the nearest point." | 3073 "Return the first textual item to the nearest point." |
3025 ;; alg stolen from etag.el | 3074 ;; alg stolen from etag.el |
3026 (save-excursion | 3075 (save-excursion |
3027 (with-syntax-table py-dotted-expression-syntax-table | 3076 (with-syntax-table py-dotted-expression-syntax-table |
3028 (if (or (bobp) (not (memq (char-syntax (char-before)) '(?w ?_)))) | 3077 (if (or (bobp) (not (memq (char-syntax (char-before)) '(?w ?_)))) |
3029 (while (not (looking-at "\\sw\\|\\s_\\|\\'")) | 3078 (while (not (looking-at "\\sw\\|\\s_\\|\\'")) |
3030 (forward-char 1))) | 3079 (forward-char 1))) |
3031 (while (looking-at "\\sw\\|\\s_") | 3080 (while (looking-at "\\sw\\|\\s_") |
3032 (forward-char 1)) | 3081 (forward-char 1)) |
3033 (if (re-search-backward "\\sw\\|\\s_" nil t) | 3082 (if (re-search-backward "\\sw\\|\\s_" nil t) |
3034 (progn (forward-char 1) | 3083 (progn (forward-char 1) |
3035 (buffer-substring (point) | 3084 (buffer-substring (point) |
3036 (progn (forward-sexp -1) | 3085 (progn (forward-sexp -1) |
3037 (while (looking-at "\\s'") | 3086 (while (looking-at "\\s'") |
3038 (forward-char 1)) | 3087 (forward-char 1)) |
3039 (point)))) | 3088 (point)))) |
3040 nil)))) | 3089 nil)))) |
3041 | 3090 |
3042 (defun py-help-at-point () | 3091 (defun py-help-at-point () |
3043 "Get help from Python based on the symbol nearest point." | 3092 "Get help from Python based on the symbol nearest point." |
3044 (interactive) | 3093 (interactive) |
3045 (let* ((sym (py-symbol-near-point)) | 3094 (let* ((sym (py-symbol-near-point)) |
3046 (base (substring sym 0 (or (search "." sym :from-end t) 0))) | 3095 (base (substring sym 0 (or (search "." sym :from-end t) 0))) |
3047 cmd) | 3096 cmd) |
3048 (if (not (equal base "")) | 3097 (if (not (equal base "")) |
3049 (setq cmd (concat "import " base "\n"))) | 3098 (setq cmd (concat "import " base "\n"))) |
3050 (setq cmd (concat "import pydoc\n" | 3099 (setq cmd (concat "import pydoc\n" |
3051 cmd | 3100 cmd |
3052 "try: pydoc.help('" sym "')\n" | 3101 "try: pydoc.help('" sym "')\n" |
3053 "except: print 'No help available on:', \"" sym "\"")) | 3102 "except: print 'No help available on:', \"" sym "\"")) |
3054 (message cmd) | 3103 (message cmd) |
3055 (py-execute-string cmd) | 3104 (py-execute-string cmd) |
3056 (set-buffer "*Python Output*") | 3105 (set-buffer "*Python Output*") |
3057 ;; BAW: Should we really be leaving the output buffer in help-mode? | 3106 ;; BAW: Should we really be leaving the output buffer in help-mode? |
3058 (help-mode))) | 3107 (help-mode))) |
3066 ;; out of the right places, along with the keys they're on & current | 3115 ;; out of the right places, along with the keys they're on & current |
3067 ;; values | 3116 ;; values |
3068 (defun py-dump-help-string (str) | 3117 (defun py-dump-help-string (str) |
3069 (with-output-to-temp-buffer "*Help*" | 3118 (with-output-to-temp-buffer "*Help*" |
3070 (let ((locals (buffer-local-variables)) | 3119 (let ((locals (buffer-local-variables)) |
3071 funckind funcname func funcdoc | 3120 funckind funcname func funcdoc |
3072 (start 0) mstart end | 3121 (start 0) mstart end |
3073 keys ) | 3122 keys ) |
3074 (while (string-match "^%\\([vc]\\):\\(.+\\)\n" str start) | 3123 (while (string-match "^%\\([vc]\\):\\(.+\\)\n" str start) |
3075 (setq mstart (match-beginning 0) end (match-end 0) | 3124 (setq mstart (match-beginning 0) end (match-end 0) |
3076 funckind (substring str (match-beginning 1) (match-end 1)) | 3125 funckind (substring str (match-beginning 1) (match-end 1)) |
3077 funcname (substring str (match-beginning 2) (match-end 2)) | 3126 funcname (substring str (match-beginning 2) (match-end 2)) |
3078 func (intern funcname)) | 3127 func (intern funcname)) |
3079 (princ (substitute-command-keys (substring str start mstart))) | 3128 (princ (substitute-command-keys (substring str start mstart))) |
3080 (cond | 3129 (cond |
3081 ((equal funckind "c") ; command | 3130 ((equal funckind "c") ; command |
3082 (setq funcdoc (documentation func) | 3131 (setq funcdoc (documentation func) |
3083 keys (concat | 3132 keys (concat |
3084 "Key(s): " | 3133 "Key(s): " |
3085 (mapconcat 'key-description | 3134 (mapconcat 'key-description |
3086 (where-is-internal func py-mode-map) | 3135 (where-is-internal func py-mode-map) |
3087 ", ")))) | 3136 ", ")))) |
3088 ((equal funckind "v") ; variable | 3137 ((equal funckind "v") ; variable |
3089 (setq funcdoc (documentation-property func 'variable-documentation) | 3138 (setq funcdoc (documentation-property func 'variable-documentation) |
3090 keys (if (assq func locals) | 3139 keys (if (assq func locals) |
3091 (concat | 3140 (concat |
3092 "Local/Global values: " | 3141 "Local/Global values: " |
3093 (prin1-to-string (symbol-value func)) | 3142 (prin1-to-string (symbol-value func)) |
3094 " / " | 3143 " / " |
3095 (prin1-to-string (default-value func))) | 3144 (prin1-to-string (default-value func))) |
3096 (concat | 3145 (concat |
3097 "Value: " | 3146 "Value: " |
3098 (prin1-to-string (symbol-value func)))))) | 3147 (prin1-to-string (symbol-value func)))))) |
3099 (t ; unexpected | 3148 (t ; unexpected |
3100 (error "Error in py-dump-help-string, tag `%s'" funckind))) | 3149 (error "Error in py-dump-help-string, tag `%s'" funckind))) |
3101 (princ (format "\n-> %s:\t%s\t%s\n\n" | 3150 (princ (format "\n-> %s:\t%s\t%s\n\n" |
3102 (if (equal funckind "c") "Command" "Variable") | 3151 (if (equal funckind "c") "Command" "Variable") |
3103 funcname keys)) | 3152 funcname keys)) |
3104 (princ funcdoc) | 3153 (princ funcdoc) |
3105 (terpri) | 3154 (terpri) |
3106 (setq start end)) | 3155 (setq start end)) |
3107 (princ (substitute-command-keys (substring str start)))) | 3156 (princ (substitute-command-keys (substring str start)))) |
3108 (print-help-return-message))) | 3157 (print-help-return-message))) |
3109 | 3158 |
3110 (defun py-describe-mode () | 3159 (defun py-describe-mode () |
3111 "Dump long form of Python-mode docs." | 3160 "Dump long form of Python-mode docs." |
3363 (when (fboundp 'info-lookup-maybe-add-help) | 3412 (when (fboundp 'info-lookup-maybe-add-help) |
3364 (info-lookup-maybe-add-help | 3413 (info-lookup-maybe-add-help |
3365 :mode 'python-mode | 3414 :mode 'python-mode |
3366 :regexp "[a-zA-Z0-9_]+" | 3415 :regexp "[a-zA-Z0-9_]+" |
3367 :doc-spec '(("(python-lib)Module Index") | 3416 :doc-spec '(("(python-lib)Module Index") |
3368 ("(python-lib)Class-Exception-Object Index") | 3417 ("(python-lib)Class-Exception-Object Index") |
3369 ("(python-lib)Function-Method-Variable Index") | 3418 ("(python-lib)Function-Method-Variable Index") |
3370 ("(python-lib)Miscellaneous Index"))) | 3419 ("(python-lib)Miscellaneous Index"))) |
3371 ) | 3420 ) |
3372 | 3421 |
3373 | 3422 |
3374 ;; Helper functions | 3423 ;; Helper functions |
3375 (defvar py-parse-state-re | 3424 (defvar py-parse-state-re |
3380 | 3429 |
3381 (defun py-parse-state () | 3430 (defun py-parse-state () |
3382 "Return the parse state at point (see `parse-partial-sexp' docs)." | 3431 "Return the parse state at point (see `parse-partial-sexp' docs)." |
3383 (save-excursion | 3432 (save-excursion |
3384 (let ((here (point)) | 3433 (let ((here (point)) |
3385 pps done) | 3434 pps done) |
3386 (while (not done) | 3435 (while (not done) |
3387 ;; back up to the first preceding line (if any; else start of | 3436 ;; back up to the first preceding line (if any; else start of |
3388 ;; buffer) that begins with a popular Python keyword, or a | 3437 ;; buffer) that begins with a popular Python keyword, or a |
3389 ;; non- whitespace and non-comment character. These are good | 3438 ;; non- whitespace and non-comment character. These are good |
3390 ;; places to start parsing to see whether where we started is | 3439 ;; places to start parsing to see whether where we started is |
3391 ;; at a non-zero nesting level. It may be slow for people who | 3440 ;; at a non-zero nesting level. It may be slow for people who |
3392 ;; write huge code blocks or huge lists ... tough beans. | 3441 ;; write huge code blocks or huge lists ... tough beans. |
3393 (re-search-backward py-parse-state-re nil 'move) | 3442 (re-search-backward py-parse-state-re nil 'move) |
3394 (beginning-of-line) | 3443 (beginning-of-line) |
3395 ;; In XEmacs, we have a much better way to test for whether | 3444 ;; In XEmacs, we have a much better way to test for whether |
3396 ;; we're in a triple-quoted string or not. Emacs does not | 3445 ;; we're in a triple-quoted string or not. Emacs does not |
3397 ;; have this built-in function, which is its loss because | 3446 ;; have this built-in function, which is its loss because |
3398 ;; without scanning from the beginning of the buffer, there's | 3447 ;; without scanning from the beginning of the buffer, there's |
3399 ;; no accurate way to determine this otherwise. | 3448 ;; no accurate way to determine this otherwise. |
3400 (save-excursion (setq pps (parse-partial-sexp (point) here))) | 3449 (save-excursion (setq pps (parse-partial-sexp (point) here))) |
3401 ;; make sure we don't land inside a triple-quoted string | 3450 ;; make sure we don't land inside a triple-quoted string |
3402 (setq done (or (not (nth 3 pps)) | 3451 (setq done (or (not (nth 3 pps)) |
3403 (bobp))) | 3452 (bobp))) |
3404 ;; Just go ahead and short circuit the test back to the | 3453 ;; Just go ahead and short circuit the test back to the |
3405 ;; beginning of the buffer. This will be slow, but not | 3454 ;; beginning of the buffer. This will be slow, but not |
3406 ;; nearly as slow as looping through many | 3455 ;; nearly as slow as looping through many |
3407 ;; re-search-backwards. | 3456 ;; re-search-backwards. |
3408 (if (not done) | 3457 (if (not done) |
3409 (goto-char (point-min)))) | 3458 (goto-char (point-min)))) |
3410 pps))) | 3459 pps))) |
3411 | 3460 |
3412 (defun py-nesting-level () | 3461 (defun py-nesting-level () |
3413 "Return the buffer position of the last unclosed enclosing list. | 3462 "Return the buffer position of the last unclosed enclosing list. |
3414 If nesting level is zero, return nil." | 3463 If nesting level is zero, return nil." |
3415 (let ((status (py-parse-state))) | 3464 (let ((status (py-parse-state))) |
3416 (if (zerop (car status)) | 3465 (if (zerop (car status)) |
3417 nil ; not in a nest | 3466 nil ; not in a nest |
3418 (car (cdr status))))) ; char# of open bracket | 3467 (car (cdr status))))) ; char# of open bracket |
3419 | 3468 |
3420 (defun py-backslash-continuation-line-p () | 3469 (defun py-backslash-continuation-line-p () |
3421 "Return t iff preceding line ends with backslash that is not in a comment." | 3470 "Return t iff preceding line ends with backslash that is not in a comment." |
3422 (save-excursion | 3471 (save-excursion |
3423 (beginning-of-line) | 3472 (beginning-of-line) |
3424 (and | 3473 (and |
3425 ;; use a cheap test first to avoid the regexp if possible | 3474 ;; use a cheap test first to avoid the regexp if possible |
3426 ;; use 'eq' because char-after may return nil | 3475 ;; use 'eq' because char-after may return nil |
3427 (eq (char-after (- (point) 2)) ?\\ ) | 3476 (eq (char-after (- (point) 2)) ?\\ ) |
3428 ;; make sure; since eq test passed, there is a preceding line | 3477 ;; make sure; since eq test passed, there is a preceding line |
3429 (forward-line -1) ; always true -- side effect | 3478 (forward-line -1) ; always true -- side effect |
3430 (looking-at py-continued-re)))) | 3479 (looking-at py-continued-re)))) |
3431 | 3480 |
3432 (defun py-continuation-line-p () | 3481 (defun py-continuation-line-p () |
3433 "Return t iff current line is a continuation line." | 3482 "Return t iff current line is a continuation line." |
3434 (save-excursion | 3483 (save-excursion |
3435 (beginning-of-line) | 3484 (beginning-of-line) |
3436 (or (py-backslash-continuation-line-p) | 3485 (or (py-backslash-continuation-line-p) |
3437 (py-nesting-level)))) | 3486 (py-nesting-level)))) |
3438 | 3487 |
3439 (defun py-goto-beginning-of-tqs (delim) | 3488 (defun py-goto-beginning-of-tqs (delim) |
3440 "Go to the beginning of the triple quoted string we find ourselves in. | 3489 "Go to the beginning of the triple quoted string we find ourselves in. |
3441 DELIM is the TQS string delimiter character we're searching backwards | 3490 DELIM is the TQS string delimiter character we're searching backwards |
3442 for." | 3491 for." |
3443 (let ((skip (and delim (make-string 1 delim))) | 3492 (let ((skip (and delim (make-string 1 delim))) |
3444 (continue t)) | 3493 (continue t)) |
3445 (when skip | 3494 (when skip |
3446 (save-excursion | 3495 (save-excursion |
3447 (while continue | 3496 (while continue |
3448 (py-safe (search-backward skip)) | 3497 (py-safe (search-backward skip)) |
3449 (setq continue (and (not (bobp)) | 3498 (setq continue (and (not (bobp)) |
3450 (= (char-before) ?\\)))) | 3499 (= (char-before) ?\\)))) |
3451 (if (and (= (char-before) delim) | 3500 (if (and (= (char-before) delim) |
3452 (= (char-before (1- (point))) delim)) | 3501 (= (char-before (1- (point))) delim)) |
3453 (setq skip (make-string 3 delim)))) | 3502 (setq skip (make-string 3 delim)))) |
3454 ;; we're looking at a triple-quoted string | 3503 ;; we're looking at a triple-quoted string |
3455 (py-safe (search-backward skip))))) | 3504 (py-safe (search-backward skip))))) |
3456 | 3505 |
3457 (defun py-goto-initial-line () | 3506 (defun py-goto-initial-line () |
3458 "Go to the initial line of the current statement. | 3507 "Go to the initial line of the current statement. |
3468 ;; drop us at the line that begins the string. | 3517 ;; drop us at the line that begins the string. |
3469 (let (open-bracket-pos) | 3518 (let (open-bracket-pos) |
3470 (while (py-continuation-line-p) | 3519 (while (py-continuation-line-p) |
3471 (beginning-of-line) | 3520 (beginning-of-line) |
3472 (if (py-backslash-continuation-line-p) | 3521 (if (py-backslash-continuation-line-p) |
3473 (while (py-backslash-continuation-line-p) | 3522 (while (py-backslash-continuation-line-p) |
3474 (forward-line -1)) | 3523 (forward-line -1)) |
3475 ;; else zip out of nested brackets/braces/parens | 3524 ;; else zip out of nested brackets/braces/parens |
3476 (while (setq open-bracket-pos (py-nesting-level)) | 3525 (while (setq open-bracket-pos (py-nesting-level)) |
3477 (goto-char open-bracket-pos))))) | 3526 (goto-char open-bracket-pos))))) |
3478 (beginning-of-line)) | 3527 (beginning-of-line)) |
3479 | 3528 |
3480 (defun py-goto-beyond-final-line () | 3529 (defun py-goto-beyond-final-line () |
3481 "Go to the point just beyond the fine line of the current statement. | 3530 "Go to the point just beyond the fine line of the current statement. |
3482 Usually this is the start of the next line, but if this is a | 3531 Usually this is the start of the next line, but if this is a |
3490 (goto-char (match-end 0))) | 3539 (goto-char (match-end 0))) |
3491 ;; | 3540 ;; |
3492 (forward-line 1) | 3541 (forward-line 1) |
3493 (let (state) | 3542 (let (state) |
3494 (while (and (py-continuation-line-p) | 3543 (while (and (py-continuation-line-p) |
3495 (not (eobp))) | 3544 (not (eobp))) |
3496 ;; skip over the backslash flavor | 3545 ;; skip over the backslash flavor |
3497 (while (and (py-backslash-continuation-line-p) | 3546 (while (and (py-backslash-continuation-line-p) |
3498 (not (eobp))) | 3547 (not (eobp))) |
3499 (forward-line 1)) | 3548 (forward-line 1)) |
3500 ;; if in nest, zip to the end of the nest | 3549 ;; if in nest, zip to the end of the nest |
3501 (setq state (py-parse-state)) | 3550 (setq state (py-parse-state)) |
3502 (if (and (not (zerop (car state))) | 3551 (if (and (not (zerop (car state))) |
3503 (not (eobp))) | 3552 (not (eobp))) |
3504 (progn | 3553 (progn |
3505 (parse-partial-sexp (point) (point-max) 0 nil state) | 3554 (parse-partial-sexp (point) (point-max) 0 nil state) |
3506 (forward-line 1)))))) | 3555 (forward-line 1)))))) |
3507 | 3556 |
3508 (defun py-statement-opens-block-p () | 3557 (defun py-statement-opens-block-p () |
3509 "Return t iff the current statement opens a block. | 3558 "Return t iff the current statement opens a block. |
3510 I.e., iff it ends with a colon that is not in a comment. Point should | 3559 I.e., iff it ends with a colon that is not in a comment. Point should |
3511 be at the start of a statement." | 3560 be at the start of a statement." |
3512 (save-excursion | 3561 (save-excursion |
3513 (let ((start (point)) | 3562 (let ((start (point)) |
3514 (finish (progn (py-goto-beyond-final-line) (1- (point)))) | 3563 (finish (progn (py-goto-beyond-final-line) (1- (point)))) |
3515 (searching t) | 3564 (searching t) |
3516 (answer nil) | 3565 (answer nil) |
3517 state) | 3566 state) |
3518 (goto-char start) | 3567 (goto-char start) |
3519 (while searching | 3568 (while searching |
3520 ;; look for a colon with nothing after it except whitespace, and | 3569 ;; look for a colon with nothing after it except whitespace, and |
3521 ;; maybe a comment | 3570 ;; maybe a comment |
3522 (if (re-search-forward ":\\([ \t]\\|\\\\\n\\)*\\(#.*\\)?$" | 3571 (if (re-search-forward ":\\([ \t]\\|\\\\\n\\)*\\(#.*\\)?$" |
3523 finish t) | 3572 finish t) |
3524 (if (eq (point) finish) ; note: no `else' clause; just | 3573 (if (eq (point) finish) ; note: no `else' clause; just |
3525 ; keep searching if we're not at | 3574 ; keep searching if we're not at |
3526 ; the end yet | 3575 ; the end yet |
3527 ;; sure looks like it opens a block -- but it might | 3576 ;; sure looks like it opens a block -- but it might |
3528 ;; be in a comment | 3577 ;; be in a comment |
3529 (progn | 3578 (progn |
3530 (setq searching nil) ; search is done either way | 3579 (setq searching nil) ; search is done either way |
3531 (setq state (parse-partial-sexp start | 3580 (setq state (parse-partial-sexp start |
3532 (match-beginning 0))) | 3581 (match-beginning 0))) |
3533 (setq answer (not (nth 4 state))))) | 3582 (setq answer (not (nth 4 state))))) |
3534 ;; search failed: couldn't find another interesting colon | 3583 ;; search failed: couldn't find another interesting colon |
3535 (setq searching nil))) | 3584 (setq searching nil))) |
3536 answer))) | 3585 answer))) |
3537 | 3586 |
3538 (defun py-statement-closes-block-p () | 3587 (defun py-statement-closes-block-p () |
3539 "Return t iff the current statement closes a block. | 3588 "Return t iff the current statement closes a block. |
3540 I.e., if the line starts with `return', `raise', `break', `continue', | 3589 I.e., if the line starts with `return', `raise', `break', `continue', |
3541 and `pass'. This doesn't catch embedded statements." | 3590 and `pass'. This doesn't catch embedded statements." |
3542 (let ((here (point))) | 3591 (let ((here (point))) |
3543 (py-goto-initial-line) | 3592 (py-goto-initial-line) |
3544 (back-to-indentation) | 3593 (back-to-indentation) |
3545 (prog1 | 3594 (prog1 |
3546 (looking-at (concat py-block-closing-keywords-re "\\>")) | 3595 (looking-at (concat py-block-closing-keywords-re "\\>")) |
3547 (goto-char here)))) | 3596 (goto-char here)))) |
3548 | 3597 |
3549 (defun py-goto-beyond-block () | 3598 (defun py-goto-beyond-block () |
3550 "Go to point just beyond the final line of block begun by the current line. | 3599 "Go to point just beyond the final line of block begun by the current line. |
3551 This is the same as where `py-goto-beyond-final-line' goes unless | 3600 This is the same as where `py-goto-beyond-final-line' goes unless |
3563 (if (looking-at py-blank-or-comment-re) | 3612 (if (looking-at py-blank-or-comment-re) |
3564 ;; skip back over blank & comment lines | 3613 ;; skip back over blank & comment lines |
3565 ;; note: will skip a blank or comment line that happens to be | 3614 ;; note: will skip a blank or comment line that happens to be |
3566 ;; a continuation line too | 3615 ;; a continuation line too |
3567 (if (re-search-backward "^[ \t]*[^ \t#\n]" nil t) | 3616 (if (re-search-backward "^[ \t]*[^ \t#\n]" nil t) |
3568 (progn (py-goto-initial-line) t) | 3617 (progn (py-goto-initial-line) t) |
3569 nil) | 3618 nil) |
3570 t)) | 3619 t)) |
3571 | 3620 |
3572 (defun py-goto-statement-below () | 3621 (defun py-goto-statement-below () |
3573 "Go to start of the first statement following the statement containing point. | 3622 "Go to start of the first statement following the statement containing point. |
3574 Return t if there is such a statement, otherwise nil. `Statement' | 3623 Return t if there is such a statement, otherwise nil. `Statement' |
3575 does not include blank lines, comments, or continuation lines." | 3624 does not include blank lines, comments, or continuation lines." |
3576 (beginning-of-line) | 3625 (beginning-of-line) |
3577 (let ((start (point))) | 3626 (let ((start (point))) |
3578 (py-goto-beyond-final-line) | 3627 (py-goto-beyond-final-line) |
3579 (while (and | 3628 (while (and |
3580 (or (looking-at py-blank-or-comment-re) | 3629 (or (looking-at py-blank-or-comment-re) |
3581 (py-in-literal)) | 3630 (py-in-literal)) |
3582 (not (eobp))) | 3631 (not (eobp))) |
3583 (forward-line 1)) | 3632 (forward-line 1)) |
3584 (if (eobp) | 3633 (if (eobp) |
3585 (progn (goto-char start) nil) | 3634 (progn (goto-char start) nil) |
3586 t))) | 3635 t))) |
3587 | 3636 |
3588 (defun py-go-up-tree-to-keyword (key) | 3637 (defun py-go-up-tree-to-keyword (key) |
3589 "Go to begining of statement starting with KEY, at or preceding point. | 3638 "Go to begining of statement starting with KEY, at or preceding point. |
3590 | 3639 |
3594 with KEY. If successful, leave point at the start of the KEY line and | 3643 with KEY. If successful, leave point at the start of the KEY line and |
3595 return t. Otherwise, leave point at an undefined place and return nil." | 3644 return t. Otherwise, leave point at an undefined place and return nil." |
3596 ;; skip blanks and non-indenting # | 3645 ;; skip blanks and non-indenting # |
3597 (py-goto-initial-line) | 3646 (py-goto-initial-line) |
3598 (while (and | 3647 (while (and |
3599 (looking-at "[ \t]*\\($\\|#[^ \t\n]\\)") | 3648 (looking-at "[ \t]*\\($\\|#[^ \t\n]\\)") |
3600 (zerop (forward-line -1))) ; go back | 3649 (zerop (forward-line -1))) ; go back |
3601 nil) | 3650 nil) |
3602 (py-goto-initial-line) | 3651 (py-goto-initial-line) |
3603 (let* ((re (concat "[ \t]*" key "\\>")) | 3652 (let* ((re (concat "[ \t]*" key "\\>")) |
3604 (case-fold-search nil) ; let* so looking-at sees this | 3653 (case-fold-search nil) ; let* so looking-at sees this |
3605 (found (looking-at re)) | 3654 (found (looking-at re)) |
3606 (dead nil)) | 3655 (dead nil)) |
3607 (while (not (or found dead)) | 3656 (while (not (or found dead)) |
3608 (condition-case nil ; in case no enclosing block | 3657 (condition-case nil ; in case no enclosing block |
3609 (py-goto-block-up 'no-mark) | 3658 (py-goto-block-up 'no-mark) |
3610 (error (setq dead t))) | 3659 (error (setq dead t))) |
3611 (or dead (setq found (looking-at re)))) | 3660 (or dead (setq found (looking-at re)))) |
3612 (beginning-of-line) | 3661 (beginning-of-line) |
3613 found)) | 3662 found)) |
3614 | 3663 |
3615 (defun py-suck-up-leading-text () | 3664 (defun py-suck-up-leading-text () |
3625 "Return first keyword on the line as a Lisp symbol. | 3674 "Return first keyword on the line as a Lisp symbol. |
3626 `Keyword' is defined (essentially) as the regular expression | 3675 `Keyword' is defined (essentially) as the regular expression |
3627 ([a-z]+). Returns nil if none was found." | 3676 ([a-z]+). Returns nil if none was found." |
3628 (let ((case-fold-search nil)) | 3677 (let ((case-fold-search nil)) |
3629 (if (looking-at "[ \t]*\\([a-z]+\\)\\>") | 3678 (if (looking-at "[ \t]*\\([a-z]+\\)\\>") |
3630 (intern (buffer-substring (match-beginning 1) (match-end 1))) | 3679 (intern (buffer-substring (match-beginning 1) (match-end 1))) |
3631 nil))) | 3680 nil))) |
3632 | 3681 |
3633 (defun py-current-defun () | 3682 (defun py-current-defun () |
3634 "Python value for `add-log-current-defun-function'. | 3683 "Python value for `add-log-current-defun-function'. |
3635 This tells add-log.el how to find the current function/method/variable." | 3684 This tells add-log.el how to find the current function/method/variable." |
3638 ;; Move back to start of the current statement. | 3687 ;; Move back to start of the current statement. |
3639 | 3688 |
3640 (py-goto-initial-line) | 3689 (py-goto-initial-line) |
3641 (back-to-indentation) | 3690 (back-to-indentation) |
3642 (while (and (or (looking-at py-blank-or-comment-re) | 3691 (while (and (or (looking-at py-blank-or-comment-re) |
3643 (py-in-literal)) | 3692 (py-in-literal)) |
3644 (not (bobp))) | 3693 (not (bobp))) |
3645 (backward-to-indentation 1)) | 3694 (backward-to-indentation 1)) |
3646 (py-goto-initial-line) | 3695 (py-goto-initial-line) |
3647 | 3696 |
3648 (let ((scopes "") | 3697 (let ((scopes "") |
3649 (sep "") | 3698 (sep "") |
3650 dead assignment) | 3699 dead assignment) |
3651 | 3700 |
3652 ;; Check for an assignment. If this assignment exists inside a | 3701 ;; Check for an assignment. If this assignment exists inside a |
3653 ;; def, it will be overwritten inside the while loop. If it | 3702 ;; def, it will be overwritten inside the while loop. If it |
3654 ;; exists at top lever or inside a class, it will be preserved. | 3703 ;; exists at top lever or inside a class, it will be preserved. |
3655 | 3704 |
3656 (when (looking-at "[ \t]*\\([a-zA-Z0-9_]+\\)[ \t]*=") | 3705 (when (looking-at "[ \t]*\\([a-zA-Z0-9_]+\\)[ \t]*=") |
3657 (setq scopes (buffer-substring (match-beginning 1) (match-end 1))) | 3706 (setq scopes (buffer-substring (match-beginning 1) (match-end 1))) |
3658 (setq assignment t) | 3707 (setq assignment t) |
3659 (setq sep ".")) | 3708 (setq sep ".")) |
3660 | 3709 |
3661 ;; Prepend the name of each outer socpe (def or class). | 3710 ;; Prepend the name of each outer socpe (def or class). |
3662 | 3711 |
3663 (while (not dead) | 3712 (while (not dead) |
3664 (if (and (py-go-up-tree-to-keyword "\\(class\\|def\\)") | 3713 (if (and (py-go-up-tree-to-keyword "\\(class\\|def\\)") |
3665 (looking-at | 3714 (looking-at |
3666 "[ \t]*\\(class\\|def\\)[ \t]*\\([a-zA-Z0-9_]+\\)[ \t]*")) | 3715 "[ \t]*\\(class\\|def\\)[ \t]*\\([a-zA-Z0-9_]+\\)[ \t]*")) |
3667 (let ((name (buffer-substring (match-beginning 2) (match-end 2)))) | 3716 (let ((name (buffer-substring (match-beginning 2) (match-end 2)))) |
3668 (if (and assignment (looking-at "[ \t]*def")) | 3717 (if (and assignment (looking-at "[ \t]*def")) |
3669 (setq scopes name) | 3718 (setq scopes name) |
3670 (setq scopes (concat name sep scopes)) | 3719 (setq scopes (concat name sep scopes)) |
3671 (setq sep ".")))) | 3720 (setq sep ".")))) |
3672 (setq assignment nil) | 3721 (setq assignment nil) |
3673 (condition-case nil ; Terminate nicely at top level. | 3722 (condition-case nil ; Terminate nicely at top level. |
3674 (py-goto-block-up 'no-mark) | 3723 (py-goto-block-up 'no-mark) |
3675 (error (setq dead t)))) | 3724 (error (setq dead t)))) |
3676 (if (string= scopes "") | 3725 (if (string= scopes "") |
3677 nil | 3726 nil |
3678 scopes)))) | 3727 scopes)))) |
3679 | 3728 |
3680 | 3729 |
3681 | 3730 |
3682 (defconst py-help-address "python-mode@python.org" | 3731 (defconst py-help-address "python-mode@python.org" |
3683 "Address accepting submission of bug reports.") | 3732 "Address accepting submission of bug reports.") |
3696 "Submit via mail a bug report on `python-mode'. | 3745 "Submit via mail a bug report on `python-mode'. |
3697 With \\[universal-argument] (programmatically, argument ENHANCEMENT-P | 3746 With \\[universal-argument] (programmatically, argument ENHANCEMENT-P |
3698 non-nil) just submit an enhancement request." | 3747 non-nil) just submit an enhancement request." |
3699 (interactive | 3748 (interactive |
3700 (list (not (y-or-n-p | 3749 (list (not (y-or-n-p |
3701 "Is this a bug report (hit `n' to send other comments)? ")))) | 3750 "Is this a bug report (hit `n' to send other comments)? ")))) |
3702 (let ((reporter-prompt-for-summary-p (if enhancement-p | 3751 (let ((reporter-prompt-for-summary-p (if enhancement-p |
3703 "(Very) brief summary: " | 3752 "(Very) brief summary: " |
3704 t))) | 3753 t))) |
3705 (require 'reporter) | 3754 (require 'reporter) |
3706 (reporter-submit-bug-report | 3755 (reporter-submit-bug-report |
3707 py-help-address ;address | 3756 py-help-address ;address |
3708 (concat "python-mode " py-version) ;pkgname | 3757 (concat "python-mode " py-version) ;pkgname |
3709 ;; varlist | 3758 ;; varlist |
3710 (if enhancement-p nil | 3759 (if enhancement-p nil |
3711 '(py-python-command | 3760 '(py-python-command |
3712 py-indent-offset | 3761 py-indent-offset |
3713 py-block-comment-prefix | 3762 py-block-comment-prefix |
3714 py-temp-directory | 3763 py-temp-directory |
3715 py-beep-if-tab-change)) | 3764 py-beep-if-tab-change)) |
3716 nil ;pre-hooks | 3765 nil ;pre-hooks |
3717 nil ;post-hooks | 3766 nil ;post-hooks |
3718 "Dear Barry,") ;salutation | 3767 "Dear Barry,") ;salutation |
3719 (if enhancement-p nil | 3768 (if enhancement-p nil |
3720 (set-mark (point)) | 3769 (set-mark (point)) |
3721 (insert | 3770 (insert |
3722 "Please replace this text with a sufficiently large code sample\n\ | 3771 "Please replace this text with a sufficiently large code sample\n\ |
3723 and an exact recipe so that I can reproduce your problem. Failure\n\ | 3772 and an exact recipe so that I can reproduce your problem. Failure\n\ |
3727 | 3776 |
3728 | 3777 |
3729 (defun py-kill-emacs-hook () | 3778 (defun py-kill-emacs-hook () |
3730 "Delete files in `py-file-queue'. | 3779 "Delete files in `py-file-queue'. |
3731 These are Python temporary files awaiting execution." | 3780 These are Python temporary files awaiting execution." |
3732 (mapcar #'(lambda (filename) | 3781 (mapc #'(lambda (filename) |
3733 (py-safe (delete-file filename))) | 3782 (py-safe (delete-file filename))) |
3734 py-file-queue)) | 3783 py-file-queue)) |
3735 | 3784 |
3736 ;; arrange to kill temp files when Emacs exists | 3785 ;; arrange to kill temp files when Emacs exists |
3737 (add-hook 'kill-emacs-hook 'py-kill-emacs-hook) | 3786 (add-hook 'kill-emacs-hook 'py-kill-emacs-hook) |
3738 (add-hook 'comint-output-filter-functions 'py-pdbtrack-track-stack-file) | 3787 (add-hook 'comint-output-filter-functions 'py-pdbtrack-track-stack-file) |
3739 | 3788 |
3740 ;; Add a designator to the minor mode strings | 3789 ;; Add a designator to the minor mode strings |
3741 (or (assq 'py-pdbtrack-is-tracking-p minor-mode-alist) | 3790 (or (assq 'py-pdbtrack-is-tracking-p minor-mode-alist) |
3742 (push '(py-pdbtrack-is-tracking-p py-pdbtrack-minor-mode-string) | 3791 (push '(py-pdbtrack-is-tracking-p py-pdbtrack-minor-mode-string) |
3743 minor-mode-alist)) | 3792 minor-mode-alist)) |
3744 | 3793 |
3745 | 3794 |
3746 | 3795 |
3747 ;;; paragraph and string filling code from Bernhard Herzog | 3796 ;;; paragraph and string filling code from Bernhard Herzog |
3748 ;;; see http://mail.python.org/pipermail/python-list/2002-May/103189.html | 3797 ;;; see http://mail.python.org/pipermail/python-list/2002-May/103189.html |
3749 | 3798 |
3750 (defun py-fill-comment (&optional justify) | 3799 (defun py-fill-comment (&optional justify) |
3751 "Fill the comment paragraph around point" | 3800 "Fill the comment paragraph around point" |
3752 (let (;; Non-nil if the current line contains a comment. | 3801 (let (;; Non-nil if the current line contains a comment. |
3753 has-comment | 3802 has-comment |
3754 | 3803 |
3755 ;; If has-comment, the appropriate fill-prefix for the comment. | 3804 ;; If has-comment, the appropriate fill-prefix for the comment. |
3756 comment-fill-prefix) | 3805 comment-fill-prefix) |
3757 | 3806 |
3758 ;; Figure out what kind of comment we are looking at. | 3807 ;; Figure out what kind of comment we are looking at. |
3759 (save-excursion | 3808 (save-excursion |
3760 (beginning-of-line) | 3809 (beginning-of-line) |
3761 (cond | 3810 (cond |
3762 ;; A line with nothing but a comment on it? | 3811 ;; A line with nothing but a comment on it? |
3763 ((looking-at "[ \t]*#[# \t]*") | 3812 ((looking-at "[ \t]*#[# \t]*") |
3764 (setq has-comment t | 3813 (setq has-comment t |
3765 comment-fill-prefix (buffer-substring (match-beginning 0) | 3814 comment-fill-prefix (buffer-substring (match-beginning 0) |
3766 (match-end 0)))) | 3815 (match-end 0)))) |
3767 | 3816 |
3768 ;; A line with some code, followed by a comment? Remember that the hash | 3817 ;; A line with some code, followed by a comment? Remember that the hash |
3769 ;; which starts the comment shouldn't be part of a string or character. | 3818 ;; which starts the comment shouldn't be part of a string or character. |
3770 ((progn | 3819 ((progn |
3771 (while (not (looking-at "#\\|$")) | 3820 (while (not (looking-at "#\\|$")) |
3772 (skip-chars-forward "^#\n\"'\\") | 3821 (skip-chars-forward "^#\n\"'\\") |
3773 (cond | 3822 (cond |
3774 ((eq (char-after (point)) ?\\) (forward-char 2)) | 3823 ((eq (char-after (point)) ?\\) (forward-char 2)) |
3775 ((memq (char-after (point)) '(?\" ?')) (forward-sexp 1)))) | 3824 ((memq (char-after (point)) '(?\" ?')) (forward-sexp 1)))) |
3776 (looking-at "#+[\t ]*")) | 3825 (looking-at "#+[\t ]*")) |
3777 (setq has-comment t) | 3826 (setq has-comment t) |
3778 (setq comment-fill-prefix | 3827 (setq comment-fill-prefix |
3779 (concat (make-string (current-column) ? ) | 3828 (concat (make-string (current-column) ? ) |
3780 (buffer-substring (match-beginning 0) (match-end 0))))))) | 3829 (buffer-substring (match-beginning 0) (match-end 0))))))) |
3781 | 3830 |
3782 (if (not has-comment) | 3831 (if (not has-comment) |
3783 (fill-paragraph justify) | 3832 (fill-paragraph justify) |
3784 | 3833 |
3785 ;; Narrow to include only the comment, and then fill the region. | 3834 ;; Narrow to include only the comment, and then fill the region. |
3786 (save-restriction | 3835 (save-restriction |
3787 (narrow-to-region | 3836 (narrow-to-region |
3788 | 3837 |
3789 ;; Find the first line we should include in the region to fill. | 3838 ;; Find the first line we should include in the region to fill. |
3790 (save-excursion | 3839 (save-excursion |
3791 (while (and (zerop (forward-line -1)) | 3840 (while (and (zerop (forward-line -1)) |
3792 (looking-at "^[ \t]*#"))) | 3841 (looking-at "^[ \t]*#"))) |
3793 | 3842 |
3794 ;; We may have gone to far. Go forward again. | 3843 ;; We may have gone to far. Go forward again. |
3795 (or (looking-at "^[ \t]*#") | 3844 (or (looking-at "^[ \t]*#") |
3796 (forward-line 1)) | 3845 (forward-line 1)) |
3797 (point)) | 3846 (point)) |
3798 | 3847 |
3799 ;; Find the beginning of the first line past the region to fill. | 3848 ;; Find the beginning of the first line past the region to fill. |
3800 (save-excursion | 3849 (save-excursion |
3801 (while (progn (forward-line 1) | 3850 (while (progn (forward-line 1) |
3802 (looking-at "^[ \t]*#"))) | 3851 (looking-at "^[ \t]*#"))) |
3803 (point))) | 3852 (point))) |
3804 | 3853 |
3805 ;; Lines with only hashes on them can be paragraph boundaries. | 3854 ;; Lines with only hashes on them can be paragraph boundaries. |
3806 (let ((paragraph-start (concat paragraph-start "\\|[ \t#]*$")) | 3855 (let ((paragraph-start (concat paragraph-start "\\|[ \t#]*$")) |
3807 (paragraph-separate (concat paragraph-separate "\\|[ \t#]*$")) | 3856 (paragraph-separate (concat paragraph-separate "\\|[ \t#]*$")) |
3808 (fill-prefix comment-fill-prefix)) | 3857 (fill-prefix comment-fill-prefix)) |
3809 ;;(message "paragraph-start %S paragraph-separate %S" | 3858 ;;(message "paragraph-start %S paragraph-separate %S" |
3810 ;;paragraph-start paragraph-separate) | 3859 ;;paragraph-start paragraph-separate) |
3811 (fill-paragraph justify)))) | 3860 (fill-paragraph justify)))) |
3812 t)) | 3861 t)) |
3813 | 3862 |
3814 | 3863 |
3815 (defun py-fill-string (start &optional justify) | 3864 (defun py-fill-string (start &optional justify) |
3816 "Fill the paragraph around (point) in the string starting at start" | 3865 "Fill the paragraph around (point) in the string starting at start" |
3817 ;; basic strategy: narrow to the string and call the default | 3866 ;; basic strategy: narrow to the string and call the default |
3818 ;; implementation | 3867 ;; implementation |
3819 (let (;; the start of the string's contents | 3868 (let (;; the start of the string's contents |
3820 string-start | 3869 string-start |
3821 ;; the end of the string's contents | 3870 ;; the end of the string's contents |
3822 string-end | 3871 string-end |
3823 ;; length of the string's delimiter | 3872 ;; length of the string's delimiter |
3824 delim-length | 3873 delim-length |
3825 ;; The string delimiter | 3874 ;; The string delimiter |
3826 delim | 3875 delim |
3827 ) | 3876 ) |
3828 | 3877 |
3829 (save-excursion | 3878 (save-excursion |
3830 (goto-char start) | 3879 (goto-char start) |
3831 (if (looking-at "\\('''\\|\"\"\"\\|'\\|\"\\)\\\\?\n?") | 3880 (if (looking-at "\\('''\\|\"\"\"\\|'\\|\"\\)\\\\?\n?") |
3832 (setq string-start (match-end 0) | 3881 (setq string-start (match-end 0) |
3833 delim-length (- (match-end 1) (match-beginning 1)) | 3882 delim-length (- (match-end 1) (match-beginning 1)) |
3834 delim (buffer-substring-no-properties (match-beginning 1) | 3883 delim (buffer-substring-no-properties (match-beginning 1) |
3835 (match-end 1))) | 3884 (match-end 1))) |
3836 (error "The parameter start is not the beginning of a python string")) | 3885 (error "The parameter start is not the beginning of a python string")) |
3837 | 3886 |
3838 ;; if the string is the first token on a line and doesn't start with | 3887 ;; if the string is the first token on a line and doesn't start with |
3839 ;; a newline, fill as if the string starts at the beginning of the | 3888 ;; a newline, fill as if the string starts at the beginning of the |
3840 ;; line. this helps with one line docstrings | 3889 ;; line. this helps with one line docstrings |
3841 (save-excursion | 3890 (save-excursion |
3842 (beginning-of-line) | 3891 (beginning-of-line) |
3843 (and (/= (char-before string-start) ?\n) | 3892 (and (/= (char-before string-start) ?\n) |
3844 (looking-at (concat "[ \t]*" delim)) | 3893 (looking-at (concat "[ \t]*" delim)) |
3845 (setq string-start (point)))) | 3894 (setq string-start (point)))) |
3846 | 3895 |
3847 (forward-sexp (if (= delim-length 3) 2 1)) | 3896 (forward-sexp (if (= delim-length 3) 2 1)) |
3848 | 3897 |
3849 ;; with both triple quoted strings and single/double quoted strings | 3898 ;; with both triple quoted strings and single/double quoted strings |
3850 ;; we're now directly behind the first char of the end delimiter | 3899 ;; we're now directly behind the first char of the end delimiter |
3855 | 3904 |
3856 ;; Narrow to the string's contents and fill the current paragraph | 3905 ;; Narrow to the string's contents and fill the current paragraph |
3857 (save-restriction | 3906 (save-restriction |
3858 (narrow-to-region string-start string-end) | 3907 (narrow-to-region string-start string-end) |
3859 (let ((ends-with-newline (= (char-before (point-max)) ?\n))) | 3908 (let ((ends-with-newline (= (char-before (point-max)) ?\n))) |
3860 (fill-paragraph justify) | 3909 (fill-paragraph justify) |
3861 (if (and (not ends-with-newline) | 3910 (if (and (not ends-with-newline) |
3862 (= (char-before (point-max)) ?\n)) | 3911 (= (char-before (point-max)) ?\n)) |
3863 ;; the default fill-paragraph implementation has inserted a | 3912 ;; the default fill-paragraph implementation has inserted a |
3864 ;; newline at the end. Remove it again. | 3913 ;; newline at the end. Remove it again. |
3865 (save-excursion | 3914 (save-excursion |
3866 (goto-char (point-max)) | 3915 (goto-char (point-max)) |
3867 (delete-char -1))))) | 3916 (delete-char -1))))) |
3868 | 3917 |
3869 ;; return t to indicate that we've done our work | 3918 ;; return t to indicate that we've done our work |
3870 t)) | 3919 t)) |
3871 | 3920 |
3872 (defun py-fill-paragraph (&optional justify) | 3921 (defun py-fill-paragraph (&optional justify) |
3875 paragraph of it that point is in, preserving the comment's indentation | 3924 paragraph of it that point is in, preserving the comment's indentation |
3876 and initial `#'s. | 3925 and initial `#'s. |
3877 If point is inside a string, narrow to that string and fill. | 3926 If point is inside a string, narrow to that string and fill. |
3878 " | 3927 " |
3879 (interactive "P") | 3928 (interactive "P") |
3880 (let* ((bod (py-point 'bod)) | 3929 ;; fill-paragraph will narrow incorrectly |
3881 (pps (parse-partial-sexp bod (point)))) | 3930 (save-restriction |
3882 (cond | 3931 (widen) |
3883 ;; are we inside a comment or on a line with only whitespace before | 3932 (let* ((bod (py-point 'bod)) |
3884 ;; the comment start? | 3933 (pps (parse-partial-sexp bod (point)))) |
3885 ((or (nth 4 pps) | 3934 (cond |
3886 (save-excursion (beginning-of-line) (looking-at "[ \t]*#"))) | 3935 ;; are we inside a comment or on a line with only whitespace before |
3887 (py-fill-comment justify)) | 3936 ;; the comment start? |
3888 ;; are we inside a string? | 3937 ((or (nth 4 pps) |
3889 ((nth 3 pps) | 3938 (save-excursion (beginning-of-line) (looking-at "[ \t]*#"))) |
3890 (py-fill-string (nth 8 pps))) | 3939 (py-fill-comment justify)) |
3891 ;; are we at the opening quote of a string, or in the indentation? | 3940 ;; are we inside a string? |
3892 ((save-excursion | 3941 ((nth 3 pps) |
3893 (forward-word 1) | 3942 (py-fill-string (nth 8 pps))) |
3894 (eq (py-in-literal) 'string)) | 3943 ;; are we at the opening quote of a string, or in the indentation? |
3895 (save-excursion | 3944 ((save-excursion |
3896 (py-fill-string (py-point 'boi)))) | 3945 (forward-word 1) |
3897 ;; are we at or after the closing quote of a string? | 3946 (eq (py-in-literal) 'string)) |
3898 ((save-excursion | 3947 (save-excursion |
3899 (backward-word 1) | 3948 (py-fill-string (py-point 'boi)))) |
3900 (eq (py-in-literal) 'string)) | 3949 ;; are we at or after the closing quote of a string? |
3901 (save-excursion | 3950 ((save-excursion |
3902 (py-fill-string (py-point 'boi)))) | 3951 (backward-word 1) |
3903 ;; otherwise use the default | 3952 (eq (py-in-literal) 'string)) |
3904 (t | 3953 (save-excursion |
3905 (fill-paragraph justify))))) | 3954 (py-fill-string (py-point 'boi)))) |
3955 ;; otherwise use the default | |
3956 (t | |
3957 (fill-paragraph justify)))))) | |
3906 | 3958 |
3907 | 3959 |
3908 | 3960 |
3909 (provide 'python-mode) | 3961 (provide 'python-mode) |
3910 ;;; python-mode.el ends here | 3962 ;;; python-mode.el ends here |