Commits

Anonymous committed c6c11af

initial commit

Comments (0)

Files changed (4)

+;; Pymacs
+;; Adiciona o python-mode no caminho de carregamento.
+(add-to-list 'load-path "~/.emacs.d/")
+
+(autoload 'pymacs-load "pymacs" nil t)
+(autoload 'pymacs-eval "pymacs" nil t)
+(autoload 'pymacs-apply "pymacs")
+(autoload 'pymacs-call "pymacs")
+
+;; bicyclerepair
+
+(pymacs-load "bikeemacs" "brm-")
+(brm-init)
+
+;; Inicio da comfiguracao python-mode.
+
+
+(autoload 'python-mode "python-mode" "Python Mode." t)
+(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode))
+(add-to-list 'interpreter-mode-alist '("python" . python-mode))
+
+(add-hook 'python-mode-hook
+          (lambda ()
+            (set (make-variable-buffer-local 'beginning-of-defun-function)
+                 'py-beginning-of-def-or-class)
+            (setq outline-regexp "def\\|class ")))
+
+(defun py-next-block ()
+  "go to the next block.  Cf. `forward-sexp' for lisp-mode"
+  (interactive)
+  (py-mark-block nil 't)
+  (back-to-indentation))
+
+(add-hook 'python-mode-hook (lambda ()
+  (define-key py-mode-map "\C-c3"
+    (lambda (beg end) (interactive "r")
+       (py-comment-region beg end '(4))))))
+
+;; Inicio syntax highlighting
+
+(custom-set-variables
+  ;; custom-set-variables was added by Custom.
+  ;; If you edit it by hand, you could mess it up, so be careful.
+  ;; Your init file should contain only one such instance.
+  ;; If there is more than one, they won't work right.
+ '(column-number-mode t)
+ '(show-paren-mode t)
+ '(speedbar-frame-parameters (quote ((minibuffer) (width . 20) (border-width . 0) (menu-bar-lines . 0) (tool-bar-lines . 0) (unsplittable . t) (set-background-color "black"))))
+ '(tab-width 4)
+ '(transient-mark-mode t))
+(custom-set-faces
+  ;; custom-set-faces was added by Custom.
+  ;; If you edit it by hand, you could mess it up, so be careful.
+  ;; Your init file should contain only one such instance.
+  ;; If there is more than one, they won't work right.
+ '(background "blue")
+ '(font-lock-builtin-face ((((class color) (background dark)) (:foreground "Turquoise"))))
+ '(font-lock-comment-face ((t (:foreground "MediumAquamarine"))))
+ '(font-lock-constant-face ((((class color) (background dark)) (:bold t :foreground "DarkOrchid"))))
+ '(font-lock-doc-string-face ((t (:foreground "green2"))))
+ '(font-lock-function-name-face ((t (:foreground "SkyBlue"))))
+ '(font-lock-keyword-face ((t (:bold t :foreground "CornflowerBlue"))))
+ '(font-lock-preprocessor-face ((t (:italic nil :foreground "CornFlowerBlue"))))
+ '(font-lock-reference-face ((t (:foreground "DodgerBlue"))))
+ '(font-lock-string-face ((t (:foreground "LimeGreen"))))
+ '(font-lock-type-face ((t (:foreground "#9290ff"))))
+ '(font-lock-variable-name-face ((t (:foreground "PaleGreen"))))
+ '(font-lock-warning-face ((((class color) (background dark)) (:foreground "yellow" :background "red"))))
+ '(highlight ((t (:background "CornflowerBlue"))))
+ '(list-mode-item-selected ((t (:background "gold"))))
+ '(makefile-space-face ((t (:background "wheat"))))
+ '(mode-line ((t (:background "Navy"))))
+ '(paren-match ((t (:background "darkseagreen4"))))
+ '(region ((t (:background "DarkSlateBlue"))))
+ '(show-paren-match ((t (:foreground "black" :background "wheat"))))
+ '(show-paren-mismatch ((((class color)) (:foreground "white" :background "red"))))
+ '(speedbar-button-face ((((class color) (background dark)) (:foreground "green4"))))
+ '(speedbar-directory-face ((((class color) (background dark)) (:foreground "khaki"))))
+ '(speedbar-file-face ((((class color) (background dark)) (:foreground "cyan"))))
+ '(speedbar-tag-face ((((class color) (background dark)) (:foreground "Springgreen"))))
+ '(vhdl-speedbar-architecture-selected-face ((((class color) (background dark)) (:underline t :foreground "Blue"))))
+ '(vhdl-speedbar-entity-face ((((class color) (background dark)) (:foreground "darkGreen"))))
+ '(vhdl-speedbar-entity-selected-face ((((class color) (background dark)) (:underline t :foreground "darkGreen"))))
+ '(vhdl-speedbar-package-face ((((class color) (background dark)) (:foreground "black"))))
+ '(vhdl-speedbar-package-selected-face ((((class color) (background dark)) (:underline t :foreground "black"))))
+ '(widget-field ((((class grayscale color) (background light)) (:background "DarkBlue")))))
+
+;; End vai para o fim da linha
+(define-key global-map [end] 'end-of-line)
+
+;; Home vai para o comeco da linha
+(define-key global-map [home] 'beginning-of-line)
+
+;; CTRL-End vai para o fim do documento
+(define-key global-map [C-end] 'end-of-buffer)
+
+;; CTRL-Home vai para o comeco do documento
+(define-key global-map [C-home] 'beginning-of-buffer)
+
+;; Backspace
+(define-key global-map [backspace]
+'delete-backward-char)
+
+;; Delete
+(define-key global-map [delete]
+'delete-char)
+
+
+  (require 'pymacs)
+  (pymacs-load "ropemacs" "rope-")
+;;; Interface between Emacs Lisp and Python - Lisp part.    -*- emacs-lisp -*-
+;;; Copyright © 2001, 2002, 2003 Progiciels Bourbeau-Pinard inc.
+;;; François Pinard <pinard@iro.umontreal.ca>, 2001.
+
+;;; This program is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 2, or (at your option)
+;;; any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program; if not, write to the Free Software Foundation,
+;;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.  */
+
+;;; Portability stunts.
+
+(defvar pymacs-use-hash-tables
+  (and (fboundp 'make-hash-table) (fboundp 'gethash) (fboundp 'puthash))
+  "Set to t if hash tables are available.")
+
+(eval-and-compile
+
+  (if (fboundp 'multibyte-string-p)
+      (defalias 'pymacs-multibyte-string-p 'multibyte-string-p)
+    (defun pymacs-multibyte-string-p (string)
+      "Tell XEmacs if STRING should be handled as multibyte."
+      (not (equal (find-charset-string string) '(ascii))))))
+
+(defalias 'pymacs-report-error (symbol-function 'error))
+
+;;; Published variables and functions.
+
+(defvar pymacs-load-path nil
+  "List of additional directories to search for Python modules.
+The directories listed will be searched first, in the order given.")
+
+(defvar pymacs-trace-transit '(5000 . 30000)
+  "Keep the communication buffer growing, for debugging.
+When this variable is nil, the `*Pymacs*' communication buffer gets erased
+before each communication round-trip.  Setting it to `t' guarantees that
+the full communication is saved, which is useful for debugging.
+It could also be given as (KEEP . LIMIT): whenever the buffer exceeds LIMIT
+bytes, it is reduced to approximately KEEP bytes.")
+
+(defvar pymacs-forget-mutability nil
+  "Transmit copies to Python instead of Lisp handles, as much as possible.
+When this variable is nil, most mutable objects are transmitted as handles.
+This variable is meant to be temporarily rebound to force copies.")
+
+(defvar pymacs-mutable-strings nil
+  "Prefer transmitting Lisp strings to Python as handles.
+When this variable is nil, strings are transmitted as copies, and the
+Python side thus has no way for modifying the original Lisp strings.
+This variable is ignored whenever `forget-mutability' is set.")
+
+(defvar pymacs-timeout-at-start 30
+  "Maximum reasonable time, in seconds, for starting the Pymacs helper.
+A machine should be pretty loaded before one needs to increment this.")
+
+(defvar pymacs-timeout-at-reply 5
+  "Expected maximum time, in seconds, to get the first line of a reply.
+The status of the Pymacs helper is checked at every such timeout.")
+
+(defvar pymacs-timeout-at-line 2
+  "Expected maximum time, in seconds, to get another line of a reply.
+The status of the Pymacs helper is checked at every such timeout.")
+
+(defvar pymacs-dreadful-zombies nil
+  "If zombies should trigger hard errors, whenever they get called.
+If `nil', calling a zombie will merely produce a diagnostic message.")
+
+(defun pymacs-load (module &optional prefix noerror)
+  "Import the Python module named MODULE into Emacs.
+Each function in the Python module is made available as an Emacs function.
+The Lisp name of each function is the concatenation of PREFIX with
+the Python name, in which underlines are replaced by dashes.  If PREFIX is
+not given, it defaults to MODULE followed by a dash.
+If NOERROR is not nil, do not raise error when the module is not found."
+  (interactive
+   (let* ((module (read-string "Python module? "))
+          (default (concat (car (last (split-string module "\\."))) "-"))
+          (prefix (read-string (format "Prefix? [%s] " default)
+                               nil nil default)))
+     (list module prefix)))
+  (message "Pymacs loading %s..." module)
+  (let ((lisp-code (pymacs-call "pymacs_load_helper" module prefix)))
+    (cond (lisp-code (let ((result (eval lisp-code)))
+                       (message "Pymacs loading %s...done" module)
+                       result))
+          (noerror (message "Pymacs loading %s...failed" module) nil)
+          (t (pymacs-report-error "Pymacs loading %s...failed" module)))))
+
+(defun pymacs-eval (text)
+  "Compile TEXT as a Python expression, and return its value."
+  (interactive "sPython expression? ")
+  (let ((value (pymacs-serve-until-reply "eval" `(princ ,text))))
+    (when (interactive-p)
+      (message "%S" value))
+    value))
+
+(defun pymacs-exec (text)
+  "Compile and execute TEXT as a sequence of Python statements.
+This functionality is experimental, and does not appear to be useful."
+  (interactive "sPython statements? ")
+  (let ((value (pymacs-serve-until-reply "exec" `(princ ,text))))
+    (when (interactive-p)
+      (message "%S" value))
+    value))
+
+(defun pymacs-call (function &rest arguments)
+  "Return the result of calling a Python function FUNCTION over ARGUMENTS.
+FUNCTION is a string denoting the Python function, ARGUMENTS are separate
+Lisp expressions, one per argument.  Immutable Lisp constants are converted
+to Python equivalents, other structures are converted into Lisp handles."
+  (pymacs-serve-until-reply
+   "eval" `(pymacs-print-for-apply ',function ',arguments)))
+
+(defun pymacs-apply (function arguments)
+  "Return the result of calling a Python function FUNCTION over ARGUMENTS.
+FUNCTION is a string denoting the Python function, ARGUMENTS is a list of
+Lisp expressions.  Immutable Lisp constants are converted to Python
+equivalents, other structures are converted into Lisp handles."
+  (pymacs-serve-until-reply
+   "eval" `(pymacs-print-for-apply ',function ',arguments)))
+
+;;; Integration details.
+
+;; Python functions and modules should ideally look like Lisp functions and
+;; modules.  This page tries to increase the integration seamlessness.
+
+(defadvice documentation (around pymacs-ad-documentation activate)
+  ;; Integration of doc-strings.
+  (let* ((reference (pymacs-python-reference function))
+         (python-doc (when reference
+                       (pymacs-eval (format "doc_string(%s)" reference)))))
+    (if (or reference python-doc)
+        (setq ad-return-value
+              (concat
+               "It interfaces to a Python function.\n\n"
+               (when python-doc
+                 (if raw python-doc (substitute-command-keys python-doc)))))
+      ad-do-it)))
+
+(defun pymacs-python-reference (object)
+  ;; Return the text reference of a Python object if possible, else nil.
+  (when (functionp object)
+    (let* ((definition (indirect-function object))
+           (body (and (pymacs-proper-list-p definition)
+                      (> (length definition) 2)
+                      (eq (car definition) 'lambda)
+                      (cddr definition))))
+      (when (and body (listp (car body)) (eq (caar body) 'interactive))
+        ;; Skip the interactive specification of a function.
+        (setq body (cdr body)))
+      (when (and body
+                 ;; Advised functions start with a string.
+                 (not (stringp (car body)))
+                 ;; Python trampolines hold exactly one expression.
+                 (= (length body) 1))
+        (let ((expression (car body)))
+          ;; EXPRESSION might now hold something like:
+          ;;    (pymacs-apply (quote (pymacs-python . N)) ARGUMENT-LIST)
+          (when (and (pymacs-proper-list-p expression)
+                     (= (length expression) 3)
+                     (eq (car expression) 'pymacs-apply)
+                     (eq (car (cadr expression)) 'quote))
+            (setq object (cadr (cadr expression))))))))
+  (when (eq (car-safe object) 'pymacs-python)
+    (format "python[%d]" (cdr object))))
+
+;; The following functions are experimental -- they are not satisfactory yet.
+
+(defun pymacs-file-handler (operation &rest arguments)
+  ;; Integration of load-file, autoload, etc.
+  ;; Emacs might want the contents of some `MODULE.el' which does not exist,
+  ;; while there is a `MODULE.py' or `MODULE.pyc' file in the same directory.
+  ;; The goal is to generate a virtual contents for this `MODULE.el' file, as
+  ;; a set of Lisp trampoline functions to the Python module functions.
+  ;; Python modules can then be loaded or autoloaded as if they were Lisp.
+  (cond ((and (eq operation 'file-readable-p)
+              (let ((module (substring (car arguments) 0 -3)))
+                (or (pymacs-file-force operation arguments)
+                    (file-readable-p (concat module ".py"))
+                    (file-readable-p (concat module ".pyc"))))))
+        ((and (eq operation 'load)
+              (not (pymacs-file-force
+                    'file-readable-p (list (car arguments))))
+              (file-readable-p (car arguments)))
+         (let ((lisp-code (pymacs-call "pymacs_load_helper"
+                                       (substring (car arguments) 0 -3)
+                                       nil)))
+           (unless lisp-code
+             (pymacs-report-error "Python import error"))
+           (eval lisp-code)))
+        ((and (eq operation 'insert-file-contents)
+              (not (pymacs-file-force
+                    'file-readable-p (list (car arguments))))
+              (file-readable-p (car arguments)))
+         (let ((lisp-code (pymacs-call "pymacs_load_helper"
+                                       (substring (car arguments) 0 -3)
+                                       nil)))
+           (unless lisp-code
+             (pymacs-report-error "Python import error"))
+           (insert (prin1-to-string lisp-code))))
+        (t (pymacs-file-force operation arguments))))
+
+(defun pymacs-file-force (operation arguments)
+  ;; Bypass the file handler.
+  (let ((inhibit-file-name-handlers
+         (cons 'pymacs-file-handler
+               (and (eq inhibit-file-name-operation operation)
+                    inhibit-file-name-handlers)))
+        (inhibit-file-name-operation operation))
+    (apply operation arguments)))
+
+;(add-to-list 'file-name-handler-alist '("\\.el\\'" . pymacs-file-handler))
+
+;;; Gargabe collection of Python IDs.
+
+;; Python objects which have no Lisp representation are allocated on the
+;; Python side as `python[INDEX]', and INDEX is transmitted to Emacs, with
+;; the value to use on the Lisp side for it.  Whenever Lisp does not need a
+;; Python object anymore, it should be freed on the Python side.  The
+;; following variables and functions are meant to fill this duty.
+
+(defvar pymacs-used-ids nil
+  "List of received IDs, currently allocated on the Python side.")
+
+(defvar pymacs-weak-hash nil
+  "Weak hash table, meant to find out which IDs are still needed.")
+
+(defvar pymacs-gc-wanted nil
+  "Flag if it is time to clean up unused IDs on the Python side.")
+
+(defvar pymacs-gc-running nil
+  "Flag telling that a Pymacs garbage collection is in progress.")
+
+(defvar pymacs-gc-timer nil
+  "Timer to trigger Pymacs garbage collection at regular time intervals.
+The timer is used only if `post-gc-hook' is not available.")
+
+(defun pymacs-schedule-gc (&optional xemacs-list)
+  (unless pymacs-gc-running
+    (setq pymacs-gc-wanted t)))
+
+(defun pymacs-garbage-collect ()
+  ;; Clean up unused IDs on the Python side.
+  (when pymacs-use-hash-tables
+    (let ((pymacs-gc-running t)
+          (pymacs-forget-mutability t)
+          (ids pymacs-used-ids)
+          used-ids unused-ids)
+      (while ids
+        (let ((id (car ids)))
+          (setq ids (cdr ids))
+          (if (gethash id pymacs-weak-hash)
+              (setq used-ids (cons id used-ids))
+            (setq unused-ids (cons id unused-ids)))))
+      (setq pymacs-used-ids used-ids
+            pymacs-gc-wanted nil)
+      (when unused-ids
+        (pymacs-apply "free_python" unused-ids)))))
+
+(defun pymacs-defuns (arguments)
+  ;; Take one argument, a list holding a number of items divisible by 3.  The
+  ;; first argument is an INDEX, the second is a NAME, the third is the
+  ;; INTERACTION specification, and so forth.  Register Python INDEX with a
+  ;; function with that NAME and INTERACTION on the Lisp side.  The strange
+  ;; calling convention is to minimise quoting at call time.
+  (while (>= (length arguments) 3)
+    (let ((index (nth 0 arguments))
+          (name (nth 1 arguments))
+          (interaction (nth 2 arguments)))
+      (fset name (pymacs-defun index interaction))
+      (setq arguments (nthcdr 3 arguments)))))
+
+(defun pymacs-defun (index interaction)
+  ;; Register INDEX on the Lisp side with a Python object that is a function,
+  ;; and return a lambda form calling that function.  If the INTERACTION
+  ;; specification is nil, the function is not interactive.  Otherwise, the
+  ;; function is interactive, INTERACTION is then either a string, or the
+  ;; index of an argument-less Python function returning the argument list.
+  (let ((object (pymacs-python index)))
+    (cond ((null interaction)
+           `(lambda (&rest arguments)
+              (pymacs-apply ',object arguments)))
+          ((stringp interaction)
+           `(lambda (&rest arguments)
+              (interactive ,interaction)
+              (pymacs-apply ',object arguments)))
+          (t `(lambda (&rest arguments)
+                (interactive (pymacs-call ',(pymacs-python interaction)))
+                (pymacs-apply ',object arguments))))))
+
+(defun pymacs-python (index)
+  ;; Register on the Lisp side a Python object having INDEX, and return it.
+  ;; The result is meant to be recognised specially by `print-for-eval', and
+  ;; in the function position by `print-for-apply'.
+  (let ((object (cons 'pymacs-python index)))
+    (when pymacs-use-hash-tables
+      (puthash index object pymacs-weak-hash)
+      (setq pymacs-used-ids (cons index pymacs-used-ids)))
+    object))
+
+;;; Generating Python code.
+
+;; Many Lisp expressions cannot fully be represented in Python, at least
+;; because the object is mutable on the Lisp side.  Such objects are allocated
+;; somewhere into a vector of handles, and the handle index is used for
+;; communication instead of the expression itself.
+
+(defvar pymacs-lisp nil
+  "Vector of handles to hold transmitted expressions.")
+
+(defvar pymacs-freed-list nil
+  "List of unallocated indices in Lisp.")
+
+;; When the Python GC is done with a Lisp object, a communication occurs so to
+;; free the object on the Lisp side as well.
+
+(defun pymacs-allocate-lisp (expression)
+  ;; This function allocates some handle for an EXPRESSION, and return its
+  ;; index.
+  (unless pymacs-freed-list
+    (let* ((previous pymacs-lisp)
+           (old-size (length previous))
+           (new-size (if (zerop old-size) 100 (+ old-size (/ old-size 2))))
+           (counter new-size))
+      (setq pymacs-lisp (make-vector new-size nil))
+      (while (> counter 0)
+        (setq counter (1- counter))
+        (if (< counter old-size)
+            (aset pymacs-lisp counter (aref previous counter))
+          (setq pymacs-freed-list (cons counter pymacs-freed-list))))))
+  (let ((index (car pymacs-freed-list)))
+    (setq pymacs-freed-list (cdr pymacs-freed-list))
+    (aset pymacs-lisp index expression)
+    index))
+
+(defun pymacs-free-lisp (indices)
+  ;; This function is triggered from Python side for Lisp handles which lost
+  ;; their last reference.  These references should be cut on the Lisp side as
+  ;; well, or else, the objects will never be garbage-collected.
+  (while indices
+    (let ((index (car indices)))
+      (aset pymacs-lisp index nil)
+      (setq pymacs-freed-list (cons index pymacs-freed-list)
+            indices (cdr indices)))))
+
+(defun pymacs-print-for-apply (function arguments)
+  ;; This function prints a Python expression calling FUNCTION, which is a
+  ;; string naming a Python function, or a Python reference, over all its
+  ;; ARGUMENTS, which are Lisp expressions.
+  (let ((separator "")
+        argument)
+    (if (eq (car-safe function) 'pymacs-python)
+        (princ (format "python[%d]" (cdr function)))
+      (princ function))
+    (princ "(")
+    (while arguments
+      (setq argument (car arguments)
+            arguments (cdr arguments))
+      (princ separator)
+      (setq separator ", ")
+      (pymacs-print-for-eval argument))
+    (princ ")")))
+
+(defun pymacs-print-for-eval (expression)
+  ;; This function prints a Python expression out of a Lisp EXPRESSION.
+  (let (done)
+    (cond ((not expression)
+           (princ "None")
+           (setq done t))
+          ((eq expression t)
+           (princ "True")
+           (setq done t))
+          ((numberp expression)
+           (princ expression)
+           (setq done t))
+          ((stringp expression)
+           (when (or pymacs-forget-mutability
+                     (not pymacs-mutable-strings))
+             (let* ((multibyte (pymacs-multibyte-string-p expression))
+                    (text (if multibyte
+                              (encode-coding-string expression 'utf-8)
+                            (copy-sequence expression))))
+               (set-text-properties 0 (length text) nil text)
+               (princ (mapconcat 'identity
+                                 (split-string (prin1-to-string text) "\n")
+                                 "\\n"))
+               (when (and multibyte
+                          (not (equal (find-charset-string text) '(ascii))))
+                 (princ ".decode('UTF-8')")))
+             (setq done t)))
+          ((symbolp expression)
+           (let ((name (symbol-name expression)))
+             ;; The symbol can only be transmitted when in the main oblist.
+             (when (eq expression (intern-soft name))
+               (princ "lisp[")
+               (prin1 name)
+               (princ "]")
+               (setq done t))))
+          ((vectorp expression)
+           (when pymacs-forget-mutability
+             (let ((limit (length expression))
+                   (counter 0))
+               (princ "(")
+               (while (< counter limit)
+                 (unless (zerop counter)
+                   (princ ", "))
+                 (pymacs-print-for-eval (aref expression counter))
+                 (setq counter (1+ counter)))
+               (when (= limit 1)
+                 (princ ","))
+               (princ ")")
+               (setq done t))))
+          ((eq (car-safe expression) 'pymacs-python)
+           (princ "python[")
+           (princ (cdr expression))
+           (princ "]")
+           (setq done t))
+          ((pymacs-proper-list-p expression)
+           (when pymacs-forget-mutability
+             (princ "[")
+             (pymacs-print-for-eval (car expression))
+             (while (setq expression (cdr expression))
+               (princ ", ")
+               (pymacs-print-for-eval (car expression)))
+             (princ "]")
+             (setq done t))))
+    (unless done
+      (let ((class (cond ((vectorp expression) "Vector")
+                         ((and pymacs-use-hash-tables
+                               (hash-table-p expression))
+                          "Table")
+                         ((bufferp expression) "Buffer")
+                         ((pymacs-proper-list-p expression) "List")
+                         (t "Lisp"))))
+        (princ class)
+        (princ "(")
+        (princ (pymacs-allocate-lisp expression))
+        (princ ")")))))
+
+;;; Communication protocol.
+
+(defvar pymacs-transit-buffer nil
+  "Communication buffer between Emacs and Python.")
+
+;; The principle behind the communication protocol is that it is easier to
+;; generate than parse, and that each language already has its own parser.
+;; So, the Emacs side generates Python text for the Python side to interpret,
+;; while the Python side generates Lisp text for the Lisp side to interpret.
+;; About nothing but expressions are transmitted, which are evaluated on
+;; arrival.  The pseudo `reply' function is meant to signal the final result
+;; of a series of exchanges following a request, while the pseudo `error'
+;; function is meant to explain why an exchange could not have been completed.
+
+;; The protocol itself is rather simple, and contains human readable text
+;; only.  A message starts at the beginning of a line in the communication
+;; buffer, either with `>' for the Lisp to Python direction, or `<' for the
+;; Python to Lisp direction.  This is followed by a decimal number giving the
+;; length of the message text, a TAB character, and the message text itself.
+;; Message direction alternates systematically between messages, it never
+;; occurs that two successive messages are sent in the same direction.  The
+;; first message is received from the Python side, it is `(version VERSION)'.
+
+(defun pymacs-start-services ()
+  ;; This function gets called automatically, as needed.
+  (let ((buffer (get-buffer-create "*Pymacs*")))
+    (with-current-buffer buffer
+      (buffer-disable-undo)
+      (set-buffer-multibyte nil)
+      (set-buffer-file-coding-system 'raw-text)
+      (save-match-data
+        ;; Launch the Pymacs helper.
+        (let ((process
+               (apply 'start-process "pymacs" buffer
+                      (let ((python (getenv "PYMACS_PYTHON")))
+                        (if (or (null python) (equal python ""))
+                            "python"
+                          python))
+                      "-c" (concat "import sys;"
+                                   " from Pymacs.pymacs import main;"
+                                   " main(*sys.argv[1:])")
+                      (mapcar 'expand-file-name pymacs-load-path))))
+          (cond ((fboundp 'set-process-query-on-exit-flag)
+                 (set-process-query-on-exit-flag process nil))
+                ((fboundp 'process-kill-without-query-process)
+                 (process-kill-without-query process)))
+          ;; Receive the synchronising reply.
+          (while (progn
+                   (goto-char (point-min))
+                   (not (re-search-forward "<\\([0-9]+\\)\t" nil t)))
+            (unless (accept-process-output process pymacs-timeout-at-start)
+              (pymacs-report-error
+               "Pymacs helper did not start within %d seconds"
+                     pymacs-timeout-at-start)))
+          (let ((marker (process-mark process))
+                (limit-position (+ (match-end 0)
+                                   (string-to-number (match-string 1)))))
+            (while (< (marker-position marker) limit-position)
+              (unless (accept-process-output process pymacs-timeout-at-start)
+                (pymacs-report-error
+                 "Pymacs helper probably was interrupted at start")))))
+        ;; Check that synchronisation occurred.
+        (goto-char (match-end 0))
+        (let ((reply (read (current-buffer))))
+          (if (and (pymacs-proper-list-p reply)
+                   (= (length reply) 2)
+                   (eq (car reply) 'version))
+              (unless (string-equal (cadr reply) "0.23")
+                (pymacs-report-error
+                 "Pymacs Lisp version is 0.23, Python is %s"
+                 (cadr reply)))
+            (pymacs-report-error "Pymacs got an invalid initial reply")))))
+    (when pymacs-use-hash-tables
+      (if pymacs-weak-hash
+          ;; A previous Pymacs session occurred in *this* Emacs session.  Some
+          ;; IDs may hang around, which do not correspond to anything on the
+          ;; Python side.  Python should not recycle such IDs for new objects.
+          (when pymacs-used-ids
+            (let ((pymacs-transit-buffer buffer)
+                  (pymacs-forget-mutability t))
+              (pymacs-apply "zombie_python" pymacs-used-ids)))
+        (setq pymacs-weak-hash (make-hash-table :weakness 'value)))
+      (if (boundp 'post-gc-hook)
+          (add-hook 'post-gc-hook 'pymacs-schedule-gc)
+        (setq pymacs-gc-timer (run-at-time 20 20 'pymacs-schedule-gc))))
+    ;; If nothing failed, only then declare that Pymacs has started!
+    (setq pymacs-transit-buffer buffer)))
+
+(defun pymacs-terminate-services ()
+  ;; This function is mainly provided for documentation purposes.
+  (interactive)
+  (garbage-collect)
+  (pymacs-garbage-collect)
+  (when (or (not pymacs-used-ids)
+            (yes-or-no-p "\
+Killing the Pymacs helper might create zombie objects.  Kill? "))
+    (cond ((boundp 'post-gc-hook)
+           (remove-hook 'post-gc-hook 'pymacs-schedule-gc))
+          ((timerp pymacs-gc-timer)
+           (cancel-timer pymacs-gc-timer)))
+    (when pymacs-transit-buffer
+      (kill-buffer pymacs-transit-buffer))
+    (setq pymacs-gc-running nil
+          pymacs-gc-timer nil
+          pymacs-transit-buffer nil
+          pymacs-lisp nil
+          pymacs-freed-list nil)))
+
+(defun pymacs-serve-until-reply (action inserter)
+  ;; This function builds a Python request by printing ACTION and
+  ;; evaluating INSERTER, which itself prints an argument.  It then
+  ;; sends the request to the Pymacs helper, and serves all
+  ;; sub-requests coming from the Python side, until either a reply or
+  ;; an error is finally received.
+  (unless (and pymacs-transit-buffer
+               (buffer-name pymacs-transit-buffer)
+               (get-buffer-process pymacs-transit-buffer))
+    (pymacs-start-services))
+  (when pymacs-gc-wanted
+    (pymacs-garbage-collect))
+  (let ((inhibit-quit t)
+        done value)
+    (while (not done)
+      (let ((form (pymacs-round-trip action inserter)))
+        (setq action (car form))
+        (when (eq action 'free)
+          (pymacs-free-lisp (cadr form))
+          (setq form (cddr form)
+                action (car form)))
+        (let* ((pair (pymacs-interruptible-eval (cadr form)))
+               (success (cdr pair)))
+          (setq value (car pair))
+          (cond ((eq action 'eval)
+                 (if success
+                     (setq action "return"
+                           inserter `(pymacs-print-for-eval ',value))
+                   (setq action "raise"
+                         inserter `(let ((pymacs-forget-mutability t))
+                                     (pymacs-print-for-eval ,value)))))
+                ((eq action 'expand)
+                 (if success
+                     (setq action "return"
+                           inserter `(let ((pymacs-forget-mutability t))
+                                       (pymacs-print-for-eval ,value)))
+                   (setq action "raise"
+                         inserter `(let ((pymacs-forget-mutability t))
+                                     (pymacs-print-for-eval ,value)))))
+                ((eq action 'return)
+                 (if success
+                     (setq done t)
+                   (pymacs-report-error "%s" value)))
+                ((eq action 'raise)
+                 (if success
+                     (pymacs-report-error "Python: %s" value)
+                   (pymacs-report-error "%s" value)))
+                (t (pymacs-report-error "Protocol error: %s" form))))))
+    value))
+
+(defun pymacs-round-trip (action inserter)
+  ;; This function produces a Python request by printing and
+  ;; evaluating INSERTER, which itself prints an argument.  It sends
+  ;; the request to the Pymacs helper, awaits for any kind of reply,
+  ;; and returns it.
+  (with-current-buffer pymacs-transit-buffer
+    ;; Possibly trim the beginning of the transit buffer.
+    (cond ((not pymacs-trace-transit)
+           (erase-buffer))
+          ((consp pymacs-trace-transit)
+           (when (> (buffer-size) (cdr pymacs-trace-transit))
+             (let ((cut (- (buffer-size) (car pymacs-trace-transit))))
+               (when (> cut 0)
+                 (save-excursion
+                   (goto-char cut)
+                   (unless (memq (preceding-char) '(0 ?\n))
+                     (forward-line 1))
+                   (delete-region (point-min) (point))))))))
+    ;; Send the request, wait for a reply, and process it.
+    (let* ((process (get-buffer-process pymacs-transit-buffer))
+           (status (process-status process))
+           (marker (process-mark process))
+           (moving (= (point) marker))
+           send-position reply-position reply)
+      (save-excursion
+        (save-match-data
+          ;; Encode request.
+          (setq send-position (marker-position marker))
+          (let ((standard-output marker))
+            (princ action)
+            (princ " ")
+            (eval inserter))
+          (goto-char marker)
+          (unless (= (preceding-char) ?\n)
+            (princ "\n" marker))
+          ;; Send request text.
+          (goto-char send-position)
+          (insert (format ">%d\t" (- marker send-position)))
+          (setq reply-position (marker-position marker))
+          (process-send-region process send-position marker)
+          ;; Receive reply text.
+          (while (and (eq status 'run)
+                      (progn
+                        (goto-char reply-position)
+                        (not (re-search-forward "<\\([0-9]+\\)\t" nil t))))
+            (unless (accept-process-output process pymacs-timeout-at-reply)
+              (setq status (process-status process))))
+          (when (eq status 'run)
+            (let ((limit-position (+ (match-end 0)
+                                     (string-to-number (match-string 1)))))
+              (while (and (eq status 'run)
+                          (< (marker-position marker) limit-position))
+                (unless (accept-process-output process pymacs-timeout-at-line)
+                  (setq status (process-status process))))))
+          ;; Decode reply.
+          (if (not (eq status 'run))
+              (pymacs-report-error "Pymacs helper status is `%S'" status)
+            (goto-char (match-end 0))
+            (setq reply (read (current-buffer))))))
+      (when (and moving (not pymacs-trace-transit))
+        (goto-char marker))
+      reply)))
+
+(defun pymacs-interruptible-eval (expression)
+  ;; This function produces a pair (VALUE . SUCCESS) for EXPRESSION.
+  ;; A cautious evaluation of EXPRESSION is attempted, and any
+  ;; error while evaluating is caught, including Emacs quit (C-g).
+  ;; Any Emacs quit also gets forward as a SIGINT to the Pymacs handler.
+  ;; With SUCCESS being true, VALUE is the expression value.
+  ;; With SUCCESS being false, VALUE is an interruption diagnostic.
+  (condition-case info
+      (cons (let ((inhibit-quit nil)) (eval expression)) t)
+    (quit (setq quit-flag t)
+          (interrupt-process pymacs-transit-buffer)
+          (cons "*Interrupted!*" nil))
+    (error (cons (prin1-to-string info) nil))))
+
+(defun pymacs-proper-list-p (expression)
+  ;; Tell if a list is proper, id est, that it is `nil' or ends with `nil'.
+  (cond ((not expression))
+        ((consp expression) (not (cdr (last expression))))))
+
+(provide 'pymacs)
+;;; python-mode.el --- Major mode for editing Python programs
+
+;; Copyright (C) 1992,1993,1994  Tim Peters
+
+;; Author: 2003-2009 https://launchpad.net/python-mode
+;;         1995-2002 Barry A. Warsaw
+;;         1992-1994 Tim Peters
+;; Maintainer: python-mode@python.org
+;; Created:    Feb 1992
+;; Keywords:   python languages oop
+
+(defconst py-version "5.1.0"
+  "`python-mode' version number.")
+
+;; This file is part of python-mode.el.
+;;
+;; python-mode.el is free software: you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by the Free
+;; Software Foundation, either version 3 of the License, or (at your option)
+;; any later version.
+;;
+;; python-mode.el is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+;; for more details.
+;;
+;; You should have received a copy of the GNU General Public License along
+;; with python-mode.el.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; 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 and in 1995, Barry Warsaw inherited the mode.  Tim came back
+;; but disavowed all responsibility for the mode.  In fact, we suspect he
+;; doesn't even use Emacs any more <wink>.  In 2003, python-mode.el was moved
+;; to its own SourceForge project apart from the Python project, and in 2008
+;; it was moved to Launchpad for all project administration.  python-mode.el
+;; is maintained by the volunteers at the python-mode@python.org mailing
+;; list.
+
+;; python-mode.el is different than, and pre-dates by many years, the
+;; python.el that comes with FSF Emacs.  We'd like to merge the two modes but
+;; have few cycles to do so.  Volunteers are welcome.
+
+;; pdbtrack support contributed by Ken Manheimer, April 2001.  Skip Montanaro
+;; has also contributed significantly to python-mode's development.
+
+;; Please use Launchpad to submit bugs or patches:
+;;
+;;     https://launchpad.net/python-mode
+
+;; 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)
+
+;; BUG REPORTING:
+
+;; As mentioned above, please use the Launchpad python-mode project for
+;; submitting bug reports or patches.  The old recommendation, to use C-c C-b
+;; will still work, but those reports have a higher chance of getting buried
+;; in our inboxes.  Please include a complete, but concise code sample and a
+;; recipe for reproducing the bug.  Send suggestions and other comments to
+;; python-mode@python.org.
+
+;; When in a Python mode buffer, do a C-h m for more help.  It's doubtful that
+;; a texinfo manual would be very useful, but if you want to contribute one,
+;; we'll certainly accept it!
+
+;;; Code:
+
+(require 'comint)
+(require 'custom)
+(require 'cl)
+(require 'compile)
+(require 'ansi-color)
+
+
+;; user definable variables
+;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+
+(defgroup python nil
+  "Support for the Python programming language, <http://www.python.org/>"
+  :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)
+
+(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 "Jython Command")
+
+(defcustom py-default-interpreter 'cpython
+  "*Which Python interpreter is used by default.
+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 `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 "Jython" jython))
+  :group 'python)
+
+(defcustom py-python-command-args '("-i")
+  "*List of string arguments to be used when starting a Python shell."
+  :type '(repeat string)
+  :group 'python)
+
+(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 "Jython Command Args")
+
+(defcustom py-indent-offset 4
+  "*Amount of offset per level of indentation.
+`\\[py-guess-indent-offset]' can usually guess a good value when
+you're editing someone else's Python code."
+  :type 'integer
+  :group 'python)
+
+(defcustom py-continuation-offset 4
+  "*Additional amount of offset to give for some continuation lines.
+Continuation lines are those that immediately follow a backslash
+terminated line.  Only those continuation lines for a block opening
+statement are given this extra offset."
+  :type 'integer
+  :group 'python)
+
+(defcustom py-smart-indentation t
+  "*Should `python-mode' try to automagically set some indentation variables?
+When this variable is non-nil, two things happen when a buffer is set
+to `python-mode':
+
+    1. `py-indent-offset' is guessed from existing code in the buffer.
+       Only guessed values between 2 and 8 are considered.  If a valid
+       guess can't be made (perhaps because you are visiting a new
+       file), then the value in `py-indent-offset' is used.
+
+    2. `indent-tabs-mode' is turned off if `py-indent-offset' does not
+       equal `tab-width' (`indent-tabs-mode' is never turned on by
+       Python mode).  This means that for newly written code, tabs are
+       only inserted in indentation if one tab is one indentation
+       level, otherwise only spaces are used.
+
+Note that both these settings occur *after* `python-mode-hook' is run,
+so if you want to defeat the automagic configuration, you must also
+set `py-smart-indentation' to nil in your `python-mode-hook'."
+  :type 'boolean
+  :group 'python)
+
+(defcustom py-align-multiline-strings-p t
+  "*Flag describing how multi-line triple quoted strings are aligned.
+When this flag is non-nil, continuation lines are lined up under the
+preceding line's indentation.  When this flag is nil, continuation
+lines are aligned to column zero."
+  :type '(choice (const :tag "Align under preceding line" t)
+                 (const :tag "Align to column zero" nil))
+  :group 'python)
+
+(defcustom py-block-comment-prefix "##"
+  "*String used by \\[comment-region] to comment out a block of code.
+This should follow the convention for non-indenting comment lines so
+that the indentation commands won't get confused (i.e., the string
+should be of the form `#x...' where `x' is not a blank or a tab, and
+`...' is arbitrary).  However, this string should not end in whitespace."
+  :type 'string
+  :group 'python)
+
+(defcustom py-honor-comment-indentation t
+  "*Controls how comment lines influence subsequent indentation.
+
+When nil, all comment lines are skipped for indentation purposes, and
+if possible, a faster algorithm is used (i.e. X/Emacs 19 and beyond).
+
+When t, lines that begin with a single `#' are a hint to subsequent
+line indentation.  If the previous line is such a comment line (as
+opposed to one that starts with `py-block-comment-prefix'), then its
+indentation is used as a hint for this line's indentation.  Lines that
+begin with `py-block-comment-prefix' are ignored for indentation
+purposes.
+
+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)
+          (const :tag "Single # `sets' indentation except at column zero"
+                 other)
+          )
+  :group 'python)
+
+(defcustom py-temp-directory
+  (let ((ok '(lambda (x)
+               (and x
+                    (setq x (expand-file-name x)) ; always true
+                    (file-directory-p x)
+                    (file-writable-p x)
+                    x))))
+    (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 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, /var/tmp, or the current directory."
+  :type 'string
+  :group 'python)
+
+(defcustom py-beep-if-tab-change t
+  "*Ring the bell if `tab-width' is changed.
+If a comment of the form
+
+  \t# vi:set tabsize=<number>:
+
+is found before the first code line when the file is entered, and the
+current value of (the general Emacs variable) `tab-width' does not
+equal <number>, `tab-width' is set to <number>, a message saying so is
+displayed in the echo area, and if `py-beep-if-tab-change' is non-nil
+the Emacs bell is also rung as a warning."
+  :type 'boolean
+  :group 'python)
+
+(defcustom py-jump-on-exception t
+  "*Jump to innermost exception frame in *Python Output* buffer.
+When this variable is non-nil and an exception occurs when running
+Python code synchronously in a subprocess, jump immediately to the
+source code of the innermost traceback frame."
+  :type 'boolean
+  :group 'python)
+
+(defcustom py-ask-about-save t
+  "If not nil, ask about which buffers to save before executing some code.
+Otherwise, all modified buffers are saved without asking."
+  :type 'boolean
+  :group 'python)
+
+(defcustom py-backspace-function 'backward-delete-char-untabify
+  "*Function called by `py-electric-backspace' when deleting backwards."
+  :type 'function
+  :group 'python)
+
+(defcustom py-delete-function 'delete-char
+  "*Function called by `py-electric-delete' when deleting forwards."
+  :type 'function
+  :group 'python)
+
+(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
+  :group 'python)
+(make-variable-buffer-local 'py-indent-offset)
+
+(defcustom py-pdbtrack-do-tracking-p t
+  "*Controls whether the pdbtrack feature is enabled or not.
+When non-nil, pdbtrack is enabled in all comint-based buffers,
+e.g. shell buffers and the *Python* buffer.  When using pdb to debug a
+Python program, pdbtrack notices the pdb prompt and displays the
+source file and line that the program is stopped at, much the same way
+as gud-mode does for debugging C programs with gdb."
+  :type 'boolean
+  :group 'python)
+(make-variable-buffer-local 'py-pdbtrack-do-tracking-p)
+
+(defcustom py-pdbtrack-minor-mode-string " PDB"
+  "*String to use in the minor mode list when pdbtrack is enabled."
+  :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.
+The intent is to allow you to set this variable in the file's local
+variable section, e.g.:
+
+    # Local Variables:
+    # py-master-file: \"master.py\"
+    # End:
+
+so that typing \\[py-execute-buffer] in that buffer executes the named
+master file instead of the buffer's file.  If the file name has a
+relative path, the value of variable `default-directory' for the
+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)
+  "A list of features extant in the Emacs you are using.
+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"
+                          "continue" "def"      "del"       "elif"
+                          "else"     "except"   "for"       "from"
+                          "global"   "if"       "import"    "in"
+                          "is"       "lambda"   "not"       "or"
+                          "pass"     "raise"    "as"        "return"
+                          "while"    "with"    "yield"
+                          )
+                        "\\|"))
+        (kw2 (mapconcat 'identity
+                        '("else:" "except:" "finally:" "try:")
+                        "\\|"))
+        (kw3 (mapconcat 'identity
+                        ;; Don't include Ellipsis in this list, since it is
+                        ;; already defined as a pseudo keyword.
+                        '("__debug__"
+                          "__import__" "__name__" "abs" "all" "any" "apply"
+                          "basestring" "bin" "bool" "buffer" "bytearray"
+                          "callable" "chr" "classmethod" "cmp" "coerce"
+                          "compile" "complex" "copyright" "credits"
+                          "delattr" "dict" "dir" "divmod" "enumerate" "eval"
+                          "exec" "execfile" "exit" "file" "filter" "float"
+                          "format" "getattr" "globals" "hasattr" "hash" "help"
+                          "hex" "id" "input" "int" "intern" "isinstance"
+                          "issubclass" "iter" "len" "license" "list" "locals"
+                          "long" "map" "max" "memoryview" "min" "next"
+                          "object" "oct" "open" "ord" "pow" "print" "property"
+                          "quit" "range" "raw_input" "reduce" "reload" "repr"
+                          "round" "set" "setattr" "slice" "sorted"
+                          "staticmethod" "str" "sum" "super" "tuple" "type"
+                          "unichr" "unicode" "vars" "xrange" "zip")
+                        "\\|"))
+        (kw4 (mapconcat 'identity
+                        ;; Exceptions and warnings
+                        '("ArithmeticError" "AssertionError"
+                          "AttributeError" "BaseException" "BufferError"
+                          "BytesWarning" "DeprecationWarning" "EOFError"
+                          "EnvironmentError" "Exception"
+                          "FloatingPointError" "FutureWarning" "GeneratorExit"
+                          "IOError" "ImportError" "ImportWarning"
+                          "IndentationError" "IndexError"
+                          "KeyError" "KeyboardInterrupt" "LookupError"
+                          "MemoryError" "NameError" "NotImplemented"
+                          "NotImplementedError" "OSError" "OverflowError"
+                          "PendingDeprecationWarning" "ReferenceError"
+                          "RuntimeError" "RuntimeWarning" "StandardError"
+                          "StopIteration" "SyntaxError" "SyntaxWarning"
+                          "SystemError" "SystemExit" "TabError" "TypeError"
+                          "UnboundLocalError" "UnicodeDecodeError"
+                          "UnicodeEncodeError" "UnicodeError"
+                          "UnicodeTranslateError" "UnicodeWarning"
+                          "UserWarning" "ValueError" "Warning"
+                          "ZeroDivisionError")
+                        "\\|"))
+        )
+    (list
+     '("^[ \t]*\\(@.+\\)" 1 'py-decorators-face)
+     ;; keywords
+     (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 "\\<\\(" kw2 "\\)[ \n\t(]") 1)
+     ;; Exceptions
+     (list (concat "\\<\\(" kw4 "\\)[ \n\t:,(]") 1 'py-builtins-face)
+     ;; classes
+     '("\\<class[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)" 1 font-lock-type-face)
+     ;; functions
+     '("\\<def[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)"
+       1 font-lock-function-name-face)
+     ;; pseudo-keywords
+     '("\\<\\(self\\|Ellipsis\\|True\\|False\\|None\\)\\>"
+       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))
+
+;; have to bind py-file-queue before installing the kill-emacs-hook
+(defvar py-file-queue nil
+  "Queue of Python temp files awaiting execution.
+Currently-active file is at the head of the list.")
+
+(defvar py-pdbtrack-is-tracking-p nil)
+
+(defvar py-pychecker-history nil)
+
+
+
+;; Constants
+
+(defconst py-stringlit-re
+  (concat
+   ;; These fail if backslash-quote ends the string (not worth
+   ;; fixing?).  They precede the short versions so that the first two
+   ;; quotes don't look like an empty short string.
+   ;;
+   ;; (maybe raw), long single quoted triple quoted strings (SQTQ),
+   ;; with potential embedded single quotes
+   "[rR]?'''[^']*\\(\\('[^']\\|''[^']\\)[^']*\\)*'''"
+   "\\|"
+   ;; (maybe raw), long double quoted triple quoted strings (DQTQ),
+   ;; with potential embedded double quotes
+   "[rR]?\"\"\"[^\"]*\\(\\(\"[^\"]\\|\"\"[^\"]\\)[^\"]*\\)*\"\"\""
+   "\\|"
+   "[rR]?'\\([^'\n\\]\\|\\\\.\\)*'"     ; single-quoted
+   "\\|"                                ; or
+   "[rR]?\"\\([^\"\n\\]\\|\\\\.\\)*\""  ; double-quoted
+   )
+  "Regular expression matching a Python string literal.")
+
+(defconst py-continued-re
+  ;; This is tricky because a trailing backslash does not mean
+  ;; continuation if it's in a comment
+  (concat
+   "\\(" "[^#'\"\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.")
+
+(defconst py-outdent-re
+  (concat "\\(" (mapconcat 'identity
+                           '("else:"
+                             "except\\(\\s +.*\\)?:"
+                             "finally:"
+                             "elif\\s +.*:")
+                           "\\|")
+          "\\)")
+  "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.")
+
+(defconst py-no-outdent-re
+  (concat
+   "\\("
+   (mapconcat 'identity
+              (list "try:"
+                    "except\\(\\s +.*\\)?:"
+                    "while\\s +.*:"
+                    "for\\s +.*:"
+                    "if\\s +.*:"
+                    "elif\\s +.*:"
+                    (concat py-block-closing-keywords-re "[ \t\n]")
+                    )
+              "\\|")
+          "\\)")
+  "Regular expression matching lines not to dedent after.")
+
+(defvar py-traceback-line-re
+  "[ \t]+File \"\\([^\"]+\\)\", line \\([0-9]+\\)"
+  "Regular expression that describes tracebacks.")
+
+;; 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[(<]*[Pp]db[>)]+ "
+  "Regular expression pdbtrack uses to recognize a pdb prompt.")
+
+(defconst py-pdbtrack-track-range 10000
+  "Max number of characters from end of buffer to search for stack entry.")
+
+
+
+;; Major mode boilerplate
+
+;; define a mode-specific abbrev table for those who use such things
+(defvar python-mode-abbrev-table nil
+  "Abbrev table in use in `python-mode' buffers.")
+(define-abbrev-table 'python-mode-abbrev-table nil)
+
+(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)
+     (make-obsolete-variable 'py-mode-hook 'python-mode-hook))
+
+(defvar py-mode-map ()
+  "Keymap used in `python-mode' buffers.")
+(if py-mode-map
+    nil
+  (setq py-mode-map (make-sparse-keymap))
+  ;; electric keys
+  (define-key py-mode-map ":" 'py-electric-colon)
+  ;; indentation level modifiers
+  (define-key py-mode-map "\C-c\C-l"  'py-shift-region-left)
+  (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)
+  ;; 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)
+  (define-key py-mode-map "\C-c\C-s"  'py-execute-string)
+  (define-key py-mode-map "\C-c|"     'py-execute-region)
+  (define-key py-mode-map "\e\C-x"    'py-execute-def-or-class)
+  (define-key py-mode-map "\C-c!"     'py-shell)
+  (define-key py-mode-map "\C-c\C-t"  'py-toggle-shells)
+  ;; Caution!  Enter here at your own risk.  We are trying to support
+  ;; several behaviors and it gets disgusting. :-( This logic ripped
+  ;; largely from CC Mode.
+  ;;
+  ;; In XEmacs 19, Emacs 19, and Emacs 20, we use this to bind
+  ;; backwards deletion behavior to DEL, which both Delete and
+  ;; Backspace get translated to.  There's no way to separate this
+  ;; behavior in a clean way, so deal with it!  Besides, it's been
+  ;; this way since the dawn of time.
+  (if (not (boundp 'delete-key-deletes-forward))
+      (define-key py-mode-map "\177" 'py-electric-backspace)
+    ;; However, XEmacs 20 actually achieved enlightenment.  It is
+    ;; possible to sanely define both backward and forward deletion
+    ;; behavior under X separately (TTYs are forever beyond hope, but
+    ;; who cares?  XEmacs 20 does the right thing with these too).
+    (define-key py-mode-map [delete]    'py-electric-delete)
+    (define-key py-mode-map [backspace] 'py-electric-backspace))
+  ;; Separate M-BS from C-M-h.  The former should remain
+  ;; backward-kill-word.
+  (define-key py-mode-map [(control meta h)] 'py-mark-def-or-class)
+  (define-key py-mode-map "\C-c\C-k"  'py-mark-block)
+  ;; Miscellaneous
+  (define-key py-mode-map "\C-c:"     'py-guess-indent-offset)
+  (define-key py-mode-map "\C-c\t"    'py-indent-region)
+  (define-key py-mode-map "\C-c\C-d"  'py-pdbtrack-toggle-stack-tracking)
+  (define-key py-mode-map "\C-c\C-f"  'py-sort-imports)
+  (define-key py-mode-map "\C-c\C-n"  'py-next-statement)
+  (define-key py-mode-map "\C-c\C-p"  'py-previous-statement)
+  (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-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)
+  (define-key py-mode-map "\C-c="     'py-down-exception)
+  ;; stuff that is `standard' but doesn't interface well with
+  ;; python-mode, which forces us to rebind to special commands
+  (define-key py-mode-map "\C-xnd"    'py-narrow-to-defun)
+  ;; 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.
+  (mapc #'(lambda (key)
+            (define-key py-mode-map key 'py-newline-and-indent))
+        (where-is-internal 'newline-and-indent))
+  ;; Force RET to be py-newline-and-indent even if it didn't get
+  ;; mapped by the above code.  motivation: Emacs' default binding for
+  ;; RET is `newline' and C-j is `newline-and-indent'.  Most Pythoneers
+  ;; 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
+  ;; change.
+  (define-key py-mode-map "\C-m" 'py-newline-and-indent)
+  )
+
+(defvar py-mode-output-map nil
+  "Keymap used in *Python Output* buffers.")
+(if py-mode-output-map
+    nil
+  (setq py-mode-output-map (make-sparse-keymap))
+  (define-key py-mode-output-map [button2]  'py-mouseto-exception)
+  (define-key py-mode-output-map "\C-c\C-c" 'py-goto-exception)
+  ;; TBD: Disable all self-inserting keys.  This is bogus, we should
+  ;; really implement this as *Python Output* buffer being read-only
+  (mapc #' (lambda (key)
+             (define-key py-mode-output-map key
+               #'(lambda () (interactive) (beep))))
+           (where-is-internal 'self-insert-command))
+  )
+
+(defvar py-shell-map nil
+  "Keymap used in *Python* shell buffers.")
+(if py-shell-map
+    nil
+  (setq py-shell-map (copy-keymap comint-mode-map))
+  (define-key py-shell-map [tab]   'tab-to-tab-stop)
+  (define-key py-shell-map "\C-c-" 'py-up-exception)
+  (define-key py-shell-map "\C-c=" 'py-down-exception)
+  )
+
+(defvar py-mode-syntax-table nil
+  "Syntax table used in `python-mode' buffers.")
+(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)
+  (modify-syntax-entry ?\[ "(]" py-mode-syntax-table)
+  (modify-syntax-entry ?\] ")[" py-mode-syntax-table)
+  (modify-syntax-entry ?\{ "(}" py-mode-syntax-table)
+  (modify-syntax-entry ?\} "){" py-mode-syntax-table)
+  ;; Add operator symbols misassigned in the std table
+  (modify-syntax-entry ?\$ "."  py-mode-syntax-table)
+  (modify-syntax-entry ?\% "."  py-mode-syntax-table)
+  (modify-syntax-entry ?\& "."  py-mode-syntax-table)
+  (modify-syntax-entry ?\* "."  py-mode-syntax-table)
+  (modify-syntax-entry ?\+ "."  py-mode-syntax-table)
+  (modify-syntax-entry ?\- "."  py-mode-syntax-table)
+  (modify-syntax-entry ?\/ "."  py-mode-syntax-table)
+  (modify-syntax-entry ?\< "."  py-mode-syntax-table)
+  (modify-syntax-entry ?\= "."  py-mode-syntax-table)
+  (modify-syntax-entry ?\> "."  py-mode-syntax-table)
+  (modify-syntax-entry ?\| "."  py-mode-syntax-table)
+  ;; For historical reasons, underscore is word class instead of
+  ;; symbol class.  GNU conventions say it should be symbol class, but
+  ;; there's a natural conflict between what major mode authors want
+  ;; and what users expect from `forward-word' and `backward-word'.
+  ;; Guido and I have hashed this out and have decided to keep
+  ;; underscore in word class.  If you're tempted to change it, try
+  ;; binding M-f and M-b to py-forward-into-nomenclature and
+  ;; py-backward-into-nomenclature instead.  This doesn't help in all
+  ;; situations where you'd want the different behavior
+  ;; (e.g. backward-kill-word).
+  (modify-syntax-entry ?\_ "w"  py-mode-syntax-table)
+  ;; Both single quote and double quote are string delimiters
+  (modify-syntax-entry ?\' "\"" py-mode-syntax-table)
+  (modify-syntax-entry ?\" "\"" py-mode-syntax-table)
+  ;; backquote is open and close paren
+  (modify-syntax-entry ?\` "$"  py-mode-syntax-table)
+  ;; comment delimiters
+  (modify-syntax-entry ?\# "<"  py-mode-syntax-table)
+  (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
+       (progn ,@ body)
+     (error nil)))
+
+(defsubst py-keep-region-active ()
+  "Keep the region active in XEmacs."
+  ;; Ignore byte-compiler warnings you might see.  Also note that
+  ;; FSF's Emacs 19 does it differently; its policy doesn't require us
+  ;; to take explicit action.
+  (and (boundp 'zmacs-region-stays)
+       (setq zmacs-region-stays t)))
+
+(defsubst py-point (position)
+  "Returns the value of point at certain commonly referenced POSITIONs.
+POSITION can be one of the following symbols:
+
+  bol  -- beginning of line
+  eol  -- end of line
+  bod  -- beginning of def or class
+  eod  -- end of def or class
+  bob  -- beginning of buffer
+  eob  -- end of buffer
+  boi  -- back to indentation
+  bos  -- beginning of statement
+
+This function does not modify point or mark."
+  (let ((here (point)))
+    (cond
+     ((eq position 'bol) (beginning-of-line))
+     ((eq position 'eol) (end-of-line))
+     ((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) (goto-char (point-min)))
+     ((eq position 'eob) (goto-char (point-max)))
+     ((eq position 'boi) (back-to-indentation))
+     ((eq position 'bos) (py-goto-initial-line))
+     (t (error "Unknown buffer position requested: %s" position))
+     )
+    (prog1
+        (point)
+      (goto-char here))))
+
+(defsubst py-highlight-line (from to file line)
+  (cond
+   ((fboundp 'make-extent)
+    ;; XEmacs
+    (let ((e (make-extent from to)))
+      (set-extent-property e 'mouse-face 'highlight)
+      (set-extent-property e 'py-exc-info (cons file line))
+      (set-extent-property e 'keymap py-mode-output-map)))
+   (t
+    ;; Emacs -- Please port this!
+    )
+   ))
+
+(defun py-in-literal (&optional lim)
+  "Return non-nil if point is in a Python literal (a comment or string).
+Optional argument LIM indicates the beginning of the containing form,
+i.e. the limit on how far back to scan."
+  ;; This is the version used for non-XEmacs, which has a nicer
+  ;; interface.
+  ;;
+  ;; WARNING: Watch out for infinite recursion.
+  (let* ((lim (or lim (py-point 'bod)))
+         (state (parse-partial-sexp lim (point))))
+    (cond
+     ((nth 3 state) 'string)
+     ((nth 4 state) 'comment)
+     (t nil))))
+
+;; XEmacs has a built-in function that should make this much quicker.
+;; In this case, lim is ignored
+(defun py-fast-in-literal (&optional lim)
+  "Fast version of `py-in-literal', used only by XEmacs.
+Optional LIM is ignored."
+  ;; don't have to worry about context == 'block-comment
+  (buffer-syntactic-context))
+
+(if (fboundp 'buffer-syntactic-context)
+    (defalias 'py-in-literal 'py-fast-in-literal))
+
+
+
+;; Menu definitions, only relevent if you have the easymenu.el package
+;; (standard in the latest Emacs 19 and XEmacs 19 distributions).
+(defvar py-menu nil
+  "Menu for Python Mode.
+This menu will get created automatically if you have the `easymenu'
+package.  Note that the latest X/Emacs releases contain this package.")
+
+(and (py-safe (require 'easymenu) t)
+     (easy-menu-define
+      py-menu py-mode-map "Python Mode menu"
+      '("Python"
+        ["Comment Out Region"   py-comment-region  (mark)]
+        ["Uncomment Region"     (py-comment-region (point) (mark) '(4)) (mark)]
+        "-"
+        ["Mark current block"   py-mark-block t]
+        ["Mark current def"     py-mark-def-or-class t]
+        ["Mark current class"   (py-mark-def-or-class t) t]
+        "-"
+        ["Shift region left"    py-shift-region-left (mark)]
+        ["Shift region right"   py-shift-region-right (mark)]
+        "-"
+        ["Import/reload file"   py-execute-import-or-reload t]
+        ["Execute buffer"       py-execute-buffer t]
+        ["Execute region"       py-execute-region (mark)]
+        ["Execute def or class" py-execute-def-or-class (mark)]
+        ["Execute string"       py-execute-string t]
+        ["Start interpreter..." py-shell t]
+        "-"
+        ["Go to start of block" py-goto-block-up t]
+        ["Go to start of class" (py-beginning-of-def-or-class t) t]
+        ["Move to end of class" (py-end-of-def-or-class t) t]
+        ["Move to start of def" py-beginning-of-def-or-class t]
+        ["Move to end of def"   py-end-of-def-or-class t]
+        "-"
+        ["Describe mode"        py-describe-mode t]
+        )))
+
+
+
+;; Imenu definitions
+(defvar py-imenu-class-regexp
+  (concat                               ; <<classes>>
+   "\\("                                ;
+   "^[ \t]*"                            ; newline and maybe whitespace
+   "\\(class[ \t]+[a-zA-Z0-9_]+\\)"     ; class name
+                                        ; possibly multiple superclasses
+   "\\([ \t]*\\((\\([a-zA-Z0-9_,. \t\n]\\)*)\\)?\\)"
+   "[ \t]*:"                            ; and the final :
+   "\\)"                                ; >>classes<<
+   )
+  "Regexp for Python classes for use with the Imenu package."
+  )
+
+(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
+                                        ;   function arguments...
+;;   "[ \t]*(\\([-+/a-zA-Z0-9_=,\* \t\n.()\"'#]*\\))"
+   "[ \t]*(\\([^:#]*\\))"
+   "\\)"                                ; end of def
+   "[ \t]*:"                            ; and then the :
+   "\\)"                                ; >>methods and functions<<
+   )
+  "Regexp for Python methods/functions for use with the Imenu package."
+  )
+
+(defvar py-imenu-method-no-arg-parens '(2 8)
+  "Indices into groups of the Python regexp for use with Imenu.
+
+Using these values will result in smaller Imenu lists, as arguments to
+functions are not listed.
+
+See the variable `py-imenu-show-method-args-p' for more
+information.")
+
+(defvar py-imenu-method-arg-parens '(2 7)
+  "Indices into groups of the Python regexp for use with imenu.
+Using these values will result in large Imenu lists, as arguments to
+functions are listed.
+
+See the variable `py-imenu-show-method-args-p' for more
+information.")
+
+;; Note that in this format, this variable can still be used with the
+;; imenu--generic-function. Otherwise, there is no real reason to have
+;; it.
+(defvar py-imenu-generic-expression
+  (cons
+   (concat
+    py-imenu-class-regexp
+    "\\|"                               ; or...
+    py-imenu-method-regexp
+    )
+   py-imenu-method-no-arg-parens)
+  "Generic Python expression which may be used directly with Imenu.
+Used by setting the variable `imenu-generic-expression' to this value.
+Also, see the function \\[py-imenu-create-index] for a better
+alternative for finding the index.")
+
+;; These next two variables are used when searching for the Python
+;; class/definitions. Just saving some time in accessing the
+;; generic-python-expression, really.
+(defvar py-imenu-generic-regexp nil)
+(defvar py-imenu-generic-parens nil)
+
+
+(defun py-imenu-create-index-function ()
+  "Python interface function for the Imenu package.
+Finds all Python classes and functions/methods. Calls function
+\\[py-imenu-create-index-engine].  See that function for the details
+of how this works."
+  (setq py-imenu-generic-regexp (car py-imenu-generic-expression)
+        py-imenu-generic-parens (if py-imenu-show-method-args-p
+                                    py-imenu-method-arg-parens
+                                  py-imenu-method-no-arg-parens))
+  (goto-char (point-min))
+  ;; Warning: When the buffer has no classes or functions, this will
+  ;; return nil, which seems proper according to the Imenu API, but
+  ;; causes an error in the XEmacs port of Imenu.  Sigh.
+  (py-imenu-create-index-engine nil))
+
+(defun py-imenu-create-index-engine (&optional start-indent)
+  "Function for finding Imenu definitions in Python.
+
+Finds all definitions (classes, methods, or functions) in a Python
+file for the Imenu package.
+
+Returns a possibly nested alist of the form
+
+        (INDEX-NAME . INDEX-POSITION)
+
+The second element of the alist may be an alist, producing a nested
+list as in
+
+        (INDEX-NAME . INDEX-ALIST)
+
+This function should not be called directly, as it calls itself
+recursively and requires some setup.  Rather this is the engine for
+the function \\[py-imenu-create-index-function].
+
+It works recursively by looking for all definitions at the current
+indention level.  When it finds one, it adds it to the alist.  If it
+finds a definition at a greater indentation level, it removes the
+previous definition from the alist. In its place it adds all
+definitions found at the next indentation level.  When it finds a
+definition that is less indented then the current level, it returns
+the alist it has created thus far.
+
+The optional argument START-INDENT indicates the starting indentation
+at which to continue looking for Python classes, methods, or
+functions.  If this is not supplied, the function uses the indentation
+of the first definition found."
+  (let (index-alist
+        sub-method-alist
+        looking-p
+        def-name prev-name
+        cur-indent def-pos
+        (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))
+    (while looking-p
+      (save-excursion
+        ;; used to set def-name to this value but generic-extract-name
+        ;; is new to imenu-1.14. this way it still works with
+        ;; imenu-1.11
+        ;;(imenu--generic-extract-name py-imenu-generic-parens))
+        (let ((cur-paren (if (match-beginning class-paren)
+                             class-paren def-paren)))
+          (setq def-name
+                (buffer-substring-no-properties (match-beginning cur-paren)
+                                                (match-end cur-paren))))
+        (save-match-data
+          (py-beginning-of-def-or-class 'either))
+        (beginning-of-line)
+        (setq cur-indent (current-indentation)))
+      ;; HACK: want to go to the next correct definition location.  We
+      ;; explicitly list them here but it would be better to have them
+      ;; in a list.
+      (setq def-pos
+            (or (match-beginning class-paren)
+                (match-beginning def-paren)))
+      ;; if we don't have a starting indent level, take this one
+      (or start-indent
+          (setq start-indent cur-indent))
+      ;; if we don't have class name yet, take this one
+      (or prev-name
+          (setq prev-name def-name))
+      ;; 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))
+       ;; deeper indented expression, recurse
+       ((< start-indent cur-indent)
+        ;; the point is currently on the expression we're supposed to
+        ;; start on, so go back to the last expression. The recursive
+        ;; call will find this place again and add it to the correct
+        ;; list
+        (re-search-backward py-imenu-generic-regexp (point-min) 'move)
+        (setq sub-method-alist (py-imenu-create-index-engine cur-indent))
+        (if sub-method-alist
+            ;; we put the last element on the index-alist on the start
+            ;; of the submethod alist so the user can still get to it.
+            (let ((save-elmt (pop index-alist)))
+              (push (cons prev-name
+                          (cons save-elmt sub-method-alist))
+                    index-alist))))
+       ;; found less indented expression, we're done.
+       (t
+        (setq looking-p nil)
+        (re-search-backward py-imenu-generic-regexp (point-min) t)))
+      ;; end-cond
+      (setq prev-name def-name)
+      (and looking-p
+           (setq looking-p
+                 (re-search-forward py-imenu-generic-regexp
+                                    (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 ()
+  "Major mode for editing Python files.
+To submit a problem report, enter `\\[py-submit-bug-report]' from a
+`python-mode' buffer.  Do `\\[py-describe-mode]' for detailed
+documentation.  To see what version of `python-mode' you are running,
+enter `\\[py-version]'.
+
+This mode knows about Python indentation, tokens, comments and
+continuation lines.  Paragraphs are separated by blank lines only.
+
+COMMANDS
+\\{py-mode-map}
+VARIABLES
+
+py-indent-offset\t\tindentation increment
+py-block-comment-prefix\t\tcomment string used by `comment-region'
+py-python-command\t\tshell command to invoke Python interpreter
+py-temp-directory\t\tdirectory used for temp files (if needed)
+py-beep-if-tab-change\t\tring the bell if `tab-width' is changed"
+  (interactive)
+  ;; set up local variables
+  (kill-all-local-variables)
+  (make-local-variable 'font-lock-defaults)
+  (make-local-variable 'paragraph-separate)
+  (make-local-variable 'paragraph-start)
+  (make-local-variable 'require-final-newline)
+  (make-local-variable 'comment-start)
+  (make-local-variable 'comment-end)
+  (make-local-variable 'comment-start-skip)
+  (make-local-variable 'comment-column)
+  (make-local-variable 'comment-indent-function)
+  (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
+        mode-name               "Python"
+        local-abbrev-table      python-mode-abbrev-table
+        font-lock-defaults      '(python-font-lock-keywords)
+        paragraph-separate      "^[ \t]*$"
+        paragraph-start         "^[ \t]*$"
+        require-final-newline   t
+        comment-start           "# "
+        comment-end             ""
+        comment-start-skip      "# *"
+        comment-column          40
+        comment-indent-function 'py-comment-indent-function
+        indent-region-function  'py-indent-region
+        indent-line-function    'py-indent-line
+        ;; tell add-log.el how to find the current function/method/variable
+        add-log-current-defun-function 'py-current-defun
+
+        fill-paragraph-function 'py-fill-paragraph
+        )
+  (use-local-map py-mode-map)
+  ;; add the menu
+  (if py-menu
+      (easy-menu-add py-menu))
+  ;; Emacs 19 requires this
+  (if (boundp 'comment-multi-line)
+      (setq comment-multi-line nil))
+  ;; Install Imenu if available
+  (when (py-safe (require 'imenu))
+    (setq imenu-create-index-function #'py-imenu-create-index-function)
+    (setq imenu-generic-expression py-imenu-generic-expression)
+    (if (fboundp 'imenu-add-to-menubar)
+        (imenu-add-to-menubar (format "%s-%s" "IM" mode-name)))
+    )
+  ;; Run the mode hook.  Note that py-mode-hook is deprecated.
+  (if python-mode-hook
+      (run-hooks 'python-mode-hook)
+    (run-hooks 'py-mode-hook))
+  ;; Now do the automagical guessing
+  (if py-smart-indentation
+    (let ((offset py-indent-offset))
+      ;; It's okay if this fails to guess a good value
+      (if (and (py-safe (py-guess-indent-offset))
+               (<= py-indent-offset 8)
+               (>= py-indent-offset 2))
+          (setq offset py-indent-offset))
+      (setq py-indent-offset offset)
+      ;; Only turn indent-tabs-mode off if tab-width !=
+      ;; py-indent-offset.  Never turn it on, because the user must
+      ;; have explicitly turned it off.
+      (if (/= tab-width py-indent-offset)
+          (setq indent-tabs-mode nil))
+      ))
+  ;; Set the default shell if not already set
+  (when (null py-which-shell)
+    (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 ()
+  "Returns non-nil if the current line should dedent one level."
+  (save-excursion
+    (and (progn (back-to-indentation)
+                (looking-at py-outdent-re))
+         ;; short circuit infloop on illegal construct
+         (not (bobp))
+         (progn (forward-line -1)
+                (py-goto-initial-line)
+                (back-to-indentation)
+                (while (or (looking-at py-blank-or-comment-re)
+                           (bobp))
+                  (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")
+  (self-insert-command (prefix-numeric-value arg))
+  ;; are we in a string or comment?
+  (if (save-excursion
+        (let ((pps (parse-partial-sexp (save-excursion
+                                         (py-beginning-of-def-or-class)
+                                         (point))
+                                       (point))))
+          (not (or (nth 3 pps) (nth 4 pps)))))
+      (save-excursion
+        (let ((here (point))
+              (outdent 0)
+              (indent (py-compute-indentation t)))
+          (if (and (not arg)
+                   (py-outdent-p)
+                   (= indent (save-excursion
+                               (py-next-statement -1)
+                               (py-compute-indentation t)))
+                   )
+              (setq outdent py-indent-offset))
+          ;; Don't indent, only dedent.  This assumes that any lines
+          ;; that are already dedented relative to
+          ;; py-compute-indentation were put there on purpose.  It's
+          ;; highly annoying to have `:' indent for you.  Use TAB, C-c
+          ;; C-l or C-c C-r to adjust.  TBD: Is there a better way to
+          ;; determine this???
+          (if (< (current-indentation) indent) nil
+            (goto-char here)
+            (beginning-of-line)
+            (delete-horizontal-space)
+            (indent-to (- indent outdent))
+            )))))
+
+
+;; Python subprocess utilities and filters
+(defun py-execute-file (proc filename)
+  "Send to Python interpreter process PROC \"execfile('FILENAME')\".
+Make that process's buffer visible and force display.  Also make
+comint believe the user typed this string so that
+`kill-output-from-shell' does The Right Thing."
+  (let ((curbuf (current-buffer))
+        (procbuf (process-buffer proc))
+;       (comint-scroll-to-bottom-on-output t)
+        (msg (format "## working on region in file %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)
+          (goto-char (point-max))
+          (move-marker (process-mark proc) (point))
+          (funcall (process-filter proc) proc msg))
+      (set-buffer curbuf))
+    (process-send-string proc cmd)))
+
+(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'."
+  ;;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
+        (let ((pyproc (get-buffer-process (current-buffer))))
+          (py-execute-file pyproc (car py-file-queue))))
+    ))
+
+(defun py-pdbtrack-overlay-arrow (activation)
+  "Activate or de arrow at beginning-of-line in current buffer."
+  ;; This was derived/simplified from edebug-overlay-arrow
+  (cond (activation
+         (setq overlay-arrow-position (make-marker))
+         (setq overlay-arrow-string "=>")
+         (set-marker overlay-arrow-position (py-point 'bol) (current-buffer))