sync with most recent version from python-mode sf project
diff --git a/Misc/python-mode.el b/Misc/python-mode.el
index 202541c..1e9be74 100644
--- a/Misc/python-mode.el
+++ b/Misc/python-mode.el
@@ -2,7 +2,8 @@
 
 ;; Copyright (C) 1992,1993,1994  Tim Peters
 
-;; Author: 1995-2002 Barry A. Warsaw
+;; Author: 2003-2007 http://sf.net/projects/python-mode
+;;         1995-2002 Barry A. Warsaw
 ;;         1992-1994 Tim Peters
 ;; Maintainer: python-mode@python.org
 ;; Created:    Feb 1992
@@ -19,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@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
@@ -60,6 +80,7 @@
 (require 'custom)
 (require 'cl)
 (require 'compile)
+(require 'ansi-color)
 
 
 ;; user definable variables
@@ -70,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")
@@ -105,11 +133,12 @@
   :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.
@@ -248,7 +277,7 @@
   :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,19 +304,20 @@
   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.
@@ -317,16 +347,39 @@
   :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)
@@ -339,9 +392,31 @@
   "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)))
+      (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
@@ -352,30 +427,17 @@
 			  "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
-			'("ArithmeticError" "AssertionError"
-			  "AttributeError" "DeprecationWarning" "EOFError"
-			  "Ellipsis" "EnvironmentError" "Exception" "False"
-			  "FloatingPointError" "FutureWarning" "IOError"
-			  "ImportError" "IndentationError" "IndexError"
-			  "KeyError" "KeyboardInterrupt" "LookupError"
-			  "MemoryError" "NameError" "None" "NotImplemented"
-			  "NotImplementedError" "OSError" "OverflowError"
-			  "OverflowWarning" "PendingDeprecationWarning"
-			  "ReferenceError" "RuntimeError" "RuntimeWarning"
-			  "StandardError" "StopIteration" "SyntaxError"
-			  "SyntaxWarning" "SystemError" "SystemExit"
-			  "TabError" "True" "TypeError" "UnboundLocalError"
-			  "UnicodeDecodeError" "UnicodeEncodeError"
-			  "UnicodeError" "UnicodeTranslateError"
-			  "UserWarning" "ValueError" "Warning"
-			  "ZeroDivisionError" "__debug__"
+			;; 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"
@@ -391,26 +453,52 @@
 			  "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
-     (cons (concat "\\(\\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))
@@ -421,13 +509,7 @@
 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)
 
 
@@ -461,7 +543,7 @@
    "\\(" "[^#'\"\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.")
 
@@ -474,7 +556,7 @@
 			   "\\|")
 	  "\\)")
   "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.")
@@ -495,30 +577,17 @@
 	  "\\)")
   "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_]+\\)()"
   "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 @@
 (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
@@ -560,8 +630,6 @@
   (define-key py-mode-map "\C-c\C-r"  'py-shift-region-right)
   (define-key py-mode-map "\C-c<"     'py-shift-region-left)
   (define-key py-mode-map "\C-c>"     'py-shift-region-right)
-  ;; paragraph and string filling
-  (define-key py-mode-map "\eq"       'py-fill-paragraph)
   ;; subprocess commands
   (define-key py-mode-map "\C-c\C-c"  'py-execute-buffer)
   (define-key py-mode-map "\C-c\C-m"  'py-execute-import-or-reload)
@@ -624,7 +692,7 @@
   ;; 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)
   )
@@ -742,8 +810,8 @@
     (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))
@@ -851,7 +919,7 @@
 
 (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
@@ -887,7 +955,7 @@
 ;; it.
 (defvar py-imenu-generic-expression
   (cons
-   (concat 
+   (concat
     py-imenu-class-regexp
     "\\|"				; or...
     py-imenu-method-regexp
@@ -956,7 +1024,7 @@
 	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))
@@ -1011,7 +1079,7 @@
 			  (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
@@ -1025,7 +1093,7 @@
 
 
 (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)."
@@ -1049,10 +1117,10 @@
 
 
 (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))
@@ -1060,14 +1128,14 @@
 		  (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'
@@ -1116,6 +1184,7 @@
   (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
@@ -1134,6 +1203,8 @@
 	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
@@ -1173,17 +1244,18 @@
     (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
@@ -1191,16 +1263,16 @@
 ;; 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.
-(let ((modes '(("jpython" . jpython-mode)
-	       ("jython" . jpython-mode)
+;;;###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 'jpython-mode auto-mode-alist)))
+	       (rassq 'jython-mode auto-mode-alist)))
   (push '("\\.py$" . python-mode) auto-mode-alist))
 
 
@@ -1272,7 +1344,8 @@
 	(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)
@@ -1285,12 +1358,13 @@
 (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
@@ -1346,7 +1420,7 @@
                                            (- procmark
                                               py-pdbtrack-track-range))
                                       procmark))
-             target target_fname target_lineno)
+             target target_fname target_lineno target_buffer)
 
         (if (not (string-match (concat py-pdbtrack-input-prompt "$") block))
             (py-pdbtrack-overlay-arrow nil)
@@ -1374,8 +1448,7 @@
 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."
@@ -1419,11 +1492,10 @@
 (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))
-        curbuf
+        buf
         got)
     (while (and buffers (not got))
       (setq buf (car buffers)
@@ -1438,7 +1510,7 @@
                                    (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.
@@ -1468,7 +1540,7 @@
 (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")
@@ -1477,14 +1549,14 @@
 (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)
@@ -1497,7 +1569,7 @@
 	(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)
@@ -1505,14 +1577,16 @@
       (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))))
@@ -1534,9 +1608,9 @@
 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
@@ -1570,10 +1644,14 @@
 			       (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
@@ -1644,11 +1722,13 @@
       (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.
@@ -1685,8 +1765,9 @@
       (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)
@@ -1720,12 +1801,14 @@
 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.
@@ -1821,6 +1904,9 @@
 		      (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))
@@ -2001,16 +2087,29 @@
   (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'.
@@ -2054,39 +2153,23 @@
        ((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
@@ -2834,7 +2917,7 @@
 ;; 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."
@@ -2888,6 +2971,11 @@
 
 
 ;; 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
@@ -3412,7 +3500,7 @@
 
 (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))
@@ -3496,8 +3584,8 @@
 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
@@ -3505,7 +3593,7 @@
 	  (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))
@@ -3531,7 +3619,7 @@
 `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)))
 
@@ -3539,14 +3627,49 @@
   "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@python.org"
@@ -3588,7 +3711,7 @@
      "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")
@@ -3608,7 +3731,7 @@
 (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))
 
@@ -3747,20 +3870,35 @@
 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)))
-     ;; 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))))))