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