| 1 | ;;; python-mode.el --- Major mode for editing Python programs
|
|---|
| 2 |
|
|---|
| 3 | ;; Copyright (C) 1992,1993,1994 Tim Peters
|
|---|
| 4 |
|
|---|
| 5 | ;; Author: 1995-2002 Barry A. Warsaw
|
|---|
| 6 | ;; 1992-1994 Tim Peters
|
|---|
| 7 | ;; Maintainer: [email protected]
|
|---|
| 8 | ;; Created: Feb 1992
|
|---|
| 9 | ;; Keywords: python languages oop
|
|---|
| 10 |
|
|---|
| 11 | (defconst py-version "$Revision: 34960 $"
|
|---|
| 12 | "`python-mode' version number.")
|
|---|
| 13 |
|
|---|
| 14 | ;; This software is provided as-is, without express or implied
|
|---|
| 15 | ;; warranty. Permission to use, copy, modify, distribute or sell this
|
|---|
| 16 | ;; software, without fee, for any purpose and by any individual or
|
|---|
| 17 | ;; organization, is hereby granted, provided that the above copyright
|
|---|
| 18 | ;; notice and this paragraph appear in all copies.
|
|---|
| 19 |
|
|---|
| 20 | ;;; Commentary:
|
|---|
| 21 |
|
|---|
| 22 | ;; This is a major mode for editing Python programs. It was developed
|
|---|
| 23 | ;; by Tim Peters after an original idea by Michael A. Guravage. Tim
|
|---|
| 24 | ;; subsequently left the net; in 1995, Barry Warsaw inherited the mode
|
|---|
| 25 | ;; and is the current maintainer. Tim's now back but disavows all
|
|---|
| 26 | ;; responsibility for the mode. Smart Tim :-)
|
|---|
| 27 |
|
|---|
| 28 | ;; pdbtrack support contributed by Ken Manheimer, April 2001.
|
|---|
| 29 |
|
|---|
| 30 | ;; Please use the SourceForge Python project to submit bugs or
|
|---|
| 31 | ;; patches:
|
|---|
| 32 | ;;
|
|---|
| 33 | ;; http://sourceforge.net/projects/python
|
|---|
| 34 |
|
|---|
| 35 | ;; FOR MORE INFORMATION:
|
|---|
| 36 |
|
|---|
| 37 | ;; There is some information on python-mode.el at
|
|---|
| 38 |
|
|---|
| 39 | ;; http://www.python.org/emacs/python-mode/
|
|---|
| 40 | ;;
|
|---|
| 41 | ;; It does contain links to other packages that you might find useful,
|
|---|
| 42 | ;; such as pdb interfaces, OO-Browser links, etc.
|
|---|
| 43 |
|
|---|
| 44 | ;; BUG REPORTING:
|
|---|
| 45 |
|
|---|
| 46 | ;; As mentioned above, please use the SourceForge Python project for
|
|---|
| 47 | ;; submitting bug reports or patches. The old recommendation, to use
|
|---|
| 48 | ;; C-c C-b will still work, but those reports have a higher chance of
|
|---|
| 49 | ;; getting buried in my mailbox. Please include a complete, but
|
|---|
| 50 | ;; concise code sample and a recipe for reproducing the bug. Send
|
|---|
| 51 | ;; suggestions and other comments to [email protected].
|
|---|
| 52 |
|
|---|
| 53 | ;; When in a Python mode buffer, do a C-h m for more help. It's
|
|---|
| 54 | ;; doubtful that a texinfo manual would be very useful, but if you
|
|---|
| 55 | ;; want to contribute one, I'll certainly accept it!
|
|---|
| 56 |
|
|---|
| 57 | ;;; Code:
|
|---|
| 58 |
|
|---|
| 59 | (require 'comint)
|
|---|
| 60 | (require 'custom)
|
|---|
| 61 | (require 'cl)
|
|---|
| 62 | (require 'compile)
|
|---|
| 63 |
|
|---|
| 64 | |
|---|
| 65 |
|
|---|
| 66 | ;; user definable variables
|
|---|
| 67 | ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
|---|
| 68 |
|
|---|
| 69 | (defgroup python nil
|
|---|
| 70 | "Support for the Python programming language, <http://www.python.org/>"
|
|---|
| 71 | :group 'languages
|
|---|
| 72 | :prefix "py-")
|
|---|
| 73 |
|
|---|
| 74 | (defcustom py-python-command "python"
|
|---|
| 75 | "*Shell command used to start Python interpreter."
|
|---|
| 76 | :type 'string
|
|---|
| 77 | :group 'python)
|
|---|
| 78 |
|
|---|
| 79 | (defcustom py-jpython-command "jpython"
|
|---|
| 80 | "*Shell command used to start the JPython interpreter."
|
|---|
| 81 | :type 'string
|
|---|
| 82 | :group 'python
|
|---|
| 83 | :tag "JPython Command")
|
|---|
| 84 |
|
|---|
| 85 | (defcustom py-default-interpreter 'cpython
|
|---|
| 86 | "*Which Python interpreter is used by default.
|
|---|
| 87 | The value for this variable can be either `cpython' or `jpython'.
|
|---|
| 88 |
|
|---|
| 89 | When the value is `cpython', the variables `py-python-command' and
|
|---|
| 90 | `py-python-command-args' are consulted to determine the interpreter
|
|---|
| 91 | and arguments to use.
|
|---|
| 92 |
|
|---|
| 93 | When the value is `jpython', the variables `py-jpython-command' and
|
|---|
| 94 | `py-jpython-command-args' are consulted to determine the interpreter
|
|---|
| 95 | and arguments to use.
|
|---|
| 96 |
|
|---|
| 97 | Note that this variable is consulted only the first time that a Python
|
|---|
| 98 | mode buffer is visited during an Emacs session. After that, use
|
|---|
| 99 | \\[py-toggle-shells] to change the interpreter shell."
|
|---|
| 100 | :type '(choice (const :tag "Python (a.k.a. CPython)" cpython)
|
|---|
| 101 | (const :tag "JPython" jpython))
|
|---|
| 102 | :group 'python)
|
|---|
| 103 |
|
|---|
| 104 | (defcustom py-python-command-args '("-i")
|
|---|
| 105 | "*List of string arguments to be used when starting a Python shell."
|
|---|
| 106 | :type '(repeat string)
|
|---|
| 107 | :group 'python)
|
|---|
| 108 |
|
|---|
| 109 | (defcustom py-jpython-command-args '("-i")
|
|---|
| 110 | "*List of string arguments to be used when starting a JPython shell."
|
|---|
| 111 | :type '(repeat string)
|
|---|
| 112 | :group 'python
|
|---|
| 113 | :tag "JPython Command Args")
|
|---|
| 114 |
|
|---|
| 115 | (defcustom py-indent-offset 4
|
|---|
| 116 | "*Amount of offset per level of indentation.
|
|---|
| 117 | `\\[py-guess-indent-offset]' can usually guess a good value when
|
|---|
| 118 | you're editing someone else's Python code."
|
|---|
| 119 | :type 'integer
|
|---|
| 120 | :group 'python)
|
|---|
| 121 |
|
|---|
| 122 | (defcustom py-continuation-offset 4
|
|---|
| 123 | "*Additional amount of offset to give for some continuation lines.
|
|---|
| 124 | Continuation lines are those that immediately follow a backslash
|
|---|
| 125 | terminated line. Only those continuation lines for a block opening
|
|---|
| 126 | statement are given this extra offset."
|
|---|
| 127 | :type 'integer
|
|---|
| 128 | :group 'python)
|
|---|
| 129 |
|
|---|
| 130 | (defcustom py-smart-indentation t
|
|---|
| 131 | "*Should `python-mode' try to automagically set some indentation variables?
|
|---|
| 132 | When this variable is non-nil, two things happen when a buffer is set
|
|---|
| 133 | to `python-mode':
|
|---|
| 134 |
|
|---|
| 135 | 1. `py-indent-offset' is guessed from existing code in the buffer.
|
|---|
| 136 | Only guessed values between 2 and 8 are considered. If a valid
|
|---|
| 137 | guess can't be made (perhaps because you are visiting a new
|
|---|
| 138 | file), then the value in `py-indent-offset' is used.
|
|---|
| 139 |
|
|---|
| 140 | 2. `indent-tabs-mode' is turned off if `py-indent-offset' does not
|
|---|
| 141 | equal `tab-width' (`indent-tabs-mode' is never turned on by
|
|---|
| 142 | Python mode). This means that for newly written code, tabs are
|
|---|
| 143 | only inserted in indentation if one tab is one indentation
|
|---|
| 144 | level, otherwise only spaces are used.
|
|---|
| 145 |
|
|---|
| 146 | Note that both these settings occur *after* `python-mode-hook' is run,
|
|---|
| 147 | so if you want to defeat the automagic configuration, you must also
|
|---|
| 148 | set `py-smart-indentation' to nil in your `python-mode-hook'."
|
|---|
| 149 | :type 'boolean
|
|---|
| 150 | :group 'python)
|
|---|
| 151 |
|
|---|
| 152 | (defcustom py-align-multiline-strings-p t
|
|---|
| 153 | "*Flag describing how multi-line triple quoted strings are aligned.
|
|---|
| 154 | When this flag is non-nil, continuation lines are lined up under the
|
|---|
| 155 | preceding line's indentation. When this flag is nil, continuation
|
|---|
| 156 | lines are aligned to column zero."
|
|---|
| 157 | :type '(choice (const :tag "Align under preceding line" t)
|
|---|
| 158 | (const :tag "Align to column zero" nil))
|
|---|
| 159 | :group 'python)
|
|---|
| 160 |
|
|---|
| 161 | (defcustom py-block-comment-prefix "##"
|
|---|
| 162 | "*String used by \\[comment-region] to comment out a block of code.
|
|---|
| 163 | This should follow the convention for non-indenting comment lines so
|
|---|
| 164 | that the indentation commands won't get confused (i.e., the string
|
|---|
| 165 | should be of the form `#x...' where `x' is not a blank or a tab, and
|
|---|
| 166 | `...' is arbitrary). However, this string should not end in whitespace."
|
|---|
| 167 | :type 'string
|
|---|
| 168 | :group 'python)
|
|---|
| 169 |
|
|---|
| 170 | (defcustom py-honor-comment-indentation t
|
|---|
| 171 | "*Controls how comment lines influence subsequent indentation.
|
|---|
| 172 |
|
|---|
| 173 | When nil, all comment lines are skipped for indentation purposes, and
|
|---|
| 174 | if possible, a faster algorithm is used (i.e. X/Emacs 19 and beyond).
|
|---|
| 175 |
|
|---|
| 176 | When t, lines that begin with a single `#' are a hint to subsequent
|
|---|
| 177 | line indentation. If the previous line is such a comment line (as
|
|---|
| 178 | opposed to one that starts with `py-block-comment-prefix'), then its
|
|---|
| 179 | indentation is used as a hint for this line's indentation. Lines that
|
|---|
| 180 | begin with `py-block-comment-prefix' are ignored for indentation
|
|---|
| 181 | purposes.
|
|---|
| 182 |
|
|---|
| 183 | When not nil or t, comment lines that begin with a single `#' are used
|
|---|
| 184 | as indentation hints, unless the comment character is in column zero."
|
|---|
| 185 | :type '(choice
|
|---|
| 186 | (const :tag "Skip all comment lines (fast)" nil)
|
|---|
| 187 | (const :tag "Single # `sets' indentation for next line" t)
|
|---|
| 188 | (const :tag "Single # `sets' indentation except at column zero"
|
|---|
| 189 | other)
|
|---|
| 190 | )
|
|---|
| 191 | :group 'python)
|
|---|
| 192 |
|
|---|
| 193 | (defcustom py-temp-directory
|
|---|
| 194 | (let ((ok '(lambda (x)
|
|---|
| 195 | (and x
|
|---|
| 196 | (setq x (expand-file-name x)) ; always true
|
|---|
| 197 | (file-directory-p x)
|
|---|
| 198 | (file-writable-p x)
|
|---|
| 199 | x))))
|
|---|
| 200 | (or (funcall ok (getenv "TMPDIR"))
|
|---|
| 201 | (funcall ok "/usr/tmp")
|
|---|
| 202 | (funcall ok "/tmp")
|
|---|
| 203 | (funcall ok "/var/tmp")
|
|---|
| 204 | (funcall ok ".")
|
|---|
| 205 | (error
|
|---|
| 206 | "Couldn't find a usable temp directory -- set `py-temp-directory'")))
|
|---|
| 207 | "*Directory used for temporary files created by a *Python* process.
|
|---|
| 208 | By default, the first directory from this list that exists and that you
|
|---|
| 209 | can write into: the value (if any) of the environment variable TMPDIR,
|
|---|
| 210 | /usr/tmp, /tmp, /var/tmp, or the current directory."
|
|---|
| 211 | :type 'string
|
|---|
| 212 | :group 'python)
|
|---|
| 213 |
|
|---|
| 214 | (defcustom py-beep-if-tab-change t
|
|---|
| 215 | "*Ring the bell if `tab-width' is changed.
|
|---|
| 216 | If a comment of the form
|
|---|
| 217 |
|
|---|
| 218 | \t# vi:set tabsize=<number>:
|
|---|
| 219 |
|
|---|
| 220 | is found before the first code line when the file is entered, and the
|
|---|
| 221 | current value of (the general Emacs variable) `tab-width' does not
|
|---|
| 222 | equal <number>, `tab-width' is set to <number>, a message saying so is
|
|---|
| 223 | displayed in the echo area, and if `py-beep-if-tab-change' is non-nil
|
|---|
| 224 | the Emacs bell is also rung as a warning."
|
|---|
| 225 | :type 'boolean
|
|---|
| 226 | :group 'python)
|
|---|
| 227 |
|
|---|
| 228 | (defcustom py-jump-on-exception t
|
|---|
| 229 | "*Jump to innermost exception frame in *Python Output* buffer.
|
|---|
| 230 | When this variable is non-nil and an exception occurs when running
|
|---|
| 231 | Python code synchronously in a subprocess, jump immediately to the
|
|---|
| 232 | source code of the innermost traceback frame."
|
|---|
| 233 | :type 'boolean
|
|---|
| 234 | :group 'python)
|
|---|
| 235 |
|
|---|
| 236 | (defcustom py-ask-about-save t
|
|---|
| 237 | "If not nil, ask about which buffers to save before executing some code.
|
|---|
| 238 | Otherwise, all modified buffers are saved without asking."
|
|---|
| 239 | :type 'boolean
|
|---|
| 240 | :group 'python)
|
|---|
| 241 |
|
|---|
| 242 | (defcustom py-backspace-function 'backward-delete-char-untabify
|
|---|
| 243 | "*Function called by `py-electric-backspace' when deleting backwards."
|
|---|
| 244 | :type 'function
|
|---|
| 245 | :group 'python)
|
|---|
| 246 |
|
|---|
| 247 | (defcustom py-delete-function 'delete-char
|
|---|
| 248 | "*Function called by `py-electric-delete' when deleting forwards."
|
|---|
| 249 | :type 'function
|
|---|
| 250 | :group 'python)
|
|---|
| 251 |
|
|---|
| 252 | (defcustom py-imenu-show-method-args-p nil
|
|---|
| 253 | "*Controls echoing of arguments of functions & methods in the Imenu buffer.
|
|---|
| 254 | When non-nil, arguments are printed."
|
|---|
| 255 | :type 'boolean
|
|---|
| 256 | :group 'python)
|
|---|
| 257 | (make-variable-buffer-local 'py-indent-offset)
|
|---|
| 258 |
|
|---|
| 259 | (defcustom py-pdbtrack-do-tracking-p t
|
|---|
| 260 | "*Controls whether the pdbtrack feature is enabled or not.
|
|---|
| 261 | When non-nil, pdbtrack is enabled in all comint-based buffers,
|
|---|
| 262 | e.g. shell buffers and the *Python* buffer. When using pdb to debug a
|
|---|
| 263 | Python program, pdbtrack notices the pdb prompt and displays the
|
|---|
| 264 | source file and line that the program is stopped at, much the same way
|
|---|
| 265 | as gud-mode does for debugging C programs with gdb."
|
|---|
| 266 | :type 'boolean
|
|---|
| 267 | :group 'python)
|
|---|
| 268 | (make-variable-buffer-local 'py-pdbtrack-do-tracking-p)
|
|---|
| 269 |
|
|---|
| 270 | (defcustom py-pdbtrack-minor-mode-string " PDB"
|
|---|
| 271 | "*String to use in the minor mode list when pdbtrack is enabled."
|
|---|
| 272 | :type 'string
|
|---|
| 273 | :group 'python)
|
|---|
| 274 |
|
|---|
| 275 | (defcustom py-import-check-point-max
|
|---|
| 276 | 20000
|
|---|
| 277 | "Maximum number of characters to search for a Java-ish import statement.
|
|---|
| 278 | When `python-mode' tries to calculate the shell to use (either a
|
|---|
| 279 | CPython or a JPython shell), it looks at the so-called `shebang' line
|
|---|
| 280 | -- i.e. #! line. If that's not available, it looks at some of the
|
|---|
| 281 | file heading imports to see if they look Java-like."
|
|---|
| 282 | :type 'integer
|
|---|
| 283 | :group 'python
|
|---|
| 284 | )
|
|---|
| 285 |
|
|---|
| 286 | (defcustom py-jpython-packages
|
|---|
| 287 | '("java" "javax" "org" "com")
|
|---|
| 288 | "Imported packages that imply `jpython-mode'."
|
|---|
| 289 | :type '(repeat string)
|
|---|
| 290 | :group 'python)
|
|---|
| 291 |
|
|---|
| 292 | ;; Not customizable
|
|---|
| 293 | (defvar py-master-file nil
|
|---|
| 294 | "If non-nil, execute the named file instead of the buffer's file.
|
|---|
| 295 | The intent is to allow you to set this variable in the file's local
|
|---|
| 296 | variable section, e.g.:
|
|---|
| 297 |
|
|---|
| 298 | # Local Variables:
|
|---|
| 299 | # py-master-file: \"master.py\"
|
|---|
| 300 | # End:
|
|---|
| 301 |
|
|---|
| 302 | so that typing \\[py-execute-buffer] in that buffer executes the named
|
|---|
| 303 | master file instead of the buffer's file. If the file name has a
|
|---|
| 304 | relative path, the value of variable `default-directory' for the
|
|---|
| 305 | buffer is prepended to come up with a file name.")
|
|---|
| 306 | (make-variable-buffer-local 'py-master-file)
|
|---|
| 307 |
|
|---|
| 308 | (defcustom py-pychecker-command "pychecker"
|
|---|
| 309 | "*Shell command used to run Pychecker."
|
|---|
| 310 | :type 'string
|
|---|
| 311 | :group 'python
|
|---|
| 312 | :tag "Pychecker Command")
|
|---|
| 313 |
|
|---|
| 314 | (defcustom py-pychecker-command-args '("--stdlib")
|
|---|
| 315 | "*List of string arguments to be passed to pychecker."
|
|---|
| 316 | :type '(repeat string)
|
|---|
| 317 | :group 'python
|
|---|
| 318 | :tag "Pychecker Command Args")
|
|---|
| 319 |
|
|---|
| 320 | (defvar py-shell-alist
|
|---|
| 321 | '(("jpython" . 'jpython)
|
|---|
| 322 | ("jython" . 'jpython)
|
|---|
| 323 | ("python" . 'cpython))
|
|---|
| 324 | "*Alist of interpreters and python shells. Used by `py-choose-shell'
|
|---|
| 325 | to select the appropriate python interpreter mode for a file.")
|
|---|
| 326 |
|
|---|
| 327 | |
|---|
| 328 |
|
|---|
| 329 | ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|---|
| 330 | ;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
|
|---|
| 331 |
|
|---|
| 332 | (defconst py-emacs-features
|
|---|
| 333 | (let (features)
|
|---|
| 334 | features)
|
|---|
| 335 | "A list of features extant in the Emacs you are using.
|
|---|
| 336 | There are many flavors of Emacs out there, with different levels of
|
|---|
| 337 | support for features needed by `python-mode'.")
|
|---|
| 338 |
|
|---|
| 339 | ;; Face for None, True, False, self, and Ellipsis
|
|---|
| 340 | (defvar py-pseudo-keyword-face 'py-pseudo-keyword-face
|
|---|
| 341 | "Face for pseudo keywords in Python mode, like self, True, False, Ellipsis.")
|
|---|
| 342 | (make-face 'py-pseudo-keyword-face)
|
|---|
| 343 |
|
|---|
| 344 | (defun py-font-lock-mode-hook ()
|
|---|
| 345 | (or (face-differs-from-default-p 'py-pseudo-keyword-face)
|
|---|
| 346 | (copy-face 'font-lock-keyword-face 'py-pseudo-keyword-face)))
|
|---|
| 347 | (add-hook 'font-lock-mode-hook 'py-font-lock-mode-hook)
|
|---|
| 348 |
|
|---|
| 349 | (defvar python-font-lock-keywords
|
|---|
| 350 | (let ((kw1 (mapconcat 'identity
|
|---|
| 351 | '("and" "assert" "break" "class"
|
|---|
| 352 | "continue" "def" "del" "elif"
|
|---|
| 353 | "else" "except" "exec" "for"
|
|---|
| 354 | "from" "global" "if" "import"
|
|---|
| 355 | "in" "is" "lambda" "not"
|
|---|
| 356 | "or" "pass" "print" "raise"
|
|---|
| 357 | "return" "while" "yield"
|
|---|
| 358 | )
|
|---|
| 359 | "\\|"))
|
|---|
| 360 | (kw2 (mapconcat 'identity
|
|---|
| 361 | '("else:" "except:" "finally:" "try:")
|
|---|
| 362 | "\\|"))
|
|---|
| 363 | (kw3 (mapconcat 'identity
|
|---|
| 364 | '("ArithmeticError" "AssertionError"
|
|---|
| 365 | "AttributeError" "DeprecationWarning" "EOFError"
|
|---|
| 366 | "Ellipsis" "EnvironmentError" "Exception" "False"
|
|---|
| 367 | "FloatingPointError" "FutureWarning" "IOError"
|
|---|
| 368 | "ImportError" "IndentationError" "IndexError"
|
|---|
| 369 | "KeyError" "KeyboardInterrupt" "LookupError"
|
|---|
| 370 | "MemoryError" "NameError" "None" "NotImplemented"
|
|---|
| 371 | "NotImplementedError" "OSError" "OverflowError"
|
|---|
| 372 | "OverflowWarning" "PendingDeprecationWarning"
|
|---|
| 373 | "ReferenceError" "RuntimeError" "RuntimeWarning"
|
|---|
| 374 | "StandardError" "StopIteration" "SyntaxError"
|
|---|
| 375 | "SyntaxWarning" "SystemError" "SystemExit"
|
|---|
| 376 | "TabError" "True" "TypeError" "UnboundLocalError"
|
|---|
| 377 | "UnicodeDecodeError" "UnicodeEncodeError"
|
|---|
| 378 | "UnicodeError" "UnicodeTranslateError"
|
|---|
| 379 | "UserWarning" "ValueError" "Warning"
|
|---|
| 380 | "ZeroDivisionError" "__debug__"
|
|---|
| 381 | "__import__" "__name__" "abs" "apply" "basestring"
|
|---|
| 382 | "bool" "buffer" "callable" "chr" "classmethod"
|
|---|
| 383 | "cmp" "coerce" "compile" "complex" "copyright"
|
|---|
| 384 | "delattr" "dict" "dir" "divmod"
|
|---|
| 385 | "enumerate" "eval" "execfile" "exit" "file"
|
|---|
| 386 | "filter" "float" "getattr" "globals" "hasattr"
|
|---|
| 387 | "hash" "hex" "id" "input" "int" "intern"
|
|---|
| 388 | "isinstance" "issubclass" "iter" "len" "license"
|
|---|
| 389 | "list" "locals" "long" "map" "max" "min" "object"
|
|---|
| 390 | "oct" "open" "ord" "pow" "property" "range"
|
|---|
| 391 | "raw_input" "reduce" "reload" "repr" "round"
|
|---|
| 392 | "setattr" "slice" "staticmethod" "str" "sum"
|
|---|
| 393 | "super" "tuple" "type" "unichr" "unicode" "vars"
|
|---|
| 394 | "xrange" "zip")
|
|---|
| 395 | "\\|"))
|
|---|
| 396 | )
|
|---|
| 397 | (list
|
|---|
| 398 | ;; keywords
|
|---|
| 399 | (cons (concat "\\b\\(" kw1 "\\)\\b[ \n\t(]") 1)
|
|---|
| 400 | ;; builtins when they don't appear as object attributes
|
|---|
| 401 | (cons (concat "\\(\\b\\|[.]\\)\\(" kw3 "\\)\\b[ \n\t(]") 2)
|
|---|
| 402 | ;; block introducing keywords with immediately following colons.
|
|---|
| 403 | ;; Yes "except" is in both lists.
|
|---|
| 404 | (cons (concat "\\b\\(" kw2 "\\)[ \n\t(]") 1)
|
|---|
| 405 | ;; `as' but only in "import foo as bar"
|
|---|
| 406 | '("[ \t]*\\(\\bfrom\\b.*\\)?\\bimport\\b.*\\b\\(as\\)\\b" . 2)
|
|---|
| 407 | ;; classes
|
|---|
| 408 | '("\\bclass[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)"
|
|---|
| 409 | 1 font-lock-type-face)
|
|---|
| 410 | ;; functions
|
|---|
| 411 | '("\\bdef[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)"
|
|---|
| 412 | 1 font-lock-function-name-face)
|
|---|
| 413 | ;; pseudo-keywords
|
|---|
| 414 | '("\\b\\(self\\|None\\|True\\|False\\|Ellipsis\\)\\b"
|
|---|
| 415 | 1 py-pseudo-keyword-face)
|
|---|
| 416 | ))
|
|---|
| 417 | "Additional expressions to highlight in Python mode.")
|
|---|
| 418 | (put 'python-mode 'font-lock-defaults '(python-font-lock-keywords))
|
|---|
| 419 |
|
|---|
| 420 | ;; have to bind py-file-queue before installing the kill-emacs-hook
|
|---|
| 421 | (defvar py-file-queue nil
|
|---|
| 422 | "Queue of Python temp files awaiting execution.
|
|---|
| 423 | Currently-active file is at the head of the list.")
|
|---|
| 424 |
|
|---|
| 425 | (defvar py-pdbtrack-is-tracking-p nil)
|
|---|
| 426 | (defvar py-pdbtrack-last-grubbed-buffer nil
|
|---|
| 427 | "Record of the last buffer used when the source path was invalid.
|
|---|
| 428 |
|
|---|
| 429 | This buffer is consulted before the buffer-list history for satisfying
|
|---|
| 430 | `py-pdbtrack-grub-for-buffer', since it's the most often the likely
|
|---|
| 431 | prospect as debugging continues.")
|
|---|
| 432 | (make-variable-buffer-local 'py-pdbtrack-last-grubbed-buffer)
|
|---|
| 433 | (defvar py-pychecker-history nil)
|
|---|
| 434 |
|
|---|
| 435 |
|
|---|
| 436 | |
|---|
| 437 |
|
|---|
| 438 | ;; Constants
|
|---|
| 439 |
|
|---|
| 440 | (defconst py-stringlit-re
|
|---|
| 441 | (concat
|
|---|
| 442 | ;; These fail if backslash-quote ends the string (not worth
|
|---|
| 443 | ;; fixing?). They precede the short versions so that the first two
|
|---|
| 444 | ;; quotes don't look like an empty short string.
|
|---|
| 445 | ;;
|
|---|
| 446 | ;; (maybe raw), long single quoted triple quoted strings (SQTQ),
|
|---|
| 447 | ;; with potential embedded single quotes
|
|---|
| 448 | "[rR]?'''[^']*\\(\\('[^']\\|''[^']\\)[^']*\\)*'''"
|
|---|
| 449 | "\\|"
|
|---|
| 450 | ;; (maybe raw), long double quoted triple quoted strings (DQTQ),
|
|---|
| 451 | ;; with potential embedded double quotes
|
|---|
| 452 | "[rR]?\"\"\"[^\"]*\\(\\(\"[^\"]\\|\"\"[^\"]\\)[^\"]*\\)*\"\"\""
|
|---|
| 453 | "\\|"
|
|---|
| 454 | "[rR]?'\\([^'\n\\]\\|\\\\.\\)*'" ; single-quoted
|
|---|
| 455 | "\\|" ; or
|
|---|
| 456 | "[rR]?\"\\([^\"\n\\]\\|\\\\.\\)*\"" ; double-quoted
|
|---|
| 457 | )
|
|---|
| 458 | "Regular expression matching a Python string literal.")
|
|---|
| 459 |
|
|---|
| 460 | (defconst py-continued-re
|
|---|
| 461 | ;; This is tricky because a trailing backslash does not mean
|
|---|
| 462 | ;; continuation if it's in a comment
|
|---|
| 463 | (concat
|
|---|
| 464 | "\\(" "[^#'\"\n\\]" "\\|" py-stringlit-re "\\)*"
|
|---|
| 465 | "\\\\$")
|
|---|
| 466 | "Regular expression matching Python backslash continuation lines.")
|
|---|
| 467 |
|
|---|
| 468 | (defconst py-blank-or-comment-re "[ \t]*\\($\\|#\\)"
|
|---|
| 469 | "Regular expression matching a blank or comment line.")
|
|---|
| 470 |
|
|---|
| 471 | (defconst py-outdent-re
|
|---|
| 472 | (concat "\\(" (mapconcat 'identity
|
|---|
| 473 | '("else:"
|
|---|
| 474 | "except\\(\\s +.*\\)?:"
|
|---|
| 475 | "finally:"
|
|---|
| 476 | "elif\\s +.*:")
|
|---|
| 477 | "\\|")
|
|---|
| 478 | "\\)")
|
|---|
| 479 | "Regular expression matching statements to be dedented one level.")
|
|---|
| 480 |
|
|---|
| 481 | (defconst py-block-closing-keywords-re
|
|---|
| 482 | "\\(return\\|raise\\|break\\|continue\\|pass\\)"
|
|---|
| 483 | "Regular expression matching keywords which typically close a block.")
|
|---|
| 484 |
|
|---|
| 485 | (defconst py-no-outdent-re
|
|---|
| 486 | (concat
|
|---|
| 487 | "\\("
|
|---|
| 488 | (mapconcat 'identity
|
|---|
| 489 | (list "try:"
|
|---|
| 490 | "except\\(\\s +.*\\)?:"
|
|---|
| 491 | "while\\s +.*:"
|
|---|
| 492 | "for\\s +.*:"
|
|---|
| 493 | "if\\s +.*:"
|
|---|
| 494 | "elif\\s +.*:"
|
|---|
| 495 | (concat py-block-closing-keywords-re "[ \t\n]")
|
|---|
| 496 | )
|
|---|
| 497 | "\\|")
|
|---|
| 498 | "\\)")
|
|---|
| 499 | "Regular expression matching lines not to dedent after.")
|
|---|
| 500 |
|
|---|
| 501 | (defconst py-defun-start-re
|
|---|
| 502 | "^\\([ \t]*\\)def[ \t]+\\([a-zA-Z_0-9]+\\)\\|\\(^[a-zA-Z_0-9]+\\)[ \t]*="
|
|---|
| 503 | ;; If you change this, you probably have to change py-current-defun
|
|---|
| 504 | ;; as well. This is only used by py-current-defun to find the name
|
|---|
| 505 | ;; for add-log.el.
|
|---|
| 506 | "Regular expression matching a function, method, or variable assignment.")
|
|---|
| 507 |
|
|---|
| 508 | (defconst py-class-start-re "^class[ \t]*\\([a-zA-Z_0-9]+\\)"
|
|---|
| 509 | ;; If you change this, you probably have to change py-current-defun
|
|---|
| 510 | ;; as well. This is only used by py-current-defun to find the name
|
|---|
| 511 | ;; for add-log.el.
|
|---|
| 512 | "Regular expression for finding a class name.")
|
|---|
| 513 |
|
|---|
| 514 | (defconst py-traceback-line-re
|
|---|
| 515 | "[ \t]+File \"\\([^\"]+\\)\", line \\([0-9]+\\)"
|
|---|
| 516 | "Regular expression that describes tracebacks.")
|
|---|
| 517 |
|
|---|
| 518 | ;; pdbtrack contants
|
|---|
| 519 | (defconst py-pdbtrack-stack-entry-regexp
|
|---|
| 520 | ; "^> \\([^(]+\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
|
|---|
| 521 | "^> \\(.*\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
|
|---|
| 522 | "Regular expression pdbtrack uses to find a stack trace entry.")
|
|---|
| 523 |
|
|---|
| 524 | (defconst py-pdbtrack-input-prompt "\n[(<]*pdb[>)]+ "
|
|---|
| 525 | "Regular expression pdbtrack uses to recognize a pdb prompt.")
|
|---|
| 526 |
|
|---|
| 527 | (defconst py-pdbtrack-track-range 10000
|
|---|
| 528 | "Max number of characters from end of buffer to search for stack entry.")
|
|---|
| 529 |
|
|---|
| 530 |
|
|---|
| 531 | |
|---|
| 532 |
|
|---|
| 533 | ;; Major mode boilerplate
|
|---|
| 534 |
|
|---|
| 535 | ;; define a mode-specific abbrev table for those who use such things
|
|---|
| 536 | (defvar python-mode-abbrev-table nil
|
|---|
| 537 | "Abbrev table in use in `python-mode' buffers.")
|
|---|
| 538 | (define-abbrev-table 'python-mode-abbrev-table nil)
|
|---|
| 539 |
|
|---|
| 540 | (defvar python-mode-hook nil
|
|---|
| 541 | "*Hook called by `python-mode'.")
|
|---|
| 542 |
|
|---|
| 543 | (defvar jpython-mode-hook nil
|
|---|
| 544 | "*Hook called by `jpython-mode'. `jpython-mode' also calls
|
|---|
| 545 | `python-mode-hook'.")
|
|---|
| 546 |
|
|---|
| 547 | (defvar py-shell-hook nil
|
|---|
| 548 | "*Hook called by `py-shell'.")
|
|---|
| 549 |
|
|---|
| 550 | ;; In previous version of python-mode.el, the hook was incorrectly
|
|---|
| 551 | ;; called py-mode-hook, and was not defvar'd. Deprecate its use.
|
|---|
| 552 | (and (fboundp 'make-obsolete-variable)
|
|---|
| 553 | (make-obsolete-variable 'py-mode-hook 'python-mode-hook))
|
|---|
| 554 |
|
|---|
| 555 | (defvar py-mode-map ()
|
|---|
| 556 | "Keymap used in `python-mode' buffers.")
|
|---|
| 557 | (if py-mode-map
|
|---|
| 558 | nil
|
|---|
| 559 | (setq py-mode-map (make-sparse-keymap))
|
|---|
| 560 | ;; electric keys
|
|---|
| 561 | (define-key py-mode-map ":" 'py-electric-colon)
|
|---|
| 562 | ;; indentation level modifiers
|
|---|
| 563 | (define-key py-mode-map "\C-c\C-l" 'py-shift-region-left)
|
|---|
| 564 | (define-key py-mode-map "\C-c\C-r" 'py-shift-region-right)
|
|---|
| 565 | (define-key py-mode-map "\C-c<" 'py-shift-region-left)
|
|---|
| 566 | (define-key py-mode-map "\C-c>" 'py-shift-region-right)
|
|---|
| 567 | ;; paragraph and string filling
|
|---|
| 568 | (define-key py-mode-map "\eq" 'py-fill-paragraph)
|
|---|
| 569 | ;; subprocess commands
|
|---|
| 570 | (define-key py-mode-map "\C-c\C-c" 'py-execute-buffer)
|
|---|
| 571 | (define-key py-mode-map "\C-c\C-m" 'py-execute-import-or-reload)
|
|---|
| 572 | (define-key py-mode-map "\C-c\C-s" 'py-execute-string)
|
|---|
| 573 | (define-key py-mode-map "\C-c|" 'py-execute-region)
|
|---|
| 574 | (define-key py-mode-map "\e\C-x" 'py-execute-def-or-class)
|
|---|
| 575 | (define-key py-mode-map "\C-c!" 'py-shell)
|
|---|
| 576 | (define-key py-mode-map "\C-c\C-t" 'py-toggle-shells)
|
|---|
| 577 | ;; Caution! Enter here at your own risk. We are trying to support
|
|---|
| 578 | ;; several behaviors and it gets disgusting. :-( This logic ripped
|
|---|
| 579 | ;; largely from CC Mode.
|
|---|
| 580 | ;;
|
|---|
| 581 | ;; In XEmacs 19, Emacs 19, and Emacs 20, we use this to bind
|
|---|
| 582 | ;; backwards deletion behavior to DEL, which both Delete and
|
|---|
| 583 | ;; Backspace get translated to. There's no way to separate this
|
|---|
| 584 | ;; behavior in a clean way, so deal with it! Besides, it's been
|
|---|
| 585 | ;; this way since the dawn of time.
|
|---|
| 586 | (if (not (boundp 'delete-key-deletes-forward))
|
|---|
| 587 | (define-key py-mode-map "\177" 'py-electric-backspace)
|
|---|
| 588 | ;; However, XEmacs 20 actually achieved enlightenment. It is
|
|---|
| 589 | ;; possible to sanely define both backward and forward deletion
|
|---|
| 590 | ;; behavior under X separately (TTYs are forever beyond hope, but
|
|---|
| 591 | ;; who cares? XEmacs 20 does the right thing with these too).
|
|---|
| 592 | (define-key py-mode-map [delete] 'py-electric-delete)
|
|---|
| 593 | (define-key py-mode-map [backspace] 'py-electric-backspace))
|
|---|
| 594 | ;; Separate M-BS from C-M-h. The former should remain
|
|---|
| 595 | ;; backward-kill-word.
|
|---|
| 596 | (define-key py-mode-map [(control meta h)] 'py-mark-def-or-class)
|
|---|
| 597 | (define-key py-mode-map "\C-c\C-k" 'py-mark-block)
|
|---|
| 598 | ;; Miscellaneous
|
|---|
| 599 | (define-key py-mode-map "\C-c:" 'py-guess-indent-offset)
|
|---|
| 600 | (define-key py-mode-map "\C-c\t" 'py-indent-region)
|
|---|
| 601 | (define-key py-mode-map "\C-c\C-d" 'py-pdbtrack-toggle-stack-tracking)
|
|---|
| 602 | (define-key py-mode-map "\C-c\C-n" 'py-next-statement)
|
|---|
| 603 | (define-key py-mode-map "\C-c\C-p" 'py-previous-statement)
|
|---|
| 604 | (define-key py-mode-map "\C-c\C-u" 'py-goto-block-up)
|
|---|
| 605 | (define-key py-mode-map "\C-c#" 'py-comment-region)
|
|---|
| 606 | (define-key py-mode-map "\C-c?" 'py-describe-mode)
|
|---|
| 607 | (define-key py-mode-map "\C-c\C-h" 'py-help-at-point)
|
|---|
| 608 | (define-key py-mode-map "\e\C-a" 'py-beginning-of-def-or-class)
|
|---|
| 609 | (define-key py-mode-map "\e\C-e" 'py-end-of-def-or-class)
|
|---|
| 610 | (define-key py-mode-map "\C-c-" 'py-up-exception)
|
|---|
| 611 | (define-key py-mode-map "\C-c=" 'py-down-exception)
|
|---|
| 612 | ;; stuff that is `standard' but doesn't interface well with
|
|---|
| 613 | ;; python-mode, which forces us to rebind to special commands
|
|---|
| 614 | (define-key py-mode-map "\C-xnd" 'py-narrow-to-defun)
|
|---|
| 615 | ;; information
|
|---|
| 616 | (define-key py-mode-map "\C-c\C-b" 'py-submit-bug-report)
|
|---|
| 617 | (define-key py-mode-map "\C-c\C-v" 'py-version)
|
|---|
| 618 | (define-key py-mode-map "\C-c\C-w" 'py-pychecker-run)
|
|---|
| 619 | ;; shadow global bindings for newline-and-indent w/ the py- version.
|
|---|
| 620 | ;; BAW - this is extremely bad form, but I'm not going to change it
|
|---|
| 621 | ;; for now.
|
|---|
| 622 | (mapcar #'(lambda (key)
|
|---|
| 623 | (define-key py-mode-map key 'py-newline-and-indent))
|
|---|
| 624 | (where-is-internal 'newline-and-indent))
|
|---|
| 625 | ;; Force RET to be py-newline-and-indent even if it didn't get
|
|---|
| 626 | ;; mapped by the above code. motivation: Emacs' default binding for
|
|---|
| 627 | ;; RET is `newline' and C-j is `newline-and-indent'. Most Pythoneers
|
|---|
| 628 | ;; expect RET to do a `py-newline-and-indent' and any Emacsers who
|
|---|
| 629 | ;; dislike this are probably knowledgeable enough to do a rebind.
|
|---|
| 630 | ;; However, we do *not* change C-j since many Emacsers have already
|
|---|
| 631 | ;; swapped RET and C-j and they don't want C-j bound to `newline' to
|
|---|
| 632 | ;; change.
|
|---|
| 633 | (define-key py-mode-map "\C-m" 'py-newline-and-indent)
|
|---|
| 634 | )
|
|---|
| 635 |
|
|---|
| 636 | (defvar py-mode-output-map nil
|
|---|
| 637 | "Keymap used in *Python Output* buffers.")
|
|---|
| 638 | (if py-mode-output-map
|
|---|
| 639 | nil
|
|---|
| 640 | (setq py-mode-output-map (make-sparse-keymap))
|
|---|
| 641 | (define-key py-mode-output-map [button2] 'py-mouseto-exception)
|
|---|
| 642 | (define-key py-mode-output-map "\C-c\C-c" 'py-goto-exception)
|
|---|
| 643 | ;; TBD: Disable all self-inserting keys. This is bogus, we should
|
|---|
| 644 | ;; really implement this as *Python Output* buffer being read-only
|
|---|
| 645 | (mapcar #' (lambda (key)
|
|---|
| 646 | (define-key py-mode-output-map key
|
|---|
| 647 | #'(lambda () (interactive) (beep))))
|
|---|
| 648 | (where-is-internal 'self-insert-command))
|
|---|
| 649 | )
|
|---|
| 650 |
|
|---|
| 651 | (defvar py-shell-map nil
|
|---|
| 652 | "Keymap used in *Python* shell buffers.")
|
|---|
| 653 | (if py-shell-map
|
|---|
| 654 | nil
|
|---|
| 655 | (setq py-shell-map (copy-keymap comint-mode-map))
|
|---|
| 656 | (define-key py-shell-map [tab] 'tab-to-tab-stop)
|
|---|
| 657 | (define-key py-shell-map "\C-c-" 'py-up-exception)
|
|---|
| 658 | (define-key py-shell-map "\C-c=" 'py-down-exception)
|
|---|
| 659 | )
|
|---|
| 660 |
|
|---|
| 661 | (defvar py-mode-syntax-table nil
|
|---|
| 662 | "Syntax table used in `python-mode' buffers.")
|
|---|
| 663 | (when (not py-mode-syntax-table)
|
|---|
| 664 | (setq py-mode-syntax-table (make-syntax-table))
|
|---|
| 665 | (modify-syntax-entry ?\( "()" py-mode-syntax-table)
|
|---|
| 666 | (modify-syntax-entry ?\) ")(" py-mode-syntax-table)
|
|---|
| 667 | (modify-syntax-entry ?\[ "(]" py-mode-syntax-table)
|
|---|
| 668 | (modify-syntax-entry ?\] ")[" py-mode-syntax-table)
|
|---|
| 669 | (modify-syntax-entry ?\{ "(}" py-mode-syntax-table)
|
|---|
| 670 | (modify-syntax-entry ?\} "){" py-mode-syntax-table)
|
|---|
| 671 | ;; Add operator symbols misassigned in the std table
|
|---|
| 672 | (modify-syntax-entry ?\$ "." py-mode-syntax-table)
|
|---|
| 673 | (modify-syntax-entry ?\% "." py-mode-syntax-table)
|
|---|
| 674 | (modify-syntax-entry ?\& "." py-mode-syntax-table)
|
|---|
| 675 | (modify-syntax-entry ?\* "." py-mode-syntax-table)
|
|---|
| 676 | (modify-syntax-entry ?\+ "." py-mode-syntax-table)
|
|---|
| 677 | (modify-syntax-entry ?\- "." py-mode-syntax-table)
|
|---|
| 678 | (modify-syntax-entry ?\/ "." py-mode-syntax-table)
|
|---|
| 679 | (modify-syntax-entry ?\< "." py-mode-syntax-table)
|
|---|
| 680 | (modify-syntax-entry ?\= "." py-mode-syntax-table)
|
|---|
| 681 | (modify-syntax-entry ?\> "." py-mode-syntax-table)
|
|---|
| 682 | (modify-syntax-entry ?\| "." py-mode-syntax-table)
|
|---|
| 683 | ;; For historical reasons, underscore is word class instead of
|
|---|
| 684 | ;; symbol class. GNU conventions say it should be symbol class, but
|
|---|
| 685 | ;; there's a natural conflict between what major mode authors want
|
|---|
| 686 | ;; and what users expect from `forward-word' and `backward-word'.
|
|---|
| 687 | ;; Guido and I have hashed this out and have decided to keep
|
|---|
| 688 | ;; underscore in word class. If you're tempted to change it, try
|
|---|
| 689 | ;; binding M-f and M-b to py-forward-into-nomenclature and
|
|---|
| 690 | ;; py-backward-into-nomenclature instead. This doesn't help in all
|
|---|
| 691 | ;; situations where you'd want the different behavior
|
|---|
| 692 | ;; (e.g. backward-kill-word).
|
|---|
| 693 | (modify-syntax-entry ?\_ "w" py-mode-syntax-table)
|
|---|
| 694 | ;; Both single quote and double quote are string delimiters
|
|---|
| 695 | (modify-syntax-entry ?\' "\"" py-mode-syntax-table)
|
|---|
| 696 | (modify-syntax-entry ?\" "\"" py-mode-syntax-table)
|
|---|
| 697 | ;; backquote is open and close paren
|
|---|
| 698 | (modify-syntax-entry ?\` "$" py-mode-syntax-table)
|
|---|
| 699 | ;; comment delimiters
|
|---|
| 700 | (modify-syntax-entry ?\# "<" py-mode-syntax-table)
|
|---|
| 701 | (modify-syntax-entry ?\n ">" py-mode-syntax-table)
|
|---|
| 702 | )
|
|---|
| 703 |
|
|---|
| 704 | ;; An auxiliary syntax table which places underscore and dot in the
|
|---|
| 705 | ;; symbol class for simplicity
|
|---|
| 706 | (defvar py-dotted-expression-syntax-table nil
|
|---|
| 707 | "Syntax table used to identify Python dotted expressions.")
|
|---|
| 708 | (when (not py-dotted-expression-syntax-table)
|
|---|
| 709 | (setq py-dotted-expression-syntax-table
|
|---|
| 710 | (copy-syntax-table py-mode-syntax-table))
|
|---|
| 711 | (modify-syntax-entry ?_ "_" py-dotted-expression-syntax-table)
|
|---|
| 712 | (modify-syntax-entry ?. "_" py-dotted-expression-syntax-table))
|
|---|
| 713 |
|
|---|
| 714 |
|
|---|
| 715 | |
|---|
| 716 |
|
|---|
| 717 | ;; Utilities
|
|---|
| 718 | (defmacro py-safe (&rest body)
|
|---|
| 719 | "Safely execute BODY, return nil if an error occurred."
|
|---|
| 720 | (` (condition-case nil
|
|---|
| 721 | (progn (,@ body))
|
|---|
| 722 | (error nil))))
|
|---|
| 723 |
|
|---|
| 724 | (defsubst py-keep-region-active ()
|
|---|
| 725 | "Keep the region active in XEmacs."
|
|---|
| 726 | ;; Ignore byte-compiler warnings you might see. Also note that
|
|---|
| 727 | ;; FSF's Emacs 19 does it differently; its policy doesn't require us
|
|---|
| 728 | ;; to take explicit action.
|
|---|
| 729 | (and (boundp 'zmacs-region-stays)
|
|---|
| 730 | (setq zmacs-region-stays t)))
|
|---|
| 731 |
|
|---|
| 732 | (defsubst py-point (position)
|
|---|
| 733 | "Returns the value of point at certain commonly referenced POSITIONs.
|
|---|
| 734 | POSITION can be one of the following symbols:
|
|---|
| 735 |
|
|---|
| 736 | bol -- beginning of line
|
|---|
| 737 | eol -- end of line
|
|---|
| 738 | bod -- beginning of def or class
|
|---|
| 739 | eod -- end of def or class
|
|---|
| 740 | bob -- beginning of buffer
|
|---|
| 741 | eob -- end of buffer
|
|---|
| 742 | boi -- back to indentation
|
|---|
| 743 | bos -- beginning of statement
|
|---|
| 744 |
|
|---|
| 745 | This function does not modify point or mark."
|
|---|
| 746 | (let ((here (point)))
|
|---|
| 747 | (cond
|
|---|
| 748 | ((eq position 'bol) (beginning-of-line))
|
|---|
| 749 | ((eq position 'eol) (end-of-line))
|
|---|
| 750 | ((eq position 'bod) (py-beginning-of-def-or-class))
|
|---|
| 751 | ((eq position 'eod) (py-end-of-def-or-class))
|
|---|
| 752 | ;; Kind of funny, I know, but useful for py-up-exception.
|
|---|
| 753 | ((eq position 'bob) (beginning-of-buffer))
|
|---|
| 754 | ((eq position 'eob) (end-of-buffer))
|
|---|
| 755 | ((eq position 'boi) (back-to-indentation))
|
|---|
| 756 | ((eq position 'bos) (py-goto-initial-line))
|
|---|
| 757 | (t (error "Unknown buffer position requested: %s" position))
|
|---|
| 758 | )
|
|---|
| 759 | (prog1
|
|---|
| 760 | (point)
|
|---|
| 761 | (goto-char here))))
|
|---|
| 762 |
|
|---|
| 763 | (defsubst py-highlight-line (from to file line)
|
|---|
| 764 | (cond
|
|---|
| 765 | ((fboundp 'make-extent)
|
|---|
| 766 | ;; XEmacs
|
|---|
| 767 | (let ((e (make-extent from to)))
|
|---|
| 768 | (set-extent-property e 'mouse-face 'highlight)
|
|---|
| 769 | (set-extent-property e 'py-exc-info (cons file line))
|
|---|
| 770 | (set-extent-property e 'keymap py-mode-output-map)))
|
|---|
| 771 | (t
|
|---|
| 772 | ;; Emacs -- Please port this!
|
|---|
| 773 | )
|
|---|
| 774 | ))
|
|---|
| 775 |
|
|---|
| 776 | (defun py-in-literal (&optional lim)
|
|---|
| 777 | "Return non-nil if point is in a Python literal (a comment or string).
|
|---|
| 778 | Optional argument LIM indicates the beginning of the containing form,
|
|---|
| 779 | i.e. the limit on how far back to scan."
|
|---|
| 780 | ;; This is the version used for non-XEmacs, which has a nicer
|
|---|
| 781 | ;; interface.
|
|---|
| 782 | ;;
|
|---|
| 783 | ;; WARNING: Watch out for infinite recursion.
|
|---|
| 784 | (let* ((lim (or lim (py-point 'bod)))
|
|---|
| 785 | (state (parse-partial-sexp lim (point))))
|
|---|
| 786 | (cond
|
|---|
| 787 | ((nth 3 state) 'string)
|
|---|
| 788 | ((nth 4 state) 'comment)
|
|---|
| 789 | (t nil))))
|
|---|
| 790 |
|
|---|
| 791 | ;; XEmacs has a built-in function that should make this much quicker.
|
|---|
| 792 | ;; In this case, lim is ignored
|
|---|
| 793 | (defun py-fast-in-literal (&optional lim)
|
|---|
| 794 | "Fast version of `py-in-literal', used only by XEmacs.
|
|---|
| 795 | Optional LIM is ignored."
|
|---|
| 796 | ;; don't have to worry about context == 'block-comment
|
|---|
| 797 | (buffer-syntactic-context))
|
|---|
| 798 |
|
|---|
| 799 | (if (fboundp 'buffer-syntactic-context)
|
|---|
| 800 | (defalias 'py-in-literal 'py-fast-in-literal))
|
|---|
| 801 |
|
|---|
| 802 |
|
|---|
| 803 | |
|---|
| 804 |
|
|---|
| 805 | ;; Menu definitions, only relevent if you have the easymenu.el package
|
|---|
| 806 | ;; (standard in the latest Emacs 19 and XEmacs 19 distributions).
|
|---|
| 807 | (defvar py-menu nil
|
|---|
| 808 | "Menu for Python Mode.
|
|---|
| 809 | This menu will get created automatically if you have the `easymenu'
|
|---|
| 810 | package. Note that the latest X/Emacs releases contain this package.")
|
|---|
| 811 |
|
|---|
| 812 | (and (py-safe (require 'easymenu) t)
|
|---|
| 813 | (easy-menu-define
|
|---|
| 814 | py-menu py-mode-map "Python Mode menu"
|
|---|
| 815 | '("Python"
|
|---|
| 816 | ["Comment Out Region" py-comment-region (mark)]
|
|---|
| 817 | ["Uncomment Region" (py-comment-region (point) (mark) '(4)) (mark)]
|
|---|
| 818 | "-"
|
|---|
| 819 | ["Mark current block" py-mark-block t]
|
|---|
| 820 | ["Mark current def" py-mark-def-or-class t]
|
|---|
| 821 | ["Mark current class" (py-mark-def-or-class t) t]
|
|---|
| 822 | "-"
|
|---|
| 823 | ["Shift region left" py-shift-region-left (mark)]
|
|---|
| 824 | ["Shift region right" py-shift-region-right (mark)]
|
|---|
| 825 | "-"
|
|---|
| 826 | ["Import/reload file" py-execute-import-or-reload t]
|
|---|
| 827 | ["Execute buffer" py-execute-buffer t]
|
|---|
| 828 | ["Execute region" py-execute-region (mark)]
|
|---|
| 829 | ["Execute def or class" py-execute-def-or-class (mark)]
|
|---|
| 830 | ["Execute string" py-execute-string t]
|
|---|
| 831 | ["Start interpreter..." py-shell t]
|
|---|
| 832 | "-"
|
|---|
| 833 | ["Go to start of block" py-goto-block-up t]
|
|---|
| 834 | ["Go to start of class" (py-beginning-of-def-or-class t) t]
|
|---|
| 835 | ["Move to end of class" (py-end-of-def-or-class t) t]
|
|---|
| 836 | ["Move to start of def" py-beginning-of-def-or-class t]
|
|---|
| 837 | ["Move to end of def" py-end-of-def-or-class t]
|
|---|
| 838 | "-"
|
|---|
| 839 | ["Describe mode" py-describe-mode t]
|
|---|
| 840 | )))
|
|---|
| 841 |
|
|---|
| 842 |
|
|---|
| 843 | |
|---|
| 844 |
|
|---|
| 845 | ;; Imenu definitions
|
|---|
| 846 | (defvar py-imenu-class-regexp
|
|---|
| 847 | (concat ; <<classes>>
|
|---|
| 848 | "\\(" ;
|
|---|
| 849 | "^[ \t]*" ; newline and maybe whitespace
|
|---|
| 850 | "\\(class[ \t]+[a-zA-Z0-9_]+\\)" ; class name
|
|---|
| 851 | ; possibly multiple superclasses
|
|---|
| 852 | "\\([ \t]*\\((\\([a-zA-Z0-9_,. \t\n]\\)*)\\)?\\)"
|
|---|
| 853 | "[ \t]*:" ; and the final :
|
|---|
| 854 | "\\)" ; >>classes<<
|
|---|
| 855 | )
|
|---|
| 856 | "Regexp for Python classes for use with the Imenu package."
|
|---|
| 857 | )
|
|---|
| 858 |
|
|---|
| 859 | (defvar py-imenu-method-regexp
|
|---|
| 860 | (concat ; <<methods and functions>>
|
|---|
| 861 | "\\(" ;
|
|---|
| 862 | "^[ \t]*" ; new line and maybe whitespace
|
|---|
| 863 | "\\(def[ \t]+" ; function definitions start with def
|
|---|
| 864 | "\\([a-zA-Z0-9_]+\\)" ; name is here
|
|---|
| 865 | ; function arguments...
|
|---|
| 866 | ;; "[ \t]*(\\([-+/a-zA-Z0-9_=,\* \t\n.()\"'#]*\\))"
|
|---|
| 867 | "[ \t]*(\\([^:#]*\\))"
|
|---|
| 868 | "\\)" ; end of def
|
|---|
| 869 | "[ \t]*:" ; and then the :
|
|---|
| 870 | "\\)" ; >>methods and functions<<
|
|---|
| 871 | )
|
|---|
| 872 | "Regexp for Python methods/functions for use with the Imenu package."
|
|---|
| 873 | )
|
|---|
| 874 |
|
|---|
| 875 | (defvar py-imenu-method-no-arg-parens '(2 8)
|
|---|
| 876 | "Indices into groups of the Python regexp for use with Imenu.
|
|---|
| 877 |
|
|---|
| 878 | Using these values will result in smaller Imenu lists, as arguments to
|
|---|
| 879 | functions are not listed.
|
|---|
| 880 |
|
|---|
| 881 | See the variable `py-imenu-show-method-args-p' for more
|
|---|
| 882 | information.")
|
|---|
| 883 |
|
|---|
| 884 | (defvar py-imenu-method-arg-parens '(2 7)
|
|---|
| 885 | "Indices into groups of the Python regexp for use with imenu.
|
|---|
| 886 | Using these values will result in large Imenu lists, as arguments to
|
|---|
| 887 | functions are listed.
|
|---|
| 888 |
|
|---|
| 889 | See the variable `py-imenu-show-method-args-p' for more
|
|---|
| 890 | information.")
|
|---|
| 891 |
|
|---|
| 892 | ;; Note that in this format, this variable can still be used with the
|
|---|
| 893 | ;; imenu--generic-function. Otherwise, there is no real reason to have
|
|---|
| 894 | ;; it.
|
|---|
| 895 | (defvar py-imenu-generic-expression
|
|---|
| 896 | (cons
|
|---|
| 897 | (concat
|
|---|
| 898 | py-imenu-class-regexp
|
|---|
| 899 | "\\|" ; or...
|
|---|
| 900 | py-imenu-method-regexp
|
|---|
| 901 | )
|
|---|
| 902 | py-imenu-method-no-arg-parens)
|
|---|
| 903 | "Generic Python expression which may be used directly with Imenu.
|
|---|
| 904 | Used by setting the variable `imenu-generic-expression' to this value.
|
|---|
| 905 | Also, see the function \\[py-imenu-create-index] for a better
|
|---|
| 906 | alternative for finding the index.")
|
|---|
| 907 |
|
|---|
| 908 | ;; These next two variables are used when searching for the Python
|
|---|
| 909 | ;; class/definitions. Just saving some time in accessing the
|
|---|
| 910 | ;; generic-python-expression, really.
|
|---|
| 911 | (defvar py-imenu-generic-regexp nil)
|
|---|
| 912 | (defvar py-imenu-generic-parens nil)
|
|---|
| 913 |
|
|---|
| 914 |
|
|---|
| 915 | (defun py-imenu-create-index-function ()
|
|---|
| 916 | "Python interface function for the Imenu package.
|
|---|
| 917 | Finds all Python classes and functions/methods. Calls function
|
|---|
| 918 | \\[py-imenu-create-index-engine]. See that function for the details
|
|---|
| 919 | of how this works."
|
|---|
| 920 | (setq py-imenu-generic-regexp (car py-imenu-generic-expression)
|
|---|
| 921 | py-imenu-generic-parens (if py-imenu-show-method-args-p
|
|---|
| 922 | py-imenu-method-arg-parens
|
|---|
| 923 | py-imenu-method-no-arg-parens))
|
|---|
| 924 | (goto-char (point-min))
|
|---|
| 925 | ;; Warning: When the buffer has no classes or functions, this will
|
|---|
| 926 | ;; return nil, which seems proper according to the Imenu API, but
|
|---|
| 927 | ;; causes an error in the XEmacs port of Imenu. Sigh.
|
|---|
| 928 | (py-imenu-create-index-engine nil))
|
|---|
| 929 |
|
|---|
| 930 | (defun py-imenu-create-index-engine (&optional start-indent)
|
|---|
| 931 | "Function for finding Imenu definitions in Python.
|
|---|
| 932 |
|
|---|
| 933 | Finds all definitions (classes, methods, or functions) in a Python
|
|---|
| 934 | file for the Imenu package.
|
|---|
| 935 |
|
|---|
| 936 | Returns a possibly nested alist of the form
|
|---|
| 937 |
|
|---|
| 938 | (INDEX-NAME . INDEX-POSITION)
|
|---|
| 939 |
|
|---|
| 940 | The second element of the alist may be an alist, producing a nested
|
|---|
| 941 | list as in
|
|---|
| 942 |
|
|---|
| 943 | (INDEX-NAME . INDEX-ALIST)
|
|---|
| 944 |
|
|---|
| 945 | This function should not be called directly, as it calls itself
|
|---|
| 946 | recursively and requires some setup. Rather this is the engine for
|
|---|
| 947 | the function \\[py-imenu-create-index-function].
|
|---|
| 948 |
|
|---|
| 949 | It works recursively by looking for all definitions at the current
|
|---|
| 950 | indention level. When it finds one, it adds it to the alist. If it
|
|---|
| 951 | finds a definition at a greater indentation level, it removes the
|
|---|
| 952 | previous definition from the alist. In its place it adds all
|
|---|
| 953 | definitions found at the next indentation level. When it finds a
|
|---|
| 954 | definition that is less indented then the current level, it returns
|
|---|
| 955 | the alist it has created thus far.
|
|---|
| 956 |
|
|---|
| 957 | The optional argument START-INDENT indicates the starting indentation
|
|---|
| 958 | at which to continue looking for Python classes, methods, or
|
|---|
| 959 | functions. If this is not supplied, the function uses the indentation
|
|---|
| 960 | of the first definition found."
|
|---|
| 961 | (let (index-alist
|
|---|
| 962 | sub-method-alist
|
|---|
| 963 | looking-p
|
|---|
| 964 | def-name prev-name
|
|---|
| 965 | cur-indent def-pos
|
|---|
| 966 | (class-paren (first py-imenu-generic-parens))
|
|---|
| 967 | (def-paren (second py-imenu-generic-parens)))
|
|---|
| 968 | (setq looking-p
|
|---|
| 969 | (re-search-forward py-imenu-generic-regexp (point-max) t))
|
|---|
| 970 | (while looking-p
|
|---|
| 971 | (save-excursion
|
|---|
| 972 | ;; used to set def-name to this value but generic-extract-name
|
|---|
| 973 | ;; is new to imenu-1.14. this way it still works with
|
|---|
| 974 | ;; imenu-1.11
|
|---|
| 975 | ;;(imenu--generic-extract-name py-imenu-generic-parens))
|
|---|
| 976 | (let ((cur-paren (if (match-beginning class-paren)
|
|---|
| 977 | class-paren def-paren)))
|
|---|
| 978 | (setq def-name
|
|---|
| 979 | (buffer-substring-no-properties (match-beginning cur-paren)
|
|---|
| 980 | (match-end cur-paren))))
|
|---|
| 981 | (save-match-data
|
|---|
| 982 | (py-beginning-of-def-or-class 'either))
|
|---|
| 983 | (beginning-of-line)
|
|---|
| 984 | (setq cur-indent (current-indentation)))
|
|---|
| 985 | ;; HACK: want to go to the next correct definition location. We
|
|---|
| 986 | ;; explicitly list them here but it would be better to have them
|
|---|
| 987 | ;; in a list.
|
|---|
| 988 | (setq def-pos
|
|---|
| 989 | (or (match-beginning class-paren)
|
|---|
| 990 | (match-beginning def-paren)))
|
|---|
| 991 | ;; if we don't have a starting indent level, take this one
|
|---|
| 992 | (or start-indent
|
|---|
| 993 | (setq start-indent cur-indent))
|
|---|
| 994 | ;; if we don't have class name yet, take this one
|
|---|
| 995 | (or prev-name
|
|---|
| 996 | (setq prev-name def-name))
|
|---|
| 997 | ;; what level is the next definition on? must be same, deeper
|
|---|
| 998 | ;; or shallower indentation
|
|---|
| 999 | (cond
|
|---|
| 1000 | ;; Skip code in comments and strings
|
|---|
| 1001 | ((py-in-literal))
|
|---|
| 1002 | ;; at the same indent level, add it to the list...
|
|---|
| 1003 | ((= start-indent cur-indent)
|
|---|
| 1004 | (push (cons def-name def-pos) index-alist))
|
|---|
| 1005 | ;; deeper indented expression, recurse
|
|---|
| 1006 | ((< start-indent cur-indent)
|
|---|
| 1007 | ;; the point is currently on the expression we're supposed to
|
|---|
| 1008 | ;; start on, so go back to the last expression. The recursive
|
|---|
| 1009 | ;; call will find this place again and add it to the correct
|
|---|
| 1010 | ;; list
|
|---|
| 1011 | (re-search-backward py-imenu-generic-regexp (point-min) 'move)
|
|---|
| 1012 | (setq sub-method-alist (py-imenu-create-index-engine cur-indent))
|
|---|
| 1013 | (if sub-method-alist
|
|---|
| 1014 | ;; we put the last element on the index-alist on the start
|
|---|
| 1015 | ;; of the submethod alist so the user can still get to it.
|
|---|
| 1016 | (let ((save-elmt (pop index-alist)))
|
|---|
| 1017 | (push (cons prev-name
|
|---|
| 1018 | (cons save-elmt sub-method-alist))
|
|---|
| 1019 | index-alist))))
|
|---|
| 1020 | ;; found less indented expression, we're done.
|
|---|
| 1021 | (t
|
|---|
| 1022 | (setq looking-p nil)
|
|---|
| 1023 | (re-search-backward py-imenu-generic-regexp (point-min) t)))
|
|---|
| 1024 | ;; end-cond
|
|---|
| 1025 | (setq prev-name def-name)
|
|---|
| 1026 | (and looking-p
|
|---|
| 1027 | (setq looking-p
|
|---|
| 1028 | (re-search-forward py-imenu-generic-regexp
|
|---|
| 1029 | (point-max) 'move))))
|
|---|
| 1030 | (nreverse index-alist)))
|
|---|
| 1031 |
|
|---|
| 1032 |
|
|---|
| 1033 | |
|---|
| 1034 |
|
|---|
| 1035 | (defun py-choose-shell-by-shebang ()
|
|---|
| 1036 | "Choose CPython or JPython mode by looking at #! on the first line.
|
|---|
| 1037 | Returns the appropriate mode function.
|
|---|
| 1038 | Used by `py-choose-shell', and similar to but distinct from
|
|---|
| 1039 | `set-auto-mode', though it uses `auto-mode-interpreter-regexp' (if available)."
|
|---|
| 1040 | ;; look for an interpreter specified in the first line
|
|---|
| 1041 | ;; similar to set-auto-mode (files.el)
|
|---|
| 1042 | (let* ((re (if (boundp 'auto-mode-interpreter-regexp)
|
|---|
| 1043 | auto-mode-interpreter-regexp
|
|---|
| 1044 | ;; stolen from Emacs 21.2
|
|---|
| 1045 | "#![ \t]?\\([^ \t\n]*/bin/env[ \t]\\)?\\([^ \t\n]+\\)"))
|
|---|
| 1046 | (interpreter (save-excursion
|
|---|
| 1047 | (goto-char (point-min))
|
|---|
| 1048 | (if (looking-at re)
|
|---|
| 1049 | (match-string 2)
|
|---|
| 1050 | "")))
|
|---|
| 1051 | elt)
|
|---|
| 1052 | ;; Map interpreter name to a mode.
|
|---|
| 1053 | (setq elt (assoc (file-name-nondirectory interpreter)
|
|---|
| 1054 | py-shell-alist))
|
|---|
| 1055 | (and elt (caddr elt))))
|
|---|
| 1056 |
|
|---|
| 1057 |
|
|---|
| 1058 | |
|---|
| 1059 |
|
|---|
| 1060 | (defun py-choose-shell-by-import ()
|
|---|
| 1061 | "Choose CPython or JPython mode based imports.
|
|---|
| 1062 | If a file imports any packages in `py-jpython-packages', within
|
|---|
| 1063 | `py-import-check-point-max' characters from the start of the file,
|
|---|
| 1064 | return `jpython', otherwise return nil."
|
|---|
| 1065 | (let (mode)
|
|---|
| 1066 | (save-excursion
|
|---|
| 1067 | (goto-char (point-min))
|
|---|
| 1068 | (while (and (not mode)
|
|---|
| 1069 | (search-forward-regexp
|
|---|
| 1070 | "^\\(\\(from\\)\\|\\(import\\)\\) \\([^ \t\n.]+\\)"
|
|---|
| 1071 | py-import-check-point-max t))
|
|---|
| 1072 | (setq mode (and (member (match-string 4) py-jpython-packages)
|
|---|
| 1073 | 'jpython
|
|---|
| 1074 | ))))
|
|---|
| 1075 | mode))
|
|---|
| 1076 |
|
|---|
| 1077 | |
|---|
| 1078 |
|
|---|
| 1079 | (defun py-choose-shell ()
|
|---|
| 1080 | "Choose CPython or JPython mode. Returns the appropriate mode function.
|
|---|
| 1081 | This does the following:
|
|---|
| 1082 | - look for an interpreter with `py-choose-shell-by-shebang'
|
|---|
| 1083 | - examine imports using `py-choose-shell-by-import'
|
|---|
| 1084 | - default to the variable `py-default-interpreter'"
|
|---|
| 1085 | (interactive)
|
|---|
| 1086 | (or (py-choose-shell-by-shebang)
|
|---|
| 1087 | (py-choose-shell-by-import)
|
|---|
| 1088 | py-default-interpreter
|
|---|
| 1089 | ; 'cpython ;; don't use to py-default-interpreter, because default
|
|---|
| 1090 | ; ;; is only way to choose CPython
|
|---|
| 1091 | ))
|
|---|
| 1092 |
|
|---|
| 1093 | |
|---|
| 1094 |
|
|---|
| 1095 | ;;;###autoload
|
|---|
| 1096 | (defun python-mode ()
|
|---|
| 1097 | "Major mode for editing Python files.
|
|---|
| 1098 | To submit a problem report, enter `\\[py-submit-bug-report]' from a
|
|---|
| 1099 | `python-mode' buffer. Do `\\[py-describe-mode]' for detailed
|
|---|
| 1100 | documentation. To see what version of `python-mode' you are running,
|
|---|
| 1101 | enter `\\[py-version]'.
|
|---|
| 1102 |
|
|---|
| 1103 | This mode knows about Python indentation, tokens, comments and
|
|---|
| 1104 | continuation lines. Paragraphs are separated by blank lines only.
|
|---|
| 1105 |
|
|---|
| 1106 | COMMANDS
|
|---|
| 1107 | \\{py-mode-map}
|
|---|
| 1108 | VARIABLES
|
|---|
| 1109 |
|
|---|
| 1110 | py-indent-offset\t\tindentation increment
|
|---|
| 1111 | py-block-comment-prefix\t\tcomment string used by `comment-region'
|
|---|
| 1112 | py-python-command\t\tshell command to invoke Python interpreter
|
|---|
| 1113 | py-temp-directory\t\tdirectory used for temp files (if needed)
|
|---|
| 1114 | py-beep-if-tab-change\t\tring the bell if `tab-width' is changed"
|
|---|
| 1115 | (interactive)
|
|---|
| 1116 | ;; set up local variables
|
|---|
| 1117 | (kill-all-local-variables)
|
|---|
| 1118 | (make-local-variable 'font-lock-defaults)
|
|---|
| 1119 | (make-local-variable 'paragraph-separate)
|
|---|
| 1120 | (make-local-variable 'paragraph-start)
|
|---|
| 1121 | (make-local-variable 'require-final-newline)
|
|---|
| 1122 | (make-local-variable 'comment-start)
|
|---|
| 1123 | (make-local-variable 'comment-end)
|
|---|
| 1124 | (make-local-variable 'comment-start-skip)
|
|---|
| 1125 | (make-local-variable 'comment-column)
|
|---|
| 1126 | (make-local-variable 'comment-indent-function)
|
|---|
| 1127 | (make-local-variable 'indent-region-function)
|
|---|
| 1128 | (make-local-variable 'indent-line-function)
|
|---|
| 1129 | (make-local-variable 'add-log-current-defun-function)
|
|---|
| 1130 | ;;
|
|---|
| 1131 | (set-syntax-table py-mode-syntax-table)
|
|---|
| 1132 | (setq major-mode 'python-mode
|
|---|
| 1133 | mode-name "Python"
|
|---|
| 1134 | local-abbrev-table python-mode-abbrev-table
|
|---|
| 1135 | font-lock-defaults '(python-font-lock-keywords)
|
|---|
| 1136 | paragraph-separate "^[ \t]*$"
|
|---|
| 1137 | paragraph-start "^[ \t]*$"
|
|---|
| 1138 | require-final-newline t
|
|---|
| 1139 | comment-start "# "
|
|---|
| 1140 | comment-end ""
|
|---|
| 1141 | comment-start-skip "# *"
|
|---|
| 1142 | comment-column 40
|
|---|
| 1143 | comment-indent-function 'py-comment-indent-function
|
|---|
| 1144 | indent-region-function 'py-indent-region
|
|---|
| 1145 | indent-line-function 'py-indent-line
|
|---|
| 1146 | ;; tell add-log.el how to find the current function/method/variable
|
|---|
| 1147 | add-log-current-defun-function 'py-current-defun
|
|---|
| 1148 | )
|
|---|
| 1149 | (use-local-map py-mode-map)
|
|---|
| 1150 | ;; add the menu
|
|---|
| 1151 | (if py-menu
|
|---|
| 1152 | (easy-menu-add py-menu))
|
|---|
| 1153 | ;; Emacs 19 requires this
|
|---|
| 1154 | (if (boundp 'comment-multi-line)
|
|---|
| 1155 | (setq comment-multi-line nil))
|
|---|
| 1156 | ;; Install Imenu if available
|
|---|
| 1157 | (when (py-safe (require 'imenu))
|
|---|
| 1158 | (setq imenu-create-index-function #'py-imenu-create-index-function)
|
|---|
| 1159 | (setq imenu-generic-expression py-imenu-generic-expression)
|
|---|
| 1160 | (if (fboundp 'imenu-add-to-menubar)
|
|---|
| 1161 | (imenu-add-to-menubar (format "%s-%s" "IM" mode-name)))
|
|---|
| 1162 | )
|
|---|
| 1163 | ;; Run the mode hook. Note that py-mode-hook is deprecated.
|
|---|
| 1164 | (if python-mode-hook
|
|---|
| 1165 | (run-hooks 'python-mode-hook)
|
|---|
| 1166 | (run-hooks 'py-mode-hook))
|
|---|
| 1167 | ;; Now do the automagical guessing
|
|---|
| 1168 | (if py-smart-indentation
|
|---|
| 1169 | (let ((offset py-indent-offset))
|
|---|
| 1170 | ;; It's okay if this fails to guess a good value
|
|---|
| 1171 | (if (and (py-safe (py-guess-indent-offset))
|
|---|
| 1172 | (<= py-indent-offset 8)
|
|---|
| 1173 | (>= py-indent-offset 2))
|
|---|
| 1174 | (setq offset py-indent-offset))
|
|---|
| 1175 | (setq py-indent-offset offset)
|
|---|
| 1176 | ;; Only turn indent-tabs-mode off if tab-width !=
|
|---|
| 1177 | ;; py-indent-offset. Never turn it on, because the user must
|
|---|
| 1178 | ;; have explicitly turned it off.
|
|---|
| 1179 | (if (/= tab-width py-indent-offset)
|
|---|
| 1180 | (setq indent-tabs-mode nil))
|
|---|
| 1181 | ))
|
|---|
| 1182 | ;; Set the default shell if not already set
|
|---|
| 1183 | (when (null py-which-shell)
|
|---|
| 1184 | (py-toggle-shells (py-choose-shell))))
|
|---|
| 1185 |
|
|---|
| 1186 |
|
|---|
| 1187 | (defun jpython-mode ()
|
|---|
| 1188 | "Major mode for editing JPython/Jython files.
|
|---|
| 1189 | This is a simple wrapper around `python-mode'.
|
|---|
| 1190 | It runs `jpython-mode-hook' then calls `python-mode.'
|
|---|
| 1191 | It is added to `interpreter-mode-alist' and `py-choose-shell'.
|
|---|
| 1192 | "
|
|---|
| 1193 | (interactive)
|
|---|
| 1194 | (python-mode)
|
|---|
| 1195 | (py-toggle-shells 'jpython)
|
|---|
| 1196 | (when jpython-mode-hook
|
|---|
| 1197 | (run-hooks 'jpython-mode-hook)))
|
|---|
| 1198 |
|
|---|
| 1199 |
|
|---|
| 1200 | ;; It's handy to add recognition of Python files to the
|
|---|
| 1201 | ;; interpreter-mode-alist and to auto-mode-alist. With the former, we
|
|---|
| 1202 | ;; can specify different `derived-modes' based on the #! line, but
|
|---|
| 1203 | ;; with the latter, we can't. So we just won't add them if they're
|
|---|
| 1204 | ;; already added.
|
|---|
| 1205 | (let ((modes '(("jpython" . jpython-mode)
|
|---|
| 1206 | ("jython" . jpython-mode)
|
|---|
| 1207 | ("python" . python-mode))))
|
|---|
| 1208 | (while modes
|
|---|
| 1209 | (when (not (assoc (car modes) interpreter-mode-alist))
|
|---|
| 1210 | (push (car modes) interpreter-mode-alist))
|
|---|
| 1211 | (setq modes (cdr modes))))
|
|---|
| 1212 |
|
|---|
| 1213 | (when (not (or (rassq 'python-mode auto-mode-alist)
|
|---|
| 1214 | (rassq 'jpython-mode auto-mode-alist)))
|
|---|
| 1215 | (push '("\\.py$" . python-mode) auto-mode-alist))
|
|---|
| 1216 |
|
|---|
| 1217 |
|
|---|
| 1218 | |
|---|
| 1219 |
|
|---|
| 1220 | ;; electric characters
|
|---|
| 1221 | (defun py-outdent-p ()
|
|---|
| 1222 | "Returns non-nil if the current line should dedent one level."
|
|---|
| 1223 | (save-excursion
|
|---|
| 1224 | (and (progn (back-to-indentation)
|
|---|
| 1225 | (looking-at py-outdent-re))
|
|---|
| 1226 | ;; short circuit infloop on illegal construct
|
|---|
| 1227 | (not (bobp))
|
|---|
| 1228 | (progn (forward-line -1)
|
|---|
| 1229 | (py-goto-initial-line)
|
|---|
| 1230 | (back-to-indentation)
|
|---|
| 1231 | (while (or (looking-at py-blank-or-comment-re)
|
|---|
| 1232 | (bobp))
|
|---|
| 1233 | (backward-to-indentation 1))
|
|---|
| 1234 | (not (looking-at py-no-outdent-re)))
|
|---|
| 1235 | )))
|
|---|
| 1236 |
|
|---|
| 1237 | (defun py-electric-colon (arg)
|
|---|
| 1238 | "Insert a colon.
|
|---|
| 1239 | In certain cases the line is dedented appropriately. If a numeric
|
|---|
| 1240 | argument ARG is provided, that many colons are inserted
|
|---|
| 1241 | non-electrically. Electric behavior is inhibited inside a string or
|
|---|
| 1242 | comment."
|
|---|
| 1243 | (interactive "*P")
|
|---|
| 1244 | (self-insert-command (prefix-numeric-value arg))
|
|---|
| 1245 | ;; are we in a string or comment?
|
|---|
| 1246 | (if (save-excursion
|
|---|
| 1247 | (let ((pps (parse-partial-sexp (save-excursion
|
|---|
| 1248 | (py-beginning-of-def-or-class)
|
|---|
| 1249 | (point))
|
|---|
| 1250 | (point))))
|
|---|
| 1251 | (not (or (nth 3 pps) (nth 4 pps)))))
|
|---|
| 1252 | (save-excursion
|
|---|
| 1253 | (let ((here (point))
|
|---|
| 1254 | (outdent 0)
|
|---|
| 1255 | (indent (py-compute-indentation t)))
|
|---|
| 1256 | (if (and (not arg)
|
|---|
| 1257 | (py-outdent-p)
|
|---|
| 1258 | (= indent (save-excursion
|
|---|
| 1259 | (py-next-statement -1)
|
|---|
| 1260 | (py-compute-indentation t)))
|
|---|
| 1261 | )
|
|---|
| 1262 | (setq outdent py-indent-offset))
|
|---|
| 1263 | ;; Don't indent, only dedent. This assumes that any lines
|
|---|
| 1264 | ;; that are already dedented relative to
|
|---|
| 1265 | ;; py-compute-indentation were put there on purpose. It's
|
|---|
| 1266 | ;; highly annoying to have `:' indent for you. Use TAB, C-c
|
|---|
| 1267 | ;; C-l or C-c C-r to adjust. TBD: Is there a better way to
|
|---|
| 1268 | ;; determine this???
|
|---|
| 1269 | (if (< (current-indentation) indent) nil
|
|---|
| 1270 | (goto-char here)
|
|---|
| 1271 | (beginning-of-line)
|
|---|
| 1272 | (delete-horizontal-space)
|
|---|
| 1273 | (indent-to (- indent outdent))
|
|---|
| 1274 | )))))
|
|---|
| 1275 |
|
|---|
| 1276 | |
|---|
| 1277 |
|
|---|
| 1278 | ;; Python subprocess utilities and filters
|
|---|
| 1279 | (defun py-execute-file (proc filename)
|
|---|
| 1280 | "Send to Python interpreter process PROC \"execfile('FILENAME')\".
|
|---|
| 1281 | Make that process's buffer visible and force display. Also make
|
|---|
| 1282 | comint believe the user typed this string so that
|
|---|
| 1283 | `kill-output-from-shell' does The Right Thing."
|
|---|
| 1284 | (let ((curbuf (current-buffer))
|
|---|
| 1285 | (procbuf (process-buffer proc))
|
|---|
| 1286 | ; (comint-scroll-to-bottom-on-output t)
|
|---|
| 1287 | (msg (format "## working on region in file %s...\n" filename))
|
|---|
| 1288 | (cmd (format "execfile(r'%s')\n" filename)))
|
|---|
| 1289 | (unwind-protect
|
|---|
| 1290 | (save-excursion
|
|---|
| 1291 | (set-buffer procbuf)
|
|---|
| 1292 | (goto-char (point-max))
|
|---|
| 1293 | (move-marker (process-mark proc) (point))
|
|---|
| 1294 | (funcall (process-filter proc) proc msg))
|
|---|
| 1295 | (set-buffer curbuf))
|
|---|
| 1296 | (process-send-string proc cmd)))
|
|---|
| 1297 |
|
|---|
| 1298 | (defun py-comint-output-filter-function (string)
|
|---|
| 1299 | "Watch output for Python prompt and exec next file waiting in queue.
|
|---|
| 1300 | This function is appropriate for `comint-output-filter-functions'."
|
|---|
| 1301 | ;; TBD: this should probably use split-string
|
|---|
| 1302 | (when (and (or (string-equal string ">>> ")
|
|---|
| 1303 | (and (>= (length string) 5)
|
|---|
| 1304 | (string-equal (substring string -5) "\n>>> ")))
|
|---|
| 1305 | py-file-queue)
|
|---|
| 1306 | (pop-to-buffer (current-buffer))
|
|---|
| 1307 | (py-safe (delete-file (car py-file-queue)))
|
|---|
| 1308 | (setq py-file-queue (cdr py-file-queue))
|
|---|
| 1309 | (if py-file-queue
|
|---|
| 1310 | (let ((pyproc (get-buffer-process (current-buffer))))
|
|---|
| 1311 | (py-execute-file pyproc (car py-file-queue))))
|
|---|
| 1312 | ))
|
|---|
| 1313 |
|
|---|
| 1314 | (defun py-pdbtrack-overlay-arrow (activation)
|
|---|
| 1315 | "Activate or de arrow at beginning-of-line in current buffer."
|
|---|
| 1316 | ;; This was derived/simplified from edebug-overlay-arrow
|
|---|
| 1317 | (cond (activation
|
|---|
| 1318 | (setq overlay-arrow-position (make-marker))
|
|---|
| 1319 | (setq overlay-arrow-string "=>")
|
|---|
| 1320 | (set-marker overlay-arrow-position (py-point 'bol) (current-buffer))
|
|---|
| 1321 | (setq py-pdbtrack-is-tracking-p t))
|
|---|
| 1322 | (overlay-arrow-position
|
|---|
| 1323 | (setq overlay-arrow-position nil)
|
|---|
| 1324 | (setq py-pdbtrack-is-tracking-p nil))
|
|---|
| 1325 | ))
|
|---|
| 1326 |
|
|---|
| 1327 | (defun py-pdbtrack-track-stack-file (text)
|
|---|
| 1328 | "Show the file indicated by the pdb stack entry line, in a separate window.
|
|---|
| 1329 |
|
|---|
| 1330 | Activity is disabled if the buffer-local variable
|
|---|
| 1331 | `py-pdbtrack-do-tracking-p' is nil.
|
|---|
| 1332 |
|
|---|
| 1333 | We depend on the pdb input prompt matching `py-pdbtrack-input-prompt'
|
|---|
| 1334 | at the beginning of the line.
|
|---|
| 1335 |
|
|---|
| 1336 | If the traceback target file path is invalid, we look for the most
|
|---|
| 1337 | recently visited python-mode buffer which either has the name of the
|
|---|
| 1338 | current function \(or class) or which defines the function \(or
|
|---|
| 1339 | class). This is to provide for remote scripts, eg, Zope's 'Script
|
|---|
| 1340 | (Python)' - put a _copy_ of the script in a buffer named for the
|
|---|
| 1341 | script, and set to python-mode, and pdbtrack will find it.)"
|
|---|
| 1342 | ;; Instead of trying to piece things together from partial text
|
|---|
| 1343 | ;; (which can be almost useless depending on Emacs version), we
|
|---|
| 1344 | ;; monitor to the point where we have the next pdb prompt, and then
|
|---|
| 1345 | ;; check all text from comint-last-input-end to process-mark.
|
|---|
| 1346 | ;;
|
|---|
| 1347 | ;; Also, we're very conservative about clearing the overlay arrow,
|
|---|
| 1348 | ;; to minimize residue. This means, for instance, that executing
|
|---|
| 1349 | ;; other pdb commands wipe out the highlight. You can always do a
|
|---|
| 1350 | ;; 'where' (aka 'w') command to reveal the overlay arrow.
|
|---|
| 1351 | (let* ((origbuf (current-buffer))
|
|---|
| 1352 | (currproc (get-buffer-process origbuf)))
|
|---|
| 1353 |
|
|---|
| 1354 | (if (not (and currproc py-pdbtrack-do-tracking-p))
|
|---|
| 1355 | (py-pdbtrack-overlay-arrow nil)
|
|---|
| 1356 |
|
|---|
| 1357 | (let* ((procmark (process-mark currproc))
|
|---|
| 1358 | (block (buffer-substring (max comint-last-input-end
|
|---|
| 1359 | (- procmark
|
|---|
| 1360 | py-pdbtrack-track-range))
|
|---|
| 1361 | procmark))
|
|---|
| 1362 | target target_fname target_lineno)
|
|---|
| 1363 |
|
|---|
| 1364 | (if (not (string-match (concat py-pdbtrack-input-prompt "$") block))
|
|---|
| 1365 | (py-pdbtrack-overlay-arrow nil)
|
|---|
| 1366 |
|
|---|
| 1367 | (setq target (py-pdbtrack-get-source-buffer block))
|
|---|
| 1368 |
|
|---|
| 1369 | (if (stringp target)
|
|---|
| 1370 | (message "pdbtrack: %s" target)
|
|---|
| 1371 |
|
|---|
| 1372 | (setq target_lineno (car target))
|
|---|
| 1373 | (setq target_buffer (cadr target))
|
|---|
| 1374 | (setq target_fname (buffer-file-name target_buffer))
|
|---|
| 1375 | (switch-to-buffer-other-window target_buffer)
|
|---|
| 1376 | (goto-line target_lineno)
|
|---|
| 1377 | (message "pdbtrack: line %s, file %s" target_lineno target_fname)
|
|---|
| 1378 | (py-pdbtrack-overlay-arrow t)
|
|---|
| 1379 | (pop-to-buffer origbuf t)
|
|---|
| 1380 |
|
|---|
| 1381 | )))))
|
|---|
| 1382 | )
|
|---|
| 1383 |
|
|---|
| 1384 | (defun py-pdbtrack-get-source-buffer (block)
|
|---|
| 1385 | "Return line number and buffer of code indicated by block's traceback text.
|
|---|
| 1386 |
|
|---|
| 1387 | We look first to visit the file indicated in the trace.
|
|---|
| 1388 |
|
|---|
| 1389 | Failing that, we look for the most recently visited python-mode buffer
|
|---|
| 1390 | with the same name or having
|
|---|
| 1391 | having the named function.
|
|---|
| 1392 |
|
|---|
| 1393 | If we're unable find the source code we return a string describing the
|
|---|
| 1394 | problem as best as we can determine."
|
|---|
| 1395 |
|
|---|
| 1396 | (if (not (string-match py-pdbtrack-stack-entry-regexp block))
|
|---|
| 1397 |
|
|---|
| 1398 | "Traceback cue not found"
|
|---|
| 1399 |
|
|---|
| 1400 | (let* ((filename (match-string 1 block))
|
|---|
| 1401 | (lineno (string-to-int (match-string 2 block)))
|
|---|
| 1402 | (funcname (match-string 3 block))
|
|---|
| 1403 | funcbuffer)
|
|---|
| 1404 |
|
|---|
| 1405 | (cond ((file-exists-p filename)
|
|---|
| 1406 | (list lineno (find-file-noselect filename)))
|
|---|
| 1407 |
|
|---|
| 1408 | ((setq funcbuffer (py-pdbtrack-grub-for-buffer funcname lineno))
|
|---|
| 1409 | (if (string-match "/Script (Python)$" filename)
|
|---|
| 1410 | ;; Add in number of lines for leading '##' comments:
|
|---|
| 1411 | (setq lineno
|
|---|
| 1412 | (+ lineno
|
|---|
| 1413 | (save-excursion
|
|---|
| 1414 | (set-buffer funcbuffer)
|
|---|
| 1415 | (count-lines
|
|---|
| 1416 | (point-min)
|
|---|
| 1417 | (max (point-min)
|
|---|
| 1418 | (string-match "^\\([^#]\\|#[^#]\\|#$\\)"
|
|---|
| 1419 | (buffer-substring (point-min)
|
|---|
| 1420 | (point-max)))
|
|---|
| 1421 | ))))))
|
|---|
| 1422 | (list lineno funcbuffer))
|
|---|
| 1423 |
|
|---|
| 1424 | ((= (elt filename 0) ?\<)
|
|---|
| 1425 | (format "(Non-file source: '%s')" filename))
|
|---|
| 1426 |
|
|---|
| 1427 | (t (format "Not found: %s(), %s" funcname filename)))
|
|---|
| 1428 | )
|
|---|
| 1429 | )
|
|---|
| 1430 | )
|
|---|
| 1431 |
|
|---|
| 1432 | (defun py-pdbtrack-grub-for-buffer (funcname lineno)
|
|---|
| 1433 | "Find most recent buffer itself named or having function funcname.
|
|---|
| 1434 |
|
|---|
| 1435 | We first check the last buffer this function found, if any, then walk
|
|---|
| 1436 | throught the buffer-list history for python-mode buffers that are
|
|---|
| 1437 | named for funcname or define a function funcname."
|
|---|
| 1438 | (let ((buffers (buffer-list))
|
|---|
| 1439 | curbuf
|
|---|
| 1440 | got)
|
|---|
| 1441 | (while (and buffers (not got))
|
|---|
| 1442 | (setq buf (car buffers)
|
|---|
| 1443 | buffers (cdr buffers))
|
|---|
| 1444 | (if (and (save-excursion (set-buffer buf)
|
|---|
| 1445 | (string= major-mode "python-mode"))
|
|---|
| 1446 | (or (string-match funcname (buffer-name buf))
|
|---|
| 1447 | (string-match (concat "^\\s-*\\(def\\|class\\)\\s-+"
|
|---|
| 1448 | funcname "\\s-*(")
|
|---|
| 1449 | (save-excursion
|
|---|
| 1450 | (set-buffer buf)
|
|---|
| 1451 | (buffer-substring (point-min)
|
|---|
| 1452 | (point-max))))))
|
|---|
| 1453 | (setq got buf)))
|
|---|
| 1454 | (setq py-pdbtrack-last-grubbed-buffer got)))
|
|---|
| 1455 |
|
|---|
| 1456 | (defun py-postprocess-output-buffer (buf)
|
|---|
| 1457 | "Highlight exceptions found in BUF.
|
|---|
| 1458 | If an exception occurred return t, otherwise return nil. BUF must exist."
|
|---|
| 1459 | (let (line file bol err-p)
|
|---|
| 1460 | (save-excursion
|
|---|
| 1461 | (set-buffer buf)
|
|---|
| 1462 | (beginning-of-buffer)
|
|---|
| 1463 | (while (re-search-forward py-traceback-line-re nil t)
|
|---|
| 1464 | (setq file (match-string 1)
|
|---|
| 1465 | line (string-to-int (match-string 2))
|
|---|
| 1466 | bol (py-point 'bol))
|
|---|
| 1467 | (py-highlight-line bol (py-point 'eol) file line)))
|
|---|
| 1468 | (when (and py-jump-on-exception line)
|
|---|
| 1469 | (beep)
|
|---|
| 1470 | (py-jump-to-exception file line)
|
|---|
| 1471 | (setq err-p t))
|
|---|
| 1472 | err-p))
|
|---|
| 1473 |
|
|---|
| 1474 |
|
|---|
| 1475 | |
|---|
| 1476 |
|
|---|
| 1477 | ;;; Subprocess commands
|
|---|
| 1478 |
|
|---|
| 1479 | ;; only used when (memq 'broken-temp-names py-emacs-features)
|
|---|
| 1480 | (defvar py-serial-number 0)
|
|---|
| 1481 | (defvar py-exception-buffer nil)
|
|---|
| 1482 | (defconst py-output-buffer "*Python Output*")
|
|---|
| 1483 | (make-variable-buffer-local 'py-output-buffer)
|
|---|
| 1484 |
|
|---|
| 1485 | ;; for toggling between CPython and JPython
|
|---|
| 1486 | (defvar py-which-shell nil)
|
|---|
| 1487 | (defvar py-which-args py-python-command-args)
|
|---|
| 1488 | (defvar py-which-bufname "Python")
|
|---|
| 1489 | (make-variable-buffer-local 'py-which-shell)
|
|---|
| 1490 | (make-variable-buffer-local 'py-which-args)
|
|---|
| 1491 | (make-variable-buffer-local 'py-which-bufname)
|
|---|
| 1492 |
|
|---|
| 1493 | (defun py-toggle-shells (arg)
|
|---|
| 1494 | "Toggles between the CPython and JPython shells.
|
|---|
| 1495 |
|
|---|
| 1496 | With positive argument ARG (interactively \\[universal-argument]),
|
|---|
| 1497 | uses the CPython shell, with negative ARG uses the JPython shell, and
|
|---|
| 1498 | with a zero argument, toggles the shell.
|
|---|
| 1499 |
|
|---|
| 1500 | Programmatically, ARG can also be one of the symbols `cpython' or
|
|---|
| 1501 | `jpython', equivalent to positive arg and negative arg respectively."
|
|---|
| 1502 | (interactive "P")
|
|---|
| 1503 | ;; default is to toggle
|
|---|
| 1504 | (if (null arg)
|
|---|
| 1505 | (setq arg 0))
|
|---|
| 1506 | ;; preprocess arg
|
|---|
| 1507 | (cond
|
|---|
| 1508 | ((equal arg 0)
|
|---|
| 1509 | ;; toggle
|
|---|
| 1510 | (if (string-equal py-which-bufname "Python")
|
|---|
| 1511 | (setq arg -1)
|
|---|
| 1512 | (setq arg 1)))
|
|---|
| 1513 | ((equal arg 'cpython) (setq arg 1))
|
|---|
| 1514 | ((equal arg 'jpython) (setq arg -1)))
|
|---|
| 1515 | (let (msg)
|
|---|
| 1516 | (cond
|
|---|
| 1517 | ((< 0 arg)
|
|---|
| 1518 | ;; set to CPython
|
|---|
| 1519 | (setq py-which-shell py-python-command
|
|---|
| 1520 | py-which-args py-python-command-args
|
|---|
| 1521 | py-which-bufname "Python"
|
|---|
| 1522 | msg "CPython"
|
|---|
| 1523 | mode-name "Python"))
|
|---|
| 1524 | ((> 0 arg)
|
|---|
| 1525 | (setq py-which-shell py-jpython-command
|
|---|
| 1526 | py-which-args py-jpython-command-args
|
|---|
| 1527 | py-which-bufname "JPython"
|
|---|
| 1528 | msg "JPython"
|
|---|
| 1529 | mode-name "JPython"))
|
|---|
| 1530 | )
|
|---|
| 1531 | (message "Using the %s shell" msg)
|
|---|
| 1532 | (setq py-output-buffer (format "*%s Output*" py-which-bufname))))
|
|---|
| 1533 |
|
|---|
| 1534 | ;;;###autoload
|
|---|
| 1535 | (defun py-shell (&optional argprompt)
|
|---|
| 1536 | "Start an interactive Python interpreter in another window.
|
|---|
| 1537 | This is like Shell mode, except that Python is running in the window
|
|---|
| 1538 | instead of a shell. See the `Interactive Shell' and `Shell Mode'
|
|---|
| 1539 | sections of the Emacs manual for details, especially for the key
|
|---|
| 1540 | bindings active in the `*Python*' buffer.
|
|---|
| 1541 |
|
|---|
| 1542 | With optional \\[universal-argument], the user is prompted for the
|
|---|
| 1543 | flags to pass to the Python interpreter. This has no effect when this
|
|---|
| 1544 | command is used to switch to an existing process, only when a new
|
|---|
| 1545 | process is started. If you use this, you will probably want to ensure
|
|---|
| 1546 | that the current arguments are retained (they will be included in the
|
|---|
| 1547 | prompt). This argument is ignored when this function is called
|
|---|
| 1548 | programmatically, or when running in Emacs 19.34 or older.
|
|---|
| 1549 |
|
|---|
| 1550 | Note: You can toggle between using the CPython interpreter and the
|
|---|
| 1551 | JPython interpreter by hitting \\[py-toggle-shells]. This toggles
|
|---|
| 1552 | buffer local variables which control whether all your subshell
|
|---|
| 1553 | interactions happen to the `*JPython*' or `*Python*' buffers (the
|
|---|
| 1554 | latter is the name used for the CPython buffer).
|
|---|
| 1555 |
|
|---|
| 1556 | Warning: Don't use an interactive Python if you change sys.ps1 or
|
|---|
| 1557 | sys.ps2 from their default values, or if you're running code that
|
|---|
| 1558 | prints `>>> ' or `... ' at the start of a line. `python-mode' can't
|
|---|
| 1559 | distinguish your output from Python's output, and assumes that `>>> '
|
|---|
| 1560 | at the start of a line is a prompt from Python. Similarly, the Emacs
|
|---|
| 1561 | Shell mode code assumes that both `>>> ' and `... ' at the start of a
|
|---|
| 1562 | line are Python prompts. Bad things can happen if you fool either
|
|---|
| 1563 | mode.
|
|---|
| 1564 |
|
|---|
| 1565 | Warning: If you do any editing *in* the process buffer *while* the
|
|---|
| 1566 | buffer is accepting output from Python, do NOT attempt to `undo' the
|
|---|
| 1567 | changes. Some of the output (nowhere near the parts you changed!) may
|
|---|
| 1568 | be lost if you do. This appears to be an Emacs bug, an unfortunate
|
|---|
| 1569 | interaction between undo and process filters; the same problem exists in
|
|---|
| 1570 | non-Python process buffers using the default (Emacs-supplied) process
|
|---|
| 1571 | filter."
|
|---|
| 1572 | (interactive "P")
|
|---|
| 1573 | ;; Set the default shell if not already set
|
|---|
| 1574 | (when (null py-which-shell)
|
|---|
| 1575 | (py-toggle-shells py-default-interpreter))
|
|---|
| 1576 | (let ((args py-which-args))
|
|---|
| 1577 | (when (and argprompt
|
|---|
| 1578 | (interactive-p)
|
|---|
| 1579 | (fboundp 'split-string))
|
|---|
| 1580 | ;; TBD: Perhaps force "-i" in the final list?
|
|---|
| 1581 | (setq args (split-string
|
|---|
| 1582 | (read-string (concat py-which-bufname
|
|---|
| 1583 | " arguments: ")
|
|---|
| 1584 | (concat
|
|---|
| 1585 | (mapconcat 'identity py-which-args " ") " ")
|
|---|
| 1586 | ))))
|
|---|
| 1587 | (switch-to-buffer-other-window
|
|---|
| 1588 | (apply 'make-comint py-which-bufname py-which-shell nil args))
|
|---|
| 1589 | (make-local-variable 'comint-prompt-regexp)
|
|---|
| 1590 | (setq comint-prompt-regexp "^>>> \\|^[.][.][.] \\|^(pdb) ")
|
|---|
| 1591 | (add-hook 'comint-output-filter-functions
|
|---|
| 1592 | 'py-comint-output-filter-function)
|
|---|
| 1593 | ;; pdbtrack
|
|---|
| 1594 | (add-hook 'comint-output-filter-functions 'py-pdbtrack-track-stack-file)
|
|---|
| 1595 | (setq py-pdbtrack-do-tracking-p t)
|
|---|
| 1596 | (set-syntax-table py-mode-syntax-table)
|
|---|
| 1597 | (use-local-map py-shell-map)
|
|---|
| 1598 | (run-hooks 'py-shell-hook)
|
|---|
| 1599 | ))
|
|---|
| 1600 |
|
|---|
| 1601 | (defun py-clear-queue ()
|
|---|
| 1602 | "Clear the queue of temporary files waiting to execute."
|
|---|
| 1603 | (interactive)
|
|---|
| 1604 | (let ((n (length py-file-queue)))
|
|---|
| 1605 | (mapcar 'delete-file py-file-queue)
|
|---|
| 1606 | (setq py-file-queue nil)
|
|---|
| 1607 | (message "%d pending files de-queued." n)))
|
|---|
| 1608 |
|
|---|
| 1609 | |
|---|
| 1610 |
|
|---|
| 1611 | (defun py-execute-region (start end &optional async)
|
|---|
| 1612 | "Execute the region in a Python interpreter.
|
|---|
| 1613 |
|
|---|
| 1614 | The region is first copied into a temporary file (in the directory
|
|---|
| 1615 | `py-temp-directory'). If there is no Python interpreter shell
|
|---|
| 1616 | running, this file is executed synchronously using
|
|---|
| 1617 | `shell-command-on-region'. If the program is long running, use
|
|---|
| 1618 | \\[universal-argument] to run the command asynchronously in its own
|
|---|
| 1619 | buffer.
|
|---|
| 1620 |
|
|---|
| 1621 | When this function is used programmatically, arguments START and END
|
|---|
| 1622 | specify the region to execute, and optional third argument ASYNC, if
|
|---|
| 1623 | non-nil, specifies to run the command asynchronously in its own
|
|---|
| 1624 | buffer.
|
|---|
| 1625 |
|
|---|
| 1626 | If the Python interpreter shell is running, the region is execfile()'d
|
|---|
| 1627 | in that shell. If you try to execute regions too quickly,
|
|---|
| 1628 | `python-mode' will queue them up and execute them one at a time when
|
|---|
| 1629 | it sees a `>>> ' prompt from Python. Each time this happens, the
|
|---|
| 1630 | process buffer is popped into a window (if it's not already in some
|
|---|
| 1631 | window) so you can see it, and a comment of the form
|
|---|
| 1632 |
|
|---|
| 1633 | \t## working on region in file <name>...
|
|---|
| 1634 |
|
|---|
| 1635 | is inserted at the end. See also the command `py-clear-queue'."
|
|---|
| 1636 | (interactive "r\nP")
|
|---|
| 1637 | ;; Skip ahead to the first non-blank line
|
|---|
| 1638 | (let* ((proc (get-process py-which-bufname))
|
|---|
| 1639 | (temp (if (memq 'broken-temp-names py-emacs-features)
|
|---|
| 1640 | (let
|
|---|
| 1641 | ((sn py-serial-number)
|
|---|
| 1642 | (pid (and (fboundp 'emacs-pid) (emacs-pid))))
|
|---|
| 1643 | (setq py-serial-number (1+ py-serial-number))
|
|---|
| 1644 | (if pid
|
|---|
| 1645 | (format "python-%d-%d" sn pid)
|
|---|
| 1646 | (format "python-%d" sn)))
|
|---|
| 1647 | (make-temp-name "python-")))
|
|---|
| 1648 | (file (concat (expand-file-name temp py-temp-directory) ".py"))
|
|---|
| 1649 | (cur (current-buffer))
|
|---|
| 1650 | (buf (get-buffer-create file))
|
|---|
| 1651 | shell)
|
|---|
| 1652 | ;; Write the contents of the buffer, watching out for indented regions.
|
|---|
| 1653 | (save-excursion
|
|---|
| 1654 | (goto-char start)
|
|---|
| 1655 | (beginning-of-line)
|
|---|
| 1656 | (while (and (looking-at "\\s *$")
|
|---|
| 1657 | (< (point) end))
|
|---|
| 1658 | (forward-line 1))
|
|---|
| 1659 | (setq start (point))
|
|---|
| 1660 | (or (< start end)
|
|---|
| 1661 | (error "Region is empty"))
|
|---|
| 1662 | (let ((needs-if (/= (py-point 'bol) (py-point 'boi))))
|
|---|
| 1663 | (set-buffer buf)
|
|---|
| 1664 | (python-mode)
|
|---|
| 1665 | (when needs-if
|
|---|
| 1666 | (insert "if 1:\n"))
|
|---|
| 1667 | (insert-buffer-substring cur start end)
|
|---|
| 1668 | ;; Set the shell either to the #! line command, or to the
|
|---|
| 1669 | ;; py-which-shell buffer local variable.
|
|---|
| 1670 | (setq shell (or (py-choose-shell-by-shebang)
|
|---|
| 1671 | (py-choose-shell-by-import)
|
|---|
| 1672 | py-which-shell))))
|
|---|
| 1673 | (cond
|
|---|
| 1674 | ;; always run the code in its own asynchronous subprocess
|
|---|
| 1675 | (async
|
|---|
| 1676 | ;; User explicitly wants this to run in its own async subprocess
|
|---|
| 1677 | (save-excursion
|
|---|
| 1678 | (set-buffer buf)
|
|---|
| 1679 | (write-region (point-min) (point-max) file nil 'nomsg))
|
|---|
| 1680 | (let* ((buf (generate-new-buffer-name py-output-buffer))
|
|---|
| 1681 | ;; TBD: a horrible hack, but why create new Custom variables?
|
|---|
| 1682 | (arg (if (string-equal py-which-bufname "Python")
|
|---|
| 1683 | "-u" "")))
|
|---|
| 1684 | (start-process py-which-bufname buf shell arg file)
|
|---|
| 1685 | (pop-to-buffer buf)
|
|---|
| 1686 | (py-postprocess-output-buffer buf)
|
|---|
| 1687 | ;; TBD: clean up the temporary file!
|
|---|
| 1688 | ))
|
|---|
| 1689 | ;; if the Python interpreter shell is running, queue it up for
|
|---|
| 1690 | ;; execution there.
|
|---|
| 1691 | (proc
|
|---|
| 1692 | ;; use the existing python shell
|
|---|
| 1693 | (save-excursion
|
|---|
| 1694 | (set-buffer buf)
|
|---|
| 1695 | (write-region (point-min) (point-max) file nil 'nomsg))
|
|---|
| 1696 | (if (not py-file-queue)
|
|---|
| 1697 | (py-execute-file proc file)
|
|---|
| 1698 | (message "File %s queued for execution" file))
|
|---|
| 1699 | (setq py-file-queue (append py-file-queue (list file)))
|
|---|
| 1700 | (setq py-exception-buffer (cons file (current-buffer))))
|
|---|
| 1701 | (t
|
|---|
| 1702 | ;; TBD: a horrible hack, but why create new Custom variables?
|
|---|
| 1703 | (let ((cmd (concat shell (if (string-equal py-which-bufname "JPython")
|
|---|
| 1704 | " -" ""))))
|
|---|
| 1705 | ;; otherwise either run it synchronously in a subprocess
|
|---|
| 1706 | (save-excursion
|
|---|
| 1707 | (set-buffer buf)
|
|---|
| 1708 | (shell-command-on-region (point-min) (point-max)
|
|---|
| 1709 | cmd py-output-buffer))
|
|---|
| 1710 | ;; shell-command-on-region kills the output buffer if it never
|
|---|
| 1711 | ;; existed and there's no output from the command
|
|---|
| 1712 | (if (not (get-buffer py-output-buffer))
|
|---|
| 1713 | (message "No output.")
|
|---|
| 1714 | (setq py-exception-buffer (current-buffer))
|
|---|
| 1715 | (let ((err-p (py-postprocess-output-buffer py-output-buffer)))
|
|---|
| 1716 | (pop-to-buffer py-output-buffer)
|
|---|
| 1717 | (if err-p
|
|---|
| 1718 | (pop-to-buffer py-exception-buffer)))
|
|---|
| 1719 | ))
|
|---|
| 1720 | ))
|
|---|
| 1721 | ;; Clean up after ourselves.
|
|---|
| 1722 | (kill-buffer buf)))
|
|---|
| 1723 |
|
|---|
| 1724 | |
|---|
| 1725 |
|
|---|
| 1726 | ;; Code execution commands
|
|---|
| 1727 | (defun py-execute-buffer (&optional async)
|
|---|
| 1728 | "Send the contents of the buffer to a Python interpreter.
|
|---|
| 1729 | If the file local variable `py-master-file' is non-nil, execute the
|
|---|
| 1730 | named file instead of the buffer's file.
|
|---|
| 1731 |
|
|---|
| 1732 | If there is a *Python* process buffer it is used. If a clipping
|
|---|
| 1733 | restriction is in effect, only the accessible portion of the buffer is
|
|---|
| 1734 | sent. A trailing newline will be supplied if needed.
|
|---|
| 1735 |
|
|---|
| 1736 | See the `\\[py-execute-region]' docs for an account of some
|
|---|
| 1737 | subtleties, including the use of the optional ASYNC argument."
|
|---|
| 1738 | (interactive "P")
|
|---|
| 1739 | (if py-master-file
|
|---|
| 1740 | (let* ((filename (expand-file-name py-master-file))
|
|---|
| 1741 | (buffer (or (get-file-buffer filename)
|
|---|
| 1742 | (find-file-noselect filename))))
|
|---|
| 1743 | (set-buffer buffer)))
|
|---|
| 1744 | (py-execute-region (point-min) (point-max) async))
|
|---|
| 1745 |
|
|---|
| 1746 | (defun py-execute-import-or-reload (&optional async)
|
|---|
| 1747 | "Import the current buffer's file in a Python interpreter.
|
|---|
| 1748 |
|
|---|
| 1749 | If the file has already been imported, then do reload instead to get
|
|---|
| 1750 | the latest version.
|
|---|
| 1751 |
|
|---|
| 1752 | If the file's name does not end in \".py\", then do execfile instead.
|
|---|
| 1753 |
|
|---|
| 1754 | If the current buffer is not visiting a file, do `py-execute-buffer'
|
|---|
| 1755 | instead.
|
|---|
| 1756 |
|
|---|
| 1757 | If the file local variable `py-master-file' is non-nil, import or
|
|---|
| 1758 | reload the named file instead of the buffer's file. The file may be
|
|---|
| 1759 | saved based on the value of `py-execute-import-or-reload-save-p'.
|
|---|
| 1760 |
|
|---|
| 1761 | See the `\\[py-execute-region]' docs for an account of some
|
|---|
| 1762 | subtleties, including the use of the optional ASYNC argument.
|
|---|
| 1763 |
|
|---|
| 1764 | This may be preferable to `\\[py-execute-buffer]' because:
|
|---|
| 1765 |
|
|---|
| 1766 | - Definitions stay in their module rather than appearing at top
|
|---|
| 1767 | level, where they would clutter the global namespace and not affect
|
|---|
| 1768 | uses of qualified names (MODULE.NAME).
|
|---|
| 1769 |
|
|---|
| 1770 | - The Python debugger gets line number information about the functions."
|
|---|
| 1771 | (interactive "P")
|
|---|
| 1772 | ;; Check file local variable py-master-file
|
|---|
| 1773 | (if py-master-file
|
|---|
| 1774 | (let* ((filename (expand-file-name py-master-file))
|
|---|
| 1775 | (buffer (or (get-file-buffer filename)
|
|---|
| 1776 | (find-file-noselect filename))))
|
|---|
| 1777 | (set-buffer buffer)))
|
|---|
| 1778 | (let ((file (buffer-file-name (current-buffer))))
|
|---|
| 1779 | (if file
|
|---|
| 1780 | (progn
|
|---|
| 1781 | ;; Maybe save some buffers
|
|---|
| 1782 | (save-some-buffers (not py-ask-about-save) nil)
|
|---|
| 1783 | (py-execute-string
|
|---|
| 1784 | (if (string-match "\\.py$" file)
|
|---|
| 1785 | (let ((f (file-name-sans-extension
|
|---|
| 1786 | (file-name-nondirectory file))))
|
|---|
| 1787 | (format "if globals().has_key('%s'):\n reload(%s)\nelse:\n import %s\n"
|
|---|
| 1788 | f f f))
|
|---|
| 1789 | (format "execfile(r'%s')\n" file))
|
|---|
| 1790 | async))
|
|---|
| 1791 | ;; else
|
|---|
| 1792 | (py-execute-buffer async))))
|
|---|
| 1793 |
|
|---|
| 1794 |
|
|---|
| 1795 | (defun py-execute-def-or-class (&optional async)
|
|---|
| 1796 | "Send the current function or class definition to a Python interpreter.
|
|---|
| 1797 |
|
|---|
| 1798 | If there is a *Python* process buffer it is used.
|
|---|
| 1799 |
|
|---|
| 1800 | See the `\\[py-execute-region]' docs for an account of some
|
|---|
| 1801 | subtleties, including the use of the optional ASYNC argument."
|
|---|
| 1802 | (interactive "P")
|
|---|
| 1803 | (save-excursion
|
|---|
| 1804 | (py-mark-def-or-class)
|
|---|
| 1805 | ;; mark is before point
|
|---|
| 1806 | (py-execute-region (mark) (point) async)))
|
|---|
| 1807 |
|
|---|
| 1808 |
|
|---|
| 1809 | (defun py-execute-string (string &optional async)
|
|---|
| 1810 | "Send the argument STRING to a Python interpreter.
|
|---|
| 1811 |
|
|---|
| 1812 | If there is a *Python* process buffer it is used.
|
|---|
| 1813 |
|
|---|
| 1814 | See the `\\[py-execute-region]' docs for an account of some
|
|---|
| 1815 | subtleties, including the use of the optional ASYNC argument."
|
|---|
| 1816 | (interactive "sExecute Python command: ")
|
|---|
| 1817 | (save-excursion
|
|---|
| 1818 | (set-buffer (get-buffer-create
|
|---|
| 1819 | (generate-new-buffer-name " *Python Command*")))
|
|---|
| 1820 | (insert string)
|
|---|
| 1821 | (py-execute-region (point-min) (point-max) async)))
|
|---|
| 1822 |
|
|---|
| 1823 |
|
|---|
| 1824 | |
|---|
| 1825 |
|
|---|
| 1826 | (defun py-jump-to-exception (file line)
|
|---|
| 1827 | "Jump to the Python code in FILE at LINE."
|
|---|
| 1828 | (let ((buffer (cond ((string-equal file "<stdin>")
|
|---|
| 1829 | (if (consp py-exception-buffer)
|
|---|
| 1830 | (cdr py-exception-buffer)
|
|---|
| 1831 | py-exception-buffer))
|
|---|
| 1832 | ((and (consp py-exception-buffer)
|
|---|
| 1833 | (string-equal file (car py-exception-buffer)))
|
|---|
| 1834 | (cdr py-exception-buffer))
|
|---|
| 1835 | ((py-safe (find-file-noselect file)))
|
|---|
| 1836 | ;; could not figure out what file the exception
|
|---|
| 1837 | ;; is pointing to, so prompt for it
|
|---|
| 1838 | (t (find-file (read-file-name "Exception file: "
|
|---|
| 1839 | nil
|
|---|
| 1840 | file t))))))
|
|---|
| 1841 | (pop-to-buffer buffer)
|
|---|
| 1842 | ;; Force Python mode
|
|---|
| 1843 | (if (not (eq major-mode 'python-mode))
|
|---|
| 1844 | (python-mode))
|
|---|
| 1845 | (goto-line line)
|
|---|
| 1846 | (message "Jumping to exception in file %s on line %d" file line)))
|
|---|
| 1847 |
|
|---|
| 1848 | (defun py-mouseto-exception (event)
|
|---|
| 1849 | "Jump to the code which caused the Python exception at EVENT.
|
|---|
| 1850 | EVENT is usually a mouse click."
|
|---|
| 1851 | (interactive "e")
|
|---|
| 1852 | (cond
|
|---|
| 1853 | ((fboundp 'event-point)
|
|---|
| 1854 | ;; XEmacs
|
|---|
| 1855 | (let* ((point (event-point event))
|
|---|
| 1856 | (buffer (event-buffer event))
|
|---|
| 1857 | (e (and point buffer (extent-at point buffer 'py-exc-info)))
|
|---|
| 1858 | (info (and e (extent-property e 'py-exc-info))))
|
|---|
| 1859 | (message "Event point: %d, info: %s" point info)
|
|---|
| 1860 | (and info
|
|---|
| 1861 | (py-jump-to-exception (car info) (cdr info)))
|
|---|
| 1862 | ))
|
|---|
| 1863 | ;; Emacs -- Please port this!
|
|---|
| 1864 | ))
|
|---|
| 1865 |
|
|---|
| 1866 | (defun py-goto-exception ()
|
|---|
| 1867 | "Go to the line indicated by the traceback."
|
|---|
| 1868 | (interactive)
|
|---|
| 1869 | (let (file line)
|
|---|
| 1870 | (save-excursion
|
|---|
| 1871 | (beginning-of-line)
|
|---|
| 1872 | (if (looking-at py-traceback-line-re)
|
|---|
| 1873 | (setq file (match-string 1)
|
|---|
| 1874 | line (string-to-int (match-string 2)))))
|
|---|
| 1875 | (if (not file)
|
|---|
| 1876 | (error "Not on a traceback line"))
|
|---|
| 1877 | (py-jump-to-exception file line)))
|
|---|
| 1878 |
|
|---|
| 1879 | (defun py-find-next-exception (start buffer searchdir errwhere)
|
|---|
| 1880 | "Find the next Python exception and jump to the code that caused it.
|
|---|
| 1881 | START is the buffer position in BUFFER from which to begin searching
|
|---|
| 1882 | for an exception. SEARCHDIR is a function, either
|
|---|
| 1883 | `re-search-backward' or `re-search-forward' indicating the direction
|
|---|
| 1884 | to search. ERRWHERE is used in an error message if the limit (top or
|
|---|
| 1885 | bottom) of the trackback stack is encountered."
|
|---|
| 1886 | (let (file line)
|
|---|
| 1887 | (save-excursion
|
|---|
| 1888 | (set-buffer buffer)
|
|---|
| 1889 | (goto-char (py-point start))
|
|---|
| 1890 | (if (funcall searchdir py-traceback-line-re nil t)
|
|---|
| 1891 | (setq file (match-string 1)
|
|---|
| 1892 | line (string-to-int (match-string 2)))))
|
|---|
| 1893 | (if (and file line)
|
|---|
| 1894 | (py-jump-to-exception file line)
|
|---|
| 1895 | (error "%s of traceback" errwhere))))
|
|---|
| 1896 |
|
|---|
| 1897 | (defun py-down-exception (&optional bottom)
|
|---|
| 1898 | "Go to the next line down in the traceback.
|
|---|
| 1899 | With \\[univeral-argument] (programmatically, optional argument
|
|---|
| 1900 | BOTTOM), jump to the bottom (innermost) exception in the exception
|
|---|
| 1901 | stack."
|
|---|
| 1902 | (interactive "P")
|
|---|
| 1903 | (let* ((proc (get-process "Python"))
|
|---|
| 1904 | (buffer (if proc "*Python*" py-output-buffer)))
|
|---|
| 1905 | (if bottom
|
|---|
| 1906 | (py-find-next-exception 'eob buffer 're-search-backward "Bottom")
|
|---|
| 1907 | (py-find-next-exception 'eol buffer 're-search-forward "Bottom"))))
|
|---|
| 1908 |
|
|---|
| 1909 | (defun py-up-exception (&optional top)
|
|---|
| 1910 | "Go to the previous line up in the traceback.
|
|---|
| 1911 | With \\[universal-argument] (programmatically, optional argument TOP)
|
|---|
| 1912 | jump to the top (outermost) exception in the exception stack."
|
|---|
| 1913 | (interactive "P")
|
|---|
| 1914 | (let* ((proc (get-process "Python"))
|
|---|
| 1915 | (buffer (if proc "*Python*" py-output-buffer)))
|
|---|
| 1916 | (if top
|
|---|
| 1917 | (py-find-next-exception 'bob buffer 're-search-forward "Top")
|
|---|
| 1918 | (py-find-next-exception 'bol buffer 're-search-backward "Top"))))
|
|---|
| 1919 |
|
|---|
| 1920 | |
|---|
| 1921 |
|
|---|
| 1922 | ;; Electric deletion
|
|---|
| 1923 | (defun py-electric-backspace (arg)
|
|---|
| 1924 | "Delete preceding character or levels of indentation.
|
|---|
| 1925 | Deletion is performed by calling the function in `py-backspace-function'
|
|---|
| 1926 | with a single argument (the number of characters to delete).
|
|---|
| 1927 |
|
|---|
| 1928 | If point is at the leftmost column, delete the preceding newline.
|
|---|
| 1929 |
|
|---|
| 1930 | Otherwise, if point is at the leftmost non-whitespace character of a
|
|---|
| 1931 | line that is neither a continuation line nor a non-indenting comment
|
|---|
| 1932 | line, or if point is at the end of a blank line, this command reduces
|
|---|
| 1933 | the indentation to match that of the line that opened the current
|
|---|
| 1934 | block of code. The line that opened the block is displayed in the
|
|---|
| 1935 | echo area to help you keep track of where you are. With
|
|---|
| 1936 | \\[universal-argument] dedents that many blocks (but not past column
|
|---|
| 1937 | zero).
|
|---|
| 1938 |
|
|---|
| 1939 | Otherwise the preceding character is deleted, converting a tab to
|
|---|
| 1940 | spaces if needed so that only a single column position is deleted.
|
|---|
| 1941 | \\[universal-argument] specifies how many characters to delete;
|
|---|
| 1942 | default is 1.
|
|---|
| 1943 |
|
|---|
| 1944 | When used programmatically, argument ARG specifies the number of
|
|---|
| 1945 | blocks to dedent, or the number of characters to delete, as indicated
|
|---|
| 1946 | above."
|
|---|
| 1947 | (interactive "*p")
|
|---|
| 1948 | (if (or (/= (current-indentation) (current-column))
|
|---|
| 1949 | (bolp)
|
|---|
| 1950 | (py-continuation-line-p)
|
|---|
| 1951 | ; (not py-honor-comment-indentation)
|
|---|
| 1952 | ; (looking-at "#[^ \t\n]") ; non-indenting #
|
|---|
| 1953 | )
|
|---|
| 1954 | (funcall py-backspace-function arg)
|
|---|
| 1955 | ;; else indent the same as the colon line that opened the block
|
|---|
| 1956 | ;; force non-blank so py-goto-block-up doesn't ignore it
|
|---|
| 1957 | (insert-char ?* 1)
|
|---|
| 1958 | (backward-char)
|
|---|
| 1959 | (let ((base-indent 0) ; indentation of base line
|
|---|
| 1960 | (base-text "") ; and text of base line
|
|---|
| 1961 | (base-found-p nil))
|
|---|
| 1962 | (save-excursion
|
|---|
| 1963 | (while (< 0 arg)
|
|---|
| 1964 | (condition-case nil ; in case no enclosing block
|
|---|
| 1965 | (progn
|
|---|
| 1966 | (py-goto-block-up 'no-mark)
|
|---|
| 1967 | (setq base-indent (current-indentation)
|
|---|
| 1968 | base-text (py-suck-up-leading-text)
|
|---|
| 1969 | base-found-p t))
|
|---|
| 1970 | (error nil))
|
|---|
| 1971 | (setq arg (1- arg))))
|
|---|
| 1972 | (delete-char 1) ; toss the dummy character
|
|---|
| 1973 | (delete-horizontal-space)
|
|---|
| 1974 | (indent-to base-indent)
|
|---|
| 1975 | (if base-found-p
|
|---|
| 1976 | (message "Closes block: %s" base-text)))))
|
|---|
| 1977 |
|
|---|
| 1978 |
|
|---|
| 1979 | (defun py-electric-delete (arg)
|
|---|
| 1980 | "Delete preceding or following character or levels of whitespace.
|
|---|
| 1981 |
|
|---|
| 1982 | The behavior of this function depends on the variable
|
|---|
| 1983 | `delete-key-deletes-forward'. If this variable is nil (or does not
|
|---|
| 1984 | exist, as in older Emacsen and non-XEmacs versions), then this
|
|---|
| 1985 | function behaves identically to \\[c-electric-backspace].
|
|---|
| 1986 |
|
|---|
| 1987 | If `delete-key-deletes-forward' is non-nil and is supported in your
|
|---|
| 1988 | Emacs, then deletion occurs in the forward direction, by calling the
|
|---|
| 1989 | function in `py-delete-function'.
|
|---|
| 1990 |
|
|---|
| 1991 | \\[universal-argument] (programmatically, argument ARG) specifies the
|
|---|
| 1992 | number of characters to delete (default is 1)."
|
|---|
| 1993 | (interactive "*p")
|
|---|
| 1994 | (if (or (and (fboundp 'delete-forward-p) ;XEmacs 21
|
|---|
| 1995 | (delete-forward-p))
|
|---|
| 1996 | (and (boundp 'delete-key-deletes-forward) ;XEmacs 20
|
|---|
| 1997 | delete-key-deletes-forward))
|
|---|
| 1998 | (funcall py-delete-function arg)
|
|---|
| 1999 | (py-electric-backspace arg)))
|
|---|
| 2000 |
|
|---|
| 2001 | ;; required for pending-del and delsel modes
|
|---|
| 2002 | (put 'py-electric-colon 'delete-selection t) ;delsel
|
|---|
| 2003 | (put 'py-electric-colon 'pending-delete t) ;pending-del
|
|---|
| 2004 | (put 'py-electric-backspace 'delete-selection 'supersede) ;delsel
|
|---|
| 2005 | (put 'py-electric-backspace 'pending-delete 'supersede) ;pending-del
|
|---|
| 2006 | (put 'py-electric-delete 'delete-selection 'supersede) ;delsel
|
|---|
| 2007 | (put 'py-electric-delete 'pending-delete 'supersede) ;pending-del
|
|---|
| 2008 |
|
|---|
| 2009 |
|
|---|
| 2010 | |
|---|
| 2011 |
|
|---|
| 2012 | (defun py-indent-line (&optional arg)
|
|---|
| 2013 | "Fix the indentation of the current line according to Python rules.
|
|---|
| 2014 | With \\[universal-argument] (programmatically, the optional argument
|
|---|
| 2015 | ARG non-nil), ignore dedenting rules for block closing statements
|
|---|
| 2016 | (e.g. return, raise, break, continue, pass)
|
|---|
| 2017 |
|
|---|
| 2018 | This function is normally bound to `indent-line-function' so
|
|---|
| 2019 | \\[indent-for-tab-command] will call it."
|
|---|
| 2020 | (interactive "P")
|
|---|
| 2021 | (let* ((ci (current-indentation))
|
|---|
| 2022 | (move-to-indentation-p (<= (current-column) ci))
|
|---|
| 2023 | (need (py-compute-indentation (not arg))))
|
|---|
| 2024 | ;; see if we need to dedent
|
|---|
| 2025 | (if (py-outdent-p)
|
|---|
| 2026 | (setq need (- need py-indent-offset)))
|
|---|
| 2027 | (if (/= ci need)
|
|---|
| 2028 | (save-excursion
|
|---|
| 2029 | (beginning-of-line)
|
|---|
| 2030 | (delete-horizontal-space)
|
|---|
| 2031 | (indent-to need)))
|
|---|
| 2032 | (if move-to-indentation-p (back-to-indentation))))
|
|---|
| 2033 |
|
|---|
| 2034 | (defun py-newline-and-indent ()
|
|---|
| 2035 | "Strives to act like the Emacs `newline-and-indent'.
|
|---|
| 2036 | This is just `strives to' because correct indentation can't be computed
|
|---|
| 2037 | from scratch for Python code. In general, deletes the whitespace before
|
|---|
| 2038 | point, inserts a newline, and takes an educated guess as to how you want
|
|---|
| 2039 | the new line indented."
|
|---|
| 2040 | (interactive)
|
|---|
| 2041 | (let ((ci (current-indentation)))
|
|---|
| 2042 | (if (< ci (current-column)) ; if point beyond indentation
|
|---|
| 2043 | (newline-and-indent)
|
|---|
| 2044 | ;; else try to act like newline-and-indent "normally" acts
|
|---|
| 2045 | (beginning-of-line)
|
|---|
| 2046 | (insert-char ?\n 1)
|
|---|
| 2047 | (move-to-column ci))))
|
|---|
| 2048 |
|
|---|
| 2049 | (defun py-compute-indentation (honor-block-close-p)
|
|---|
| 2050 | "Compute Python indentation.
|
|---|
| 2051 | When HONOR-BLOCK-CLOSE-P is non-nil, statements such as `return',
|
|---|
| 2052 | `raise', `break', `continue', and `pass' force one level of
|
|---|
| 2053 | dedenting."
|
|---|
| 2054 | (save-excursion
|
|---|
| 2055 | (beginning-of-line)
|
|---|
| 2056 | (let* ((bod (py-point 'bod))
|
|---|
| 2057 | (pps (parse-partial-sexp bod (point)))
|
|---|
| 2058 | (boipps (parse-partial-sexp bod (py-point 'boi)))
|
|---|
| 2059 | placeholder)
|
|---|
| 2060 | (cond
|
|---|
| 2061 | ;; are we inside a multi-line string or comment?
|
|---|
| 2062 | ((or (and (nth 3 pps) (nth 3 boipps))
|
|---|
| 2063 | (and (nth 4 pps) (nth 4 boipps)))
|
|---|
| 2064 | (save-excursion
|
|---|
| 2065 | (if (not py-align-multiline-strings-p) 0
|
|---|
| 2066 | ;; skip back over blank & non-indenting comment lines
|
|---|
| 2067 | ;; note: will skip a blank or non-indenting comment line
|
|---|
| 2068 | ;; that happens to be a continuation line too
|
|---|
| 2069 | (re-search-backward "^[ \t]*\\([^ \t\n#]\\|#[ \t\n]\\)" nil 'move)
|
|---|
| 2070 | (back-to-indentation)
|
|---|
| 2071 | (current-column))))
|
|---|
| 2072 | ;; are we on a continuation line?
|
|---|
| 2073 | ((py-continuation-line-p)
|
|---|
| 2074 | (let ((startpos (point))
|
|---|
| 2075 | (open-bracket-pos (py-nesting-level))
|
|---|
| 2076 | endpos searching found state)
|
|---|
| 2077 | (if open-bracket-pos
|
|---|
| 2078 | (progn
|
|---|
| 2079 | ;; align with first item in list; else a normal
|
|---|
| 2080 | ;; indent beyond the line with the open bracket
|
|---|
| 2081 | (goto-char (1+ open-bracket-pos)) ; just beyond bracket
|
|---|
| 2082 | ;; is the first list item on the same line?
|
|---|
| 2083 | (skip-chars-forward " \t")
|
|---|
| 2084 | (if (null (memq (following-char) '(?\n ?# ?\\)))
|
|---|
| 2085 | ; yes, so line up with it
|
|---|
| 2086 | (current-column)
|
|---|
| 2087 | ;; first list item on another line, or doesn't exist yet
|
|---|
| 2088 | (forward-line 1)
|
|---|
| 2089 | (while (and (< (point) startpos)
|
|---|
| 2090 | (looking-at "[ \t]*[#\n\\\\]")) ; skip noise
|
|---|
| 2091 | (forward-line 1))
|
|---|
| 2092 | (if (and (< (point) startpos)
|
|---|
| 2093 | (/= startpos
|
|---|
| 2094 | (save-excursion
|
|---|
| 2095 | (goto-char (1+ open-bracket-pos))
|
|---|
| 2096 | (forward-comment (point-max))
|
|---|
| 2097 | (point))))
|
|---|
| 2098 | ;; again mimic the first list item
|
|---|
| 2099 | (current-indentation)
|
|---|
| 2100 | ;; else they're about to enter the first item
|
|---|
| 2101 | (goto-char open-bracket-pos)
|
|---|
| 2102 | (setq placeholder (point))
|
|---|
| 2103 | (py-goto-initial-line)
|
|---|
| 2104 | (py-goto-beginning-of-tqs
|
|---|
| 2105 | (save-excursion (nth 3 (parse-partial-sexp
|
|---|
| 2106 | placeholder (point)))))
|
|---|
| 2107 | (+ (current-indentation) py-indent-offset))))
|
|---|
| 2108 |
|
|---|
| 2109 | ;; else on backslash continuation line
|
|---|
| 2110 | (forward-line -1)
|
|---|
| 2111 | (if (py-continuation-line-p) ; on at least 3rd line in block
|
|---|
| 2112 | (current-indentation) ; so just continue the pattern
|
|---|
| 2113 | ;; else started on 2nd line in block, so indent more.
|
|---|
| 2114 | ;; if base line is an assignment with a start on a RHS,
|
|---|
| 2115 | ;; indent to 2 beyond the leftmost "="; else skip first
|
|---|
| 2116 | ;; chunk of non-whitespace characters on base line, + 1 more
|
|---|
| 2117 | ;; column
|
|---|
| 2118 | (end-of-line)
|
|---|
| 2119 | (setq endpos (point)
|
|---|
| 2120 | searching t)
|
|---|
| 2121 | (back-to-indentation)
|
|---|
| 2122 | (setq startpos (point))
|
|---|
| 2123 | ;; look at all "=" from left to right, stopping at first
|
|---|
| 2124 | ;; one not nested in a list or string
|
|---|
| 2125 | (while searching
|
|---|
| 2126 | (skip-chars-forward "^=" endpos)
|
|---|
| 2127 | (if (= (point) endpos)
|
|---|
| 2128 | (setq searching nil)
|
|---|
| 2129 | (forward-char 1)
|
|---|
| 2130 | (setq state (parse-partial-sexp startpos (point)))
|
|---|
| 2131 | (if (and (zerop (car state)) ; not in a bracket
|
|---|
| 2132 | (null (nth 3 state))) ; & not in a string
|
|---|
| 2133 | (progn
|
|---|
| 2134 | (setq searching nil) ; done searching in any case
|
|---|
| 2135 | (setq found
|
|---|
| 2136 | (not (or
|
|---|
| 2137 | (eq (following-char) ?=)
|
|---|
| 2138 | (memq (char-after (- (point) 2))
|
|---|
| 2139 | '(?< ?> ?!)))))))))
|
|---|
| 2140 | (if (or (not found) ; not an assignment
|
|---|
| 2141 | (looking-at "[ \t]*\\\\")) ; <=><spaces><backslash>
|
|---|
| 2142 | (progn
|
|---|
| 2143 | (goto-char startpos)
|
|---|
| 2144 | (skip-chars-forward "^ \t\n")))
|
|---|
| 2145 | ;; if this is a continuation for a block opening
|
|---|
| 2146 | ;; statement, add some extra offset.
|
|---|
| 2147 | (+ (current-column) (if (py-statement-opens-block-p)
|
|---|
| 2148 | py-continuation-offset 0)
|
|---|
| 2149 | 1)
|
|---|
| 2150 | ))))
|
|---|
| 2151 |
|
|---|
| 2152 | ;; not on a continuation line
|
|---|
| 2153 | ((bobp) (current-indentation))
|
|---|
| 2154 |
|
|---|
| 2155 | ;; Dfn: "Indenting comment line". A line containing only a
|
|---|
| 2156 | ;; comment, but which is treated like a statement for
|
|---|
| 2157 | ;; indentation calculation purposes. Such lines are only
|
|---|
| 2158 | ;; treated specially by the mode; they are not treated
|
|---|
| 2159 | ;; specially by the Python interpreter.
|
|---|
| 2160 |
|
|---|
| 2161 | ;; The rules for indenting comment lines are a line where:
|
|---|
| 2162 | ;; - the first non-whitespace character is `#', and
|
|---|
| 2163 | ;; - the character following the `#' is whitespace, and
|
|---|
| 2164 | ;; - the line is dedented with respect to (i.e. to the left
|
|---|
| 2165 | ;; of) the indentation of the preceding non-blank line.
|
|---|
| 2166 |
|
|---|
| 2167 | ;; The first non-blank line following an indenting comment
|
|---|
| 2168 | ;; line is given the same amount of indentation as the
|
|---|
| 2169 | ;; indenting comment line.
|
|---|
| 2170 |
|
|---|
| 2171 | ;; All other comment-only lines are ignored for indentation
|
|---|
| 2172 | ;; purposes.
|
|---|
| 2173 |
|
|---|
| 2174 | ;; Are we looking at a comment-only line which is *not* an
|
|---|
| 2175 | ;; indenting comment line? If so, we assume that it's been
|
|---|
| 2176 | ;; placed at the desired indentation, so leave it alone.
|
|---|
| 2177 | ;; Indenting comment lines are aligned as statements down
|
|---|
| 2178 | ;; below.
|
|---|
| 2179 | ((and (looking-at "[ \t]*#[^ \t\n]")
|
|---|
| 2180 | ;; NOTE: this test will not be performed in older Emacsen
|
|---|
| 2181 | (fboundp 'forward-comment)
|
|---|
| 2182 | (<= (current-indentation)
|
|---|
| 2183 | (save-excursion
|
|---|
| 2184 | (forward-comment (- (point-max)))
|
|---|
| 2185 | (current-indentation))))
|
|---|
| 2186 | (current-indentation))
|
|---|
| 2187 |
|
|---|
| 2188 | ;; else indentation based on that of the statement that
|
|---|
| 2189 | ;; precedes us; use the first line of that statement to
|
|---|
| 2190 | ;; establish the base, in case the user forced a non-std
|
|---|
| 2191 | ;; indentation for the continuation lines (if any)
|
|---|
| 2192 | (t
|
|---|
| 2193 | ;; skip back over blank & non-indenting comment lines note:
|
|---|
| 2194 | ;; will skip a blank or non-indenting comment line that
|
|---|
| 2195 | ;; happens to be a continuation line too. use fast Emacs 19
|
|---|
| 2196 | ;; function if it's there.
|
|---|
| 2197 | (if (and (eq py-honor-comment-indentation nil)
|
|---|
| 2198 | (fboundp 'forward-comment))
|
|---|
| 2199 | (forward-comment (- (point-max)))
|
|---|
| 2200 | (let ((prefix-re (concat py-block-comment-prefix "[ \t]*"))
|
|---|
| 2201 | done)
|
|---|
| 2202 | (while (not done)
|
|---|
| 2203 | (re-search-backward "^[ \t]*\\([^ \t\n#]\\|#\\)" nil 'move)
|
|---|
| 2204 | (setq done (or (bobp)
|
|---|
| 2205 | (and (eq py-honor-comment-indentation t)
|
|---|
| 2206 | (save-excursion
|
|---|
| 2207 | (back-to-indentation)
|
|---|
| 2208 | (not (looking-at prefix-re))
|
|---|
| 2209 | ))
|
|---|
| 2210 | (and (not (eq py-honor-comment-indentation t))
|
|---|
| 2211 | (save-excursion
|
|---|
| 2212 | (back-to-indentation)
|
|---|
| 2213 | (and (not (looking-at prefix-re))
|
|---|
| 2214 | (or (looking-at "[^#]")
|
|---|
| 2215 | (not (zerop (current-column)))
|
|---|
| 2216 | ))
|
|---|
| 2217 | ))
|
|---|
| 2218 | ))
|
|---|
| 2219 | )))
|
|---|
| 2220 | ;; if we landed inside a string, go to the beginning of that
|
|---|
| 2221 | ;; string. this handles triple quoted, multi-line spanning
|
|---|
| 2222 | ;; strings.
|
|---|
| 2223 | (py-goto-beginning-of-tqs (nth 3 (parse-partial-sexp bod (point))))
|
|---|
| 2224 | ;; now skip backward over continued lines
|
|---|
| 2225 | (setq placeholder (point))
|
|---|
| 2226 | (py-goto-initial-line)
|
|---|
| 2227 | ;; we may *now* have landed in a TQS, so find the beginning of
|
|---|
| 2228 | ;; this string.
|
|---|
| 2229 | (py-goto-beginning-of-tqs
|
|---|
| 2230 | (save-excursion (nth 3 (parse-partial-sexp
|
|---|
| 2231 | placeholder (point)))))
|
|---|
| 2232 | (+ (current-indentation)
|
|---|
| 2233 | (if (py-statement-opens-block-p)
|
|---|
| 2234 | py-indent-offset
|
|---|
| 2235 | (if (and honor-block-close-p (py-statement-closes-block-p))
|
|---|
| 2236 | (- py-indent-offset)
|
|---|
| 2237 | 0)))
|
|---|
| 2238 | )))))
|
|---|
| 2239 |
|
|---|
| 2240 | (defun py-guess-indent-offset (&optional global)
|
|---|
| 2241 | "Guess a good value for, and change, `py-indent-offset'.
|
|---|
| 2242 |
|
|---|
| 2243 | By default, make a buffer-local copy of `py-indent-offset' with the
|
|---|
| 2244 | new value, so that other Python buffers are not affected. With
|
|---|
| 2245 | \\[universal-argument] (programmatically, optional argument GLOBAL),
|
|---|
| 2246 | change the global value of `py-indent-offset'. This affects all
|
|---|
| 2247 | Python buffers (that don't have their own buffer-local copy), both
|
|---|
| 2248 | those currently existing and those created later in the Emacs session.
|
|---|
| 2249 |
|
|---|
| 2250 | Some people use a different value for `py-indent-offset' than you use.
|
|---|
| 2251 | There's no excuse for such foolishness, but sometimes you have to deal
|
|---|
| 2252 | with their ugly code anyway. This function examines the file and sets
|
|---|
| 2253 | `py-indent-offset' to what it thinks it was when they created the
|
|---|
| 2254 | mess.
|
|---|
| 2255 |
|
|---|
| 2256 | Specifically, it searches forward from the statement containing point,
|
|---|
| 2257 | looking for a line that opens a block of code. `py-indent-offset' is
|
|---|
| 2258 | set to the difference in indentation between that line and the Python
|
|---|
| 2259 | statement following it. If the search doesn't succeed going forward,
|
|---|
| 2260 | it's tried again going backward."
|
|---|
| 2261 | (interactive "P") ; raw prefix arg
|
|---|
| 2262 | (let (new-value
|
|---|
| 2263 | (start (point))
|
|---|
| 2264 | (restart (point))
|
|---|
| 2265 | (found nil)
|
|---|
| 2266 | colon-indent)
|
|---|
| 2267 | (py-goto-initial-line)
|
|---|
| 2268 | (while (not (or found (eobp)))
|
|---|
| 2269 | (when (and (re-search-forward ":[ \t]*\\($\\|[#\\]\\)" nil 'move)
|
|---|
| 2270 | (not (py-in-literal restart)))
|
|---|
| 2271 | (setq restart (point))
|
|---|
| 2272 | (py-goto-initial-line)
|
|---|
| 2273 | (if (py-statement-opens-block-p)
|
|---|
| 2274 | (setq found t)
|
|---|
| 2275 | (goto-char restart))))
|
|---|
| 2276 | (unless found
|
|---|
| 2277 | (goto-char start)
|
|---|
| 2278 | (py-goto-initial-line)
|
|---|
| 2279 | (while (not (or found (bobp)))
|
|---|
| 2280 | (setq found (and
|
|---|
| 2281 | (re-search-backward ":[ \t]*\\($\\|[#\\]\\)" nil 'move)
|
|---|
| 2282 | (or (py-goto-initial-line) t) ; always true -- side effect
|
|---|
| 2283 | (py-statement-opens-block-p)))))
|
|---|
| 2284 | (setq colon-indent (current-indentation)
|
|---|
| 2285 | found (and found (zerop (py-next-statement 1)))
|
|---|
| 2286 | new-value (- (current-indentation) colon-indent))
|
|---|
| 2287 | (goto-char start)
|
|---|
| 2288 | (if (not found)
|
|---|
| 2289 | (error "Sorry, couldn't guess a value for py-indent-offset")
|
|---|
| 2290 | (funcall (if global 'kill-local-variable 'make-local-variable)
|
|---|
| 2291 | 'py-indent-offset)
|
|---|
| 2292 | (setq py-indent-offset new-value)
|
|---|
| 2293 | (or noninteractive
|
|---|
| 2294 | (message "%s value of py-indent-offset set to %d"
|
|---|
| 2295 | (if global "Global" "Local")
|
|---|
| 2296 | py-indent-offset)))
|
|---|
| 2297 | ))
|
|---|
| 2298 |
|
|---|
| 2299 | (defun py-comment-indent-function ()
|
|---|
| 2300 | "Python version of `comment-indent-function'."
|
|---|
| 2301 | ;; This is required when filladapt is turned off. Without it, when
|
|---|
| 2302 | ;; filladapt is not used, comments which start in column zero
|
|---|
| 2303 | ;; cascade one character to the right
|
|---|
| 2304 | (save-excursion
|
|---|
| 2305 | (beginning-of-line)
|
|---|
| 2306 | (let ((eol (py-point 'eol)))
|
|---|
| 2307 | (and comment-start-skip
|
|---|
| 2308 | (re-search-forward comment-start-skip eol t)
|
|---|
| 2309 | (setq eol (match-beginning 0)))
|
|---|
| 2310 | (goto-char eol)
|
|---|
| 2311 | (skip-chars-backward " \t")
|
|---|
| 2312 | (max comment-column (+ (current-column) (if (bolp) 0 1)))
|
|---|
| 2313 | )))
|
|---|
| 2314 |
|
|---|
| 2315 | (defun py-narrow-to-defun (&optional class)
|
|---|
| 2316 | "Make text outside current defun invisible.
|
|---|
| 2317 | The defun visible is the one that contains point or follows point.
|
|---|
| 2318 | Optional CLASS is passed directly to `py-beginning-of-def-or-class'."
|
|---|
| 2319 | (interactive "P")
|
|---|
| 2320 | (save-excursion
|
|---|
| 2321 | (widen)
|
|---|
| 2322 | (py-end-of-def-or-class class)
|
|---|
| 2323 | (let ((end (point)))
|
|---|
| 2324 | (py-beginning-of-def-or-class class)
|
|---|
| 2325 | (narrow-to-region (point) end))))
|
|---|
| 2326 |
|
|---|
| 2327 | |
|---|
| 2328 |
|
|---|
| 2329 | (defun py-shift-region (start end count)
|
|---|
| 2330 | "Indent lines from START to END by COUNT spaces."
|
|---|
| 2331 | (save-excursion
|
|---|
| 2332 | (goto-char end)
|
|---|
| 2333 | (beginning-of-line)
|
|---|
| 2334 | (setq end (point))
|
|---|
| 2335 | (goto-char start)
|
|---|
| 2336 | (beginning-of-line)
|
|---|
| 2337 | (setq start (point))
|
|---|
| 2338 | (indent-rigidly start end count)))
|
|---|
| 2339 |
|
|---|
| 2340 | (defun py-shift-region-left (start end &optional count)
|
|---|
| 2341 | "Shift region of Python code to the left.
|
|---|
| 2342 | The lines from the line containing the start of the current region up
|
|---|
| 2343 | to (but not including) the line containing the end of the region are
|
|---|
| 2344 | shifted to the left, by `py-indent-offset' columns.
|
|---|
| 2345 |
|
|---|
| 2346 | If a prefix argument is given, the region is instead shifted by that
|
|---|
| 2347 | many columns. With no active region, dedent only the current line.
|
|---|
| 2348 | You cannot dedent the region if any line is already at column zero."
|
|---|
| 2349 | (interactive
|
|---|
| 2350 | (let ((p (point))
|
|---|
| 2351 | (m (mark))
|
|---|
| 2352 | (arg current-prefix-arg))
|
|---|
| 2353 | (if m
|
|---|
| 2354 | (list (min p m) (max p m) arg)
|
|---|
| 2355 | (list p (save-excursion (forward-line 1) (point)) arg))))
|
|---|
| 2356 | ;; if any line is at column zero, don't shift the region
|
|---|
| 2357 | (save-excursion
|
|---|
| 2358 | (goto-char start)
|
|---|
| 2359 | (while (< (point) end)
|
|---|
| 2360 | (back-to-indentation)
|
|---|
| 2361 | (if (and (zerop (current-column))
|
|---|
| 2362 | (not (looking-at "\\s *$")))
|
|---|
| 2363 | (error "Region is at left edge"))
|
|---|
| 2364 | (forward-line 1)))
|
|---|
| 2365 | (py-shift-region start end (- (prefix-numeric-value
|
|---|
| 2366 | (or count py-indent-offset))))
|
|---|
| 2367 | (py-keep-region-active))
|
|---|
| 2368 |
|
|---|
| 2369 | (defun py-shift-region-right (start end &optional count)
|
|---|
| 2370 | "Shift region of Python code to the right.
|
|---|
| 2371 | The lines from the line containing the start of the current region up
|
|---|
| 2372 | to (but not including) the line containing the end of the region are
|
|---|
| 2373 | shifted to the right, by `py-indent-offset' columns.
|
|---|
| 2374 |
|
|---|
| 2375 | If a prefix argument is given, the region is instead shifted by that
|
|---|
| 2376 | many columns. With no active region, indent only the current line."
|
|---|
| 2377 | (interactive
|
|---|
| 2378 | (let ((p (point))
|
|---|
| 2379 | (m (mark))
|
|---|
| 2380 | (arg current-prefix-arg))
|
|---|
| 2381 | (if m
|
|---|
| 2382 | (list (min p m) (max p m) arg)
|
|---|
| 2383 | (list p (save-excursion (forward-line 1) (point)) arg))))
|
|---|
| 2384 | (py-shift-region start end (prefix-numeric-value
|
|---|
| 2385 | (or count py-indent-offset)))
|
|---|
| 2386 | (py-keep-region-active))
|
|---|
| 2387 |
|
|---|
| 2388 | (defun py-indent-region (start end &optional indent-offset)
|
|---|
| 2389 | "Reindent a region of Python code.
|
|---|
| 2390 |
|
|---|
| 2391 | The lines from the line containing the start of the current region up
|
|---|
| 2392 | to (but not including) the line containing the end of the region are
|
|---|
| 2393 | reindented. If the first line of the region has a non-whitespace
|
|---|
| 2394 | character in the first column, the first line is left alone and the
|
|---|
| 2395 | rest of the region is reindented with respect to it. Else the entire
|
|---|
| 2396 | region is reindented with respect to the (closest code or indenting
|
|---|
| 2397 | comment) statement immediately preceding the region.
|
|---|
| 2398 |
|
|---|
| 2399 | This is useful when code blocks are moved or yanked, when enclosing
|
|---|
| 2400 | control structures are introduced or removed, or to reformat code
|
|---|
| 2401 | using a new value for the indentation offset.
|
|---|
| 2402 |
|
|---|
| 2403 | If a numeric prefix argument is given, it will be used as the value of
|
|---|
| 2404 | the indentation offset. Else the value of `py-indent-offset' will be
|
|---|
| 2405 | used.
|
|---|
| 2406 |
|
|---|
| 2407 | Warning: The region must be consistently indented before this function
|
|---|
| 2408 | is called! This function does not compute proper indentation from
|
|---|
| 2409 | scratch (that's impossible in Python), it merely adjusts the existing
|
|---|
| 2410 | indentation to be correct in context.
|
|---|
| 2411 |
|
|---|
| 2412 | Warning: This function really has no idea what to do with
|
|---|
| 2413 | non-indenting comment lines, and shifts them as if they were indenting
|
|---|
| 2414 | comment lines. Fixing this appears to require telepathy.
|
|---|
| 2415 |
|
|---|
| 2416 | Special cases: whitespace is deleted from blank lines; continuation
|
|---|
| 2417 | lines are shifted by the same amount their initial line was shifted,
|
|---|
| 2418 | in order to preserve their relative indentation with respect to their
|
|---|
| 2419 | initial line; and comment lines beginning in column 1 are ignored."
|
|---|
| 2420 | (interactive "*r\nP") ; region; raw prefix arg
|
|---|
| 2421 | (save-excursion
|
|---|
| 2422 | (goto-char end) (beginning-of-line) (setq end (point-marker))
|
|---|
| 2423 | (goto-char start) (beginning-of-line)
|
|---|
| 2424 | (let ((py-indent-offset (prefix-numeric-value
|
|---|
| 2425 | (or indent-offset py-indent-offset)))
|
|---|
| 2426 | (indents '(-1)) ; stack of active indent levels
|
|---|
| 2427 | (target-column 0) ; column to which to indent
|
|---|
| 2428 | (base-shifted-by 0) ; amount last base line was shifted
|
|---|
| 2429 | (indent-base (if (looking-at "[ \t\n]")
|
|---|
| 2430 | (py-compute-indentation t)
|
|---|
| 2431 | 0))
|
|---|
| 2432 | ci)
|
|---|
| 2433 | (while (< (point) end)
|
|---|
| 2434 | (setq ci (current-indentation))
|
|---|
| 2435 | ;; figure out appropriate target column
|
|---|
| 2436 | (cond
|
|---|
| 2437 | ((or (eq (following-char) ?#) ; comment in column 1
|
|---|
| 2438 | (looking-at "[ \t]*$")) ; entirely blank
|
|---|
| 2439 | (setq target-column 0))
|
|---|
| 2440 | ((py-continuation-line-p) ; shift relative to base line
|
|---|
| 2441 | (setq target-column (+ ci base-shifted-by)))
|
|---|
| 2442 | (t ; new base line
|
|---|
| 2443 | (if (> ci (car indents)) ; going deeper; push it
|
|---|
| 2444 | (setq indents (cons ci indents))
|
|---|
| 2445 | ;; else we should have seen this indent before
|
|---|
| 2446 | (setq indents (memq ci indents)) ; pop deeper indents
|
|---|
| 2447 | (if (null indents)
|
|---|
| 2448 | (error "Bad indentation in region, at line %d"
|
|---|
| 2449 | (save-restriction
|
|---|
| 2450 | (widen)
|
|---|
| 2451 | (1+ (count-lines 1 (point)))))))
|
|---|
| 2452 | (setq target-column (+ indent-base
|
|---|
| 2453 | (* py-indent-offset
|
|---|
| 2454 | (- (length indents) 2))))
|
|---|
| 2455 | (setq base-shifted-by (- target-column ci))))
|
|---|
| 2456 | ;; shift as needed
|
|---|
| 2457 | (if (/= ci target-column)
|
|---|
| 2458 | (progn
|
|---|
| 2459 | (delete-horizontal-space)
|
|---|
| 2460 | (indent-to target-column)))
|
|---|
| 2461 | (forward-line 1))))
|
|---|
| 2462 | (set-marker end nil))
|
|---|
| 2463 |
|
|---|
| 2464 | (defun py-comment-region (beg end &optional arg)
|
|---|
| 2465 | "Like `comment-region' but uses double hash (`#') comment starter."
|
|---|
| 2466 | (interactive "r\nP")
|
|---|
| 2467 | (let ((comment-start py-block-comment-prefix))
|
|---|
| 2468 | (comment-region beg end arg)))
|
|---|
| 2469 |
|
|---|
| 2470 | |
|---|
| 2471 |
|
|---|
| 2472 | ;; Functions for moving point
|
|---|
| 2473 | (defun py-previous-statement (count)
|
|---|
| 2474 | "Go to the start of the COUNTth preceding Python statement.
|
|---|
| 2475 | By default, goes to the previous statement. If there is no such
|
|---|
| 2476 | statement, goes to the first statement. Return count of statements
|
|---|
| 2477 | left to move. `Statements' do not include blank, comment, or
|
|---|
| 2478 | continuation lines."
|
|---|
| 2479 | (interactive "p") ; numeric prefix arg
|
|---|
| 2480 | (if (< count 0) (py-next-statement (- count))
|
|---|
| 2481 | (py-goto-initial-line)
|
|---|
| 2482 | (let (start)
|
|---|
| 2483 | (while (and
|
|---|
| 2484 | (setq start (point)) ; always true -- side effect
|
|---|
| 2485 | (> count 0)
|
|---|
| 2486 | (zerop (forward-line -1))
|
|---|
| 2487 | (py-goto-statement-at-or-above))
|
|---|
| 2488 | (setq count (1- count)))
|
|---|
| 2489 | (if (> count 0) (goto-char start)))
|
|---|
| 2490 | count))
|
|---|
| 2491 |
|
|---|
| 2492 | (defun py-next-statement (count)
|
|---|
| 2493 | "Go to the start of next Python statement.
|
|---|
| 2494 | If the statement at point is the i'th Python statement, goes to the
|
|---|
| 2495 | start of statement i+COUNT. If there is no such statement, goes to the
|
|---|
| 2496 | last statement. Returns count of statements left to move. `Statements'
|
|---|
| 2497 | do not include blank, comment, or continuation lines."
|
|---|
| 2498 | (interactive "p") ; numeric prefix arg
|
|---|
| 2499 | (if (< count 0) (py-previous-statement (- count))
|
|---|
| 2500 | (beginning-of-line)
|
|---|
| 2501 | (let (start)
|
|---|
| 2502 | (while (and
|
|---|
| 2503 | (setq start (point)) ; always true -- side effect
|
|---|
| 2504 | (> count 0)
|
|---|
| 2505 | (py-goto-statement-below))
|
|---|
| 2506 | (setq count (1- count)))
|
|---|
| 2507 | (if (> count 0) (goto-char start)))
|
|---|
| 2508 | count))
|
|---|
| 2509 |
|
|---|
| 2510 | (defun py-goto-block-up (&optional nomark)
|
|---|
| 2511 | "Move up to start of current block.
|
|---|
| 2512 | Go to the statement that starts the smallest enclosing block; roughly
|
|---|
| 2513 | speaking, this will be the closest preceding statement that ends with a
|
|---|
| 2514 | colon and is indented less than the statement you started on. If
|
|---|
| 2515 | successful, also sets the mark to the starting point.
|
|---|
| 2516 |
|
|---|
| 2517 | `\\[py-mark-block]' can be used afterward to mark the whole code
|
|---|
| 2518 | block, if desired.
|
|---|
| 2519 |
|
|---|
| 2520 | If called from a program, the mark will not be set if optional argument
|
|---|
| 2521 | NOMARK is not nil."
|
|---|
| 2522 | (interactive)
|
|---|
| 2523 | (let ((start (point))
|
|---|
| 2524 | (found nil)
|
|---|
| 2525 | initial-indent)
|
|---|
| 2526 | (py-goto-initial-line)
|
|---|
| 2527 | ;; if on blank or non-indenting comment line, use the preceding stmt
|
|---|
| 2528 | (if (looking-at "[ \t]*\\($\\|#[^ \t\n]\\)")
|
|---|
| 2529 | (progn
|
|---|
| 2530 | (py-goto-statement-at-or-above)
|
|---|
| 2531 | (setq found (py-statement-opens-block-p))))
|
|---|
| 2532 | ;; search back for colon line indented less
|
|---|
| 2533 | (setq initial-indent (current-indentation))
|
|---|
| 2534 | (if (zerop initial-indent)
|
|---|
| 2535 | ;; force fast exit
|
|---|
| 2536 | (goto-char (point-min)))
|
|---|
| 2537 | (while (not (or found (bobp)))
|
|---|
| 2538 | (setq found
|
|---|
| 2539 | (and
|
|---|
| 2540 | (re-search-backward ":[ \t]*\\($\\|[#\\]\\)" nil 'move)
|
|---|
| 2541 | (or (py-goto-initial-line) t) ; always true -- side effect
|
|---|
| 2542 | (< (current-indentation) initial-indent)
|
|---|
| 2543 | (py-statement-opens-block-p))))
|
|---|
| 2544 | (if found
|
|---|
| 2545 | (progn
|
|---|
| 2546 | (or nomark (push-mark start))
|
|---|
| 2547 | (back-to-indentation))
|
|---|
| 2548 | (goto-char start)
|
|---|
| 2549 | (error "Enclosing block not found"))))
|
|---|
| 2550 |
|
|---|
| 2551 | (defun py-beginning-of-def-or-class (&optional class count)
|
|---|
| 2552 | "Move point to start of `def' or `class'.
|
|---|
| 2553 |
|
|---|
| 2554 | Searches back for the closest preceding `def'. If you supply a prefix
|
|---|
| 2555 | arg, looks for a `class' instead. The docs below assume the `def'
|
|---|
| 2556 | case; just substitute `class' for `def' for the other case.
|
|---|
| 2557 | Programmatically, if CLASS is `either', then moves to either `class'
|
|---|
| 2558 | or `def'.
|
|---|
| 2559 |
|
|---|
| 2560 | When second optional argument is given programmatically, move to the
|
|---|
| 2561 | COUNTth start of `def'.
|
|---|
| 2562 |
|
|---|
| 2563 | If point is in a `def' statement already, and after the `d', simply
|
|---|
| 2564 | moves point to the start of the statement.
|
|---|
| 2565 |
|
|---|
| 2566 | Otherwise (i.e. when point is not in a `def' statement, or at or
|
|---|
| 2567 | before the `d' of a `def' statement), searches for the closest
|
|---|
| 2568 | preceding `def' statement, and leaves point at its start. If no such
|
|---|
| 2569 | statement can be found, leaves point at the start of the buffer.
|
|---|
| 2570 |
|
|---|
| 2571 | Returns t iff a `def' statement is found by these rules.
|
|---|
| 2572 |
|
|---|
| 2573 | Note that doing this command repeatedly will take you closer to the
|
|---|
| 2574 | start of the buffer each time.
|
|---|
| 2575 |
|
|---|
| 2576 | To mark the current `def', see `\\[py-mark-def-or-class]'."
|
|---|
| 2577 | (interactive "P") ; raw prefix arg
|
|---|
| 2578 | (setq count (or count 1))
|
|---|
| 2579 | (let ((at-or-before-p (<= (current-column) (current-indentation)))
|
|---|
| 2580 | (start-of-line (goto-char (py-point 'bol)))
|
|---|
| 2581 | (start-of-stmt (goto-char (py-point 'bos)))
|
|---|
| 2582 | (start-re (cond ((eq class 'either) "^[ \t]*\\(class\\|def\\)\\>")
|
|---|
| 2583 | (class "^[ \t]*class\\>")
|
|---|
| 2584 | (t "^[ \t]*def\\>")))
|
|---|
| 2585 | )
|
|---|
| 2586 | ;; searching backward
|
|---|
| 2587 | (if (and (< 0 count)
|
|---|
| 2588 | (or (/= start-of-stmt start-of-line)
|
|---|
| 2589 | (not at-or-before-p)))
|
|---|
| 2590 | (end-of-line))
|
|---|
| 2591 | ;; search forward
|
|---|
| 2592 | (if (and (> 0 count)
|
|---|
| 2593 | (zerop (current-column))
|
|---|
| 2594 | (looking-at start-re))
|
|---|
| 2595 | (end-of-line))
|
|---|
| 2596 | (if (re-search-backward start-re nil 'move count)
|
|---|
| 2597 | (goto-char (match-beginning 0)))))
|
|---|
| 2598 |
|
|---|
| 2599 | ;; Backwards compatibility
|
|---|
| 2600 | (defalias 'beginning-of-python-def-or-class 'py-beginning-of-def-or-class)
|
|---|
| 2601 |
|
|---|
| 2602 | (defun py-end-of-def-or-class (&optional class count)
|
|---|
| 2603 | "Move point beyond end of `def' or `class' body.
|
|---|
| 2604 |
|
|---|
| 2605 | By default, looks for an appropriate `def'. If you supply a prefix
|
|---|
| 2606 | arg, looks for a `class' instead. The docs below assume the `def'
|
|---|
| 2607 | case; just substitute `class' for `def' for the other case.
|
|---|
| 2608 | Programmatically, if CLASS is `either', then moves to either `class'
|
|---|
| 2609 | or `def'.
|
|---|
| 2610 |
|
|---|
| 2611 | When second optional argument is given programmatically, move to the
|
|---|
| 2612 | COUNTth end of `def'.
|
|---|
| 2613 |
|
|---|
| 2614 | If point is in a `def' statement already, this is the `def' we use.
|
|---|
| 2615 |
|
|---|
| 2616 | Else, if the `def' found by `\\[py-beginning-of-def-or-class]'
|
|---|
| 2617 | contains the statement you started on, that's the `def' we use.
|
|---|
| 2618 |
|
|---|
| 2619 | Otherwise, we search forward for the closest following `def', and use that.
|
|---|
| 2620 |
|
|---|
| 2621 | If a `def' can be found by these rules, point is moved to the start of
|
|---|
| 2622 | the line immediately following the `def' block, and the position of the
|
|---|
| 2623 | start of the `def' is returned.
|
|---|
| 2624 |
|
|---|
| 2625 | Else point is moved to the end of the buffer, and nil is returned.
|
|---|
| 2626 |
|
|---|
| 2627 | Note that doing this command repeatedly will take you closer to the
|
|---|
| 2628 | end of the buffer each time.
|
|---|
| 2629 |
|
|---|
| 2630 | To mark the current `def', see `\\[py-mark-def-or-class]'."
|
|---|
| 2631 | (interactive "P") ; raw prefix arg
|
|---|
| 2632 | (if (and count (/= count 1))
|
|---|
| 2633 | (py-beginning-of-def-or-class (- 1 count)))
|
|---|
| 2634 | (let ((start (progn (py-goto-initial-line) (point)))
|
|---|
| 2635 | (which (cond ((eq class 'either) "\\(class\\|def\\)")
|
|---|
| 2636 | (class "class")
|
|---|
| 2637 | (t "def")))
|
|---|
| 2638 | (state 'not-found))
|
|---|
| 2639 | ;; move point to start of appropriate def/class
|
|---|
| 2640 | (if (looking-at (concat "[ \t]*" which "\\>")) ; already on one
|
|---|
| 2641 | (setq state 'at-beginning)
|
|---|
| 2642 | ;; else see if py-beginning-of-def-or-class hits container
|
|---|
| 2643 | (if (and (py-beginning-of-def-or-class class)
|
|---|
| 2644 | (progn (py-goto-beyond-block)
|
|---|
| 2645 | (> (point) start)))
|
|---|
| 2646 | (setq state 'at-end)
|
|---|
| 2647 | ;; else search forward
|
|---|
| 2648 | (goto-char start)
|
|---|
| 2649 | (if (re-search-forward (concat "^[ \t]*" which "\\>") nil 'move)
|
|---|
| 2650 | (progn (setq state 'at-beginning)
|
|---|
| 2651 | (beginning-of-line)))))
|
|---|
| 2652 | (cond
|
|---|
| 2653 | ((eq state 'at-beginning) (py-goto-beyond-block) t)
|
|---|
| 2654 | ((eq state 'at-end) t)
|
|---|
| 2655 | ((eq state 'not-found) nil)
|
|---|
| 2656 | (t (error "Internal error in `py-end-of-def-or-class'")))))
|
|---|
| 2657 |
|
|---|
| 2658 | ;; Backwards compabitility
|
|---|
| 2659 | (defalias 'end-of-python-def-or-class 'py-end-of-def-or-class)
|
|---|
| 2660 |
|
|---|
| 2661 | |
|---|
| 2662 |
|
|---|
| 2663 | ;; Functions for marking regions
|
|---|
| 2664 | (defun py-mark-block (&optional extend just-move)
|
|---|
| 2665 | "Mark following block of lines. With prefix arg, mark structure.
|
|---|
| 2666 | Easier to use than explain. It sets the region to an `interesting'
|
|---|
| 2667 | block of succeeding lines. If point is on a blank line, it goes down to
|
|---|
| 2668 | the next non-blank line. That will be the start of the region. The end
|
|---|
| 2669 | of the region depends on the kind of line at the start:
|
|---|
| 2670 |
|
|---|
| 2671 | - If a comment, the region will include all succeeding comment lines up
|
|---|
| 2672 | to (but not including) the next non-comment line (if any).
|
|---|
| 2673 |
|
|---|
| 2674 | - Else if a prefix arg is given, and the line begins one of these
|
|---|
| 2675 | structures:
|
|---|
| 2676 |
|
|---|
| 2677 | if elif else try except finally for while def class
|
|---|
| 2678 |
|
|---|
| 2679 | the region will be set to the body of the structure, including
|
|---|
| 2680 | following blocks that `belong' to it, but excluding trailing blank
|
|---|
| 2681 | and comment lines. E.g., if on a `try' statement, the `try' block
|
|---|
| 2682 | and all (if any) of the following `except' and `finally' blocks
|
|---|
| 2683 | that belong to the `try' structure will be in the region. Ditto
|
|---|
| 2684 | for if/elif/else, for/else and while/else structures, and (a bit
|
|---|
| 2685 | degenerate, since they're always one-block structures) def and
|
|---|
| 2686 | class blocks.
|
|---|
| 2687 |
|
|---|
| 2688 | - Else if no prefix argument is given, and the line begins a Python
|
|---|
| 2689 | block (see list above), and the block is not a `one-liner' (i.e.,
|
|---|
| 2690 | the statement ends with a colon, not with code), the region will
|
|---|
| 2691 | include all succeeding lines up to (but not including) the next
|
|---|
| 2692 | code statement (if any) that's indented no more than the starting
|
|---|
| 2693 | line, except that trailing blank and comment lines are excluded.
|
|---|
| 2694 | E.g., if the starting line begins a multi-statement `def'
|
|---|
| 2695 | structure, the region will be set to the full function definition,
|
|---|
| 2696 | but without any trailing `noise' lines.
|
|---|
| 2697 |
|
|---|
| 2698 | - Else the region will include all succeeding lines up to (but not
|
|---|
| 2699 | including) the next blank line, or code or indenting-comment line
|
|---|
| 2700 | indented strictly less than the starting line. Trailing indenting
|
|---|
| 2701 | comment lines are included in this case, but not trailing blank
|
|---|
| 2702 | lines.
|
|---|
| 2703 |
|
|---|
| 2704 | A msg identifying the location of the mark is displayed in the echo
|
|---|
| 2705 | area; or do `\\[exchange-point-and-mark]' to flip down to the end.
|
|---|
| 2706 |
|
|---|
| 2707 | If called from a program, optional argument EXTEND plays the role of
|
|---|
| 2708 | the prefix arg, and if optional argument JUST-MOVE is not nil, just
|
|---|
| 2709 | moves to the end of the block (& does not set mark or display a msg)."
|
|---|
| 2710 | (interactive "P") ; raw prefix arg
|
|---|
| 2711 | (py-goto-initial-line)
|
|---|
| 2712 | ;; skip over blank lines
|
|---|
| 2713 | (while (and
|
|---|
| 2714 | (looking-at "[ \t]*$") ; while blank line
|
|---|
| 2715 | (not (eobp))) ; & somewhere to go
|
|---|
| 2716 | (forward-line 1))
|
|---|
| 2717 | (if (eobp)
|
|---|
| 2718 | (error "Hit end of buffer without finding a non-blank stmt"))
|
|---|
| 2719 | (let ((initial-pos (point))
|
|---|
| 2720 | (initial-indent (current-indentation))
|
|---|
| 2721 | last-pos ; position of last stmt in region
|
|---|
| 2722 | (followers
|
|---|
| 2723 | '((if elif else) (elif elif else) (else)
|
|---|
| 2724 | (try except finally) (except except) (finally)
|
|---|
| 2725 | (for else) (while else)
|
|---|
| 2726 | (def) (class) ) )
|
|---|
| 2727 | first-symbol next-symbol)
|
|---|
| 2728 |
|
|---|
| 2729 | (cond
|
|---|
| 2730 | ;; if comment line, suck up the following comment lines
|
|---|
| 2731 | ((looking-at "[ \t]*#")
|
|---|
| 2732 | (re-search-forward "^[ \t]*[^ \t#]" nil 'move) ; look for non-comment
|
|---|
| 2733 | (re-search-backward "^[ \t]*#") ; and back to last comment in block
|
|---|
| 2734 | (setq last-pos (point)))
|
|---|
| 2735 |
|
|---|
| 2736 | ;; else if line is a block line and EXTEND given, suck up
|
|---|
| 2737 | ;; the whole structure
|
|---|
| 2738 | ((and extend
|
|---|
| 2739 | (setq first-symbol (py-suck-up-first-keyword) )
|
|---|
| 2740 | (assq first-symbol followers))
|
|---|
| 2741 | (while (and
|
|---|
| 2742 | (or (py-goto-beyond-block) t) ; side effect
|
|---|
| 2743 | (forward-line -1) ; side effect
|
|---|
| 2744 | (setq last-pos (point)) ; side effect
|
|---|
| 2745 | (py-goto-statement-below)
|
|---|
| 2746 | (= (current-indentation) initial-indent)
|
|---|
| 2747 | (setq next-symbol (py-suck-up-first-keyword))
|
|---|
| 2748 | (memq next-symbol (cdr (assq first-symbol followers))))
|
|---|
| 2749 | (setq first-symbol next-symbol)))
|
|---|
| 2750 |
|
|---|
| 2751 | ;; else if line *opens* a block, search for next stmt indented <=
|
|---|
| 2752 | ((py-statement-opens-block-p)
|
|---|
| 2753 | (while (and
|
|---|
| 2754 | (setq last-pos (point)) ; always true -- side effect
|
|---|
| 2755 | (py-goto-statement-below)
|
|---|
| 2756 | (> (current-indentation) initial-indent)
|
|---|
| 2757 | )))
|
|---|
| 2758 |
|
|---|
| 2759 | ;; else plain code line; stop at next blank line, or stmt or
|
|---|
| 2760 | ;; indenting comment line indented <
|
|---|
| 2761 | (t
|
|---|
| 2762 | (while (and
|
|---|
| 2763 | (setq last-pos (point)) ; always true -- side effect
|
|---|
| 2764 | (or (py-goto-beyond-final-line) t)
|
|---|
| 2765 | (not (looking-at "[ \t]*$")) ; stop at blank line
|
|---|
| 2766 | (or
|
|---|
| 2767 | (>= (current-indentation) initial-indent)
|
|---|
| 2768 | (looking-at "[ \t]*#[^ \t\n]"))) ; ignore non-indenting #
|
|---|
| 2769 | nil)))
|
|---|
| 2770 |
|
|---|
| 2771 | ;; skip to end of last stmt
|
|---|
| 2772 | (goto-char last-pos)
|
|---|
| 2773 | (py-goto-beyond-final-line)
|
|---|
| 2774 |
|
|---|
| 2775 | ;; set mark & display
|
|---|
| 2776 | (if just-move
|
|---|
| 2777 | () ; just return
|
|---|
| 2778 | (push-mark (point) 'no-msg)
|
|---|
| 2779 | (forward-line -1)
|
|---|
| 2780 | (message "Mark set after: %s" (py-suck-up-leading-text))
|
|---|
| 2781 | (goto-char initial-pos))))
|
|---|
| 2782 |
|
|---|
| 2783 | (defun py-mark-def-or-class (&optional class)
|
|---|
| 2784 | "Set region to body of def (or class, with prefix arg) enclosing point.
|
|---|
| 2785 | Pushes the current mark, then point, on the mark ring (all language
|
|---|
| 2786 | modes do this, but although it's handy it's never documented ...).
|
|---|
| 2787 |
|
|---|
| 2788 | In most Emacs language modes, this function bears at least a
|
|---|
| 2789 | hallucinogenic resemblance to `\\[py-end-of-def-or-class]' and
|
|---|
| 2790 | `\\[py-beginning-of-def-or-class]'.
|
|---|
| 2791 |
|
|---|
| 2792 | And in earlier versions of Python mode, all 3 were tightly connected.
|
|---|
| 2793 | Turned out that was more confusing than useful: the `goto start' and
|
|---|
| 2794 | `goto end' commands are usually used to search through a file, and
|
|---|
| 2795 | people expect them to act a lot like `search backward' and `search
|
|---|
| 2796 | forward' string-search commands. But because Python `def' and `class'
|
|---|
| 2797 | can nest to arbitrary levels, finding the smallest def containing
|
|---|
| 2798 | point cannot be done via a simple backward search: the def containing
|
|---|
| 2799 | point may not be the closest preceding def, or even the closest
|
|---|
| 2800 | preceding def that's indented less. The fancy algorithm required is
|
|---|
| 2801 | appropriate for the usual uses of this `mark' command, but not for the
|
|---|
| 2802 | `goto' variations.
|
|---|
| 2803 |
|
|---|
| 2804 | So the def marked by this command may not be the one either of the
|
|---|
| 2805 | `goto' commands find: If point is on a blank or non-indenting comment
|
|---|
| 2806 | line, moves back to start of the closest preceding code statement or
|
|---|
| 2807 | indenting comment line. If this is a `def' statement, that's the def
|
|---|
| 2808 | we use. Else searches for the smallest enclosing `def' block and uses
|
|---|
| 2809 | that. Else signals an error.
|
|---|
| 2810 |
|
|---|
| 2811 | When an enclosing def is found: The mark is left immediately beyond
|
|---|
| 2812 | the last line of the def block. Point is left at the start of the
|
|---|
| 2813 | def, except that: if the def is preceded by a number of comment lines
|
|---|
| 2814 | followed by (at most) one optional blank line, point is left at the
|
|---|
| 2815 | start of the comments; else if the def is preceded by a blank line,
|
|---|
| 2816 | point is left at its start.
|
|---|
| 2817 |
|
|---|
| 2818 | The intent is to mark the containing def/class and its associated
|
|---|
| 2819 | documentation, to make moving and duplicating functions and classes
|
|---|
| 2820 | pleasant."
|
|---|
| 2821 | (interactive "P") ; raw prefix arg
|
|---|
| 2822 | (let ((start (point))
|
|---|
| 2823 | (which (cond ((eq class 'either) "\\(class\\|def\\)")
|
|---|
| 2824 | (class "class")
|
|---|
| 2825 | (t "def"))))
|
|---|
| 2826 | (push-mark start)
|
|---|
| 2827 | (if (not (py-go-up-tree-to-keyword which))
|
|---|
| 2828 | (progn (goto-char start)
|
|---|
| 2829 | (error "Enclosing %s not found"
|
|---|
| 2830 | (if (eq class 'either)
|
|---|
| 2831 | "def or class"
|
|---|
| 2832 | which)))
|
|---|
| 2833 | ;; else enclosing def/class found
|
|---|
| 2834 | (setq start (point))
|
|---|
| 2835 | (py-goto-beyond-block)
|
|---|
| 2836 | (push-mark (point))
|
|---|
| 2837 | (goto-char start)
|
|---|
| 2838 | (if (zerop (forward-line -1)) ; if there is a preceding line
|
|---|
| 2839 | (progn
|
|---|
| 2840 | (if (looking-at "[ \t]*$") ; it's blank
|
|---|
| 2841 | (setq start (point)) ; so reset start point
|
|---|
| 2842 | (goto-char start)) ; else try again
|
|---|
| 2843 | (if (zerop (forward-line -1))
|
|---|
| 2844 | (if (looking-at "[ \t]*#") ; a comment
|
|---|
| 2845 | ;; look back for non-comment line
|
|---|
| 2846 | ;; tricky: note that the regexp matches a blank
|
|---|
| 2847 | ;; line, cuz \n is in the 2nd character class
|
|---|
| 2848 | (and
|
|---|
| 2849 | (re-search-backward "^[ \t]*[^ \t#]" nil 'move)
|
|---|
| 2850 | (forward-line 1))
|
|---|
| 2851 | ;; no comment, so go back
|
|---|
| 2852 | (goto-char start)))))))
|
|---|
| 2853 | (exchange-point-and-mark)
|
|---|
| 2854 | (py-keep-region-active))
|
|---|
| 2855 |
|
|---|
| 2856 | ;; ripped from cc-mode
|
|---|
| 2857 | (defun py-forward-into-nomenclature (&optional arg)
|
|---|
| 2858 | "Move forward to end of a nomenclature section or word.
|
|---|
| 2859 | With \\[universal-argument] (programmatically, optional argument ARG),
|
|---|
| 2860 | do it that many times.
|
|---|
| 2861 |
|
|---|
| 2862 | A `nomenclature' is a fancy way of saying AWordWithMixedCaseNotUnderscores."
|
|---|
| 2863 | (interactive "p")
|
|---|
| 2864 | (let ((case-fold-search nil))
|
|---|
| 2865 | (if (> arg 0)
|
|---|
| 2866 | (re-search-forward
|
|---|
| 2867 | "\\(\\W\\|[_]\\)*\\([A-Z]*[a-z0-9]*\\)"
|
|---|
| 2868 | (point-max) t arg)
|
|---|
| 2869 | (while (and (< arg 0)
|
|---|
| 2870 | (re-search-backward
|
|---|
| 2871 | "\\(\\W\\|[a-z0-9]\\)[A-Z]+\\|\\(\\W\\|[_]\\)\\w+"
|
|---|
| 2872 | (point-min) 0))
|
|---|
| 2873 | (forward-char 1)
|
|---|
| 2874 | (setq arg (1+ arg)))))
|
|---|
| 2875 | (py-keep-region-active))
|
|---|
| 2876 |
|
|---|
| 2877 | (defun py-backward-into-nomenclature (&optional arg)
|
|---|
| 2878 | "Move backward to beginning of a nomenclature section or word.
|
|---|
| 2879 | With optional ARG, move that many times. If ARG is negative, move
|
|---|
| 2880 | forward.
|
|---|
| 2881 |
|
|---|
| 2882 | A `nomenclature' is a fancy way of saying AWordWithMixedCaseNotUnderscores."
|
|---|
| 2883 | (interactive "p")
|
|---|
| 2884 | (py-forward-into-nomenclature (- arg))
|
|---|
| 2885 | (py-keep-region-active))
|
|---|
| 2886 |
|
|---|
| 2887 |
|
|---|
| 2888 | |
|---|
| 2889 |
|
|---|
| 2890 | ;; pdbtrack functions
|
|---|
| 2891 | (defun py-pdbtrack-toggle-stack-tracking (arg)
|
|---|
| 2892 | (interactive "P")
|
|---|
| 2893 | (if (not (get-buffer-process (current-buffer)))
|
|---|
| 2894 | (error "No process associated with buffer '%s'" (current-buffer)))
|
|---|
| 2895 | ;; missing or 0 is toggle, >0 turn on, <0 turn off
|
|---|
| 2896 | (if (or (not arg)
|
|---|
| 2897 | (zerop (setq arg (prefix-numeric-value arg))))
|
|---|
| 2898 | (setq py-pdbtrack-do-tracking-p (not py-pdbtrack-do-tracking-p))
|
|---|
| 2899 | (setq py-pdbtrack-do-tracking-p (> arg 0)))
|
|---|
| 2900 | (message "%sabled Python's pdbtrack"
|
|---|
| 2901 | (if py-pdbtrack-do-tracking-p "En" "Dis")))
|
|---|
| 2902 |
|
|---|
| 2903 | (defun turn-on-pdbtrack ()
|
|---|
| 2904 | (interactive)
|
|---|
| 2905 | (py-pdbtrack-toggle-stack-tracking 1))
|
|---|
| 2906 |
|
|---|
| 2907 | (defun turn-off-pdbtrack ()
|
|---|
| 2908 | (interactive)
|
|---|
| 2909 | (py-pdbtrack-toggle-stack-tracking 0))
|
|---|
| 2910 |
|
|---|
| 2911 |
|
|---|
| 2912 | |
|---|
| 2913 |
|
|---|
| 2914 | ;; Pychecker
|
|---|
| 2915 | (defun py-pychecker-run (command)
|
|---|
| 2916 | "*Run pychecker (default on the file currently visited)."
|
|---|
| 2917 | (interactive
|
|---|
| 2918 | (let ((default
|
|---|
| 2919 | (format "%s %s %s" py-pychecker-command
|
|---|
| 2920 | (mapconcat 'identity py-pychecker-command-args " ")
|
|---|
| 2921 | (buffer-file-name)))
|
|---|
| 2922 | (last (when py-pychecker-history
|
|---|
| 2923 | (let* ((lastcmd (car py-pychecker-history))
|
|---|
| 2924 | (cmd (cdr (reverse (split-string lastcmd))))
|
|---|
| 2925 | (newcmd (reverse (cons (buffer-file-name) cmd))))
|
|---|
| 2926 | (mapconcat 'identity newcmd " ")))))
|
|---|
| 2927 |
|
|---|
| 2928 | (list
|
|---|
| 2929 | (if (fboundp 'read-shell-command)
|
|---|
| 2930 | (read-shell-command "Run pychecker like this: "
|
|---|
| 2931 | (if last
|
|---|
| 2932 | last
|
|---|
| 2933 | default)
|
|---|
| 2934 | 'py-pychecker-history)
|
|---|
| 2935 | (read-string "Run pychecker like this: "
|
|---|
| 2936 | (if last
|
|---|
| 2937 | last
|
|---|
| 2938 | default)
|
|---|
| 2939 | 'py-pychecker-history))
|
|---|
| 2940 | )))
|
|---|
| 2941 | (save-some-buffers (not py-ask-about-save) nil)
|
|---|
| 2942 | (compile-internal command "No more errors"))
|
|---|
| 2943 |
|
|---|
| 2944 |
|
|---|
| 2945 | |
|---|
| 2946 |
|
|---|
| 2947 | ;; pydoc commands. The guts of this function is stolen from XEmacs's
|
|---|
| 2948 | ;; symbol-near-point, but without the useless regexp-quote call on the
|
|---|
| 2949 | ;; results, nor the interactive bit. Also, we've added the temporary
|
|---|
| 2950 | ;; syntax table setting, which Skip originally had broken out into a
|
|---|
| 2951 | ;; separate function. Note that Emacs doesn't have the original
|
|---|
| 2952 | ;; function.
|
|---|
| 2953 | (defun py-symbol-near-point ()
|
|---|
| 2954 | "Return the first textual item to the nearest point."
|
|---|
| 2955 | ;; alg stolen from etag.el
|
|---|
| 2956 | (save-excursion
|
|---|
| 2957 | (with-syntax-table py-dotted-expression-syntax-table
|
|---|
| 2958 | (if (or (bobp) (not (memq (char-syntax (char-before)) '(?w ?_))))
|
|---|
| 2959 | (while (not (looking-at "\\sw\\|\\s_\\|\\'"))
|
|---|
| 2960 | (forward-char 1)))
|
|---|
| 2961 | (while (looking-at "\\sw\\|\\s_")
|
|---|
| 2962 | (forward-char 1))
|
|---|
| 2963 | (if (re-search-backward "\\sw\\|\\s_" nil t)
|
|---|
| 2964 | (progn (forward-char 1)
|
|---|
| 2965 | (buffer-substring (point)
|
|---|
| 2966 | (progn (forward-sexp -1)
|
|---|
| 2967 | (while (looking-at "\\s'")
|
|---|
| 2968 | (forward-char 1))
|
|---|
| 2969 | (point))))
|
|---|
| 2970 | nil))))
|
|---|
| 2971 |
|
|---|
| 2972 | (defun py-help-at-point ()
|
|---|
| 2973 | "Get help from Python based on the symbol nearest point."
|
|---|
| 2974 | (interactive)
|
|---|
| 2975 | (let* ((sym (py-symbol-near-point))
|
|---|
| 2976 | (base (substring sym 0 (or (search "." sym :from-end t) 0)))
|
|---|
| 2977 | cmd)
|
|---|
| 2978 | (if (not (equal base ""))
|
|---|
| 2979 | (setq cmd (concat "import " base "\n")))
|
|---|
| 2980 | (setq cmd (concat "import pydoc\n"
|
|---|
| 2981 | cmd
|
|---|
| 2982 | "try: pydoc.help('" sym "')\n"
|
|---|
| 2983 | "except: print 'No help available on:', \"" sym "\""))
|
|---|
| 2984 | (message cmd)
|
|---|
| 2985 | (py-execute-string cmd)
|
|---|
| 2986 | (set-buffer "*Python Output*")
|
|---|
| 2987 | ;; BAW: Should we really be leaving the output buffer in help-mode?
|
|---|
| 2988 | (help-mode)))
|
|---|
| 2989 |
|
|---|
| 2990 |
|
|---|
| 2991 | |
|---|
| 2992 |
|
|---|
| 2993 | ;; Documentation functions
|
|---|
| 2994 |
|
|---|
| 2995 | ;; dump the long form of the mode blurb; does the usual doc escapes,
|
|---|
| 2996 | ;; plus lines of the form ^[vc]:name$ to suck variable & command docs
|
|---|
| 2997 | ;; out of the right places, along with the keys they're on & current
|
|---|
| 2998 | ;; values
|
|---|
| 2999 | (defun py-dump-help-string (str)
|
|---|
| 3000 | (with-output-to-temp-buffer "*Help*"
|
|---|
| 3001 | (let ((locals (buffer-local-variables))
|
|---|
| 3002 | funckind funcname func funcdoc
|
|---|
| 3003 | (start 0) mstart end
|
|---|
| 3004 | keys )
|
|---|
| 3005 | (while (string-match "^%\\([vc]\\):\\(.+\\)\n" str start)
|
|---|
| 3006 | (setq mstart (match-beginning 0) end (match-end 0)
|
|---|
| 3007 | funckind (substring str (match-beginning 1) (match-end 1))
|
|---|
| 3008 | funcname (substring str (match-beginning 2) (match-end 2))
|
|---|
| 3009 | func (intern funcname))
|
|---|
| 3010 | (princ (substitute-command-keys (substring str start mstart)))
|
|---|
| 3011 | (cond
|
|---|
| 3012 | ((equal funckind "c") ; command
|
|---|
| 3013 | (setq funcdoc (documentation func)
|
|---|
| 3014 | keys (concat
|
|---|
| 3015 | "Key(s): "
|
|---|
| 3016 | (mapconcat 'key-description
|
|---|
| 3017 | (where-is-internal func py-mode-map)
|
|---|
| 3018 | ", "))))
|
|---|
| 3019 | ((equal funckind "v") ; variable
|
|---|
| 3020 | (setq funcdoc (documentation-property func 'variable-documentation)
|
|---|
| 3021 | keys (if (assq func locals)
|
|---|
| 3022 | (concat
|
|---|
| 3023 | "Local/Global values: "
|
|---|
| 3024 | (prin1-to-string (symbol-value func))
|
|---|
| 3025 | " / "
|
|---|
| 3026 | (prin1-to-string (default-value func)))
|
|---|
| 3027 | (concat
|
|---|
| 3028 | "Value: "
|
|---|
| 3029 | (prin1-to-string (symbol-value func))))))
|
|---|
| 3030 | (t ; unexpected
|
|---|
| 3031 | (error "Error in py-dump-help-string, tag `%s'" funckind)))
|
|---|
| 3032 | (princ (format "\n-> %s:\t%s\t%s\n\n"
|
|---|
| 3033 | (if (equal funckind "c") "Command" "Variable")
|
|---|
| 3034 | funcname keys))
|
|---|
| 3035 | (princ funcdoc)
|
|---|
| 3036 | (terpri)
|
|---|
| 3037 | (setq start end))
|
|---|
| 3038 | (princ (substitute-command-keys (substring str start))))
|
|---|
| 3039 | (print-help-return-message)))
|
|---|
| 3040 |
|
|---|
| 3041 | (defun py-describe-mode ()
|
|---|
| 3042 | "Dump long form of Python-mode docs."
|
|---|
| 3043 | (interactive)
|
|---|
| 3044 | (py-dump-help-string "Major mode for editing Python files.
|
|---|
| 3045 | Knows about Python indentation, tokens, comments and continuation lines.
|
|---|
| 3046 | Paragraphs are separated by blank lines only.
|
|---|
| 3047 |
|
|---|
| 3048 | Major sections below begin with the string `@'; specific function and
|
|---|
| 3049 | variable docs begin with `->'.
|
|---|
| 3050 |
|
|---|
| 3051 | @EXECUTING PYTHON CODE
|
|---|
| 3052 |
|
|---|
| 3053 | \\[py-execute-import-or-reload]\timports or reloads the file in the Python interpreter
|
|---|
| 3054 | \\[py-execute-buffer]\tsends the entire buffer to the Python interpreter
|
|---|
| 3055 | \\[py-execute-region]\tsends the current region
|
|---|
| 3056 | \\[py-execute-def-or-class]\tsends the current function or class definition
|
|---|
| 3057 | \\[py-execute-string]\tsends an arbitrary string
|
|---|
| 3058 | \\[py-shell]\tstarts a Python interpreter window; this will be used by
|
|---|
| 3059 | \tsubsequent Python execution commands
|
|---|
| 3060 | %c:py-execute-import-or-reload
|
|---|
| 3061 | %c:py-execute-buffer
|
|---|
| 3062 | %c:py-execute-region
|
|---|
| 3063 | %c:py-execute-def-or-class
|
|---|
| 3064 | %c:py-execute-string
|
|---|
| 3065 | %c:py-shell
|
|---|
| 3066 |
|
|---|
| 3067 | @VARIABLES
|
|---|
| 3068 |
|
|---|
| 3069 | py-indent-offset\tindentation increment
|
|---|
| 3070 | py-block-comment-prefix\tcomment string used by comment-region
|
|---|
| 3071 |
|
|---|
| 3072 | py-python-command\tshell command to invoke Python interpreter
|
|---|
| 3073 | py-temp-directory\tdirectory used for temp files (if needed)
|
|---|
| 3074 |
|
|---|
| 3075 | py-beep-if-tab-change\tring the bell if tab-width is changed
|
|---|
| 3076 | %v:py-indent-offset
|
|---|
| 3077 | %v:py-block-comment-prefix
|
|---|
| 3078 | %v:py-python-command
|
|---|
| 3079 | %v:py-temp-directory
|
|---|
| 3080 | %v:py-beep-if-tab-change
|
|---|
| 3081 |
|
|---|
| 3082 | @KINDS OF LINES
|
|---|
| 3083 |
|
|---|
| 3084 | Each physical line in the file is either a `continuation line' (the
|
|---|
| 3085 | preceding line ends with a backslash that's not part of a comment, or
|
|---|
| 3086 | the paren/bracket/brace nesting level at the start of the line is
|
|---|
| 3087 | non-zero, or both) or an `initial line' (everything else).
|
|---|
| 3088 |
|
|---|
| 3089 | An initial line is in turn a `blank line' (contains nothing except
|
|---|
| 3090 | possibly blanks or tabs), a `comment line' (leftmost non-blank
|
|---|
| 3091 | character is `#'), or a `code line' (everything else).
|
|---|
| 3092 |
|
|---|
| 3093 | Comment Lines
|
|---|
| 3094 |
|
|---|
| 3095 | Although all comment lines are treated alike by Python, Python mode
|
|---|
| 3096 | recognizes two kinds that act differently with respect to indentation.
|
|---|
| 3097 |
|
|---|
| 3098 | An `indenting comment line' is a comment line with a blank, tab or
|
|---|
| 3099 | nothing after the initial `#'. The indentation commands (see below)
|
|---|
| 3100 | treat these exactly as if they were code lines: a line following an
|
|---|
| 3101 | indenting comment line will be indented like the comment line. All
|
|---|
| 3102 | other comment lines (those with a non-whitespace character immediately
|
|---|
| 3103 | following the initial `#') are `non-indenting comment lines', and
|
|---|
| 3104 | their indentation is ignored by the indentation commands.
|
|---|
| 3105 |
|
|---|
| 3106 | Indenting comment lines are by far the usual case, and should be used
|
|---|
| 3107 | whenever possible. Non-indenting comment lines are useful in cases
|
|---|
| 3108 | like these:
|
|---|
| 3109 |
|
|---|
| 3110 | \ta = b # a very wordy single-line comment that ends up being
|
|---|
| 3111 | \t #... continued onto another line
|
|---|
| 3112 |
|
|---|
| 3113 | \tif a == b:
|
|---|
| 3114 | ##\t\tprint 'panic!' # old code we've `commented out'
|
|---|
| 3115 | \t\treturn a
|
|---|
| 3116 |
|
|---|
| 3117 | Since the `#...' and `##' comment lines have a non-whitespace
|
|---|
| 3118 | character following the initial `#', Python mode ignores them when
|
|---|
| 3119 | computing the proper indentation for the next line.
|
|---|
| 3120 |
|
|---|
| 3121 | Continuation Lines and Statements
|
|---|
| 3122 |
|
|---|
| 3123 | The Python-mode commands generally work on statements instead of on
|
|---|
| 3124 | individual lines, where a `statement' is a comment or blank line, or a
|
|---|
| 3125 | code line and all of its following continuation lines (if any)
|
|---|
| 3126 | considered as a single logical unit. The commands in this mode
|
|---|
| 3127 | generally (when it makes sense) automatically move to the start of the
|
|---|
| 3128 | statement containing point, even if point happens to be in the middle
|
|---|
| 3129 | of some continuation line.
|
|---|
| 3130 |
|
|---|
| 3131 |
|
|---|
| 3132 | @INDENTATION
|
|---|
| 3133 |
|
|---|
| 3134 | Primarily for entering new code:
|
|---|
| 3135 | \t\\[indent-for-tab-command]\t indent line appropriately
|
|---|
| 3136 | \t\\[py-newline-and-indent]\t insert newline, then indent
|
|---|
| 3137 | \t\\[py-electric-backspace]\t reduce indentation, or delete single character
|
|---|
| 3138 |
|
|---|
| 3139 | Primarily for reindenting existing code:
|
|---|
| 3140 | \t\\[py-guess-indent-offset]\t guess py-indent-offset from file content; change locally
|
|---|
| 3141 | \t\\[universal-argument] \\[py-guess-indent-offset]\t ditto, but change globally
|
|---|
| 3142 |
|
|---|
| 3143 | \t\\[py-indent-region]\t reindent region to match its context
|
|---|
| 3144 | \t\\[py-shift-region-left]\t shift region left by py-indent-offset
|
|---|
| 3145 | \t\\[py-shift-region-right]\t shift region right by py-indent-offset
|
|---|
| 3146 |
|
|---|
| 3147 | Unlike most programming languages, Python uses indentation, and only
|
|---|
| 3148 | indentation, to specify block structure. Hence the indentation supplied
|
|---|
| 3149 | automatically by Python-mode is just an educated guess: only you know
|
|---|
| 3150 | the block structure you intend, so only you can supply correct
|
|---|
| 3151 | indentation.
|
|---|
| 3152 |
|
|---|
| 3153 | The \\[indent-for-tab-command] and \\[py-newline-and-indent] keys try to suggest plausible indentation, based on
|
|---|
| 3154 | the indentation of preceding statements. E.g., assuming
|
|---|
| 3155 | py-indent-offset is 4, after you enter
|
|---|
| 3156 | \tif a > 0: \\[py-newline-and-indent]
|
|---|
| 3157 | the cursor will be moved to the position of the `_' (_ is not a
|
|---|
| 3158 | character in the file, it's just used here to indicate the location of
|
|---|
| 3159 | the cursor):
|
|---|
| 3160 | \tif a > 0:
|
|---|
| 3161 | \t _
|
|---|
| 3162 | If you then enter `c = d' \\[py-newline-and-indent], the cursor will move
|
|---|
| 3163 | to
|
|---|
| 3164 | \tif a > 0:
|
|---|
| 3165 | \t c = d
|
|---|
| 3166 | \t _
|
|---|
| 3167 | Python-mode cannot know whether that's what you intended, or whether
|
|---|
| 3168 | \tif a > 0:
|
|---|
| 3169 | \t c = d
|
|---|
| 3170 | \t_
|
|---|
| 3171 | was your intent. In general, Python-mode either reproduces the
|
|---|
| 3172 | indentation of the (closest code or indenting-comment) preceding
|
|---|
| 3173 | statement, or adds an extra py-indent-offset blanks if the preceding
|
|---|
| 3174 | statement has `:' as its last significant (non-whitespace and non-
|
|---|
| 3175 | comment) character. If the suggested indentation is too much, use
|
|---|
| 3176 | \\[py-electric-backspace] to reduce it.
|
|---|
| 3177 |
|
|---|
| 3178 | Continuation lines are given extra indentation. If you don't like the
|
|---|
| 3179 | suggested indentation, change it to something you do like, and Python-
|
|---|
| 3180 | mode will strive to indent later lines of the statement in the same way.
|
|---|
| 3181 |
|
|---|
| 3182 | If a line is a continuation line by virtue of being in an unclosed
|
|---|
| 3183 | paren/bracket/brace structure (`list', for short), the suggested
|
|---|
| 3184 | indentation depends on whether the current line contains the first item
|
|---|
| 3185 | in the list. If it does, it's indented py-indent-offset columns beyond
|
|---|
| 3186 | the indentation of the line containing the open bracket. If you don't
|
|---|
| 3187 | like that, change it by hand. The remaining items in the list will mimic
|
|---|
| 3188 | whatever indentation you give to the first item.
|
|---|
| 3189 |
|
|---|
| 3190 | If a line is a continuation line because the line preceding it ends with
|
|---|
| 3191 | a backslash, the third and following lines of the statement inherit their
|
|---|
| 3192 | indentation from the line preceding them. The indentation of the second
|
|---|
| 3193 | line in the statement depends on the form of the first (base) line: if
|
|---|
| 3194 | the base line is an assignment statement with anything more interesting
|
|---|
| 3195 | than the backslash following the leftmost assigning `=', the second line
|
|---|
| 3196 | is indented two columns beyond that `='. Else it's indented to two
|
|---|
| 3197 | columns beyond the leftmost solid chunk of non-whitespace characters on
|
|---|
| 3198 | the base line.
|
|---|
| 3199 |
|
|---|
| 3200 | Warning: indent-region should not normally be used! It calls \\[indent-for-tab-command]
|
|---|
| 3201 | repeatedly, and as explained above, \\[indent-for-tab-command] can't guess the block
|
|---|
| 3202 | structure you intend.
|
|---|
| 3203 | %c:indent-for-tab-command
|
|---|
| 3204 | %c:py-newline-and-indent
|
|---|
| 3205 | %c:py-electric-backspace
|
|---|
| 3206 |
|
|---|
| 3207 |
|
|---|
| 3208 | The next function may be handy when editing code you didn't write:
|
|---|
| 3209 | %c:py-guess-indent-offset
|
|---|
| 3210 |
|
|---|
| 3211 |
|
|---|
| 3212 | The remaining `indent' functions apply to a region of Python code. They
|
|---|
| 3213 | assume the block structure (equals indentation, in Python) of the region
|
|---|
| 3214 | is correct, and alter the indentation in various ways while preserving
|
|---|
| 3215 | the block structure:
|
|---|
| 3216 | %c:py-indent-region
|
|---|
| 3217 | %c:py-shift-region-left
|
|---|
| 3218 | %c:py-shift-region-right
|
|---|
| 3219 |
|
|---|
| 3220 | @MARKING & MANIPULATING REGIONS OF CODE
|
|---|
| 3221 |
|
|---|
| 3222 | \\[py-mark-block]\t mark block of lines
|
|---|
| 3223 | \\[py-mark-def-or-class]\t mark smallest enclosing def
|
|---|
| 3224 | \\[universal-argument] \\[py-mark-def-or-class]\t mark smallest enclosing class
|
|---|
| 3225 | \\[comment-region]\t comment out region of code
|
|---|
| 3226 | \\[universal-argument] \\[comment-region]\t uncomment region of code
|
|---|
| 3227 | %c:py-mark-block
|
|---|
| 3228 | %c:py-mark-def-or-class
|
|---|
| 3229 | %c:comment-region
|
|---|
| 3230 |
|
|---|
| 3231 | @MOVING POINT
|
|---|
| 3232 |
|
|---|
| 3233 | \\[py-previous-statement]\t move to statement preceding point
|
|---|
| 3234 | \\[py-next-statement]\t move to statement following point
|
|---|
| 3235 | \\[py-goto-block-up]\t move up to start of current block
|
|---|
| 3236 | \\[py-beginning-of-def-or-class]\t move to start of def
|
|---|
| 3237 | \\[universal-argument] \\[py-beginning-of-def-or-class]\t move to start of class
|
|---|
| 3238 | \\[py-end-of-def-or-class]\t move to end of def
|
|---|
| 3239 | \\[universal-argument] \\[py-end-of-def-or-class]\t move to end of class
|
|---|
| 3240 |
|
|---|
| 3241 | The first two move to one statement beyond the statement that contains
|
|---|
| 3242 | point. A numeric prefix argument tells them to move that many
|
|---|
| 3243 | statements instead. Blank lines, comment lines, and continuation lines
|
|---|
| 3244 | do not count as `statements' for these commands. So, e.g., you can go
|
|---|
| 3245 | to the first code statement in a file by entering
|
|---|
| 3246 | \t\\[beginning-of-buffer]\t to move to the top of the file
|
|---|
| 3247 | \t\\[py-next-statement]\t to skip over initial comments and blank lines
|
|---|
| 3248 | Or do `\\[py-previous-statement]' with a huge prefix argument.
|
|---|
| 3249 | %c:py-previous-statement
|
|---|
| 3250 | %c:py-next-statement
|
|---|
| 3251 | %c:py-goto-block-up
|
|---|
| 3252 | %c:py-beginning-of-def-or-class
|
|---|
| 3253 | %c:py-end-of-def-or-class
|
|---|
| 3254 |
|
|---|
| 3255 | @LITTLE-KNOWN EMACS COMMANDS PARTICULARLY USEFUL IN PYTHON MODE
|
|---|
| 3256 |
|
|---|
| 3257 | `\\[indent-new-comment-line]' is handy for entering a multi-line comment.
|
|---|
| 3258 |
|
|---|
| 3259 | `\\[set-selective-display]' with a `small' prefix arg is ideally suited for viewing the
|
|---|
| 3260 | overall class and def structure of a module.
|
|---|
| 3261 |
|
|---|
| 3262 | `\\[back-to-indentation]' moves point to a line's first non-blank character.
|
|---|
| 3263 |
|
|---|
| 3264 | `\\[indent-relative]' is handy for creating odd indentation.
|
|---|
| 3265 |
|
|---|
| 3266 | @OTHER EMACS HINTS
|
|---|
| 3267 |
|
|---|
| 3268 | If you don't like the default value of a variable, change its value to
|
|---|
| 3269 | whatever you do like by putting a `setq' line in your .emacs file.
|
|---|
| 3270 | E.g., to set the indentation increment to 4, put this line in your
|
|---|
| 3271 | .emacs:
|
|---|
| 3272 | \t(setq py-indent-offset 4)
|
|---|
| 3273 | To see the value of a variable, do `\\[describe-variable]' and enter the variable
|
|---|
| 3274 | name at the prompt.
|
|---|
| 3275 |
|
|---|
| 3276 | When entering a key sequence like `C-c C-n', it is not necessary to
|
|---|
| 3277 | release the CONTROL key after doing the `C-c' part -- it suffices to
|
|---|
| 3278 | press the CONTROL key, press and release `c' (while still holding down
|
|---|
| 3279 | CONTROL), press and release `n' (while still holding down CONTROL), &
|
|---|
| 3280 | then release CONTROL.
|
|---|
| 3281 |
|
|---|
| 3282 | Entering Python mode calls with no arguments the value of the variable
|
|---|
| 3283 | `python-mode-hook', if that value exists and is not nil; for backward
|
|---|
| 3284 | compatibility it also tries `py-mode-hook'; see the `Hooks' section of
|
|---|
| 3285 | the Elisp manual for details.
|
|---|
| 3286 |
|
|---|
| 3287 | Obscure: When python-mode is first loaded, it looks for all bindings
|
|---|
| 3288 | to newline-and-indent in the global keymap, and shadows them with
|
|---|
| 3289 | local bindings to py-newline-and-indent."))
|
|---|
| 3290 |
|
|---|
| 3291 | (require 'info-look)
|
|---|
| 3292 | ;; The info-look package does not always provide this function (it
|
|---|
| 3293 | ;; appears this is the case with XEmacs 21.1)
|
|---|
| 3294 | (when (fboundp 'info-lookup-maybe-add-help)
|
|---|
| 3295 | (info-lookup-maybe-add-help
|
|---|
| 3296 | :mode 'python-mode
|
|---|
| 3297 | :regexp "[a-zA-Z0-9_]+"
|
|---|
| 3298 | :doc-spec '(("(python-lib)Module Index")
|
|---|
| 3299 | ("(python-lib)Class-Exception-Object Index")
|
|---|
| 3300 | ("(python-lib)Function-Method-Variable Index")
|
|---|
| 3301 | ("(python-lib)Miscellaneous Index")))
|
|---|
| 3302 | )
|
|---|
| 3303 |
|
|---|
| 3304 | |
|---|
| 3305 |
|
|---|
| 3306 | ;; Helper functions
|
|---|
| 3307 | (defvar py-parse-state-re
|
|---|
| 3308 | (concat
|
|---|
| 3309 | "^[ \t]*\\(elif\\|else\\|while\\|def\\|class\\)\\>"
|
|---|
| 3310 | "\\|"
|
|---|
| 3311 | "^[^ #\t\n]"))
|
|---|
| 3312 |
|
|---|
| 3313 | (defun py-parse-state ()
|
|---|
| 3314 | "Return the parse state at point (see `parse-partial-sexp' docs)."
|
|---|
| 3315 | (save-excursion
|
|---|
| 3316 | (let ((here (point))
|
|---|
| 3317 | pps done)
|
|---|
| 3318 | (while (not done)
|
|---|
| 3319 | ;; back up to the first preceding line (if any; else start of
|
|---|
| 3320 | ;; buffer) that begins with a popular Python keyword, or a
|
|---|
| 3321 | ;; non- whitespace and non-comment character. These are good
|
|---|
| 3322 | ;; places to start parsing to see whether where we started is
|
|---|
| 3323 | ;; at a non-zero nesting level. It may be slow for people who
|
|---|
| 3324 | ;; write huge code blocks or huge lists ... tough beans.
|
|---|
| 3325 | (re-search-backward py-parse-state-re nil 'move)
|
|---|
| 3326 | (beginning-of-line)
|
|---|
| 3327 | ;; In XEmacs, we have a much better way to test for whether
|
|---|
| 3328 | ;; we're in a triple-quoted string or not. Emacs does not
|
|---|
| 3329 | ;; have this built-in function, which is its loss because
|
|---|
| 3330 | ;; without scanning from the beginning of the buffer, there's
|
|---|
| 3331 | ;; no accurate way to determine this otherwise.
|
|---|
| 3332 | (save-excursion (setq pps (parse-partial-sexp (point) here)))
|
|---|
| 3333 | ;; make sure we don't land inside a triple-quoted string
|
|---|
| 3334 | (setq done (or (not (nth 3 pps))
|
|---|
| 3335 | (bobp)))
|
|---|
| 3336 | ;; Just go ahead and short circuit the test back to the
|
|---|
| 3337 | ;; beginning of the buffer. This will be slow, but not
|
|---|
| 3338 | ;; nearly as slow as looping through many
|
|---|
| 3339 | ;; re-search-backwards.
|
|---|
| 3340 | (if (not done)
|
|---|
| 3341 | (goto-char (point-min))))
|
|---|
| 3342 | pps)))
|
|---|
| 3343 |
|
|---|
| 3344 | (defun py-nesting-level ()
|
|---|
| 3345 | "Return the buffer position of the last unclosed enclosing list.
|
|---|
| 3346 | If nesting level is zero, return nil."
|
|---|
| 3347 | (let ((status (py-parse-state)))
|
|---|
| 3348 | (if (zerop (car status))
|
|---|
| 3349 | nil ; not in a nest
|
|---|
| 3350 | (car (cdr status))))) ; char# of open bracket
|
|---|
| 3351 |
|
|---|
| 3352 | (defun py-backslash-continuation-line-p ()
|
|---|
| 3353 | "Return t iff preceding line ends with backslash that is not in a comment."
|
|---|
| 3354 | (save-excursion
|
|---|
| 3355 | (beginning-of-line)
|
|---|
| 3356 | (and
|
|---|
| 3357 | ;; use a cheap test first to avoid the regexp if possible
|
|---|
| 3358 | ;; use 'eq' because char-after may return nil
|
|---|
| 3359 | (eq (char-after (- (point) 2)) ?\\ )
|
|---|
| 3360 | ;; make sure; since eq test passed, there is a preceding line
|
|---|
| 3361 | (forward-line -1) ; always true -- side effect
|
|---|
| 3362 | (looking-at py-continued-re))))
|
|---|
| 3363 |
|
|---|
| 3364 | (defun py-continuation-line-p ()
|
|---|
| 3365 | "Return t iff current line is a continuation line."
|
|---|
| 3366 | (save-excursion
|
|---|
| 3367 | (beginning-of-line)
|
|---|
| 3368 | (or (py-backslash-continuation-line-p)
|
|---|
| 3369 | (py-nesting-level))))
|
|---|
| 3370 |
|
|---|
| 3371 | (defun py-goto-beginning-of-tqs (delim)
|
|---|
| 3372 | "Go to the beginning of the triple quoted string we find ourselves in.
|
|---|
| 3373 | DELIM is the TQS string delimiter character we're searching backwards
|
|---|
| 3374 | for."
|
|---|
| 3375 | (let ((skip (and delim (make-string 1 delim)))
|
|---|
| 3376 | (continue t))
|
|---|
| 3377 | (when skip
|
|---|
| 3378 | (save-excursion
|
|---|
| 3379 | (while continue
|
|---|
| 3380 | (py-safe (search-backward skip))
|
|---|
| 3381 | (setq continue (and (not (bobp))
|
|---|
| 3382 | (= (char-before) ?\\))))
|
|---|
| 3383 | (if (and (= (char-before) delim)
|
|---|
| 3384 | (= (char-before (1- (point))) delim))
|
|---|
| 3385 | (setq skip (make-string 3 delim))))
|
|---|
| 3386 | ;; we're looking at a triple-quoted string
|
|---|
| 3387 | (py-safe (search-backward skip)))))
|
|---|
| 3388 |
|
|---|
| 3389 | (defun py-goto-initial-line ()
|
|---|
| 3390 | "Go to the initial line of the current statement.
|
|---|
| 3391 | Usually this is the line we're on, but if we're on the 2nd or
|
|---|
| 3392 | following lines of a continuation block, we need to go up to the first
|
|---|
| 3393 | line of the block."
|
|---|
| 3394 | ;; Tricky: We want to avoid quadratic-time behavior for long
|
|---|
| 3395 | ;; continued blocks, whether of the backslash or open-bracket
|
|---|
| 3396 | ;; varieties, or a mix of the two. The following manages to do that
|
|---|
| 3397 | ;; in the usual cases.
|
|---|
| 3398 | ;;
|
|---|
| 3399 | ;; Also, if we're sitting inside a triple quoted string, this will
|
|---|
| 3400 | ;; drop us at the line that begins the string.
|
|---|
| 3401 | (let (open-bracket-pos)
|
|---|
| 3402 | (while (py-continuation-line-p)
|
|---|
| 3403 | (beginning-of-line)
|
|---|
| 3404 | (if (py-backslash-continuation-line-p)
|
|---|
| 3405 | (while (py-backslash-continuation-line-p)
|
|---|
| 3406 | (forward-line -1))
|
|---|
| 3407 | ;; else zip out of nested brackets/braces/parens
|
|---|
| 3408 | (while (setq open-bracket-pos (py-nesting-level))
|
|---|
| 3409 | (goto-char open-bracket-pos)))))
|
|---|
| 3410 | (beginning-of-line))
|
|---|
| 3411 |
|
|---|
| 3412 | (defun py-goto-beyond-final-line ()
|
|---|
| 3413 | "Go to the point just beyond the fine line of the current statement.
|
|---|
| 3414 | Usually this is the start of the next line, but if this is a
|
|---|
| 3415 | multi-line statement we need to skip over the continuation lines."
|
|---|
| 3416 | ;; Tricky: Again we need to be clever to avoid quadratic time
|
|---|
| 3417 | ;; behavior.
|
|---|
| 3418 | ;;
|
|---|
| 3419 | ;; XXX: Not quite the right solution, but deals with multi-line doc
|
|---|
| 3420 | ;; strings
|
|---|
| 3421 | (if (looking-at (concat "[ \t]*\\(" py-stringlit-re "\\)"))
|
|---|
| 3422 | (goto-char (match-end 0)))
|
|---|
| 3423 | ;;
|
|---|
| 3424 | (forward-line 1)
|
|---|
| 3425 | (let (state)
|
|---|
| 3426 | (while (and (py-continuation-line-p)
|
|---|
| 3427 | (not (eobp)))
|
|---|
| 3428 | ;; skip over the backslash flavor
|
|---|
| 3429 | (while (and (py-backslash-continuation-line-p)
|
|---|
| 3430 | (not (eobp)))
|
|---|
| 3431 | (forward-line 1))
|
|---|
| 3432 | ;; if in nest, zip to the end of the nest
|
|---|
| 3433 | (setq state (py-parse-state))
|
|---|
| 3434 | (if (and (not (zerop (car state)))
|
|---|
| 3435 | (not (eobp)))
|
|---|
| 3436 | (progn
|
|---|
| 3437 | (parse-partial-sexp (point) (point-max) 0 nil state)
|
|---|
| 3438 | (forward-line 1))))))
|
|---|
| 3439 |
|
|---|
| 3440 | (defun py-statement-opens-block-p ()
|
|---|
| 3441 | "Return t iff the current statement opens a block.
|
|---|
| 3442 | I.e., iff it ends with a colon that is not in a comment. Point should
|
|---|
| 3443 | be at the start of a statement."
|
|---|
| 3444 | (save-excursion
|
|---|
| 3445 | (let ((start (point))
|
|---|
| 3446 | (finish (progn (py-goto-beyond-final-line) (1- (point))))
|
|---|
| 3447 | (searching t)
|
|---|
| 3448 | (answer nil)
|
|---|
| 3449 | state)
|
|---|
| 3450 | (goto-char start)
|
|---|
| 3451 | (while searching
|
|---|
| 3452 | ;; look for a colon with nothing after it except whitespace, and
|
|---|
| 3453 | ;; maybe a comment
|
|---|
| 3454 | (if (re-search-forward ":\\([ \t]\\|\\\\\n\\)*\\(#.*\\)?$"
|
|---|
| 3455 | finish t)
|
|---|
| 3456 | (if (eq (point) finish) ; note: no `else' clause; just
|
|---|
| 3457 | ; keep searching if we're not at
|
|---|
| 3458 | ; the end yet
|
|---|
| 3459 | ;; sure looks like it opens a block -- but it might
|
|---|
| 3460 | ;; be in a comment
|
|---|
| 3461 | (progn
|
|---|
| 3462 | (setq searching nil) ; search is done either way
|
|---|
| 3463 | (setq state (parse-partial-sexp start
|
|---|
| 3464 | (match-beginning 0)))
|
|---|
| 3465 | (setq answer (not (nth 4 state)))))
|
|---|
| 3466 | ;; search failed: couldn't find another interesting colon
|
|---|
| 3467 | (setq searching nil)))
|
|---|
| 3468 | answer)))
|
|---|
| 3469 |
|
|---|
| 3470 | (defun py-statement-closes-block-p ()
|
|---|
| 3471 | "Return t iff the current statement closes a block.
|
|---|
| 3472 | I.e., if the line starts with `return', `raise', `break', `continue',
|
|---|
| 3473 | and `pass'. This doesn't catch embedded statements."
|
|---|
| 3474 | (let ((here (point)))
|
|---|
| 3475 | (py-goto-initial-line)
|
|---|
| 3476 | (back-to-indentation)
|
|---|
| 3477 | (prog1
|
|---|
| 3478 | (looking-at (concat py-block-closing-keywords-re "\\>"))
|
|---|
| 3479 | (goto-char here))))
|
|---|
| 3480 |
|
|---|
| 3481 | (defun py-goto-beyond-block ()
|
|---|
| 3482 | "Go to point just beyond the final line of block begun by the current line.
|
|---|
| 3483 | This is the same as where `py-goto-beyond-final-line' goes unless
|
|---|
| 3484 | we're on colon line, in which case we go to the end of the block.
|
|---|
| 3485 | Assumes point is at the beginning of the line."
|
|---|
| 3486 | (if (py-statement-opens-block-p)
|
|---|
| 3487 | (py-mark-block nil 'just-move)
|
|---|
| 3488 | (py-goto-beyond-final-line)))
|
|---|
| 3489 |
|
|---|
| 3490 | (defun py-goto-statement-at-or-above ()
|
|---|
| 3491 | "Go to the start of the first statement at or preceding point.
|
|---|
| 3492 | Return t if there is such a statement, otherwise nil. `Statement'
|
|---|
| 3493 | does not include blank lines, comments, or continuation lines."
|
|---|
| 3494 | (py-goto-initial-line)
|
|---|
| 3495 | (if (looking-at py-blank-or-comment-re)
|
|---|
| 3496 | ;; skip back over blank & comment lines
|
|---|
| 3497 | ;; note: will skip a blank or comment line that happens to be
|
|---|
| 3498 | ;; a continuation line too
|
|---|
| 3499 | (if (re-search-backward "^[ \t]*[^ \t#\n]" nil t)
|
|---|
| 3500 | (progn (py-goto-initial-line) t)
|
|---|
| 3501 | nil)
|
|---|
| 3502 | t))
|
|---|
| 3503 |
|
|---|
| 3504 | (defun py-goto-statement-below ()
|
|---|
| 3505 | "Go to start of the first statement following the statement containing point.
|
|---|
| 3506 | Return t if there is such a statement, otherwise nil. `Statement'
|
|---|
| 3507 | does not include blank lines, comments, or continuation lines."
|
|---|
| 3508 | (beginning-of-line)
|
|---|
| 3509 | (let ((start (point)))
|
|---|
| 3510 | (py-goto-beyond-final-line)
|
|---|
| 3511 | (while (and
|
|---|
| 3512 | (or (looking-at py-blank-or-comment-re)
|
|---|
| 3513 | (py-in-literal))
|
|---|
| 3514 | (not (eobp)))
|
|---|
| 3515 | (forward-line 1))
|
|---|
| 3516 | (if (eobp)
|
|---|
| 3517 | (progn (goto-char start) nil)
|
|---|
| 3518 | t)))
|
|---|
| 3519 |
|
|---|
| 3520 | (defun py-go-up-tree-to-keyword (key)
|
|---|
| 3521 | "Go to begining of statement starting with KEY, at or preceding point.
|
|---|
| 3522 |
|
|---|
| 3523 | KEY is a regular expression describing a Python keyword. Skip blank
|
|---|
| 3524 | lines and non-indenting comments. If the statement found starts with
|
|---|
| 3525 | KEY, then stop, otherwise go back to first enclosing block starting
|
|---|
| 3526 | with KEY. If successful, leave point at the start of the KEY line and
|
|---|
| 3527 | return t. Otherwise, leav point at an undefined place and return nil."
|
|---|
| 3528 | ;; skip blanks and non-indenting #
|
|---|
| 3529 | (py-goto-initial-line)
|
|---|
| 3530 | (while (and
|
|---|
| 3531 | (looking-at "[ \t]*\\($\\|#[^ \t\n]\\)")
|
|---|
| 3532 | (zerop (forward-line -1))) ; go back
|
|---|
| 3533 | nil)
|
|---|
| 3534 | (py-goto-initial-line)
|
|---|
| 3535 | (let* ((re (concat "[ \t]*" key "\\b"))
|
|---|
| 3536 | (case-fold-search nil) ; let* so looking-at sees this
|
|---|
| 3537 | (found (looking-at re))
|
|---|
| 3538 | (dead nil))
|
|---|
| 3539 | (while (not (or found dead))
|
|---|
| 3540 | (condition-case nil ; in case no enclosing block
|
|---|
| 3541 | (py-goto-block-up 'no-mark)
|
|---|
| 3542 | (error (setq dead t)))
|
|---|
| 3543 | (or dead (setq found (looking-at re))))
|
|---|
| 3544 | (beginning-of-line)
|
|---|
| 3545 | found))
|
|---|
| 3546 |
|
|---|
| 3547 | (defun py-suck-up-leading-text ()
|
|---|
| 3548 | "Return string in buffer from start of indentation to end of line.
|
|---|
| 3549 | Prefix with \"...\" if leading whitespace was skipped."
|
|---|
| 3550 | (save-excursion
|
|---|
| 3551 | (back-to-indentation)
|
|---|
| 3552 | (concat
|
|---|
| 3553 | (if (bolp) "" "...")
|
|---|
| 3554 | (buffer-substring (point) (progn (end-of-line) (point))))))
|
|---|
| 3555 |
|
|---|
| 3556 | (defun py-suck-up-first-keyword ()
|
|---|
| 3557 | "Return first keyword on the line as a Lisp symbol.
|
|---|
| 3558 | `Keyword' is defined (essentially) as the regular expression
|
|---|
| 3559 | ([a-z]+). Returns nil if none was found."
|
|---|
| 3560 | (let ((case-fold-search nil))
|
|---|
| 3561 | (if (looking-at "[ \t]*\\([a-z]+\\)\\b")
|
|---|
| 3562 | (intern (buffer-substring (match-beginning 1) (match-end 1)))
|
|---|
| 3563 | nil)))
|
|---|
| 3564 |
|
|---|
| 3565 | (defun py-current-defun ()
|
|---|
| 3566 | "Python value for `add-log-current-defun-function'.
|
|---|
| 3567 | This tells add-log.el how to find the current function/method/variable."
|
|---|
| 3568 | (save-excursion
|
|---|
| 3569 | (if (re-search-backward py-defun-start-re nil t)
|
|---|
| 3570 | (or (match-string 3)
|
|---|
| 3571 | (let ((method (match-string 2)))
|
|---|
| 3572 | (if (and (not (zerop (length (match-string 1))))
|
|---|
| 3573 | (re-search-backward py-class-start-re nil t))
|
|---|
| 3574 | (concat (match-string 1) "." method)
|
|---|
| 3575 | method)))
|
|---|
| 3576 | nil)))
|
|---|
| 3577 |
|
|---|
| 3578 | |
|---|
| 3579 |
|
|---|
| 3580 | (defconst py-help-address "[email protected]"
|
|---|
| 3581 | "Address accepting submission of bug reports.")
|
|---|
| 3582 |
|
|---|
| 3583 | (defun py-version ()
|
|---|
| 3584 | "Echo the current version of `python-mode' in the minibuffer."
|
|---|
| 3585 | (interactive)
|
|---|
| 3586 | (message "Using `python-mode' version %s" py-version)
|
|---|
| 3587 | (py-keep-region-active))
|
|---|
| 3588 |
|
|---|
| 3589 | ;; only works under Emacs 19
|
|---|
| 3590 | ;(eval-when-compile
|
|---|
| 3591 | ; (require 'reporter))
|
|---|
| 3592 |
|
|---|
| 3593 | (defun py-submit-bug-report (enhancement-p)
|
|---|
| 3594 | "Submit via mail a bug report on `python-mode'.
|
|---|
| 3595 | With \\[universal-argument] (programmatically, argument ENHANCEMENT-P
|
|---|
| 3596 | non-nil) just submit an enhancement request."
|
|---|
| 3597 | (interactive
|
|---|
| 3598 | (list (not (y-or-n-p
|
|---|
| 3599 | "Is this a bug report (hit `n' to send other comments)? "))))
|
|---|
| 3600 | (let ((reporter-prompt-for-summary-p (if enhancement-p
|
|---|
| 3601 | "(Very) brief summary: "
|
|---|
| 3602 | t)))
|
|---|
| 3603 | (require 'reporter)
|
|---|
| 3604 | (reporter-submit-bug-report
|
|---|
| 3605 | py-help-address ;address
|
|---|
| 3606 | (concat "python-mode " py-version) ;pkgname
|
|---|
| 3607 | ;; varlist
|
|---|
| 3608 | (if enhancement-p nil
|
|---|
| 3609 | '(py-python-command
|
|---|
| 3610 | py-indent-offset
|
|---|
| 3611 | py-block-comment-prefix
|
|---|
| 3612 | py-temp-directory
|
|---|
| 3613 | py-beep-if-tab-change))
|
|---|
| 3614 | nil ;pre-hooks
|
|---|
| 3615 | nil ;post-hooks
|
|---|
| 3616 | "Dear Barry,") ;salutation
|
|---|
| 3617 | (if enhancement-p nil
|
|---|
| 3618 | (set-mark (point))
|
|---|
| 3619 | (insert
|
|---|
| 3620 | "Please replace this text with a sufficiently large code sample\n\
|
|---|
| 3621 | and an exact recipe so that I can reproduce your problem. Failure\n\
|
|---|
| 3622 | to do so may mean a greater delay in fixing your bug.\n\n")
|
|---|
| 3623 | (exchange-point-and-mark)
|
|---|
| 3624 | (py-keep-region-active))))
|
|---|
| 3625 |
|
|---|
| 3626 | |
|---|
| 3627 |
|
|---|
| 3628 | (defun py-kill-emacs-hook ()
|
|---|
| 3629 | "Delete files in `py-file-queue'.
|
|---|
| 3630 | These are Python temporary files awaiting execution."
|
|---|
| 3631 | (mapcar #'(lambda (filename)
|
|---|
| 3632 | (py-safe (delete-file filename)))
|
|---|
| 3633 | py-file-queue))
|
|---|
| 3634 |
|
|---|
| 3635 | ;; arrange to kill temp files when Emacs exists
|
|---|
| 3636 | (add-hook 'kill-emacs-hook 'py-kill-emacs-hook)
|
|---|
| 3637 | (add-hook 'comint-output-filter-functions 'py-pdbtrack-track-stack-file)
|
|---|
| 3638 |
|
|---|
| 3639 | ;; Add a designator to the minor mode strings
|
|---|
| 3640 | (or (assq 'py-pdbtrack-minor-mode-string minor-mode-alist)
|
|---|
| 3641 | (push '(py-pdbtrack-is-tracking-p py-pdbtrack-minor-mode-string)
|
|---|
| 3642 | minor-mode-alist))
|
|---|
| 3643 |
|
|---|
| 3644 |
|
|---|
| 3645 | |
|---|
| 3646 |
|
|---|
| 3647 | ;;; paragraph and string filling code from Bernhard Herzog
|
|---|
| 3648 | ;;; see http://mail.python.org/pipermail/python-list/2002-May/103189.html
|
|---|
| 3649 |
|
|---|
| 3650 | (defun py-fill-comment (&optional justify)
|
|---|
| 3651 | "Fill the comment paragraph around point"
|
|---|
| 3652 | (let (;; Non-nil if the current line contains a comment.
|
|---|
| 3653 | has-comment
|
|---|
| 3654 |
|
|---|
| 3655 | ;; If has-comment, the appropriate fill-prefix for the comment.
|
|---|
| 3656 | comment-fill-prefix)
|
|---|
| 3657 |
|
|---|
| 3658 | ;; Figure out what kind of comment we are looking at.
|
|---|
| 3659 | (save-excursion
|
|---|
| 3660 | (beginning-of-line)
|
|---|
| 3661 | (cond
|
|---|
| 3662 | ;; A line with nothing but a comment on it?
|
|---|
| 3663 | ((looking-at "[ \t]*#[# \t]*")
|
|---|
| 3664 | (setq has-comment t
|
|---|
| 3665 | comment-fill-prefix (buffer-substring (match-beginning 0)
|
|---|
| 3666 | (match-end 0))))
|
|---|
| 3667 |
|
|---|
| 3668 | ;; A line with some code, followed by a comment? Remember that the hash
|
|---|
| 3669 | ;; which starts the comment shouldn't be part of a string or character.
|
|---|
| 3670 | ((progn
|
|---|
| 3671 | (while (not (looking-at "#\\|$"))
|
|---|
| 3672 | (skip-chars-forward "^#\n\"'\\")
|
|---|
| 3673 | (cond
|
|---|
| 3674 | ((eq (char-after (point)) ?\\) (forward-char 2))
|
|---|
| 3675 | ((memq (char-after (point)) '(?\" ?')) (forward-sexp 1))))
|
|---|
| 3676 | (looking-at "#+[\t ]*"))
|
|---|
| 3677 | (setq has-comment t)
|
|---|
| 3678 | (setq comment-fill-prefix
|
|---|
| 3679 | (concat (make-string (current-column) ? )
|
|---|
| 3680 | (buffer-substring (match-beginning 0) (match-end 0)))))))
|
|---|
| 3681 |
|
|---|
| 3682 | (if (not has-comment)
|
|---|
| 3683 | (fill-paragraph justify)
|
|---|
| 3684 |
|
|---|
| 3685 | ;; Narrow to include only the comment, and then fill the region.
|
|---|
| 3686 | (save-restriction
|
|---|
| 3687 | (narrow-to-region
|
|---|
| 3688 |
|
|---|
| 3689 | ;; Find the first line we should include in the region to fill.
|
|---|
| 3690 | (save-excursion
|
|---|
| 3691 | (while (and (zerop (forward-line -1))
|
|---|
| 3692 | (looking-at "^[ \t]*#")))
|
|---|
| 3693 |
|
|---|
| 3694 | ;; We may have gone to far. Go forward again.
|
|---|
| 3695 | (or (looking-at "^[ \t]*#")
|
|---|
| 3696 | (forward-line 1))
|
|---|
| 3697 | (point))
|
|---|
| 3698 |
|
|---|
| 3699 | ;; Find the beginning of the first line past the region to fill.
|
|---|
| 3700 | (save-excursion
|
|---|
| 3701 | (while (progn (forward-line 1)
|
|---|
| 3702 | (looking-at "^[ \t]*#")))
|
|---|
| 3703 | (point)))
|
|---|
| 3704 |
|
|---|
| 3705 | ;; Lines with only hashes on them can be paragraph boundaries.
|
|---|
| 3706 | (let ((paragraph-start (concat paragraph-start "\\|[ \t#]*$"))
|
|---|
| 3707 | (paragraph-separate (concat paragraph-separate "\\|[ \t#]*$"))
|
|---|
| 3708 | (fill-prefix comment-fill-prefix))
|
|---|
| 3709 | ;;(message "paragraph-start %S paragraph-separate %S"
|
|---|
| 3710 | ;;paragraph-start paragraph-separate)
|
|---|
| 3711 | (fill-paragraph justify))))
|
|---|
| 3712 | t))
|
|---|
| 3713 |
|
|---|
| 3714 |
|
|---|
| 3715 | (defun py-fill-string (start &optional justify)
|
|---|
| 3716 | "Fill the paragraph around (point) in the string starting at start"
|
|---|
| 3717 | ;; basic strategy: narrow to the string and call the default
|
|---|
| 3718 | ;; implementation
|
|---|
| 3719 | (let (;; the start of the string's contents
|
|---|
| 3720 | string-start
|
|---|
| 3721 | ;; the end of the string's contents
|
|---|
| 3722 | string-end
|
|---|
| 3723 | ;; length of the string's delimiter
|
|---|
| 3724 | delim-length
|
|---|
| 3725 | ;; The string delimiter
|
|---|
| 3726 | delim
|
|---|
| 3727 | )
|
|---|
| 3728 |
|
|---|
| 3729 | (save-excursion
|
|---|
| 3730 | (goto-char start)
|
|---|
| 3731 | (if (looking-at "\\('''\\|\"\"\"\\|'\\|\"\\)\\\\?\n?")
|
|---|
| 3732 | (setq string-start (match-end 0)
|
|---|
| 3733 | delim-length (- (match-end 1) (match-beginning 1))
|
|---|
| 3734 | delim (buffer-substring-no-properties (match-beginning 1)
|
|---|
| 3735 | (match-end 1)))
|
|---|
| 3736 | (error "The parameter start is not the beginning of a python string"))
|
|---|
| 3737 |
|
|---|
| 3738 | ;; if the string is the first token on a line and doesn't start with
|
|---|
| 3739 | ;; a newline, fill as if the string starts at the beginning of the
|
|---|
| 3740 | ;; line. this helps with one line docstrings
|
|---|
| 3741 | (save-excursion
|
|---|
| 3742 | (beginning-of-line)
|
|---|
| 3743 | (and (/= (char-before string-start) ?\n)
|
|---|
| 3744 | (looking-at (concat "[ \t]*" delim))
|
|---|
| 3745 | (setq string-start (point))))
|
|---|
| 3746 |
|
|---|
| 3747 | (forward-sexp (if (= delim-length 3) 2 1))
|
|---|
| 3748 |
|
|---|
| 3749 | ;; with both triple quoted strings and single/double quoted strings
|
|---|
| 3750 | ;; we're now directly behind the first char of the end delimiter
|
|---|
| 3751 | ;; (this doesn't work correctly when the triple quoted string
|
|---|
| 3752 | ;; contains the quote mark itself). The end of the string's contents
|
|---|
| 3753 | ;; is one less than point
|
|---|
| 3754 | (setq string-end (1- (point))))
|
|---|
| 3755 |
|
|---|
| 3756 | ;; Narrow to the string's contents and fill the current paragraph
|
|---|
| 3757 | (save-restriction
|
|---|
| 3758 | (narrow-to-region string-start string-end)
|
|---|
| 3759 | (let ((ends-with-newline (= (char-before (point-max)) ?\n)))
|
|---|
| 3760 | (fill-paragraph justify)
|
|---|
| 3761 | (if (and (not ends-with-newline)
|
|---|
| 3762 | (= (char-before (point-max)) ?\n))
|
|---|
| 3763 | ;; the default fill-paragraph implementation has inserted a
|
|---|
| 3764 | ;; newline at the end. Remove it again.
|
|---|
| 3765 | (save-excursion
|
|---|
| 3766 | (goto-char (point-max))
|
|---|
| 3767 | (delete-char -1)))))
|
|---|
| 3768 |
|
|---|
| 3769 | ;; return t to indicate that we've done our work
|
|---|
| 3770 | t))
|
|---|
| 3771 |
|
|---|
| 3772 | (defun py-fill-paragraph (&optional justify)
|
|---|
| 3773 | "Like \\[fill-paragraph], but handle Python comments and strings.
|
|---|
| 3774 | If any of the current line is a comment, fill the comment or the
|
|---|
| 3775 | paragraph of it that point is in, preserving the comment's indentation
|
|---|
| 3776 | and initial `#'s.
|
|---|
| 3777 | If point is inside a string, narrow to that string and fill.
|
|---|
| 3778 | "
|
|---|
| 3779 | (interactive "P")
|
|---|
| 3780 | (let* ((bod (py-point 'bod))
|
|---|
| 3781 | (pps (parse-partial-sexp bod (point))))
|
|---|
| 3782 | (cond
|
|---|
| 3783 | ;; are we inside a comment or on a line with only whitespace before
|
|---|
| 3784 | ;; the comment start?
|
|---|
| 3785 | ((or (nth 4 pps)
|
|---|
| 3786 | (save-excursion (beginning-of-line) (looking-at "[ \t]*#")))
|
|---|
| 3787 | (py-fill-comment justify))
|
|---|
| 3788 | ;; are we inside a string?
|
|---|
| 3789 | ((nth 3 pps)
|
|---|
| 3790 | (py-fill-string (nth 8 pps)))
|
|---|
| 3791 | ;; otherwise use the default
|
|---|
| 3792 | (t
|
|---|
| 3793 | (fill-paragraph justify)))))
|
|---|
| 3794 |
|
|---|
| 3795 |
|
|---|
| 3796 | |
|---|
| 3797 |
|
|---|
| 3798 | (provide 'python-mode)
|
|---|
| 3799 | ;;; python-mode.el ends here
|
|---|