Mercurial > hg > xemacs-beta
diff lisp/modes/python-mode.el @ 4:b82b59fe008d r19-15b3
Import from CVS: tag r19-15b3
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:46:56 +0200 |
parents | ac2d302a0011 |
children | 8fc7fe29b841 |
line wrap: on
line diff
--- a/lisp/modes/python-mode.el Mon Aug 13 08:46:35 2007 +0200 +++ b/lisp/modes/python-mode.el Mon Aug 13 08:46:56 2007 +0200 @@ -6,8 +6,8 @@ ;; 1992-1994 Tim Peters ;; Maintainer: python-mode@python.org ;; Created: Feb 1992 -;; Version: 2.67 -;; Last Modified: 1996/08/01 20:11:51 +;; Version: 2.83 +;; Last Modified: 1996/10/23 20:44:59 ;; Keywords: python languages oop ;; This software is provided as-is, without express or implied @@ -17,12 +17,11 @@ ;; notice and this paragraph appear in all copies. ;;; Commentary: -;; ;; This is a major mode for editing Python programs. It was developed ;; by Tim Peters after an original idea by Michael A. Guravage. Tim -;; left the net for a while and in the interim, Barry Warsaw has -;; undertaken maintenance of the mode. +;; subsequently left the net; in 1995, Barry Warsaw inherited the +;; mode and is the current maintainer. ;; At some point this mode will undergo a rewrite to bring it more in ;; line with GNU Emacs Lisp coding standards, and to wax all the Emacs @@ -59,7 +58,8 @@ ;; - proper interaction with pending-del and del-sel modes. ;; - Better support for outdenting: py-electric-colon (:) and ;; py-indent-line (TAB) improvements; one level of outdentation -;; added after a return, raise, break, or continue statement +;; added after a return, raise, break, pass, or continue statement. +;; Defeated by prefixing command with C-u. ;; - New py-electric-colon (:) command for improved outdenting Also ;; py-indent-line (TAB) should handle outdented lines better ;; - improved (I think) C-c > and C-c < @@ -84,6 +84,8 @@ ;; hasn't been a problem... yet. ;; - have py-execute-region on indented code act as if the region is ;; left justified. Avoids syntax errors. +;; - Add a py-goto-error or some such that would scan an exception in +;; the py-shell buffer, and pop you to that line in the file. ;; If you can think of more things you'd like to see, drop me a line. ;; If you want to report bugs, use py-submit-bug-report (C-c C-b). @@ -207,7 +209,7 @@ the Emacs bell is also rung as a warning.") (defconst python-font-lock-keywords - (let* ((keywords '("access" "and" "break" "class" + (let* ((keywords '("and" "break" "class" "continue" "def" "del" "elif" "else:" "except" "except:" "exec" "finally:" "for" "from" "global" @@ -385,14 +387,37 @@ "while\\s +.*:" "for\\s +.*:" "if\\s +.*:" - "elif\\s +.*:") + "elif\\s +.*:" + "\\(return\\|break\\|raise\\|continue\\)[ \t\n]" + ) "\\|") "\\)") "Regexp matching lines to not outdent after.") +(defvar py-defun-start-re + "^\\([ \t]*\\)def[ \t]+\\([a-zA-Z_0-9]+\\)\\|\\(^[a-zA-Z_0-9]+\\)[ \t]*=" + "Regexp matching a function, method or variable assignment. + +If you change this, you probably have to change `py-current-defun' as well. +This is only used by `py-current-defun' to find the name for add-log.el.") + +(defvar py-class-start-re "^class[ \t]*\\([a-zA-Z_0-9]+\\)" + "Regexp for finding a class name. + +If you change this, you probably have to change `py-current-defun' as well. +This is only used by `py-current-defun' to find the name for add-log.el.") + + ;; Menu definitions, only relevent if you have the easymenu.el package ;; (standard in the latest Emacs 19 and XEmacs 19 distributions). +(defvar py-menu nil + "Menu for Python Mode. + +This menu will get created automatically if you have the easymenu +package. Note that the latest XEmacs 19 and Emacs 19 versions contain +this package.") + (if (condition-case nil (require 'easymenu) (error nil)) @@ -489,8 +514,8 @@ ;; These next two variables are used when searching for the python ;; class/definitions. Just saving some time in accessing the ;; generic-python-expression, really. -(defvar imenu-example--python-generic-regexp) -(defvar imenu-example--python-generic-parens) +(defvar imenu-example--python-generic-regexp nil) +(defvar imenu-example--python-generic-parens nil) ;;;###autoload @@ -650,11 +675,35 @@ py-temp-directory\t\tdirectory used for temp files (if needed) py-beep-if-tab-change\t\tring the bell if tab-width is changed" (interactive) + ;; set up local variables (kill-all-local-variables) + (make-local-variable 'font-lock-defaults) + (make-local-variable 'paragraph-separate) + (make-local-variable 'paragraph-start) + (make-local-variable 'require-final-newline) + (make-local-variable 'comment-start) + (make-local-variable 'comment-start-skip) + (make-local-variable 'comment-column) + (make-local-variable 'indent-region-function) + (make-local-variable 'indent-line-function) + (make-local-variable 'add-log-current-defun-function) + ;; (set-syntax-table py-mode-syntax-table) - (setq major-mode 'python-mode - mode-name "Python" - local-abbrev-table python-mode-abbrev-table) + (setq major-mode 'python-mode + mode-name "Python" + local-abbrev-table python-mode-abbrev-table + font-lock-defaults '(python-font-lock-keywords) + paragraph-separate "^[ \t]*$" + paragraph-start "^[ \t]*$" + require-final-newline t + comment-start "# " + comment-start-skip "# *" + comment-column 40 + indent-region-function 'py-indent-region + indent-line-function 'py-indent-line + ;; tell add-log.el how to find the current function/method/variable + add-log-current-defun-function 'py-current-defun + ) (use-local-map py-mode-map) ;; add the menu (if py-menu @@ -662,18 +711,6 @@ ;; Emacs 19 requires this (if (or py-this-is-lucid-emacs-p py-this-is-emacs-19-p) (setq comment-multi-line nil)) - ;; BAW -- style... - (mapcar (function (lambda (x) - (make-local-variable (car x)) - (set (car x) (cdr x)))) - '((paragraph-separate . "^[ \t]*$") - (paragraph-start . "^[ \t]*$") - (require-final-newline . t) - (comment-start . "# ") - (comment-start-skip . "# *") - (comment-column . 40) - (indent-region-function . py-indent-region) - (indent-line-function . py-indent-line))) ;; hack to allow overriding the tabsize in the file (see tokenizer.c) ;; ;; not sure where the magic comment has to be; to save time @@ -752,12 +789,12 @@ (save-excursion (let ((here (point)) (outdent 0) - (indent (py-compute-indentation))) + (indent (py-compute-indentation t))) (if (and (not arg) (py-outdent-p) (= indent (save-excursion - (forward-line -1) - (py-compute-indentation))) + (py-next-statement -1) + (py-compute-indentation t))) ) (setq outdent py-indent-offset)) ;; Don't indent, only outdent. This assumes that any lines that @@ -774,6 +811,7 @@ ;;; Functions that execute Python commands in a subprocess +;;;###autoload (defun py-shell () "Start an interactive Python interpreter in another window. This is like Shell mode, except that Python is running in the window @@ -895,42 +933,47 @@ ;; read_process_output has update_mode_lines++ for a similar ;; reason? beats me ... - ;; BAW - we want to check to see if this still applies - (if (eq curbuf pbuf) ; mysterious ugly hack - (set-buffer (get-buffer-create "*scratch*"))) + (unwind-protect + ;; make sure current buffer is restored + ;; BAW - we want to check to see if this still applies + (progn + ;; mysterious ugly hack + (if (eq curbuf pbuf) + (set-buffer (get-buffer-create "*scratch*"))) - (set-buffer pbuf) - (let* ((start (point)) - (goback (< start pmark)) - (goend (and (not goback) (= start (point-max)))) - (buffer-read-only nil)) - (goto-char pmark) - (insert string) - (move-marker pmark (point)) - (setq file-finished - (and py-file-queue - (equal ">>> " - (buffer-substring - (prog2 (beginning-of-line) (point) - (goto-char pmark)) - (point))))) - (if goback (goto-char start) - ;; else - (if py-scroll-process-buffer - (let* ((pop-up-windows t) - (pwin (display-buffer pbuf))) - (set-window-point pwin (point))))) - (set-buffer curbuf) - (if file-finished - (progn - (py-delete-file-silently (car py-file-queue)) - (setq py-file-queue (cdr py-file-queue)) - (if py-file-queue - (py-execute-file pyproc (car py-file-queue))))) - (and goend - (progn (set-buffer pbuf) - (goto-char (point-max)))) - ))) + (set-buffer pbuf) + (let* ((start (point)) + (goback (< start pmark)) + (goend (and (not goback) (= start (point-max)))) + (buffer-read-only nil)) + (goto-char pmark) + (insert string) + (move-marker pmark (point)) + (setq file-finished + (and py-file-queue + (equal ">>> " + (buffer-substring + (prog2 (beginning-of-line) (point) + (goto-char pmark)) + (point))))) + (if goback (goto-char start) + ;; else + (if py-scroll-process-buffer + (let* ((pop-up-windows t) + (pwin (display-buffer pbuf))) + (set-window-point pwin (point))))) + (set-buffer curbuf) + (if file-finished + (progn + (py-delete-file-silently (car py-file-queue)) + (setq py-file-queue (cdr py-file-queue)) + (if py-file-queue + (py-execute-file pyproc (car py-file-queue))))) + (and goend + (progn (set-buffer pbuf) + (goto-char (point-max)))) + )) + (set-buffer curbuf)))) (defun py-execute-buffer () "Send the contents of the buffer to a Python interpreter. @@ -995,12 +1038,17 @@ (put 'py-delete-char 'delete-selection 'supersede) (put 'py-delete-char 'pending-delete 'supersede) -(defun py-indent-line () - "Fix the indentation of the current line according to Python rules." - (interactive) +(defun py-indent-line (&optional arg) + "Fix the indentation of the current line according to Python rules. +With \\[universal-argument], ignore outdenting rules for block +closing statements (e.g. return, raise, break, continue, pass) + +This function is normally bound to `indent-line-function' so +\\[indent-for-tab-command] will call it." + (interactive "P") (let* ((ci (current-indentation)) (move-to-indentation-p (<= (current-column) ci)) - (need (py-compute-indentation))) + (need (py-compute-indentation (not arg)))) ;; see if we need to outdent (if (py-outdent-p) (setq need (- need py-indent-offset))) @@ -1026,7 +1074,10 @@ (insert-char ?\n 1) (move-to-column ci)))) -(defun py-compute-indentation () +(defun py-compute-indentation (honor-block-close-p) + ;; implements all the rules for indentation computation. when + ;; honor-block-close-p is non-nil, statements such as return, raise, + ;; break, continue, and pass force one level of outdenting. (save-excursion (let ((pps (parse-partial-sexp (save-excursion (beginning-of-python-def-or-class) @@ -1172,7 +1223,7 @@ (+ (current-indentation) (if (py-statement-opens-block-p) py-indent-offset - (if (py-statement-closes-block-p) + (if (and honor-block-close-p (py-statement-closes-block-p)) (- py-indent-offset) 0))) ))))) @@ -1332,7 +1383,7 @@ (target-column 0) ; column to which to indent (base-shifted-by 0) ; amount last base line was shifted (indent-base (if (looking-at "[ \t\n]") - (py-compute-indentation) + (py-compute-indentation t) 0)) ci) (while (< (point) end) @@ -1728,10 +1779,12 @@ (interactive "p") (let ((case-fold-search nil)) (if (> arg 0) - (re-search-forward "\\W*\\([A-Z_]*[a-z0-9]*\\)" (point-max) t arg) + (re-search-forward + "\\(\\W\\|[_]\\)*\\([A-Z]*[a-z0-9]*\\)" + (point-max) t arg) (while (and (< arg 0) (re-search-backward - "\\(\\(\\W\\|[a-z0-9]\\)[A-Z]+\\|\\W\\w+\\)" + "\\(\\W\\|[a-z0-9]\\)[A-Z]+\\|\\(\\W\\|[_]\\)\\w+" (point-min) 0)) (forward-char 1) (setq arg (1+ arg))))) @@ -1776,8 +1829,7 @@ (where-is-internal func py-mode-map) ", ")))) ((equal funckind "v") ; variable - (setq funcdoc (substitute-command-keys - (get func 'variable-documentation)) + (setq funcdoc (documentation-property func 'variable-documentation) keys (if (assq func locals) (concat "Local/Global values: " @@ -2180,12 +2232,12 @@ (defun py-statement-closes-block-p () ;; true iff the current statement `closes' a block == the line - ;; starts with `return', `raise', `break' or `continue'. doesn't - ;; catch embedded statements + ;; starts with `return', `raise', `break', `continue', and `pass'. + ;; doesn't catch embedded statements (let ((here (point))) (back-to-indentation) (prog1 - (looking-at "\\(return\\|raise\\|break\\|continue\\)\\>") + (looking-at "\\(return\\|raise\\|break\\|continue\\|pass\\)\\>") (goto-char here)))) ;; go to point right beyond final line of block begun by the current @@ -2309,9 +2361,20 @@ (set-buffer cbuf)) (sit-for 0)) +(defun py-current-defun () + ;; tell add-log.el how to find the current function/method/variable + (save-excursion + (if (re-search-backward py-defun-start-re nil t) + (or (match-string 3) + (let ((method (match-string 2))) + (if (and (not (zerop (length (match-string 1)))) + (re-search-backward py-class-start-re nil t)) + (concat (match-string 1) "." method) + method))) + nil))) -(defconst py-version "2.67" +(defconst py-version "2.83" "`python-mode' version number.") (defconst py-help-address "python-mode@python.org" "Address accepting submission of bug reports.")