CVS update by skip packages/xemacs-packages/python-modes, python-mode.el ...

xemacs-cvs at xemacs.org xemacs-cvs at xemacs.org
Sat Jan 19 09:49:16 EST 2008


  User: skip    
  Date: 08/01/19 15:49:16

  Modified:    packages/xemacs-packages/python-modes ChangeLog Makefile
                        python-mode.el python-mode.el.upstream
Log:
sync python-mode from SF project

Revision  Changes    Path
1.22      +9 -0      XEmacs/packages/xemacs-packages/python-modes/ChangeLog

Index: ChangeLog
===================================================================
RCS file: /pack/xemacscvs/XEmacs/packages/xemacs-packages/python-modes/ChangeLog,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -p -r1.21 -r1.22
--- ChangeLog	2007/05/22 06:39:12	1.21
+++ ChangeLog	2008/01/19 14:49:14	1.22
@@ -1,3 +1,12 @@
+2008-01-17  Skip Montanaro  <skip at pobox.com>
+
+	* python-mode.el: Replace what's here with the current version
+	from the python-mode SF project.
+	* python-mode.el.upstream: Sync with the SF version.  In the
+	future, XEmacs maintainers can update python-mode.el, then I can
+	diff to see what needs to either move upstream or be retained in
+	future sync operations.
+	
 2007-05-22  Norbert Koch  <viteno at xemacs.org>
 
 	* Makefile (VERSION): XEmacs package 1.09 released.



1.18      +1 -1      XEmacs/packages/xemacs-packages/python-modes/Makefile

Index: Makefile
===================================================================
RCS file: /pack/xemacscvs/XEmacs/packages/xemacs-packages/python-modes/Makefile,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -p -r1.17 -r1.18
--- Makefile	2007/05/22 06:39:12	1.17
+++ Makefile	2008/01/19 14:49:14	1.18
@@ -18,7 +18,7 @@
 # Boston, MA 02111-1307, USA.
 
 VERSION = 1.09
-AUTHOR_VERSION =
+AUTHOR_VERSION = 426
 MAINTAINER = Skip Montanaro <skip at pobox.com>
 PACKAGE = python-modes
 PKG_TYPE = single-file



4.53      +286 -197  XEmacs/packages/xemacs-packages/python-modes/python-mode.el

Index: python-mode.el
===================================================================
RCS file: /pack/xemacscvs/XEmacs/packages/xemacs-packages/python-modes/python-mode.el,v
retrieving revision 4.52
retrieving revision 4.53
diff -u -p -r4.52 -r4.53
--- python-mode.el	2004/04/09 15:42:19	4.52
+++ python-mode.el	2008/01/19 14:49:14	4.53
@@ -2,14 +2,14 @@
 
 ;; Copyright (C) 1992,1993,1994  Tim Peters
 
-;; Author: 2003-2004 http://sf.net/projects/python-mode
+;; Author: 2003-2007 http://sf.net/projects/python-mode
 ;;         1995-2002 Barry A. Warsaw
 ;;         1992-1994 Tim Peters
 ;; Maintainer: python-mode at python.org
 ;; Created:    Feb 1992
 ;; Keywords:   python languages oop
 
-(defconst py-version "$Revision: 4.52 $"
+(defconst py-version "$Revision: 4.53 $"
   "`python-mode' version number.")
 
 ;; This software is provided as-is, without express or implied
@@ -20,19 +20,38 @@
 
 ;;; 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
-;; subsequently left the net; in 1995, Barry Warsaw inherited the mode
-;; and is the current maintainer.  Tim's now back but disavows all
-;; responsibility for the mode.  Smart Tim :-)
+;; This is a major mode for editing Python programs.  It was developed by Tim
+;; Peters after an original idea by Michael A. Guravage.  Tim subsequently
+;; left the net and in 1995, Barry Warsaw inherited the mode.  Tim's now back
+;; but disavows all responsibility for the mode.  In fact, we suspect he
+;; doesn't even use Emacs any more.  In 2003, python-mode.el was moved to its
+;; own SourceForge project apart from the Python project, and now is
+;; maintained by the volunteers at the python-mode at python.org mailing list.
 
-;; pdbtrack support contributed by Ken Manheimer, April 2001.
+;; pdbtrack support contributed by Ken Manheimer, April 2001.  Skip Montanaro
+;; has also contributed significantly to python-mode's development.
 
 ;; Please use the SourceForge Python project to submit bugs or
 ;; patches:
 ;;
 ;;     http://sourceforge.net/projects/python
 
+;; INSTALLATION:
+
+;; To install, just drop this file into a directory on your load-path and
+;; byte-compile it.  To set up Emacs to automatically edit files ending in
+;; ".py" using python-mode add the following to your ~/.emacs file (GNU
+;; Emacs) or ~/.xemacs/init.el file (XEmacs):
+;;    (setq auto-mode-alist (cons '("\\.py$" . python-mode) auto-mode-alist))
+;;    (setq interpreter-mode-alist (cons '("python" . python-mode)
+;;                                       interpreter-mode-alist))
+;;    (autoload 'python-mode "python-mode" "Python editing mode." t)
+;;
+;; In XEmacs syntax highlighting should be enabled automatically.  In GNU
+;; Emacs you may have to add these lines to your ~/.emacs file:
+;;    (global-font-lock-mode t)
+;;    (setq font-lock-maximum-decoration t)
+
 ;; FOR MORE INFORMATION:
 
 ;; There is some information on python-mode.el at
@@ -61,6 +80,7 @@
 (require 'custom)
 (require 'cl)
 (require 'compile)
+(require 'ansi-color)
 
 
 ;; user definable variables
@@ -71,34 +91,41 @@
   :group 'languages
   :prefix "py-")
 
+(defcustom py-tab-always-indent t
+  "*Non-nil means TAB in Python mode should always reindent the current line,
+regardless of where in the line point is when the TAB command is used."
+:type 'boolean
+:group 'python)
+
 (defcustom py-python-command "python"
   "*Shell command used to start Python interpreter."
   :type 'string
   :group 'python)
 
-(defcustom py-jpython-command "jpython"
-  "*Shell command used to start the JPython interpreter."
+(make-obsolete-variable 'py-jpython-command 'py-jython-command)
+(defcustom py-jython-command "jython"
+  "*Shell command used to start the Jython interpreter."
   :type 'string
   :group 'python
-:tag "JPython Command")
+:tag "Jython Command")
 
 (defcustom py-default-interpreter 'cpython
   "*Which Python interpreter is used by default.
-The value for this variable can be either `cpython' or `jpython'.
+The value for this variable can be either `cpython' or `jython'.
 
 When the value is `cpython', the variables `py-python-command' and
 `py-python-command-args' are consulted to determine the interpreter
 and arguments to use.
 
-When the value is `jpython', the variables `py-jpython-command' and
-`py-jpython-command-args' are consulted to determine the interpreter
+When the value is `jython', the variables `py-jython-command' and
+`py-jython-command-args' are consulted to determine the interpreter
 and arguments to use.
 
 Note that this variable is consulted only the first time that a Python
 mode buffer is visited during an Emacs session.  After that, use
 \\[py-toggle-shells] to change the interpreter shell."
   :type '(choice (const :tag "Python (a.k.a. CPython)" cpython)
-		 (const :tag "JPython" jpython))
+		 (const :tag "Jython" jython))
   :group 'python)
 
 (defcustom py-python-command-args '("-i")
@@ -106,11 +133,12 @@ mode buffer is visited during an Emacs s
   :type '(repeat string)
   :group 'python)
 
-(defcustom py-jpython-command-args '("-i")
-  "*List of string arguments to be used when starting a JPython shell."
+(make-obsolete-variable 'py-jpython-command-args 'py-jython-command-args)
+(defcustom py-jython-command-args '("-i")
+  "*List of string arguments to be used when starting a Jython shell."
   :type '(repeat string)
   :group 'python
-:tag "JPython Command Args")
+:tag "Jython Command Args")
 
 (defcustom py-indent-offset 4
   "*Amount of offset per level of indentation.
@@ -249,7 +277,7 @@ Otherwise, all modified buffers are save
   :type 'function
   :group 'python)
 
-(defcustom py-imenu-show-method-args-p nil 
+(defcustom py-imenu-show-method-args-p nil
   "*Controls echoing of arguments of functions & methods in the Imenu buffer.
 When non-nil, arguments are printed."
   :type 'boolean
@@ -276,19 +304,20 @@ as gud-mode does for debugging C program
   20000
   "Maximum number of characters to search for a Java-ish import statement.
 When `python-mode' tries to calculate the shell to use (either a
-CPython or a JPython shell), it looks at the so-called `shebang' line
+CPython or a Jython shell), it looks at the so-called `shebang' line
 -- i.e. #! line.  If that's not available, it looks at some of the
 file heading imports to see if they look Java-like."
   :type 'integer
   :group 'python
   )
 
-(defcustom py-jpython-packages
+(make-obsolete-variable 'py-jpython-packages 'py-jython-packages)
+(defcustom py-jython-packages
   '("java" "javax" "org" "com")
-  "Imported packages that imply `jpython-mode'."
+  "Imported packages that imply `jython-mode'."
   :type '(repeat string)
   :group 'python)
-  
+
 ;; Not customizable
 (defvar py-master-file nil
   "If non-nil, execute the named file instead of the buffer's file.
@@ -318,16 +347,39 @@ buffer is prepended to come up with a fi
   :tag "Pychecker Command Args")
 
 (defvar py-shell-alist
-  '(("jpython" . 'jpython)
-    ("jython" . 'jpython)
+  '(("jython" . 'jython)
     ("python" . 'cpython))
   "*Alist of interpreters and python shells. Used by `py-choose-shell'
 to select the appropriate python interpreter mode for a file.")
 
+(defcustom py-shell-input-prompt-1-regexp "^>>> "
+  "*A regular expression to match the input prompt of the shell."
+:type 'string
+:group 'python)
+
+(defcustom py-shell-input-prompt-2-regexp "^[.][.][.] "
+  "*A regular expression to match the input prompt of the shell after the
+  first line of input."
+:type 'string
+:group 'python)
+
+(defcustom py-shell-switch-buffers-on-execute t
+  "*Controls switching to the Python buffer where commands are
+  executed.  When non-nil the buffer switches to the Python buffer, if
+  not no switching occurs."
+:type 'boolean
+:group 'python)
+
 
 ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
 
+(defvar py-line-number-offset 0
+  "When an exception occurs as a result of py-execute-region, a
+subsequent py-up-exception needs the line number where the region
+started, in order to jump to the correct file line.  This variable is
+set in py-execute-region and used in py-jump-to-exception.")
+
 (defconst py-emacs-features
   (let (features)
    features)
@@ -340,16 +392,30 @@ support for features needed by `python-m
   "Face for pseudo keywords in Python mode, like self, True, False, Ellipsis.")
 (make-face 'py-pseudo-keyword-face)
 
+;; PEP 318 decorators
+(defvar py-decorators-face 'py-decorators-face
+  "Face method decorators.")
+(make-face 'py-decorators-face)
+
 ;; Face for builtins
 (defvar py-builtins-face 'py-builtins-face
   "Face for builtins like TypeError, object, open, and exec.")
 (make-face 'py-builtins-face)
 
+;; XXX, TODO, and FIXME comments and such
+(defvar py-XXX-tag-face 'py-XXX-tag-face
+  "Face for XXX, TODO, and FIXME tags")
+(make-face 'py-XXX-tag-face)
+
 (defun py-font-lock-mode-hook ()
   (or (face-differs-from-default-p 'py-pseudo-keyword-face)
       (copy-face 'font-lock-keyword-face 'py-pseudo-keyword-face))
   (or (face-differs-from-default-p 'py-builtins-face)
       (copy-face 'font-lock-keyword-face 'py-builtins-face))
+  (or (face-differs-from-default-p 'py-decorators-face)
+      (copy-face 'py-pseudo-keyword-face 'py-decorators-face))
+  (or (face-differs-from-default-p 'py-XXX-tag-face)
+      (copy-face 'font-lock-comment-face 'py-XXX-tag-face))
   )
 (add-hook 'font-lock-mode-hook 'py-font-lock-mode-hook)
 
@@ -361,7 +427,7 @@ support for features needed by `python-m
 			  "from"     "global"   "if"      "import"
 			  "in"       "is"       "lambda"  "not"
 			  "or"       "pass"     "print"   "raise"
-			  "return"   "while"    "yield"
+			  "return"   "while"    "with"    "yield"
 			  )
 			"\\|"))
 	(kw2 (mapconcat 'identity
@@ -371,6 +437,24 @@ support for features needed by `python-m
 			;; Don't include True, False, None, or
 			;; Ellipsis in this list, since they are
 			;; already defined as pseudo keywords.
+			'("__debug__"
+			  "__import__" "__name__" "abs" "apply" "basestring"
+			  "bool" "buffer" "callable" "chr" "classmethod"
+			  "cmp" "coerce" "compile" "complex" "copyright"
+			  "delattr" "dict" "dir" "divmod"
+			  "enumerate" "eval" "execfile" "exit" "file"
+			  "filter" "float" "getattr" "globals" "hasattr"
+			  "hash" "hex" "id" "input" "int" "intern"
+			  "isinstance" "issubclass" "iter" "len" "license"
+			  "list" "locals" "long" "map" "max" "min" "object"
+			  "oct" "open" "ord" "pow" "property" "range"
+			  "raw_input" "reduce" "reload" "repr" "round"
+			  "setattr" "slice" "staticmethod" "str" "sum"
+			  "super" "tuple" "type" "unichr" "unicode" "vars"
+			  "xrange" "zip")
+			"\\|"))
+	(kw4 (mapconcat 'identity
+			;; Exceptions and warnings
 			'("ArithmeticError" "AssertionError"
 			  "AttributeError" "DeprecationWarning" "EOFError"
 			  "EnvironmentError" "Exception"
@@ -387,43 +471,34 @@ support for features needed by `python-m
 			  "UnicodeDecodeError" "UnicodeEncodeError"
 			  "UnicodeError" "UnicodeTranslateError"
 			  "UserWarning" "ValueError" "Warning"
-			  "ZeroDivisionError" "__debug__"
-			  "__import__" "__name__" "abs" "apply" "basestring"
-			  "bool" "buffer" "callable" "chr" "classmethod"
-			  "cmp" "coerce" "compile" "complex" "copyright"
-			  "delattr" "dict" "dir" "divmod"
-			  "enumerate" "eval" "execfile" "exit" "file"
-			  "filter" "float" "getattr" "globals" "hasattr"
-			  "hash" "hex" "id" "input" "int" "intern"
-			  "isinstance" "issubclass" "iter" "len" "license"
-			  "list" "locals" "long" "map" "max" "min" "object"
-			  "oct" "open" "ord" "pow" "property" "range"
-			  "raw_input" "reduce" "reload" "repr" "round"
-			  "setattr" "slice" "staticmethod" "str" "sum"
-			  "super" "tuple" "type" "unichr" "unicode" "vars"
-			  "xrange" "zip")
+			  "ZeroDivisionError")
 			"\\|"))
 	)
     (list
+     '("^[ \t]*\\(@.+\\)" 1 'py-decorators-face)
      ;; keywords
-     (cons (concat "\\b\\(" kw1 "\\)\\b[ \n\t(]") 1)
+     (cons (concat "\\<\\(" kw1 "\\)\\>[ \n\t(]") 1)
      ;; builtins when they don't appear as object attributes
-     (list (concat "\\([^. \t]\\|^\\)[ \t]*\\b\\(" kw3 "\\)\\b[ \n\t(]") 2
+     (list (concat "\\([^. \t]\\|^\\)[ \t]*\\<\\(" kw3 "\\)\\>[ \n\t(]") 2
 	   'py-builtins-face)
      ;; block introducing keywords with immediately following colons.
      ;; Yes "except" is in both lists.
-     (cons (concat "\\b\\(" kw2 "\\)[ \n\t(]") 1)
-     ;; `as' but only in "import foo as bar"
-     '("[ \t]*\\(\\bfrom\\b.*\\)?\\bimport\\b.*\\b\\(as\\)\\b" . 2)
+     (cons (concat "\\<\\(" kw2 "\\)[ \n\t(]") 1)
+     ;; Exceptions
+     (list (concat "\\<\\(" kw4 "\\)[ \n\t:,(]") 1 'py-builtins-face)
+     ;; `as' but only in "import foo as bar" or "with foo as bar"
+     '("[ \t]*\\(\\<from\\>.*\\)?\\<import\\>.*\\<\\(as\\)\\>" . 2)
+     '("[ \t]*\\<with\\>.*\\<\\(as\\)\\>" . 1)
      ;; classes
-     '("\\bclass[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)"
-       1 font-lock-type-face)
+     '("\\<class[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)" 1 font-lock-type-face)
      ;; functions
-     '("\\bdef[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)"
+     '("\\<def[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)"
        1 font-lock-function-name-face)
      ;; pseudo-keywords
-     '("\\b\\(self\\|None\\|True\\|False\\|Ellipsis\\)\\b"
+     '("\\<\\(self\\|None\\|True\\|False\\|Ellipsis\\)\\>"
        1 py-pseudo-keyword-face)
+     ;; XXX, TODO, and FIXME tags
+     '("XXX\\|TODO\\|FIXME" 0 py-XXX-tag-face t)
      ))
   "Additional expressions to highlight in Python mode.")
 (put 'python-mode 'font-lock-defaults '(python-font-lock-keywords))
@@ -434,13 +509,7 @@ support for features needed by `python-m
 Currently-active file is at the head of the list.")
 
 (defvar py-pdbtrack-is-tracking-p nil)
-(defvar py-pdbtrack-last-grubbed-buffer nil
-  "Record of the last buffer used when the source path was invalid.
 
-This buffer is consulted before the buffer-list history for satisfying
-`py-pdbtrack-grub-for-buffer', since it's the most often the likely
-prospect as debugging continues.")
-(make-variable-buffer-local 'py-pdbtrack-last-grubbed-buffer)
 (defvar py-pychecker-history nil)
 
 
@@ -474,7 +543,7 @@ prospect as debugging continues.")
    "\\(" "[^#'\"\n\\]" "\\|" py-stringlit-re "\\)*"
    "\\\\$")
   "Regular expression matching Python backslash continuation lines.")
-  
+
 (defconst py-blank-or-comment-re "[ \t]*\\($\\|#\\)"
   "Regular expression matching a blank or comment line.")
 
@@ -487,7 +556,7 @@ prospect as debugging continues.")
 			   "\\|")
 	  "\\)")
   "Regular expression matching statements to be dedented one level.")
-  
+
 (defconst py-block-closing-keywords-re
   "\\(return\\|raise\\|break\\|continue\\|pass\\)"
   "Regular expression matching keywords which typically close a block.")
@@ -508,17 +577,17 @@ prospect as debugging continues.")
 	  "\\)")
   "Regular expression matching lines not to dedent after.")
 
-(defconst py-traceback-line-re
+(defvar py-traceback-line-re
   "[ \t]+File \"\\([^\"]+\\)\", line \\([0-9]+\\)"
   "Regular expression that describes tracebacks.")
 
-;; pdbtrack contants
+;; pdbtrack constants
 (defconst py-pdbtrack-stack-entry-regexp
 ;  "^> \\([^(]+\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
   "^> \\(.*\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
   "Regular expression pdbtrack uses to find a stack trace entry.")
 
-(defconst py-pdbtrack-input-prompt "\n[(<]*pdb[>)]+ "
+(defconst py-pdbtrack-input-prompt "\n[(<]*[Pp]db[>)]+ "
   "Regular expression pdbtrack uses to recognize a pdb prompt.")
 
 (defconst py-pdbtrack-track-range 10000
@@ -536,8 +605,9 @@ prospect as debugging continues.")
 (defvar python-mode-hook nil
   "*Hook called by `python-mode'.")
 
-(defvar jpython-mode-hook nil
-  "*Hook called by `jpython-mode'. `jpython-mode' also calls
+(make-obsolete-variable 'jpython-mode-hook 'jython-mode-hook)
+(defvar jython-mode-hook nil
+  "*Hook called by `jython-mode'. `jython-mode' also calls
 `python-mode-hook'.")
 
 (defvar py-shell-hook nil
@@ -622,7 +692,7 @@ prospect as debugging continues.")
   ;; expect RET to do a `py-newline-and-indent' and any Emacsers who
   ;; dislike this are probably knowledgeable enough to do a rebind.
   ;; However, we do *not* change C-j since many Emacsers have already
-  ;; swapped RET and C-j and they don't want C-j bound to `newline' to 
+  ;; swapped RET and C-j and they don't want C-j bound to `newline' to
   ;; change.
   (define-key py-mode-map "\C-m" 'py-newline-and-indent)
   )
@@ -849,7 +919,7 @@ package.  Note that the latest X/Emacs r
 
 (defvar py-imenu-method-regexp
   (concat                               ; <<methods and functions>>
-   "\\("                                ; 
+   "\\("                                ;
    "^[ \t]*"                            ; new line and maybe whitespace
    "\\(def[ \t]+"                       ; function definitions start with def
    "\\([a-zA-Z0-9_]+\\)"                ;   name is here
@@ -885,7 +955,7 @@ information.")
 ;; it.
 (defvar py-imenu-generic-expression
   (cons
-   (concat 
+   (concat
     py-imenu-class-regexp
     "\\|"				; or...
     py-imenu-method-regexp
@@ -954,7 +1024,7 @@ of the first definition found."
 	looking-p
 	def-name prev-name
 	cur-indent def-pos
-	(class-paren (first  py-imenu-generic-parens)) 
+	(class-paren (first  py-imenu-generic-parens))
 	(def-paren   (second py-imenu-generic-parens)))
     (setq looking-p
 	  (re-search-forward py-imenu-generic-regexp (point-max) t))
@@ -1009,7 +1079,7 @@ of the first definition found."
 			  (cons save-elmt sub-method-alist))
 		    index-alist))))
        ;; found less indented expression, we're done.
-       (t 
+       (t
 	(setq looking-p nil)
 	(re-search-backward py-imenu-generic-regexp (point-min) t)))
       ;; end-cond
@@ -1023,7 +1093,7 @@ of the first definition found."
 
 
 (defun py-choose-shell-by-shebang ()
-  "Choose CPython or JPython mode by looking at #! on the first line.
+  "Choose CPython or Jython mode by looking at #! on the first line.
 Returns the appropriate mode function.
 Used by `py-choose-shell', and similar to but distinct from
 `set-auto-mode', though it uses `auto-mode-interpreter-regexp' (if available)."
@@ -1047,10 +1117,10 @@ Used by `py-choose-shell', and similar t
 
 
 (defun py-choose-shell-by-import ()
-  "Choose CPython or JPython mode based imports.
-If a file imports any packages in `py-jpython-packages', within
+  "Choose CPython or Jython mode based imports.
+If a file imports any packages in `py-jython-packages', within
 `py-import-check-point-max' characters from the start of the file,
-return `jpython', otherwise return nil."
+return `jython', otherwise return nil."
   (let (mode)
     (save-excursion
       (goto-char (point-min))
@@ -1058,14 +1128,14 @@ return `jpython', otherwise return nil."
 		  (search-forward-regexp
 		   "^\\(\\(from\\)\\|\\(import\\)\\) \\([^ \t\n.]+\\)"
 		   py-import-check-point-max t))
-	(setq mode (and (member (match-string 4) py-jpython-packages)
-			'jpython
+	(setq mode (and (member (match-string 4) py-jython-packages)
+			'jython
 			))))
     mode))
 
 
 (defun py-choose-shell ()
-  "Choose CPython or JPython mode. Returns the appropriate mode function.
+  "Choose CPython or Jython mode. Returns the appropriate mode function.
 This does the following:
  - look for an interpreter with `py-choose-shell-by-shebang'
  - examine imports using `py-choose-shell-by-import'
@@ -1174,17 +1244,18 @@ py-beep-if-tab-change\t\tring the bell i
     (py-toggle-shells (py-choose-shell))))
 
 
-(defun jpython-mode ()
-  "Major mode for editing JPython/Jython files.
+(make-obsolete 'jpython-mode 'jython-mode)
+(defun jython-mode ()
+  "Major mode for editing Jython/Jython files.
 This is a simple wrapper around `python-mode'.
-It runs `jpython-mode-hook' then calls `python-mode.'
+It runs `jython-mode-hook' then calls `python-mode.'
 It is added to `interpreter-mode-alist' and `py-choose-shell'.
 "
   (interactive)
   (python-mode)
-  (py-toggle-shells 'jpython)
-  (when jpython-mode-hook
-      (run-hooks 'jpython-mode-hook)))
+  (py-toggle-shells 'jython)
+  (when jython-mode-hook
+      (run-hooks 'jython-mode-hook)))
 
 
 ;; It's handy to add recognition of Python files to the
@@ -1193,8 +1264,7 @@ It is added to `interpreter-mode-alist' 
 ;; with the latter, we can't.  So we just won't add them if they're
 ;; already added.
 ;;;###autoload
-(let ((modes '(("jpython" . jpython-mode)
-	       ("jython" . jpython-mode)
+(let ((modes '(("jython" . jython-mode)
 	       ("python" . python-mode))))
   (while modes
     (when (not (assoc (car modes) interpreter-mode-alist))
@@ -1202,7 +1272,7 @@ It is added to `interpreter-mode-alist' 
     (setq modes (cdr modes))))
 ;;;###autoload
 (when (not (or (rassq 'python-mode auto-mode-alist)
-	       (rassq 'jpython-mode auto-mode-alist)))
+	       (rassq 'jython-mode auto-mode-alist)))
   (push '("\\.py$" . python-mode) auto-mode-alist))
 
 
@@ -1274,7 +1344,8 @@ comint believe the user typed this strin
 	(procbuf (process-buffer proc))
 ;	(comint-scroll-to-bottom-on-output t)
 	(msg (format "## working on region in file %s...\n" filename))
-	(cmd (format "execfile(r'%s')\n" filename)))
+        ;; add some comment, so that we can filter it out of history
+	(cmd (format "execfile(r'%s') # PYTHON-MODE\n" filename)))
     (unwind-protect
 	(save-excursion
 	  (set-buffer procbuf)
@@ -1287,12 +1358,13 @@ comint believe the user typed this strin
 (defun py-comint-output-filter-function (string)
   "Watch output for Python prompt and exec next file waiting in queue.
 This function is appropriate for `comint-output-filter-functions'."
-  ;; TBD: this should probably use split-string
-  (when (and (or (string-equal string ">>> ")
-		 (and (>= (length string) 5)
-		      (string-equal (substring string -5) "\n>>> ")))
-	     py-file-queue)
-    (pop-to-buffer (current-buffer))
+  ;;remove ansi terminal escape sequences from string, not sure why they are
+  ;;still around...
+  (setq string (ansi-color-filter-apply string))
+  (when (and (string-match py-shell-input-prompt-1-regexp string)
+                   py-file-queue)
+    (if py-shell-switch-buffers-on-execute
+      (pop-to-buffer (current-buffer)))
     (py-safe (delete-file (car py-file-queue)))
     (setq py-file-queue (cdr py-file-queue))
     (if py-file-queue
@@ -1376,8 +1448,7 @@ script, and set to python-mode, and pdbt
 We look first to visit the file indicated in the trace.
 
 Failing that, we look for the most recently visited python-mode buffer
-with the same name or having 
-having the named function.
+with the same name or having the named function.
 
 If we're unable find the source code we return a string describing the
 problem as best as we can determine."
@@ -1421,8 +1492,7 @@ problem as best as we can determine."
 (defun py-pdbtrack-grub-for-buffer (funcname lineno)
   "Find most recent buffer itself named or having function funcname.
 
-We first check the last buffer this function found, if any, then walk
-throught the buffer-list history for python-mode buffers that are
+We walk the buffer-list history for python-mode buffers that are
 named for funcname or define a function funcname."
   (let ((buffers (buffer-list))
         buf
@@ -1440,7 +1510,7 @@ named for funcname or define a function 
                                    (buffer-substring (point-min)
                                                      (point-max))))))
           (setq got buf)))
-    (setq py-pdbtrack-last-grubbed-buffer got)))
+    got))
 
 (defun py-postprocess-output-buffer (buf)
   "Highlight exceptions found in BUF.
@@ -1470,7 +1540,7 @@ If an exception occurred return t, other
 (defconst py-output-buffer "*Python Output*")
 (make-variable-buffer-local 'py-output-buffer)
 
-;; for toggling between CPython and JPython
+;; for toggling between CPython and Jython
 (defvar py-which-shell nil)
 (defvar py-which-args  py-python-command-args)
 (defvar py-which-bufname "Python")
@@ -1479,14 +1549,14 @@ If an exception occurred return t, other
 (make-variable-buffer-local 'py-which-bufname)
 
 (defun py-toggle-shells (arg)
-  "Toggles between the CPython and JPython shells.
+  "Toggles between the CPython and Jython shells.
 
 With positive argument ARG (interactively \\[universal-argument]),
-uses the CPython shell, with negative ARG uses the JPython shell, and
+uses the CPython shell, with negative ARG uses the Jython shell, and
 with a zero argument, toggles the shell.
 
 Programmatically, ARG can also be one of the symbols `cpython' or
-`jpython', equivalent to positive arg and negative arg respectively."
+`jython', equivalent to positive arg and negative arg respectively."
   (interactive "P")
   ;; default is to toggle
   (if (null arg)
@@ -1499,7 +1569,7 @@ Programmatically, ARG can also be one of
 	(setq arg -1)
       (setq arg 1)))
    ((equal arg 'cpython) (setq arg 1))
-   ((equal arg 'jpython) (setq arg -1)))
+   ((equal arg 'jython) (setq arg -1)))
   (let (msg)
     (cond
      ((< 0 arg)
@@ -1507,14 +1577,16 @@ Programmatically, ARG can also be one of
       (setq py-which-shell py-python-command
 	    py-which-args py-python-command-args
 	    py-which-bufname "Python"
-	    msg "CPython"
-	    mode-name "Python"))
+	    msg "CPython")
+      (if (string-equal py-which-bufname "Jython")
+	  (setq mode-name "Python")))
      ((> 0 arg)
-      (setq py-which-shell py-jpython-command
-	    py-which-args py-jpython-command-args
-	    py-which-bufname "JPython"
-	    msg "JPython"
-	    mode-name "JPython"))
+      (setq py-which-shell py-jython-command
+	    py-which-args py-jython-command-args
+	    py-which-bufname "Jython"
+	    msg "Jython")
+      (if (string-equal py-which-bufname "Python")
+	  (setq mode-name "Jython")))
      )
     (message "Using the %s shell" msg)
     (setq py-output-buffer (format "*%s Output*" py-which-bufname))))
@@ -1536,9 +1608,9 @@ prompt).  This argument is ignored when 
 programmatically, or when running in Emacs 19.34 or older.
 
 Note: You can toggle between using the CPython interpreter and the
-JPython interpreter by hitting \\[py-toggle-shells].  This toggles
+Jython interpreter by hitting \\[py-toggle-shells].  This toggles
 buffer local variables which control whether all your subshell
-interactions happen to the `*JPython*' or `*Python*' buffers (the
+interactions happen to the `*Jython*' or `*Python*' buffers (the
 latter is the name used for the CPython buffer).
 
 Warning: Don't use an interactive Python if you change sys.ps1 or
@@ -1572,10 +1644,14 @@ filter."
 			       (concat
 				(mapconcat 'identity py-which-args " ") " ")
 			       ))))
-    (switch-to-buffer-other-window
-     (apply 'make-comint py-which-bufname py-which-shell nil args))
+    (if (not (equal (buffer-name) "*Python*"))
+        (switch-to-buffer-other-window
+         (apply 'make-comint py-which-bufname py-which-shell nil args))
+      (apply 'make-comint py-which-bufname py-which-shell nil args))
     (make-local-variable 'comint-prompt-regexp)
-    (setq comint-prompt-regexp "^>>> \\|^[.][.][.] \\|^(pdb) ")
+    (setq comint-prompt-regexp (concat py-shell-input-prompt-1-regexp "\\|"
+                                       py-shell-input-prompt-2-regexp "\\|"
+                                       "^([Pp]db) "))
     (add-hook 'comint-output-filter-functions
 	      'py-comint-output-filter-function)
     ;; pdbtrack
@@ -1646,11 +1722,13 @@ is inserted at the end.  See also the co
       (setq start (point))
       (or (< start end)
 	  (error "Region is empty"))
+      (setq py-line-number-offset (count-lines 1 start))
       (let ((needs-if (/= (py-point 'bol) (py-point 'boi))))
 	(set-buffer buf)
 	(python-mode)
 	(when needs-if
-	  (insert "if 1:\n"))
+	  (insert "if 1:\n")
+	  (setq py-line-number-offset (- py-line-number-offset 1)))
 	(insert-buffer-substring cur start end)
 	;; Set the shell either to the #! line command, or to the
 	;; py-which-shell buffer local variable.
@@ -1687,8 +1765,9 @@ is inserted at the end.  See also the co
       (setq py-exception-buffer (cons file (current-buffer))))
      (t
       ;; TBD: a horrible hack, but why create new Custom variables?
-      (let ((cmd (concat shell (if (string-equal py-which-bufname "JPython")
-				   " -" ""))))
+      (let ((cmd (concat py-which-shell (if (string-equal py-which-bufname
+							  "Jython")
+					    " -" ""))))
 	;; otherwise either run it synchronously in a subprocess
 	(save-excursion
 	  (set-buffer buf)
@@ -1722,12 +1801,14 @@ sent.  A trailing newline will be suppli
 See the `\\[py-execute-region]' docs for an account of some
 subtleties, including the use of the optional ASYNC argument."
   (interactive "P")
-  (if py-master-file
-      (let* ((filename (expand-file-name py-master-file))
-	     (buffer (or (get-file-buffer filename)
-			 (find-file-noselect filename))))
-	(set-buffer buffer)))
-  (py-execute-region (point-min) (point-max) async))
+  (let ((old-buffer (current-buffer)))
+    (if py-master-file
+        (let* ((filename (expand-file-name py-master-file))
+               (buffer (or (get-file-buffer filename)
+                           (find-file-noselect filename))))
+          (set-buffer buffer)))
+    (py-execute-region (point-min) (point-max) async)
+       (pop-to-buffer old-buffer)))
 
 (defun py-execute-import-or-reload (&optional async)
   "Import the current buffer's file in a Python interpreter.
@@ -1823,6 +1904,9 @@ subtleties, including the use of the opt
 		      (t (find-file (read-file-name "Exception file: "
 						    nil
 						    file t))))))
+    ;; Fiddle about with line number
+    (setq line (+ py-line-number-offset line))
+
     (pop-to-buffer buffer)
     ;; Force Python mode
     (if (not (eq major-mode 'python-mode))
@@ -2003,16 +2087,29 @@ This function is normally bound to `inde
   (interactive "P")
   (let* ((ci (current-indentation))
 	 (move-to-indentation-p (<= (current-column) ci))
-	 (need (py-compute-indentation (not arg))))
-    ;; see if we need to dedent
-    (if (py-outdent-p)
-	(setq need (- need py-indent-offset)))
-    (if (/= ci need)
-	(save-excursion
-	  (beginning-of-line)
-	  (delete-horizontal-space)
-	  (indent-to need)))
-    (if move-to-indentation-p (back-to-indentation))))
+	 (need (py-compute-indentation (not arg)))
+         (cc (current-column)))
+    ;; dedent out a level if previous command was the same unless we're in
+    ;; column 1
+    (if (and (equal last-command this-command)
+             (/= cc 0))
+        (progn
+          (beginning-of-line)
+          (delete-horizontal-space)
+          (indent-to (* (/ (- cc 1) py-indent-offset) py-indent-offset)))
+      (progn
+	;; see if we need to dedent
+	(if (py-outdent-p)
+	    (setq need (- need py-indent-offset)))
+	(if (or py-tab-always-indent
+		move-to-indentation-p)
+	    (progn (if (/= ci need)
+		       (save-excursion
+		       (beginning-of-line)
+		       (delete-horizontal-space)
+		       (indent-to need)))
+		   (if move-to-indentation-p (back-to-indentation)))
+	    (insert-tab))))))
 
 (defun py-newline-and-indent ()
   "Strives to act like the Emacs `newline-and-indent'.
@@ -2056,39 +2153,23 @@ dedenting."
        ((py-continuation-line-p)
 	(let ((startpos (point))
 	      (open-bracket-pos (py-nesting-level))
-	      endpos searching found state)
+	      endpos searching found state cind cline)
 	  (if open-bracket-pos
 	      (progn
-		;; align with first item in list; else a normal
-		;; indent beyond the line with the open bracket
-		(goto-char (1+ open-bracket-pos)) ; just beyond bracket
-		;; is the first list item on the same line?
-		(skip-chars-forward " \t")
-		(if (null (memq (following-char) '(?\n ?# ?\\)))
-					; yes, so line up with it
-		    (current-column)
-		  ;; first list item on another line, or doesn't exist yet
-		  (forward-line 1)
-		  (while (and (< (point) startpos)
-			      (looking-at "[ \t]*[#\n\\\\]")) ; skip noise
-		    (forward-line 1))
-		  (if (and (< (point) startpos)
-			   (/= startpos
-			       (save-excursion
-				 (goto-char (1+ open-bracket-pos))
-				 (forward-comment (point-max))
-				 (point))))
-		      ;; again mimic the first list item
-		      (current-indentation)
-		    ;; else they're about to enter the first item
-		    (goto-char open-bracket-pos)
-		    (setq placeholder (point))
-		    (py-goto-initial-line)
-		    (py-goto-beginning-of-tqs
-		     (save-excursion (nth 3 (parse-partial-sexp
-					     placeholder (point)))))
-		    (+ (current-indentation) py-indent-offset))))
-
+		(setq endpos (py-point 'bol))
+		(py-goto-initial-line)
+		(setq cind (current-indentation))
+		(setq cline cind)
+		(dolist (bp 
+			 (nth 9 (save-excursion
+				  (parse-partial-sexp (point) endpos)))
+			 cind)
+		  (if (search-forward "\n" bp t) (setq cline cind))
+		  (goto-char (1+ bp))
+		  (skip-chars-forward " \t")
+		  (setq cind (if (memq (following-char) '(?\n ?# ?\\))
+				 (+ cline py-indent-offset)
+			       (current-column)))))
 	    ;; else on backslash continuation line
 	    (forward-line -1)
 	    (if (py-continuation-line-p) ; on at least 3rd line in block
@@ -2836,7 +2917,7 @@ pleasant."
 ;; ripped from cc-mode
 (defun py-forward-into-nomenclature (&optional arg)
   "Move forward to end of a nomenclature section or word.
-With \\[universal-argument] (programmatically, optional argument ARG), 
+With \\[universal-argument] (programmatically, optional argument ARG),
 do it that many times.
 
 A `nomenclature' is a fancy way of saying AWordWithMixedCaseNotUnderscores."
@@ -2890,6 +2971,11 @@ A `nomenclature' is a fancy way of sayin
 
 
 ;; Pychecker
+
+;; hack for FSF Emacs
+(unless (fboundp 'read-shell-command)
+  (defalias 'read-shell-command 'read-string))
+
 (defun py-pychecker-run (command)
   "*Run pychecker (default on the file currently visited)."
   (interactive
@@ -3414,7 +3500,7 @@ multi-line statement we need to skip ove
 
 (defun py-statement-opens-block-p ()
   "Return t iff the current statement opens a block.
-I.e., iff it ends with a colon that is not in a comment.  Point should 
+I.e., iff it ends with a colon that is not in a comment.  Point should
 be at the start of a statement."
   (save-excursion
     (let ((start (point))
@@ -3498,8 +3584,8 @@ does not include blank lines, comments, 
 KEY is a regular expression describing a Python keyword.  Skip blank
 lines and non-indenting comments.  If the statement found starts with
 KEY, then stop, otherwise go back to first enclosing block starting
-with KEY.  If successful, leave point at the start of the KEY line and 
-return t.  Otherwise, leav point at an undefined place and return nil."
+with KEY.  If successful, leave point at the start of the KEY line and
+return t.  Otherwise, leave point at an undefined place and return nil."
   ;; skip blanks and non-indenting #
   (py-goto-initial-line)
   (while (and
@@ -3507,7 +3593,7 @@ return t.  Otherwise, leav point at an u
 	  (zerop (forward-line -1)))	; go back
     nil)
   (py-goto-initial-line)
-  (let* ((re (concat "[ \t]*" key "\\b"))
+  (let* ((re (concat "[ \t]*" key "\\>"))
 	 (case-fold-search nil)		; let* so looking-at sees this
 	 (found (looking-at re))
 	 (dead nil))
@@ -3533,7 +3619,7 @@ Prefix with \"...\" if leading whitespac
 `Keyword' is defined (essentially) as the regular expression
 ([a-z]+).  Returns nil if none was found."
   (let ((case-fold-search nil))
-    (if (looking-at "[ \t]*\\([a-z]+\\)\\b")
+    (if (looking-at "[ \t]*\\([a-z]+\\)\\>")
 	(intern (buffer-substring (match-beginning 1) (match-end 1)))
       nil)))
 
@@ -3625,7 +3711,7 @@ non-nil) just submit an enhancement requ
      "Dear Barry,")			;salutation
     (if enhancement-p nil
       (set-mark (point))
-      (insert 
+      (insert
 "Please replace this text with a sufficiently large code sample\n\
 and an exact recipe so that I can reproduce your problem.  Failure\n\
 to do so may mean a greater delay in fixing your bug.\n\n")
@@ -3645,7 +3731,7 @@ These are Python temporary files awaitin
 (add-hook 'comint-output-filter-functions 'py-pdbtrack-track-stack-file)
 
 ;; Add a designator to the minor mode strings
-(or (assq 'py-pdbtrack-minor-mode-string minor-mode-alist)
+(or (assq 'py-pdbtrack-is-tracking-p minor-mode-alist)
     (push '(py-pdbtrack-is-tracking-p py-pdbtrack-minor-mode-string)
 	  minor-mode-alist))
 
@@ -3784,32 +3870,35 @@ and initial `#'s.
 If point is inside a string, narrow to that string and fill.
 "
   (interactive "P")
-  (let* ((bod (py-point 'bod))
-	 (pps (parse-partial-sexp bod (point))))
-    (cond
-     ;; are we inside a comment or on a line with only whitespace before
-     ;; the comment start?
-     ((or (nth 4 pps)
-	  (save-excursion (beginning-of-line) (looking-at "[ \t]*#")))
-      (py-fill-comment justify))
-     ;; are we inside a string?
-     ((nth 3 pps)
-      (py-fill-string (nth 8 pps)))
-     ;; are we at the opening quote of a string, or in the indentation?
-     ((save-excursion
-	(forward-word 1)
-	(eq (py-in-literal) 'string))
-      (save-excursion
-	(py-fill-string (py-point 'boi))))
-     ;; are we at or after the closing quote of a string?
-     ((save-excursion
-	(backward-word 1)
-	(eq (py-in-literal) 'string))
-      (save-excursion
-	(py-fill-string (py-point 'boi))))
-     ;; otherwise use the default
-     (t
-      (fill-paragraph justify)))))
+  ;; fill-paragraph will narrow incorrectly
+  (save-restriction
+    (widen)
+    (let* ((bod (py-point 'bod))
+	   (pps (parse-partial-sexp bod (point))))
+      (cond
+       ;; are we inside a comment or on a line with only whitespace before
+       ;; the comment start?
+       ((or (nth 4 pps)
+	    (save-excursion (beginning-of-line) (looking-at "[ \t]*#")))
+	(py-fill-comment justify))
+       ;; are we inside a string?
+       ((nth 3 pps)
+	(py-fill-string (nth 8 pps)))
+       ;; are we at the opening quote of a string, or in the indentation?
+       ((save-excursion
+	  (forward-word 1)
+	  (eq (py-in-literal) 'string))
+	(save-excursion
+	  (py-fill-string (py-point 'boi))))
+       ;; are we at or after the closing quote of a string?
+       ((save-excursion
+	  (backward-word 1)
+	  (eq (py-in-literal) 'string))
+	(save-excursion
+	  (py-fill-string (py-point 'boi))))
+       ;; otherwise use the default
+       (t
+	(fill-paragraph justify))))))
 
 
 



1.2       +894 -241  XEmacs/packages/xemacs-packages/python-modes/python-mode.el.upstream

Index: python-mode.el.upstream
===================================================================
RCS file: /pack/xemacscvs/XEmacs/packages/xemacs-packages/python-modes/python-mode.el.upstream,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -p -r1.1 -r1.2
--- python-mode.el.upstream	2002/09/18 06:04:28	1.1
+++ python-mode.el.upstream	2008/01/19 14:49:15	1.2
@@ -2,13 +2,14 @@
 
 ;; Copyright (C) 1992,1993,1994  Tim Peters
 
-;; Author: 1995-2001 Barry A. Warsaw
+;; Author: 2003-2007 http://sf.net/projects/python-mode
+;;         1995-2002 Barry A. Warsaw
 ;;         1992-1994 Tim Peters
 ;; Maintainer: python-mode at python.org
 ;; Created:    Feb 1992
 ;; Keywords:   python languages oop
 
-(defconst py-version "4.6"
+(defconst py-version "$Revision: 1.2 $"
   "`python-mode' version number.")
 
 ;; This software is provided as-is, without express or implied
@@ -19,33 +20,46 @@
 
 ;;; 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
-;; subsequently left the net; in 1995, Barry Warsaw inherited the mode
-;; and is the current maintainer.  Tim's now back but disavows all
-;; responsibility for the mode.  Smart Tim :-)
-
-;; pdbtrack support contributed by Ken Manheimer, April 2001.
-
-;; This version of python-mode.el has only been tested with XEmacs
-;; 21.1.14 and Emacs 20.7 as these are the latest versions of these
-;; Emacsen as of this writing (11-Apr-2001).  I have no intent to test
-;; it with earlier Emacsen, but I will accept patches if they are
-;; small and reasonable.  Please use the SourceForge Python project to
-;; submit bugs or patches:
+;; This is a major mode for editing Python programs.  It was developed by Tim
+;; Peters after an original idea by Michael A. Guravage.  Tim subsequently
+;; left the net and in 1995, Barry Warsaw inherited the mode.  Tim's now back
+;; but disavows all responsibility for the mode.  In fact, we suspect he
+;; doesn't even use Emacs any more.  In 2003, python-mode.el was moved to its
+;; own SourceForge project apart from the Python project, and now is
+;; maintained by the volunteers at the python-mode at python.org mailing list.
+
+;; pdbtrack support contributed by Ken Manheimer, April 2001.  Skip Montanaro
+;; has also contributed significantly to python-mode's development.
+
+;; Please use the SourceForge Python project to submit bugs or
+;; patches:
 ;;
 ;;     http://sourceforge.net/projects/python
 
+;; INSTALLATION:
+
+;; To install, just drop this file into a directory on your load-path and
+;; byte-compile it.  To set up Emacs to automatically edit files ending in
+;; ".py" using python-mode add the following to your ~/.emacs file (GNU
+;; Emacs) or ~/.xemacs/init.el file (XEmacs):
+;;    (setq auto-mode-alist (cons '("\\.py$" . python-mode) auto-mode-alist))
+;;    (setq interpreter-mode-alist (cons '("python" . python-mode)
+;;                                       interpreter-mode-alist))
+;;    (autoload 'python-mode "python-mode" "Python editing mode." t)
+;;
+;; In XEmacs syntax highlighting should be enabled automatically.  In GNU
+;; Emacs you may have to add these lines to your ~/.emacs file:
+;;    (global-font-lock-mode t)
+;;    (setq font-lock-maximum-decoration t)
+
 ;; FOR MORE INFORMATION:
 
 ;; There is some information on python-mode.el at
 
 ;;     http://www.python.org/emacs/python-mode/
 ;;
-;; but this link is fairly out of date, due to the current difficulty
-;; in updating that site. It does contain links to other packages that
-;; you might find useful, such as pdb interfaces, OO-Browser links,
-;; etc.  Eventually, we'll be able to update it much more easily.
+;; It does contain links to other packages that you might find useful,
+;; such as pdb interfaces, OO-Browser links, etc.
 
 ;; BUG REPORTING:
 
@@ -65,6 +79,8 @@
 (require 'comint)
 (require 'custom)
 (require 'cl)
+(require 'compile)
+(require 'ansi-color)
 
 
 ;; user definable variables
@@ -75,34 +91,41 @@
   :group 'languages
   :prefix "py-")
 
+(defcustom py-tab-always-indent t
+  "*Non-nil means TAB in Python mode should always reindent the current line,
+regardless of where in the line point is when the TAB command is used."
+:type 'boolean
+:group 'python)
+
 (defcustom py-python-command "python"
   "*Shell command used to start Python interpreter."
   :type 'string
   :group 'python)
 
-(defcustom py-jpython-command "jpython"
-  "*Shell command used to start the JPython interpreter."
+(make-obsolete-variable 'py-jpython-command 'py-jython-command)
+(defcustom py-jython-command "jython"
+  "*Shell command used to start the Jython interpreter."
   :type 'string
   :group 'python
-:tag "JPython Command")
+:tag "Jython Command")
 
 (defcustom py-default-interpreter 'cpython
   "*Which Python interpreter is used by default.
-The value for this variable can be either `cpython' or `jpython'.
+The value for this variable can be either `cpython' or `jython'.
 
 When the value is `cpython', the variables `py-python-command' and
 `py-python-command-args' are consulted to determine the interpreter
 and arguments to use.
 
-When the value is `jpython', the variables `py-jpython-command' and
-`py-jpython-command-args' are consulted to determine the interpreter
+When the value is `jython', the variables `py-jython-command' and
+`py-jython-command-args' are consulted to determine the interpreter
 and arguments to use.
 
 Note that this variable is consulted only the first time that a Python
 mode buffer is visited during an Emacs session.  After that, use
 \\[py-toggle-shells] to change the interpreter shell."
   :type '(choice (const :tag "Python (a.k.a. CPython)" cpython)
-		 (const :tag "JPython" jpython))
+		 (const :tag "Jython" jython))
   :group 'python)
 
 (defcustom py-python-command-args '("-i")
@@ -110,11 +133,12 @@ mode buffer is visited during an Emacs s
   :type '(repeat string)
   :group 'python)
 
-(defcustom py-jpython-command-args '("-i")
-  "*List of string arguments to be used when starting a JPython shell."
+(make-obsolete-variable 'py-jpython-command-args 'py-jython-command-args)
+(defcustom py-jython-command-args '("-i")
+  "*List of string arguments to be used when starting a Jython shell."
   :type '(repeat string)
   :group 'python
-:tag "JPython Command Args")
+:tag "Jython Command Args")
 
 (defcustom py-indent-offset 4
   "*Amount of offset per level of indentation.
@@ -184,8 +208,8 @@ indentation is used as a hint for this l
 begin with `py-block-comment-prefix' are ignored for indentation
 purposes.
 
-When not nil or t, comment lines that begin with a `#' are used as
-indentation hints, unless the comment character is in column zero."
+When not nil or t, comment lines that begin with a single `#' are used
+as indentation hints, unless the comment character is in column zero."
   :type '(choice
 	  (const :tag "Skip all comment lines (fast)" nil)
 	  (const :tag "Single # `sets' indentation for next line" t)
@@ -204,13 +228,14 @@ indentation hints, unless the comment ch
     (or (funcall ok (getenv "TMPDIR"))
 	(funcall ok "/usr/tmp")
 	(funcall ok "/tmp")
+	(funcall ok "/var/tmp")
 	(funcall ok  ".")
 	(error
 	 "Couldn't find a usable temp directory -- set `py-temp-directory'")))
-  "*Directory used for temp files created by a *Python* process.
+  "*Directory used for temporary files created by a *Python* process.
 By default, the first directory from this list that exists and that you
-can write into:  the value (if any) of the environment variable TMPDIR,
-/usr/tmp, /tmp, or the current directory."
+can write into: the value (if any) of the environment variable TMPDIR,
+/usr/tmp, /tmp, /var/tmp, or the current directory."
   :type 'string
   :group 'python)
 
@@ -252,7 +277,7 @@ Otherwise, all modified buffers are save
   :type 'function
   :group 'python)
 
-(defcustom py-imenu-show-method-args-p nil 
+(defcustom py-imenu-show-method-args-p nil
   "*Controls echoing of arguments of functions & methods in the Imenu buffer.
 When non-nil, arguments are printed."
   :type 'boolean
@@ -275,6 +300,24 @@ as gud-mode does for debugging C program
   :type 'string
   :group 'python)
 
+(defcustom py-import-check-point-max
+  20000
+  "Maximum number of characters to search for a Java-ish import statement.
+When `python-mode' tries to calculate the shell to use (either a
+CPython or a Jython shell), it looks at the so-called `shebang' line
+-- i.e. #! line.  If that's not available, it looks at some of the
+file heading imports to see if they look Java-like."
+:type 'integer
+:group 'python
+  )
+
+(make-obsolete-variable 'py-jpython-packages 'py-jython-packages)
+(defcustom py-jython-packages
+  '("java" "javax" "org" "com")
+  "Imported packages that imply `jython-mode'."
+:type '(repeat string)
+:group 'python)
+
 ;; Not customizable
 (defvar py-master-file nil
   "If non-nil, execute the named file instead of the buffer's file.
@@ -291,11 +334,52 @@ relative path, the value of variable `de
 buffer is prepended to come up with a file name.")
 (make-variable-buffer-local 'py-master-file)
 
+(defcustom py-pychecker-command "pychecker"
+  "*Shell command used to run Pychecker."
+:type 'string
+:group 'python
+:tag "Pychecker Command")
+
+(defcustom py-pychecker-command-args '("--stdlib")
+  "*List of string arguments to be passed to pychecker."
+:type '(repeat string)
+:group 'python
+:tag "Pychecker Command Args")
+
+(defvar py-shell-alist
+  '(("jython" . 'jython)
+    ("python" . 'cpython))
+  "*Alist of interpreters and python shells. Used by `py-choose-shell'
+to select the appropriate python interpreter mode for a file.")
+
+(defcustom py-shell-input-prompt-1-regexp "^>>> "
+  "*A regular expression to match the input prompt of the shell."
+:type 'string
+:group 'python)
+
+(defcustom py-shell-input-prompt-2-regexp "^[.][.][.] "
+  "*A regular expression to match the input prompt of the shell after the
+  first line of input."
+:type 'string
+:group 'python)
+
+(defcustom py-shell-switch-buffers-on-execute t
+  "*Controls switching to the Python buffer where commands are
+  executed.  When non-nil the buffer switches to the Python buffer, if
+  not no switching occurs."
+:type 'boolean
+:group 'python)
 
 
 ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
 
+(defvar py-line-number-offset 0
+  "When an exception occurs as a result of py-execute-region, a
+subsequent py-up-exception needs the line number where the region
+started, in order to jump to the correct file line.  This variable is
+set in py-execute-region and used in py-jump-to-exception.")
+
 (defconst py-emacs-features
   (let (features)
    features)
@@ -303,6 +387,38 @@ buffer is prepended to come up with a fi
 There are many flavors of Emacs out there, with different levels of
 support for features needed by `python-mode'.")
 
+;; Face for None, True, False, self, and Ellipsis
+(defvar py-pseudo-keyword-face 'py-pseudo-keyword-face
+  "Face for pseudo keywords in Python mode, like self, True, False, Ellipsis.")
+(make-face 'py-pseudo-keyword-face)
+
+;; PEP 318 decorators
+(defvar py-decorators-face 'py-decorators-face
+  "Face method decorators.")
+(make-face 'py-decorators-face)
+
+;; Face for builtins
+(defvar py-builtins-face 'py-builtins-face
+  "Face for builtins like TypeError, object, open, and exec.")
+(make-face 'py-builtins-face)
+
+;; XXX, TODO, and FIXME comments and such
+(defvar py-XXX-tag-face 'py-XXX-tag-face
+  "Face for XXX, TODO, and FIXME tags")
+(make-face 'py-XXX-tag-face)
+
+(defun py-font-lock-mode-hook ()
+  (or (face-differs-from-default-p 'py-pseudo-keyword-face)
+      (copy-face 'font-lock-keyword-face 'py-pseudo-keyword-face))
+  (or (face-differs-from-default-p 'py-builtins-face)
+      (copy-face 'font-lock-keyword-face 'py-builtins-face))
+  (or (face-differs-from-default-p 'py-decorators-face)
+      (copy-face 'py-pseudo-keyword-face 'py-decorators-face))
+  (or (face-differs-from-default-p 'py-XXX-tag-face)
+      (copy-face 'font-lock-comment-face 'py-XXX-tag-face))
+  )
+(add-hook 'font-lock-mode-hook 'py-font-lock-mode-hook)
+
 (defvar python-font-lock-keywords
   (let ((kw1 (mapconcat 'identity
 			'("and"      "assert"   "break"   "class"
@@ -311,27 +427,78 @@ support for features needed by `python-m
 			  "from"     "global"   "if"      "import"
 			  "in"       "is"       "lambda"  "not"
 			  "or"       "pass"     "print"   "raise"
-			  "return"   "while"    "yield"
+			  "return"   "while"    "with"    "yield"
 			  )
 			"\\|"))
 	(kw2 (mapconcat 'identity
 			'("else:" "except:" "finally:" "try:")
 			"\\|"))
+	(kw3 (mapconcat 'identity
+			;; Don't include True, False, None, or
+			;; Ellipsis in this list, since they are
+			;; already defined as pseudo keywords.
+			'("__debug__"
+			  "__import__" "__name__" "abs" "apply" "basestring"
+			  "bool" "buffer" "callable" "chr" "classmethod"
+			  "cmp" "coerce" "compile" "complex" "copyright"
+			  "delattr" "dict" "dir" "divmod"
+			  "enumerate" "eval" "execfile" "exit" "file"
+			  "filter" "float" "getattr" "globals" "hasattr"
+			  "hash" "hex" "id" "input" "int" "intern"
+			  "isinstance" "issubclass" "iter" "len" "license"
+			  "list" "locals" "long" "map" "max" "min" "object"
+			  "oct" "open" "ord" "pow" "property" "range"
+			  "raw_input" "reduce" "reload" "repr" "round"
+			  "setattr" "slice" "staticmethod" "str" "sum"
+			  "super" "tuple" "type" "unichr" "unicode" "vars"
+			  "xrange" "zip")
+			"\\|"))
+	(kw4 (mapconcat 'identity
+			;; Exceptions and warnings
+			'("ArithmeticError" "AssertionError"
+			  "AttributeError" "DeprecationWarning" "EOFError"
+			  "EnvironmentError" "Exception"
+			  "FloatingPointError" "FutureWarning" "IOError"
+			  "ImportError" "IndentationError" "IndexError"
+			  "KeyError" "KeyboardInterrupt" "LookupError"
+			  "MemoryError" "NameError" "NotImplemented"
+			  "NotImplementedError" "OSError" "OverflowError"
+			  "OverflowWarning" "PendingDeprecationWarning"
+			  "ReferenceError" "RuntimeError" "RuntimeWarning"
+			  "StandardError" "StopIteration" "SyntaxError"
+			  "SyntaxWarning" "SystemError" "SystemExit"
+			  "TabError" "TypeError" "UnboundLocalError"
+			  "UnicodeDecodeError" "UnicodeEncodeError"
+			  "UnicodeError" "UnicodeTranslateError"
+			  "UserWarning" "ValueError" "Warning"
+			  "ZeroDivisionError")
+			"\\|"))
 	)
     (list
+     '("^[ \t]*\\(@.+\\)" 1 'py-decorators-face)
      ;; keywords
-     (cons (concat "\\b\\(" kw1 "\\)\\b[ \n\t(]") 1)
+     (cons (concat "\\<\\(" kw1 "\\)\\>[ \n\t(]") 1)
+     ;; builtins when they don't appear as object attributes
+     (list (concat "\\([^. \t]\\|^\\)[ \t]*\\<\\(" kw3 "\\)\\>[ \n\t(]") 2
+	   'py-builtins-face)
      ;; block introducing keywords with immediately following colons.
      ;; Yes "except" is in both lists.
-     (cons (concat "\\b\\(" kw2 "\\)[ \n\t(]") 1)
-     ;; `as' but only in "import foo as bar"
-     '("[ \t]*\\(\\bfrom\\b.*\\)?\\bimport\\b.*\\b\\(as\\)\\b" . 2)
+     (cons (concat "\\<\\(" kw2 "\\)[ \n\t(]") 1)
+     ;; Exceptions
+     (list (concat "\\<\\(" kw4 "\\)[ \n\t:,(]") 1 'py-builtins-face)
+     ;; `as' but only in "import foo as bar" or "with foo as bar"
+     '("[ \t]*\\(\\<from\\>.*\\)?\\<import\\>.*\\<\\(as\\)\\>" . 2)
+     '("[ \t]*\\<with\\>.*\\<\\(as\\)\\>" . 1)
      ;; classes
-     '("\\bclass[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)"
-       1 font-lock-type-face)
+     '("\\<class[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)" 1 font-lock-type-face)
      ;; functions
-     '("\\bdef[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)"
+     '("\\<def[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)"
        1 font-lock-function-name-face)
+     ;; pseudo-keywords
+     '("\\<\\(self\\|None\\|True\\|False\\|Ellipsis\\)\\>"
+       1 py-pseudo-keyword-face)
+     ;; XXX, TODO, and FIXME tags
+     '("XXX\\|TODO\\|FIXME" 0 py-XXX-tag-face t)
      ))
   "Additional expressions to highlight in Python mode.")
 (put 'python-mode 'font-lock-defaults '(python-font-lock-keywords))
@@ -343,7 +510,9 @@ Currently-active file is at the head of 
 
 (defvar py-pdbtrack-is-tracking-p nil)
 
+(defvar py-pychecker-history nil)
 
+
 
 ;; Constants
 
@@ -374,7 +543,7 @@ Currently-active file is at the head of 
    "\\(" "[^#'\"\n\\]" "\\|" py-stringlit-re "\\)*"
    "\\\\$")
   "Regular expression matching Python backslash continuation lines.")
-  
+
 (defconst py-blank-or-comment-re "[ \t]*\\($\\|#\\)"
   "Regular expression matching a blank or comment line.")
 
@@ -387,7 +556,7 @@ Currently-active file is at the head of 
 			   "\\|")
 	  "\\)")
   "Regular expression matching statements to be dedented one level.")
-  
+
 (defconst py-block-closing-keywords-re
   "\\(return\\|raise\\|break\\|continue\\|pass\\)"
   "Regular expression matching keywords which typically close a block.")
@@ -408,29 +577,17 @@ Currently-active file is at the head of 
 	  "\\)")
   "Regular expression matching lines not to dedent after.")
 
-(defconst py-defun-start-re
-  "^\\([ \t]*\\)def[ \t]+\\([a-zA-Z_0-9]+\\)\\|\\(^[a-zA-Z_0-9]+\\)[ \t]*="
-  ;; 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.
-  "Regular expression matching a function, method, or variable assignment.")
-
-(defconst py-class-start-re "^class[ \t]*\\([a-zA-Z_0-9]+\\)"
-  ;; 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.
-  "Regular expression for finding a class name.")
-
-(defconst py-traceback-line-re
+(defvar py-traceback-line-re
   "[ \t]+File \"\\([^\"]+\\)\", line \\([0-9]+\\)"
   "Regular expression that describes tracebacks.")
 
-;; pdbtrack contants
+;; pdbtrack constants
 (defconst py-pdbtrack-stack-entry-regexp
-  "> \\([^(]+\\)(\\([0-9]+\\))[?a-zA-Z0-9_]+()"
+;  "^> \\([^(]+\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
+  "^> \\(.*\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
   "Regular expression pdbtrack uses to find a stack trace entry.")
 
-(defconst py-pdbtrack-input-prompt "\n[(<]?pdb[>)]? "
+(defconst py-pdbtrack-input-prompt "\n[(<]*[Pp]db[>)]+ "
   "Regular expression pdbtrack uses to recognize a pdb prompt.")
 
 (defconst py-pdbtrack-track-range 10000
@@ -448,6 +605,14 @@ Currently-active file is at the head of 
 (defvar python-mode-hook nil
   "*Hook called by `python-mode'.")
 
+(make-obsolete-variable 'jpython-mode-hook 'jython-mode-hook)
+(defvar jython-mode-hook nil
+  "*Hook called by `jython-mode'. `jython-mode' also calls
+`python-mode-hook'.")
+
+(defvar py-shell-hook nil
+  "*Hook called by `py-shell'.")
+
 ;; In previous version of python-mode.el, the hook was incorrectly
 ;; called py-mode-hook, and was not defvar'd.  Deprecate its use.
 (and (fboundp 'make-obsolete-variable)
@@ -503,7 +668,7 @@ Currently-active file is at the head of 
   (define-key py-mode-map "\C-c\C-u"  'py-goto-block-up)
   (define-key py-mode-map "\C-c#"     'py-comment-region)
   (define-key py-mode-map "\C-c?"     'py-describe-mode)
-  (define-key py-mode-map "\C-c\C-hm" 'py-describe-mode)
+  (define-key py-mode-map "\C-c\C-h"  'py-help-at-point)
   (define-key py-mode-map "\e\C-a"    'py-beginning-of-def-or-class)
   (define-key py-mode-map "\e\C-e"    'py-end-of-def-or-class)
   (define-key py-mode-map "\C-c-"     'py-up-exception)
@@ -514,6 +679,7 @@ Currently-active file is at the head of 
   ;; information
   (define-key py-mode-map "\C-c\C-b" 'py-submit-bug-report)
   (define-key py-mode-map "\C-c\C-v" 'py-version)
+  (define-key py-mode-map "\C-c\C-w" 'py-pychecker-run)
   ;; shadow global bindings for newline-and-indent w/ the py- version.
   ;; BAW - this is extremely bad form, but I'm not going to change it
   ;; for now.
@@ -526,7 +692,7 @@ Currently-active file is at the head of 
   ;; expect RET to do a `py-newline-and-indent' and any Emacsers who
   ;; dislike this are probably knowledgeable enough to do a rebind.
   ;; However, we do *not* change C-j since many Emacsers have already
-  ;; swapped RET and C-j and they don't want C-j bound to `newline' to 
+  ;; swapped RET and C-j and they don't want C-j bound to `newline' to
   ;; change.
   (define-key py-mode-map "\C-m" 'py-newline-and-indent)
   )
@@ -558,8 +724,7 @@ Currently-active file is at the head of 
 
 (defvar py-mode-syntax-table nil
   "Syntax table used in `python-mode' buffers.")
-(if py-mode-syntax-table
-    nil
+(when (not py-mode-syntax-table)
   (setq py-mode-syntax-table (make-syntax-table))
   (modify-syntax-entry ?\( "()" py-mode-syntax-table)
   (modify-syntax-entry ?\) ")(" py-mode-syntax-table)
@@ -600,10 +765,19 @@ Currently-active file is at the head of 
   (modify-syntax-entry ?\n ">"  py-mode-syntax-table)
   )
 
+;; An auxiliary syntax table which places underscore and dot in the
+;; symbol class for simplicity
+(defvar py-dotted-expression-syntax-table nil
+  "Syntax table used to identify Python dotted expressions.")
+(when (not py-dotted-expression-syntax-table)
+  (setq py-dotted-expression-syntax-table
+	(copy-syntax-table py-mode-syntax-table))
+  (modify-syntax-entry ?_ "_" py-dotted-expression-syntax-table)
+  (modify-syntax-entry ?. "_" py-dotted-expression-syntax-table))
+
 
 
 ;; Utilities
-
 (defmacro py-safe (&rest body)
   "Safely execute BODY, return nil if an error occurred."
   (` (condition-case nil
@@ -636,8 +810,8 @@ This function does not modify point or m
     (cond
      ((eq position 'bol) (beginning-of-line))
      ((eq position 'eol) (end-of-line))
-     ((eq position 'bod) (py-beginning-of-def-or-class))
-     ((eq position 'eod) (py-end-of-def-or-class))
+     ((eq position 'bod) (py-beginning-of-def-or-class 'either))
+     ((eq position 'eod) (py-end-of-def-or-class 'either))
      ;; Kind of funny, I know, but useful for py-up-exception.
      ((eq position 'bob) (beginning-of-buffer))
      ((eq position 'eob) (end-of-buffer))
@@ -745,7 +919,7 @@ package.  Note that the latest X/Emacs r
 
 (defvar py-imenu-method-regexp
   (concat                               ; <<methods and functions>>
-   "\\("                                ; 
+   "\\("                                ;
    "^[ \t]*"                            ; new line and maybe whitespace
    "\\(def[ \t]+"                       ; function definitions start with def
    "\\([a-zA-Z0-9_]+\\)"                ;   name is here
@@ -781,7 +955,7 @@ information.")
 ;; it.
 (defvar py-imenu-generic-expression
   (cons
-   (concat 
+   (concat
     py-imenu-class-regexp
     "\\|"				; or...
     py-imenu-method-regexp
@@ -850,7 +1024,7 @@ of the first definition found."
 	looking-p
 	def-name prev-name
 	cur-indent def-pos
-	(class-paren (first  py-imenu-generic-parens)) 
+	(class-paren (first  py-imenu-generic-parens))
 	(def-paren   (second py-imenu-generic-parens)))
     (setq looking-p
 	  (re-search-forward py-imenu-generic-regexp (point-max) t))
@@ -884,6 +1058,8 @@ of the first definition found."
       ;; what level is the next definition on?  must be same, deeper
       ;; or shallower indentation
       (cond
+       ;; Skip code in comments and strings
+       ((py-in-literal))
        ;; at the same indent level, add it to the list...
        ((= start-indent cur-indent)
 	(push (cons def-name def-pos) index-alist))
@@ -903,7 +1079,7 @@ of the first definition found."
 			  (cons save-elmt sub-method-alist))
 		    index-alist))))
        ;; found less indented expression, we're done.
-       (t 
+       (t
 	(setq looking-p nil)
 	(re-search-backward py-imenu-generic-regexp (point-min) t)))
       ;; end-cond
@@ -914,6 +1090,64 @@ of the first definition found."
 				    (point-max) 'move))))
     (nreverse index-alist)))
 
+
+
+(defun py-choose-shell-by-shebang ()
+  "Choose CPython or Jython mode by looking at #! on the first line.
+Returns the appropriate mode function.
+Used by `py-choose-shell', and similar to but distinct from
+`set-auto-mode', though it uses `auto-mode-interpreter-regexp' (if available)."
+  ;; look for an interpreter specified in the first line
+  ;; similar to set-auto-mode (files.el)
+  (let* ((re (if (boundp 'auto-mode-interpreter-regexp)
+		 auto-mode-interpreter-regexp
+	       ;; stolen from Emacs 21.2
+	       "#![ \t]?\\([^ \t\n]*/bin/env[ \t]\\)?\\([^ \t\n]+\\)"))
+	 (interpreter (save-excursion
+			(goto-char (point-min))
+			(if (looking-at re)
+			    (match-string 2)
+			  "")))
+	 elt)
+    ;; Map interpreter name to a mode.
+    (setq elt (assoc (file-name-nondirectory interpreter)
+		     py-shell-alist))
+    (and elt (caddr elt))))
+
+
+
+(defun py-choose-shell-by-import ()
+  "Choose CPython or Jython mode based imports.
+If a file imports any packages in `py-jython-packages', within
+`py-import-check-point-max' characters from the start of the file,
+return `jython', otherwise return nil."
+  (let (mode)
+    (save-excursion
+      (goto-char (point-min))
+      (while (and (not mode)
+		  (search-forward-regexp
+		   "^\\(\\(from\\)\\|\\(import\\)\\) \\([^ \t\n.]+\\)"
+		   py-import-check-point-max t))
+	(setq mode (and (member (match-string 4) py-jython-packages)
+			'jython
+			))))
+    mode))
+
+
+(defun py-choose-shell ()
+  "Choose CPython or Jython mode. Returns the appropriate mode function.
+This does the following:
+ - look for an interpreter with `py-choose-shell-by-shebang'
+ - examine imports using `py-choose-shell-by-import'
+ - default to the variable `py-default-interpreter'"
+  (interactive)
+  (or (py-choose-shell-by-shebang)
+      (py-choose-shell-by-import)
+      py-default-interpreter
+;      'cpython ;; don't use to py-default-interpreter, because default
+;               ;; is only way to choose CPython
+      ))
+
 
 ;;;###autoload
 (defun python-mode ()
@@ -950,6 +1184,7 @@ py-beep-if-tab-change\t\tring the bell i
   (make-local-variable 'indent-region-function)
   (make-local-variable 'indent-line-function)
   (make-local-variable 'add-log-current-defun-function)
+  (make-local-variable 'fill-paragraph-function)
   ;;
   (set-syntax-table py-mode-syntax-table)
   (setq major-mode              'python-mode
@@ -968,6 +1203,8 @@ py-beep-if-tab-change\t\tring the bell i
 	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
+
+	fill-paragraph-function 'py-fill-paragraph
 	)
   (use-local-map py-mode-map)
   ;; add the menu
@@ -1004,9 +1241,41 @@ py-beep-if-tab-change\t\tring the bell i
       ))
   ;; Set the default shell if not already set
   (when (null py-which-shell)
-    (py-toggle-shells py-default-interpreter))
-  )
+    (py-toggle-shells (py-choose-shell))))
+
+
+(make-obsolete 'jpython-mode 'jython-mode)
+(defun jython-mode ()
+  "Major mode for editing Jython/Jython files.
+This is a simple wrapper around `python-mode'.
+It runs `jython-mode-hook' then calls `python-mode.'
+It is added to `interpreter-mode-alist' and `py-choose-shell'.
+"
+  (interactive)
+  (python-mode)
+  (py-toggle-shells 'jython)
+  (when jython-mode-hook
+      (run-hooks 'jython-mode-hook)))
 
+
+;; It's handy to add recognition of Python files to the
+;; interpreter-mode-alist and to auto-mode-alist.  With the former, we
+;; can specify different `derived-modes' based on the #! line, but
+;; with the latter, we can't.  So we just won't add them if they're
+;; already added.
+;;;###autoload
+(let ((modes '(("jython" . jython-mode)
+	       ("python" . python-mode))))
+  (while modes
+    (when (not (assoc (car modes) interpreter-mode-alist))
+      (push (car modes) interpreter-mode-alist))
+    (setq modes (cdr modes))))
+;;;###autoload
+(when (not (or (rassq 'python-mode auto-mode-alist)
+	       (rassq 'jython-mode auto-mode-alist)))
+  (push '("\\.py$" . python-mode) auto-mode-alist))
+
+
 
 ;; electric characters
 (defun py-outdent-p ()
@@ -1024,14 +1293,14 @@ py-beep-if-tab-change\t\tring the bell i
 		  (backward-to-indentation 1))
 		(not (looking-at py-no-outdent-re)))
 	 )))
-      
+
 (defun py-electric-colon (arg)
   "Insert a colon.
 In certain cases the line is dedented appropriately.  If a numeric
 argument ARG is provided, that many colons are inserted
 non-electrically.  Electric behavior is inhibited inside a string or
 comment."
-  (interactive "P")
+  (interactive "*P")
   (self-insert-command (prefix-numeric-value arg))
   ;; are we in a string or comment?
   (if (save-excursion
@@ -1075,7 +1344,8 @@ comint believe the user typed this strin
 	(procbuf (process-buffer proc))
 ;	(comint-scroll-to-bottom-on-output t)
 	(msg (format "## working on region in file %s...\n" filename))
-	(cmd (format "execfile(r'%s')\n" filename)))
+        ;; add some comment, so that we can filter it out of history
+	(cmd (format "execfile(r'%s') # PYTHON-MODE\n" filename)))
     (unwind-protect
 	(save-excursion
 	  (set-buffer procbuf)
@@ -1088,11 +1358,13 @@ comint believe the user typed this strin
 (defun py-comint-output-filter-function (string)
   "Watch output for Python prompt and exec next file waiting in queue.
 This function is appropriate for `comint-output-filter-functions'."
-  ;; TBD: this should probably use split-string
-  (when (and (or (string-equal string ">>> ")
-		 (and (>= (length string) 5)
-		      (string-equal (substring string -5) "\n>>> ")))
-	     py-file-queue)
+  ;;remove ansi terminal escape sequences from string, not sure why they are
+  ;;still around...
+  (setq string (ansi-color-filter-apply string))
+  (when (and (string-match py-shell-input-prompt-1-regexp string)
+                   py-file-queue)
+    (if py-shell-switch-buffers-on-execute
+      (pop-to-buffer (current-buffer)))
     (py-safe (delete-file (car py-file-queue)))
     (setq py-file-queue (cdr py-file-queue))
     (if py-file-queue
@@ -1120,50 +1392,126 @@ Activity is disabled if the buffer-local
 `py-pdbtrack-do-tracking-p' is nil.
 
 We depend on the pdb input prompt matching `py-pdbtrack-input-prompt'
-at the beginning of the line."
+at the beginning of the line.
+
+If the traceback target file path is invalid, we look for the most
+recently visited python-mode buffer which either has the name of the
+current function \(or class) or which defines the function \(or
+class).  This is to provide for remote scripts, eg, Zope's 'Script
+(Python)' - put a _copy_ of the script in a buffer named for the
+script, and set to python-mode, and pdbtrack will find it.)"
   ;; Instead of trying to piece things together from partial text
   ;; (which can be almost useless depending on Emacs version), we
   ;; monitor to the point where we have the next pdb prompt, and then
   ;; check all text from comint-last-input-end to process-mark.
   ;;
-  ;; KLM: It might be nice to provide an optional override, so this
-  ;; routine could be fed debugger output strings as the text
-  ;; argument, for deliberate application elsewhere.
-  ;;
-  ;; KLM: We're very conservative about clearing the overlay arrow, to
-  ;; minimize residue.  This means, for instance, that executing other
-  ;; pdb commands wipes out the highlight.
+  ;; Also, we're very conservative about clearing the overlay arrow,
+  ;; to minimize residue.  This means, for instance, that executing
+  ;; other pdb commands wipe out the highlight.  You can always do a
+  ;; 'where' (aka 'w') command to reveal the overlay arrow.
   (let* ((origbuf (current-buffer))
 	 (currproc (get-buffer-process origbuf)))
+
     (if (not (and currproc py-pdbtrack-do-tracking-p))
         (py-pdbtrack-overlay-arrow nil)
-      (let* (;(origdir default-directory)
-             (procmark (process-mark currproc))
+
+      (let* ((procmark (process-mark currproc))
              (block (buffer-substring (max comint-last-input-end
                                            (- procmark
                                               py-pdbtrack-track-range))
                                       procmark))
-             fname lineno)
+             target target_fname target_lineno target_buffer)
+
         (if (not (string-match (concat py-pdbtrack-input-prompt "$") block))
             (py-pdbtrack-overlay-arrow nil)
-          (if (not (string-match
-                    (concat ".*" py-pdbtrack-stack-entry-regexp ".*")
-                    block))
-              (py-pdbtrack-overlay-arrow nil)
-            (setq fname (match-string 1 block)
-                  lineno (match-string 2 block))
-            (if (file-exists-p fname)
-                (progn
-                  (find-file-other-window fname)
-                  (goto-line (string-to-int lineno))
-                  (message "pdbtrack: line %s, file %s" lineno fname)
-                  (py-pdbtrack-overlay-arrow t)
-                  (pop-to-buffer origbuf t) )
-              (if (= (elt fname 0) ?\<)
-                  (message "pdbtrack: (Non-file source: '%s')" fname)
-                (message "pdbtrack: File not found: %s" fname))
-              )))))))
 
+          (setq target (py-pdbtrack-get-source-buffer block))
+
+          (if (stringp target)
+              (message "pdbtrack: %s" target)
+
+            (setq target_lineno (car target))
+            (setq target_buffer (cadr target))
+            (setq target_fname (buffer-file-name target_buffer))
+            (switch-to-buffer-other-window target_buffer)
+            (goto-line target_lineno)
+            (message "pdbtrack: line %s, file %s" target_lineno target_fname)
+            (py-pdbtrack-overlay-arrow t)
+            (pop-to-buffer origbuf t)
+
+            )))))
+  )
+
+(defun py-pdbtrack-get-source-buffer (block)
+  "Return line number and buffer of code indicated by block's traceback text.
+
+We look first to visit the file indicated in the trace.
+
+Failing that, we look for the most recently visited python-mode buffer
+with the same name or having the named function.
+
+If we're unable find the source code we return a string describing the
+problem as best as we can determine."
+
+  (if (not (string-match py-pdbtrack-stack-entry-regexp block))
+
+      "Traceback cue not found"
+
+    (let* ((filename (match-string 1 block))
+           (lineno (string-to-int (match-string 2 block)))
+           (funcname (match-string 3 block))
+           funcbuffer)
+
+      (cond ((file-exists-p filename)
+             (list lineno (find-file-noselect filename)))
+
+            ((setq funcbuffer (py-pdbtrack-grub-for-buffer funcname lineno))
+             (if (string-match "/Script (Python)$" filename)
+                 ;; Add in number of lines for leading '##' comments:
+                 (setq lineno
+                       (+ lineno
+                          (save-excursion
+                            (set-buffer funcbuffer)
+                            (count-lines
+                             (point-min)
+                             (max (point-min)
+                                  (string-match "^\\([^#]\\|#[^#]\\|#$\\)"
+                                                (buffer-substring (point-min)
+                                                                  (point-max)))
+                                  ))))))
+             (list lineno funcbuffer))
+
+            ((= (elt filename 0) ?\<)
+             (format "(Non-file source: '%s')" filename))
+
+            (t (format "Not found: %s(), %s" funcname filename)))
+      )
+    )
+  )
+
+(defun py-pdbtrack-grub-for-buffer (funcname lineno)
+  "Find most recent buffer itself named or having function funcname.
+
+We walk the buffer-list history for python-mode buffers that are
+named for funcname or define a function funcname."
+  (let ((buffers (buffer-list))
+        buf
+        got)
+    (while (and buffers (not got))
+      (setq buf (car buffers)
+            buffers (cdr buffers))
+      (if (and (save-excursion (set-buffer buf)
+                               (string= major-mode "python-mode"))
+               (or (string-match funcname (buffer-name buf))
+                   (string-match (concat "^\\s-*\\(def\\|class\\)\\s-+"
+                                         funcname "\\s-*(")
+                                 (save-excursion
+                                   (set-buffer buf)
+                                   (buffer-substring (point-min)
+                                                     (point-max))))))
+          (setq got buf)))
+    got))
+
 (defun py-postprocess-output-buffer (buf)
   "Highlight exceptions found in BUF.
 If an exception occurred return t, otherwise return nil.  BUF must exist."
@@ -1192,7 +1540,7 @@ If an exception occurred return t, other
 (defconst py-output-buffer "*Python Output*")
 (make-variable-buffer-local 'py-output-buffer)
 
-;; for toggling between CPython and JPython
+;; for toggling between CPython and Jython
 (defvar py-which-shell nil)
 (defvar py-which-args  py-python-command-args)
 (defvar py-which-bufname "Python")
@@ -1201,14 +1549,14 @@ If an exception occurred return t, other
 (make-variable-buffer-local 'py-which-bufname)
 
 (defun py-toggle-shells (arg)
-  "Toggles between the CPython and JPython shells.
+  "Toggles between the CPython and Jython shells.
 
 With positive argument ARG (interactively \\[universal-argument]),
-uses the CPython shell, with negative ARG uses the JPython shell, and
+uses the CPython shell, with negative ARG uses the Jython shell, and
 with a zero argument, toggles the shell.
 
 Programmatically, ARG can also be one of the symbols `cpython' or
-`jpython', equivalent to positive arg and negative arg respectively."
+`jython', equivalent to positive arg and negative arg respectively."
   (interactive "P")
   ;; default is to toggle
   (if (null arg)
@@ -1221,7 +1569,7 @@ Programmatically, ARG can also be one of
 	(setq arg -1)
       (setq arg 1)))
    ((equal arg 'cpython) (setq arg 1))
-   ((equal arg 'jpython) (setq arg -1)))
+   ((equal arg 'jython) (setq arg -1)))
   (let (msg)
     (cond
      ((< 0 arg)
@@ -1229,14 +1577,16 @@ Programmatically, ARG can also be one of
       (setq py-which-shell py-python-command
 	    py-which-args py-python-command-args
 	    py-which-bufname "Python"
-	    msg "CPython"
-	    mode-name "Python"))
+	    msg "CPython")
+      (if (string-equal py-which-bufname "Jython")
+	  (setq mode-name "Python")))
      ((> 0 arg)
-      (setq py-which-shell py-jpython-command
-	    py-which-args py-jpython-command-args
-	    py-which-bufname "JPython"
-	    msg "JPython"
-	    mode-name "JPython"))
+      (setq py-which-shell py-jython-command
+	    py-which-args py-jython-command-args
+	    py-which-bufname "Jython"
+	    msg "Jython")
+      (if (string-equal py-which-bufname "Python")
+	  (setq mode-name "Jython")))
      )
     (message "Using the %s shell" msg)
     (setq py-output-buffer (format "*%s Output*" py-which-bufname))))
@@ -1258,9 +1608,9 @@ prompt).  This argument is ignored when 
 programmatically, or when running in Emacs 19.34 or older.
 
 Note: You can toggle between using the CPython interpreter and the
-JPython interpreter by hitting \\[py-toggle-shells].  This toggles
+Jython interpreter by hitting \\[py-toggle-shells].  This toggles
 buffer local variables which control whether all your subshell
-interactions happen to the `*JPython*' or `*Python*' buffers (the
+interactions happen to the `*Jython*' or `*Python*' buffers (the
 latter is the name used for the CPython buffer).
 
 Warning: Don't use an interactive Python if you change sys.ps1 or
@@ -1294,10 +1644,14 @@ filter."
 			       (concat
 				(mapconcat 'identity py-which-args " ") " ")
 			       ))))
-    (switch-to-buffer-other-window
-     (apply 'make-comint py-which-bufname py-which-shell nil args))
+    (if (not (equal (buffer-name) "*Python*"))
+        (switch-to-buffer-other-window
+         (apply 'make-comint py-which-bufname py-which-shell nil args))
+      (apply 'make-comint py-which-bufname py-which-shell nil args))
     (make-local-variable 'comint-prompt-regexp)
-    (setq comint-prompt-regexp "^>>> \\|^[.][.][.] \\|^(pdb) ")
+    (setq comint-prompt-regexp (concat py-shell-input-prompt-1-regexp "\\|"
+                                       py-shell-input-prompt-2-regexp "\\|"
+                                       "^([Pp]db) "))
     (add-hook 'comint-output-filter-functions
 	      'py-comint-output-filter-function)
     ;; pdbtrack
@@ -1305,6 +1659,7 @@ filter."
     (setq py-pdbtrack-do-tracking-p t)
     (set-syntax-table py-mode-syntax-table)
     (use-local-map py-shell-map)
+    (run-hooks 'py-shell-hook)
     ))
 
 (defun py-clear-queue ()
@@ -1342,8 +1697,7 @@ window) so you can see it, and a comment
 
 is inserted at the end.  See also the command `py-clear-queue'."
   (interactive "r\nP")
-  (or (< start end)
-      (error "Region is empty"))
+  ;; Skip ahead to the first non-blank line
   (let* ((proc (get-process py-which-bufname))
 	 (temp (if (memq 'broken-temp-names py-emacs-features)
 		   (let
@@ -1354,17 +1708,33 @@ is inserted at the end.  See also the co
 			 (format "python-%d-%d" sn pid)
 		       (format "python-%d" sn)))
 		 (make-temp-name "python-")))
-	 (file (expand-file-name temp py-temp-directory))
+	 (file (concat (expand-file-name temp py-temp-directory) ".py"))
 	 (cur (current-buffer))
-	 (buf (get-buffer-create file)))
+	 (buf (get-buffer-create file))
+	 shell)
     ;; Write the contents of the buffer, watching out for indented regions.
     (save-excursion
       (goto-char start)
+      (beginning-of-line)
+      (while (and (looking-at "\\s *$")
+		  (< (point) end))
+	(forward-line 1))
+      (setq start (point))
+      (or (< start end)
+	  (error "Region is empty"))
+      (setq py-line-number-offset (count-lines 1 start))
       (let ((needs-if (/= (py-point 'bol) (py-point 'boi))))
 	(set-buffer buf)
+	(python-mode)
 	(when needs-if
-	  (insert "if 1:\n"))
-	(insert-buffer-substring cur start end)))
+	  (insert "if 1:\n")
+	  (setq py-line-number-offset (- py-line-number-offset 1)))
+	(insert-buffer-substring cur start end)
+	;; Set the shell either to the #! line command, or to the
+	;; py-which-shell buffer local variable.
+	(setq shell (or (py-choose-shell-by-shebang)
+			(py-choose-shell-by-import)
+			py-which-shell))))
     (cond
      ;; always run the code in its own asynchronous subprocess
      (async
@@ -1376,7 +1746,7 @@ is inserted at the end.  See also the co
 	     ;; TBD: a horrible hack, but why create new Custom variables?
 	     (arg (if (string-equal py-which-bufname "Python")
 		      "-u" "")))
-	(start-process py-which-bufname buf py-which-shell arg file)
+	(start-process py-which-bufname buf shell arg file)
 	(pop-to-buffer buf)
 	(py-postprocess-output-buffer buf)
 	;; TBD: clean up the temporary file!
@@ -1394,10 +1764,10 @@ is inserted at the end.  See also the co
       (setq py-file-queue (append py-file-queue (list file)))
       (setq py-exception-buffer (cons file (current-buffer))))
      (t
-      ;; TBD: a horrible hack, buy why create new Custom variables?
-      (let ((cmd (concat py-which-shell
-			 (if (string-equal py-which-bufname "JPython")
-			     " -" ""))))
+      ;; TBD: a horrible hack, but why create new Custom variables?
+      (let ((cmd (concat py-which-shell (if (string-equal py-which-bufname
+							  "Jython")
+					    " -" ""))))
 	;; otherwise either run it synchronously in a subprocess
 	(save-excursion
 	  (set-buffer buf)
@@ -1413,9 +1783,7 @@ is inserted at the end.  See also the co
 	    (if err-p
 		(pop-to-buffer py-exception-buffer)))
 	  ))
-      ;; TBD: delete the buffer
-      )
-     )
+      ))
     ;; Clean up after ourselves.
     (kill-buffer buf)))
 
@@ -1433,12 +1801,14 @@ sent.  A trailing newline will be suppli
 See the `\\[py-execute-region]' docs for an account of some
 subtleties, including the use of the optional ASYNC argument."
   (interactive "P")
-  (if py-master-file
-      (let* ((filename (expand-file-name py-master-file))
-	     (buffer (or (get-file-buffer filename)
-			 (find-file-noselect filename))))
-	(set-buffer buffer)))
-  (py-execute-region (point-min) (point-max) async))
+  (let ((old-buffer (current-buffer)))
+    (if py-master-file
+        (let* ((filename (expand-file-name py-master-file))
+               (buffer (or (get-file-buffer filename)
+                           (find-file-noselect filename))))
+          (set-buffer buffer)))
+    (py-execute-region (point-min) (point-max) async)
+       (pop-to-buffer old-buffer)))
 
 (defun py-execute-import-or-reload (&optional async)
   "Import the current buffer's file in a Python interpreter.
@@ -1534,6 +1904,9 @@ subtleties, including the use of the opt
 		      (t (find-file (read-file-name "Exception file: "
 						    nil
 						    file t))))))
+    ;; Fiddle about with line number
+    (setq line (+ py-line-number-offset line))
+
     (pop-to-buffer buffer)
     ;; Force Python mode
     (if (not (eq major-mode 'python-mode))
@@ -1694,6 +2067,8 @@ number of characters to delete (default 
     (py-electric-backspace arg)))
 
 ;; required for pending-del and delsel modes
+(put 'py-electric-colon 'delete-selection t) ;delsel
+(put 'py-electric-colon 'pending-delete   t) ;pending-del
 (put 'py-electric-backspace 'delete-selection 'supersede) ;delsel
 (put 'py-electric-backspace 'pending-delete   'supersede) ;pending-del
 (put 'py-electric-delete    'delete-selection 'supersede) ;delsel
@@ -1712,16 +2087,29 @@ This function is normally bound to `inde
   (interactive "P")
   (let* ((ci (current-indentation))
 	 (move-to-indentation-p (<= (current-column) ci))
-	 (need (py-compute-indentation (not arg))))
-    ;; see if we need to dedent
-    (if (py-outdent-p)
-	(setq need (- need py-indent-offset)))
-    (if (/= ci need)
-	(save-excursion
-	  (beginning-of-line)
-	  (delete-horizontal-space)
-	  (indent-to need)))
-    (if move-to-indentation-p (back-to-indentation))))
+	 (need (py-compute-indentation (not arg)))
+         (cc (current-column)))
+    ;; dedent out a level if previous command was the same unless we're in
+    ;; column 1
+    (if (and (equal last-command this-command)
+             (/= cc 0))
+        (progn
+          (beginning-of-line)
+          (delete-horizontal-space)
+          (indent-to (* (/ (- cc 1) py-indent-offset) py-indent-offset)))
+      (progn
+	;; see if we need to dedent
+	(if (py-outdent-p)
+	    (setq need (- need py-indent-offset)))
+	(if (or py-tab-always-indent
+		move-to-indentation-p)
+	    (progn (if (/= ci need)
+		       (save-excursion
+		       (beginning-of-line)
+		       (delete-horizontal-space)
+		       (indent-to need)))
+		   (if move-to-indentation-p (back-to-indentation)))
+	    (insert-tab))))))
 
 (defun py-newline-and-indent ()
   "Strives to act like the Emacs `newline-and-indent'.
@@ -1765,39 +2153,23 @@ dedenting."
        ((py-continuation-line-p)
 	(let ((startpos (point))
 	      (open-bracket-pos (py-nesting-level))
-	      endpos searching found state)
+	      endpos searching found state cind cline)
 	  (if open-bracket-pos
 	      (progn
-		;; align with first item in list; else a normal
-		;; indent beyond the line with the open bracket
-		(goto-char (1+ open-bracket-pos)) ; just beyond bracket
-		;; is the first list item on the same line?
-		(skip-chars-forward " \t")
-		(if (null (memq (following-char) '(?\n ?# ?\\)))
-					; yes, so line up with it
-		    (current-column)
-		  ;; first list item on another line, or doesn't exist yet
-		  (forward-line 1)
-		  (while (and (< (point) startpos)
-			      (looking-at "[ \t]*[#\n\\\\]")) ; skip noise
-		    (forward-line 1))
-		  (if (and (< (point) startpos)
-			   (/= startpos
-			       (save-excursion
-				 (goto-char (1+ open-bracket-pos))
-				 (forward-comment (point-max))
-				 (point))))
-		      ;; again mimic the first list item
-		      (current-indentation)
-		    ;; else they're about to enter the first item
-		    (goto-char open-bracket-pos)
-		    (setq placeholder (point))
-		    (py-goto-initial-line)
-		    (py-goto-beginning-of-tqs
-		     (save-excursion (nth 3 (parse-partial-sexp
-					     placeholder (point)))))
-		    (+ (current-indentation) py-indent-offset))))
-
+		(setq endpos (py-point 'bol))
+		(py-goto-initial-line)
+		(setq cind (current-indentation))
+		(setq cline cind)
+		(dolist (bp 
+			 (nth 9 (save-excursion
+				  (parse-partial-sexp (point) endpos)))
+			 cind)
+		  (if (search-forward "\n" bp t) (setq cline cind))
+		  (goto-char (1+ bp))
+		  (skip-chars-forward " \t")
+		  (setq cind (if (memq (following-char) '(?\n ?# ?\\))
+				 (+ cline py-indent-offset)
+			       (current-column)))))
 	    ;; else on backslash continuation line
 	    (forward-line -1)
 	    (if (py-continuation-line-p) ; on at least 3rd line in block
@@ -1902,7 +2274,11 @@ dedenting."
 			     (and (not (eq py-honor-comment-indentation t))
 				  (save-excursion
 				    (back-to-indentation)
-				    (not (zerop (current-column)))))
+				    (and (not (looking-at prefix-re))
+					 (or (looking-at "[^#]")
+					     (not (zerop (current-column)))
+					     ))
+				    ))
 			     ))
 	      )))
 	;; if we landed inside a string, go to the beginning of that
@@ -2438,8 +2814,8 @@ moves to the end of the block (& does no
       (while (and
 	      (setq last-pos (point))	; always true -- side effect
 	      (py-goto-statement-below)
-	      (> (current-indentation) initial-indent))
-	nil))
+	      (> (current-indentation) initial-indent)
+	      )))
 
      ;; else plain code line; stop at next blank line, or stmt or
      ;; indenting comment line indented <
@@ -2541,7 +2917,7 @@ pleasant."
 ;; ripped from cc-mode
 (defun py-forward-into-nomenclature (&optional arg)
   "Move forward to end of a nomenclature section or word.
-With \\[universal-argument] (programmatically, optional argument ARG), 
+With \\[universal-argument] (programmatically, optional argument ARG),
 do it that many times.
 
 A `nomenclature' is a fancy way of saying AWordWithMixedCaseNotUnderscores."
@@ -2594,6 +2970,88 @@ A `nomenclature' is a fancy way of sayin
 
 
 
+;; Pychecker
+
+;; hack for FSF Emacs
+(unless (fboundp 'read-shell-command)
+  (defalias 'read-shell-command 'read-string))
+
+(defun py-pychecker-run (command)
+  "*Run pychecker (default on the file currently visited)."
+  (interactive
+   (let ((default
+           (format "%s %s %s" py-pychecker-command
+		   (mapconcat 'identity py-pychecker-command-args " ")
+		   (buffer-file-name)))
+	 (last (when py-pychecker-history
+		 (let* ((lastcmd (car py-pychecker-history))
+			(cmd (cdr (reverse (split-string lastcmd))))
+			(newcmd (reverse (cons (buffer-file-name) cmd))))
+		   (mapconcat 'identity newcmd " ")))))
+
+     (list
+      (if (fboundp 'read-shell-command)
+	  (read-shell-command "Run pychecker like this: "
+			      (if last
+				  last
+				default)
+			      'py-pychecker-history)
+	(read-string "Run pychecker like this: "
+		     (if last
+			 last
+		       default)
+		     'py-pychecker-history))
+	)))
+  (save-some-buffers (not py-ask-about-save) nil)
+  (compile-internal command "No more errors"))
+
+
+
+;; pydoc commands. The guts of this function is stolen from XEmacs's
+;; symbol-near-point, but without the useless regexp-quote call on the
+;; results, nor the interactive bit.  Also, we've added the temporary
+;; syntax table setting, which Skip originally had broken out into a
+;; separate function.  Note that Emacs doesn't have the original
+;; function.
+(defun py-symbol-near-point ()
+  "Return the first textual item to the nearest point."
+  ;; alg stolen from etag.el
+  (save-excursion
+    (with-syntax-table py-dotted-expression-syntax-table
+      (if (or (bobp) (not (memq (char-syntax (char-before)) '(?w ?_))))
+	  (while (not (looking-at "\\sw\\|\\s_\\|\\'"))
+	    (forward-char 1)))
+      (while (looking-at "\\sw\\|\\s_")
+	(forward-char 1))
+      (if (re-search-backward "\\sw\\|\\s_" nil t)
+	  (progn (forward-char 1)
+		 (buffer-substring (point)
+				   (progn (forward-sexp -1)
+					  (while (looking-at "\\s'")
+					    (forward-char 1))
+					  (point))))
+	nil))))
+
+(defun py-help-at-point ()
+  "Get help from Python based on the symbol nearest point."
+  (interactive)
+  (let* ((sym (py-symbol-near-point))
+	 (base (substring sym 0 (or (search "." sym :from-end t) 0)))
+	 cmd)
+    (if (not (equal base ""))
+        (setq cmd (concat "import " base "\n")))
+    (setq cmd (concat "import pydoc\n"
+                      cmd
+		      "try: pydoc.help('" sym "')\n"
+		      "except: print 'No help available on:', \"" sym "\""))
+    (message cmd)
+    (py-execute-string cmd)
+    (set-buffer "*Python Output*")
+    ;; BAW: Should we really be leaving the output buffer in help-mode?
+    (help-mode)))
+
+
+
 ;; Documentation functions
 
 ;; dump the long form of the mode blurb; does the usual doc escapes,
@@ -2892,11 +3350,24 @@ Obscure:  When python-mode is first load
 to newline-and-indent in the global keymap, and shadows them with
 local bindings to py-newline-and-indent."))
 
+(require 'info-look)
+;; The info-look package does not always provide this function (it
+;; appears this is the case with XEmacs 21.1)
+(when (fboundp 'info-lookup-maybe-add-help)
+  (info-lookup-maybe-add-help
+:mode 'python-mode
+:regexp "[a-zA-Z0-9_]+"
+:doc-spec '(("(python-lib)Module Index")
+	       ("(python-lib)Class-Exception-Object Index")
+	       ("(python-lib)Function-Method-Variable Index")
+	       ("(python-lib)Miscellaneous Index")))
+  )
+
 
 ;; Helper functions
 (defvar py-parse-state-re
   (concat
-   "^[ \t]*\\(if\\|elif\\|else\\|while\\|def\\|class\\)\\>"
+   "^[ \t]*\\(elif\\|else\\|while\\|def\\|class\\)\\>"
    "\\|"
    "^[^ #\t\n]"))
 
@@ -2904,7 +3375,7 @@ local bindings to py-newline-and-indent.
   "Return the parse state at point (see `parse-partial-sexp' docs)."
   (save-excursion
     (let ((here (point))
-	  in-listcomp pps done)
+	  pps done)
       (while (not done)
 	;; back up to the first preceding line (if any; else start of
 	;; buffer) that begins with a popular Python keyword, or a
@@ -2913,41 +3384,22 @@ local bindings to py-newline-and-indent.
 	;; at a non-zero nesting level.  It may be slow for people who
 	;; write huge code blocks or huge lists ... tough beans.
 	(re-search-backward py-parse-state-re nil 'move)
-	;; Watch out for landing inside a list comprehension
-	(save-excursion
-	  (if (and (looking-at "[ \t]*\\<\\(if\\|for\\)\\>")
-		   (py-safe (progn (up-list -1) t))
-		   (eq (char-after) ?\[))
-	      (setq in-listcomp (point))
-	    (setq in-listcomp nil)))
 	(beginning-of-line)
 	;; In XEmacs, we have a much better way to test for whether
 	;; we're in a triple-quoted string or not.  Emacs does not
 	;; have this built-in function, which is its loss because
 	;; without scanning from the beginning of the buffer, there's
 	;; no accurate way to determine this otherwise.
-	(if (not (fboundp 'buffer-syntactic-context))
-	    ;; Emacs
-	    (progn
-	      (save-excursion (setq pps (parse-partial-sexp (point) here)))
-	      ;; make sure we don't land inside a triple-quoted string
-	      (setq done (or (not (nth 3 pps))
-			     (bobp)))
-	      ;; Just go ahead and short circuit the test back to the
-	      ;; beginning of the buffer.  This will be slow, but not
-	      ;; nearly as slow as looping through many
-	      ;; re-search-backwards.
-	      (if (not done)
-		  (goto-char (point-min))))
-	  ;; XEmacs
-	  (setq done (or (not (buffer-syntactic-context))
-			 (bobp)))
-	  (when in-listcomp
-	    (goto-char in-listcomp)
-	    (setq done nil))
-	  (when done
-	    (setq pps (parse-partial-sexp (point) here)))
-	  ))
+	(save-excursion (setq pps (parse-partial-sexp (point) here)))
+	;; make sure we don't land inside a triple-quoted string
+	(setq done (or (not (nth 3 pps))
+		       (bobp)))
+	;; Just go ahead and short circuit the test back to the
+	;; beginning of the buffer.  This will be slow, but not
+	;; nearly as slow as looping through many
+	;; re-search-backwards.
+	(if (not done)
+	    (goto-char (point-min))))
       pps)))
 
 (defun py-nesting-level ()
@@ -3048,7 +3500,7 @@ multi-line statement we need to skip ove
 
 (defun py-statement-opens-block-p ()
   "Return t iff the current statement opens a block.
-I.e., iff it ends with a colon that is not in a comment.  Point should 
+I.e., iff it ends with a colon that is not in a comment.  Point should
 be at the start of a statement."
   (save-excursion
     (let ((start (point))
@@ -3118,7 +3570,8 @@ does not include blank lines, comments, 
   (let ((start (point)))
     (py-goto-beyond-final-line)
     (while (and
-	    (looking-at py-blank-or-comment-re)
+	    (or (looking-at py-blank-or-comment-re)
+		(py-in-literal))
 	    (not (eobp)))
       (forward-line 1))
     (if (eobp)
@@ -3131,8 +3584,8 @@ does not include blank lines, comments, 
 KEY is a regular expression describing a Python keyword.  Skip blank
 lines and non-indenting comments.  If the statement found starts with
 KEY, then stop, otherwise go back to first enclosing block starting
-with KEY.  If successful, leave point at the start of the KEY line and 
-return t.  Otherwise, leav point at an undefined place and return nil."
+with KEY.  If successful, leave point at the start of the KEY line and
+return t.  Otherwise, leave point at an undefined place and return nil."
   ;; skip blanks and non-indenting #
   (py-goto-initial-line)
   (while (and
@@ -3140,7 +3593,7 @@ return t.  Otherwise, leav point at an u
 	  (zerop (forward-line -1)))	; go back
     nil)
   (py-goto-initial-line)
-  (let* ((re (concat "[ \t]*" key "\\b"))
+  (let* ((re (concat "[ \t]*" key "\\>"))
 	 (case-fold-search nil)		; let* so looking-at sees this
 	 (found (looking-at re))
 	 (dead nil))
@@ -3166,7 +3619,7 @@ Prefix with \"...\" if leading whitespac
 `Keyword' is defined (essentially) as the regular expression
 ([a-z]+).  Returns nil if none was found."
   (let ((case-fold-search nil))
-    (if (looking-at "[ \t]*\\([a-z]+\\)\\b")
+    (if (looking-at "[ \t]*\\([a-z]+\\)\\>")
 	(intern (buffer-substring (match-beginning 1) (match-end 1)))
       nil)))
 
@@ -3174,15 +3627,50 @@ Prefix with \"...\" if leading whitespac
   "Python value for `add-log-current-defun-function'.
 This tells 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)))
 
+    ;; Move back to start of the current statement.
+
+    (py-goto-initial-line)
+    (back-to-indentation)
+    (while (and (or (looking-at py-blank-or-comment-re)
+		    (py-in-literal))
+		(not (bobp)))
+      (backward-to-indentation 1))
+    (py-goto-initial-line)
+
+    (let ((scopes "")
+	  (sep "")
+	  dead assignment)
+
+      ;; Check for an assignment.  If this assignment exists inside a
+      ;; def, it will be overwritten inside the while loop.  If it
+      ;; exists at top lever or inside a class, it will be preserved.
+
+      (when (looking-at "[ \t]*\\([a-zA-Z0-9_]+\\)[ \t]*=")
+	(setq scopes (buffer-substring (match-beginning 1) (match-end 1)))
+	(setq assignment t)
+	(setq sep "."))
+
+      ;; Prepend the name of each outer socpe (def or class).
+
+      (while (not dead)
+	(if (and (py-go-up-tree-to-keyword "\\(class\\|def\\)")
+		 (looking-at
+		  "[ \t]*\\(class\\|def\\)[ \t]*\\([a-zA-Z0-9_]+\\)[ \t]*"))
+	    (let ((name (buffer-substring (match-beginning 2) (match-end 2))))
+	      (if (and assignment (looking-at "[ \t]*def"))
+		  (setq scopes name)
+		(setq scopes (concat name sep scopes))
+		(setq sep "."))))
+	(setq assignment nil)
+	(condition-case nil		; Terminate nicely at top level.
+	    (py-goto-block-up 'no-mark)
+	  (error (setq dead t))))
+      (if (string= scopes "")
+	  nil
+	scopes))))
+
+
 
 (defconst py-help-address "python-mode at python.org"
   "Address accepting submission of bug reports.")
@@ -3223,7 +3711,7 @@ non-nil) just submit an enhancement requ
      "Dear Barry,")			;salutation
     (if enhancement-p nil
       (set-mark (point))
-      (insert 
+      (insert
 "Please replace this text with a sufficiently large code sample\n\
 and an exact recipe so that I can reproduce your problem.  Failure\n\
 to do so may mean a greater delay in fixing your bug.\n\n")
@@ -3243,9 +3731,174 @@ These are Python temporary files awaitin
 (add-hook 'comint-output-filter-functions 'py-pdbtrack-track-stack-file)
 
 ;; Add a designator to the minor mode strings
-(or (assq 'py-pdbtrack-minor-mode-string minor-mode-alist)
+(or (assq 'py-pdbtrack-is-tracking-p minor-mode-alist)
     (push '(py-pdbtrack-is-tracking-p py-pdbtrack-minor-mode-string)
 	  minor-mode-alist))
+
+
+
+;;; paragraph and string filling code from Bernhard Herzog
+;;; see http://mail.python.org/pipermail/python-list/2002-May/103189.html
+
+(defun py-fill-comment (&optional justify)
+  "Fill the comment paragraph around point"
+  (let (;; Non-nil if the current line contains a comment.
+	has-comment
+
+	;; If has-comment, the appropriate fill-prefix for the comment.
+	comment-fill-prefix)
+
+    ;; Figure out what kind of comment we are looking at.
+    (save-excursion
+      (beginning-of-line)
+      (cond
+       ;; A line with nothing but a comment on it?
+       ((looking-at "[ \t]*#[# \t]*")
+	(setq has-comment t
+	      comment-fill-prefix (buffer-substring (match-beginning 0)
+						    (match-end 0))))
+
+       ;; A line with some code, followed by a comment? Remember that the hash
+       ;; which starts the comment shouldn't be part of a string or character.
+       ((progn
+	  (while (not (looking-at "#\\|$"))
+	    (skip-chars-forward "^#\n\"'\\")
+	    (cond
+	     ((eq (char-after (point)) ?\\) (forward-char 2))
+	     ((memq (char-after (point)) '(?\" ?')) (forward-sexp 1))))
+	  (looking-at "#+[\t ]*"))
+	(setq has-comment t)
+	(setq comment-fill-prefix
+	      (concat (make-string (current-column) ? )
+		      (buffer-substring (match-beginning 0) (match-end 0)))))))
+
+    (if (not has-comment)
+	(fill-paragraph justify)
+
+      ;; Narrow to include only the comment, and then fill the region.
+      (save-restriction
+	(narrow-to-region
+
+	 ;; Find the first line we should include in the region to fill.
+	 (save-excursion
+	   (while (and (zerop (forward-line -1))
+		       (looking-at "^[ \t]*#")))
+
+	   ;; We may have gone to far.  Go forward again.
+	   (or (looking-at "^[ \t]*#")
+	       (forward-line 1))
+	   (point))
+
+	 ;; Find the beginning of the first line past the region to fill.
+	 (save-excursion
+	   (while (progn (forward-line 1)
+			 (looking-at "^[ \t]*#")))
+	   (point)))
+
+	;; Lines with only hashes on them can be paragraph boundaries.
+	(let ((paragraph-start (concat paragraph-start "\\|[ \t#]*$"))
+	      (paragraph-separate (concat paragraph-separate "\\|[ \t#]*$"))
+	      (fill-prefix comment-fill-prefix))
+	  ;;(message "paragraph-start %S paragraph-separate %S"
+	  ;;paragraph-start paragraph-separate)
+	  (fill-paragraph justify))))
+    t))
+
+
+(defun py-fill-string (start &optional justify)
+  "Fill the paragraph around (point) in the string starting at start"
+  ;; basic strategy: narrow to the string and call the default
+  ;; implementation
+  (let (;; the start of the string's contents
+	string-start
+	;; the end of the string's contents
+	string-end
+	;; length of the string's delimiter
+	delim-length
+	;; The string delimiter
+	delim
+	)
+
+    (save-excursion
+      (goto-char start)
+      (if (looking-at "\\('''\\|\"\"\"\\|'\\|\"\\)\\\\?\n?")
+	  (setq string-start (match-end 0)
+		delim-length (- (match-end 1) (match-beginning 1))
+		delim (buffer-substring-no-properties (match-beginning 1)
+						      (match-end 1)))
+	(error "The parameter start is not the beginning of a python string"))
+
+      ;; if the string is the first token on a line and doesn't start with
+      ;; a newline, fill as if the string starts at the beginning of the
+      ;; line. this helps with one line docstrings
+      (save-excursion
+	(beginning-of-line)
+	(and (/= (char-before string-start) ?\n)
+	     (looking-at (concat "[ \t]*" delim))
+	     (setq string-start (point))))
+
+      (forward-sexp (if (= delim-length 3) 2 1))
+
+      ;; with both triple quoted strings and single/double quoted strings
+      ;; we're now directly behind the first char of the end delimiter
+      ;; (this doesn't work correctly when the triple quoted string
+      ;; contains the quote mark itself). The end of the string's contents
+      ;; is one less than point
+      (setq string-end (1- (point))))
+
+    ;; Narrow to the string's contents and fill the current paragraph
+    (save-restriction
+      (narrow-to-region string-start string-end)
+      (let ((ends-with-newline (= (char-before (point-max)) ?\n)))
+	(fill-paragraph justify)
+	(if (and (not ends-with-newline)
+		 (= (char-before (point-max)) ?\n))
+	    ;; the default fill-paragraph implementation has inserted a
+	    ;; newline at the end. Remove it again.
+	    (save-excursion
+	      (goto-char (point-max))
+	      (delete-char -1)))))
+
+    ;; return t to indicate that we've done our work
+    t))
+
+(defun py-fill-paragraph (&optional justify)
+  "Like \\[fill-paragraph], but handle Python comments and strings.
+If any of the current line is a comment, fill the comment or the
+paragraph of it that point is in, preserving the comment's indentation
+and initial `#'s.
+If point is inside a string, narrow to that string and fill.
+"
+  (interactive "P")
+  ;; fill-paragraph will narrow incorrectly
+  (save-restriction
+    (widen)
+    (let* ((bod (py-point 'bod))
+	   (pps (parse-partial-sexp bod (point))))
+      (cond
+       ;; are we inside a comment or on a line with only whitespace before
+       ;; the comment start?
+       ((or (nth 4 pps)
+	    (save-excursion (beginning-of-line) (looking-at "[ \t]*#")))
+	(py-fill-comment justify))
+       ;; are we inside a string?
+       ((nth 3 pps)
+	(py-fill-string (nth 8 pps)))
+       ;; are we at the opening quote of a string, or in the indentation?
+       ((save-excursion
+	  (forward-word 1)
+	  (eq (py-in-literal) 'string))
+	(save-excursion
+	  (py-fill-string (py-point 'boi))))
+       ;; are we at or after the closing quote of a string?
+       ((save-excursion
+	  (backward-word 1)
+	  (eq (py-in-literal) 'string))
+	(save-excursion
+	  (py-fill-string (py-point 'boi))))
+       ;; otherwise use the default
+       (t
+	(fill-paragraph justify))))))
 
 
 





More information about the XEmacs-CVS mailing list