]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/python.el
Revision: miles@gnu.org--gnu-2005/emacs--unicode--0--patch-24
[gnu-emacs] / lisp / progmodes / python.el
index 214b6f0e24cf61ef72434cc7fa2ca062dfb4fb66..745bc57a9b07715d92cb8fd9364a8a592874b2b1 100644 (file)
@@ -1,6 +1,6 @@
 ;;; python.el --- silly walks for Python
 
-;; Copyright (C) 2003, 04  Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004  Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Maintainer: FSF
@@ -72,7 +72,7 @@
 (defgroup python nil
   "Silly walks in the Python language"
   :group 'languages
-  :version "21.4"
+  :version "22.1"
   :link '(emacs-commentary-link "python"))
 \f
 ;;;###autoload
 (defconst python-font-lock-syntactic-keywords
   ;; Make outer chars of matching triple-quote sequences into generic
   ;; string delimiters.  Fixme: Is there a better way?
-  `((,(rx (and (group (optional (any "uUrR"))) ; prefix gets syntax property
+  `((,(rx (and (or line-start buffer-start (not (syntax escape))) ; avoid escaped
+                                                      ; leading quote
+              (group (optional (any "uUrR"))) ; prefix gets syntax property
               (optional (any "rR"))    ; possible second prefix
               (group (syntax string-quote))    ; maybe gets property
               (backref 2)                      ; per first quote
@@ -130,32 +132,31 @@ Used for syntactic keywords.  N is the match number (1, 2 or 3)."
   ;;  ur"""ar""" x='"' # """
   ;; x = ''' """ ' a
   ;; '''
-  ;; x '"""' x
+  ;; x '"""' x """ \"""" x
   (save-excursion
     (goto-char (match-beginning 0))
-    (unless (eq ?\\ (char-before))
-      (cond
-       ;; Consider property for the last char if in a fenced string.
-       ((= n 3)
-       (let ((syntax (syntax-ppss)))
-         (when (eq t (nth 3 syntax))    ; after unclosed fence
-           (goto-char (nth 8 syntax))   ; fence position
-           ;; Skip any prefix.
-           (if (memq (char-after) '(?u ?U ?R ?r))
-               (skip-chars-forward "uUrR"))
-           ;; Is it a matching sequence?
-           (if (eq (char-after) (char-after (match-beginning 2)))
-               (eval-when-compile (string-to-syntax "|"))))))
-       ;; Consider property for initial char, accounting for prefixes.
-       ((or (and (= n 2)                               ; not prefix
-                (= (match-beginning 1) (match-end 1))) ; prefix is null
-           (and (= n 1)                                ; prefix
-                (/= (match-beginning 1) (match-end 1)))) ; non-empty
-       (unless (eq 'string (syntax-ppss-context (syntax-ppss)))
-         (eval-when-compile (string-to-syntax "|")))))
-      ;; Otherwise (we're in a non-matching string) the property is
-      ;; nil, which is OK.
-      )))
+    (cond
+     ;; Consider property for the last char if in a fenced string.
+     ((= n 3)
+      (let ((syntax (syntax-ppss)))
+       (when (eq t (nth 3 syntax))     ; after unclosed fence
+         (goto-char (nth 8 syntax))    ; fence position
+         ;; Skip any prefix.
+         (if (memq (char-after) '(?u ?U ?R ?r))
+             (skip-chars-forward "uUrR"))
+         ;; Is it a matching sequence?
+         (if (eq (char-after) (char-after (match-beginning 2)))
+             (eval-when-compile (string-to-syntax "|"))))))
+     ;; Consider property for initial char, accounting for prefixes.
+     ((or (and (= n 2)                 ; not prefix
+              (= (match-beginning 1) (match-end 1))) ; prefix is null
+         (and (= n 1)                  ; prefix
+              (/= (match-beginning 1) (match-end 1)))) ; non-empty
+      (unless (eq 'string (syntax-ppss-context (syntax-ppss)))
+       (eval-when-compile (string-to-syntax "|"))))
+     ;; Otherwise (we're in a non-matching string) the property is
+     ;; nil, which is OK.
+     )))
 
 ;; This isn't currently in `font-lock-defaults' as probably not worth
 ;; it -- we basically only mess with a few normally-symbol characters.
@@ -297,10 +298,9 @@ comments and strings, or that the bracket/paren nesting depth is nonzero."
               (syntax-ppss (line-beginning-position)))))))
 
 (defun python-comment-line-p ()
-  "Return non-nil if current line has only a comment or is blank."
+  "Return non-nil iff current line has only a comment."
   (save-excursion
     (end-of-line)
-    ;; FIXME: This looks wrong because it returns nil for empty lines.  --Stef
     (when (eq 'comment (syntax-ppss-context (syntax-ppss)))
       (back-to-indentation)
       (looking-at (rx (or (syntax comment-start) line-end))))))
@@ -324,7 +324,8 @@ BOS non-nil means point is known to be at beginning of statement."
                                     line-end))
                            (save-excursion (python-end-of-statement))
                            t)
-        (not (python-in-string/comment)))))
+        (not (progn (goto-char (match-beginning 0))
+                    (python-in-string/comment))))))
 
 (defun python-close-block-statement-p (&optional bos)
   "Return non-nil if current line is a statement closing a block.
@@ -710,16 +711,17 @@ Accounts for continuation lines, multi-line strings, and multi-line bracketed
 expressions."
   (beginning-of-line)
   (python-beginning-of-string)
-  (while (python-continuation-line-p)
-    (beginning-of-line)
-    (if (python-backslash-continuation-line-p)
-       (while (python-backslash-continuation-line-p)
-         (forward-line -1))
-      (python-beginning-of-string)
-      ;; Skip forward out of nested brackets.
-      (condition-case ()               ; beware invalid syntax
-         (progn (backward-up-list (syntax-ppss-depth (syntax-ppss))) t)
-       (error (end-of-line)))))
+  (catch 'foo
+    (while (python-continuation-line-p)
+      (beginning-of-line)
+      (if (python-backslash-continuation-line-p)
+         (while (python-backslash-continuation-line-p)
+           (forward-line -1))
+       (python-beginning-of-string)
+       ;; Skip forward out of nested brackets.
+       (condition-case ()              ; beware invalid syntax
+           (progn (backward-up-list (syntax-ppss-depth (syntax-ppss))) t)
+         (error (throw 'foo nil))))))
   (back-to-indentation))
 
 (defun python-end-of-statement ()
@@ -1025,7 +1027,6 @@ et al.")
   (let ((map (make-sparse-keymap)))
     ;; This will inherit from comint-mode-map.
     (define-key map "\C-c\C-l" 'python-load-file)
-    (define-key map "\C-c\C-z" 'python-switch-to-python) ;What for?  --Stef
     (define-key map "\C-c\C-v" 'python-check)
     ;; Note that we _can_ still use these commands which send to the
     ;; Python process even at the prompt iff we have a normal prompt,
@@ -1127,7 +1128,7 @@ CMD is the Python command to run.  NOSHOW non-nil means don't show the
 buffer automatically.
 If there is a process already running in `*Python*', switch to
 that buffer.  Interactively, a prefix arg allows you to edit the initial
-command line (default is `python-command'); `-i' etc. args will be added
+command line (default is `python-command'); `-i' etc.  args will be added
 to this as appropriate.  Runs the hook `inferior-python-mode-hook'
 \(after the `comint-mode-hook' is run).
 \(Type \\[describe-mode] in the process buffer for a list of commands.)"
@@ -1140,13 +1141,15 @@ to this as appropriate.  Runs the hook `inferior-python-mode-hook'
   ;; (not a name) in Python buffers from which `run-python' &c is
   ;; invoked.  Would support multiple processes better.
   (unless (comint-check-proc python-buffer)
-    (let ((cmdlist (append (python-args-to-list cmd) '("-i")))
-         (process-environment          ; to import emacs.py
-          (push (concat "PYTHONPATH=" data-directory)
-                process-environment)))
+    (let* ((cmdlist (append (python-args-to-list cmd) '("-i")))
+          (path (getenv "PYTHONPATH"))
+          (process-environment         ; to import emacs.py
+           (cons (concat "PYTHONPATH=" data-directory
+                         (if path (concat ":" path)))
+                 process-environment)))
       (set-buffer (apply 'make-comint "Python" (car cmdlist) nil
                         (cdr cmdlist)))
-      (setq python-buffer "*Python*"))
+      (setq python-buffer (buffer-name)))
     (inferior-python-mode)
     ;; Load function defintions we need.
     ;; Before the preoutput function was used, this was done via -c in
@@ -1202,13 +1205,12 @@ to this as appropriate.  Runs the hook `inferior-python-mode-hook'
        (set-marker orig-start (line-beginning-position 0)))
       (write-region "if True:\n" nil f nil 'nomsg))
     (write-region start end f t 'nomsg)
-    (let ((proc (python-proc)))                ;Make sure we're running a process.
-      (with-current-buffer python-buffer
-       (python-send-command command)
-       ;; Tell compile.el to redirect error locations in file `f' to
-       ;; positions past marker `orig-start'.  It has to be done *after*
-       ;; python-send-command's call to compilation-forget-errors.
-       (compilation-fake-loc orig-start f)))))
+    (with-current-buffer (process-buffer (python-proc))        ;Runs python if needed.
+      (python-send-command command)
+      ;; Tell compile.el to redirect error locations in file `f' to
+      ;; positions past marker `orig-start'.  It has to be done *after*
+      ;; python-send-command's call to compilation-forget-errors.
+      (compilation-fake-loc orig-start f))))
 
 (defun python-send-string (string)
   "Evaluate STRING in inferior Python process."
@@ -1233,15 +1235,11 @@ to this as appropriate.  Runs the hook `inferior-python-mode-hook'
   "Switch to the Python process buffer.
 With prefix arg, position cursor at end of buffer."
   (interactive "P")
-  (if (get-buffer python-buffer)
-      (pop-to-buffer python-buffer)
-    (error "No current process buffer.  See variable `python-buffer'"))
+  (pop-to-buffer (process-buffer (python-proc))) ;Runs python if needed.
   (when eob-p
     (push-mark)
     (goto-char (point-max))))
 
-(add-to-list 'debug-ignored-errors "^No current process buffer.")
-
 (defun python-send-region-and-go (start end)
   "Send the region to the inferior Python process.
 Then switch to the process buffer."
@@ -1273,18 +1271,16 @@ module-qualified names."
   (comint-check-source file-name)     ; Check to see if buffer needs saving.
   (setq python-prev-dir/file (cons (file-name-directory file-name)
                                   (file-name-nondirectory file-name)))
-  (let ((proc (python-proc)))          ;Make sure we have a process.
-    (with-current-buffer python-buffer
-      ;; Fixme: I'm not convinced by this logic from python-mode.el.
-      (python-send-command
-       (if (string-match "\\.py\\'" file-name)
-          ;; Fixme: make sure the directory is in the path list
-          (let ((module (file-name-sans-extension
-                         (file-name-nondirectory file-name))))
-            (format "emacs.eimport(%S,%S)"
-                    module (file-name-directory file-name)))
-        (format "execfile(%S)" file-name)))
-      (message "%s loaded" file-name))))
+  (with-current-buffer (process-buffer (python-proc)) ;Runs python if needed.
+    ;; Fixme: I'm not convinced by this logic from python-mode.el.
+    (python-send-command
+     (if (string-match "\\.py\\'" file-name)
+        (let ((module (file-name-sans-extension
+                       (file-name-nondirectory file-name))))
+          (format "emacs.eimport(%S,%S)"
+                  module (file-name-directory file-name)))
+       (format "execfile(%S)" file-name)))
+    (message "%s loaded" file-name)))
 
 ;; Fixme: If we need to start the process, wait until we've got the OK
 ;; from the startup.
@@ -1309,6 +1305,7 @@ See variable `python-buffer'.  Starts a new process if necessary."
 Otherwise inherits from `python-mode-syntax-table'.")
 
 (defvar view-return-to-alist)
+(eval-when-compile (autoload 'help-buffer "help-fns"))
 
 ;; Fixme: Should this actually be used instead of info-look, i.e. be
 ;; bound to C-h S?  Can we use other pydoc stuff before python 2.2?
@@ -1394,7 +1391,8 @@ Used with `eval-after-load'."
                ;; Don't use `info' because it would pop-up a *info* buffer.
                (with-no-warnings
                 (Info-goto-node (format "(python%s-lib)Miscellaneous Index"
-                                        version)))
+                                        version))
+                t)
              (error nil)))))
     (info-lookup-maybe-add-help
      :mode 'python-mode
@@ -1714,7 +1712,7 @@ lines count as headers.
   (set (make-local-variable 'indent-line-function) #'python-indent-line)
   (set (make-local-variable 'paragraph-start) "\\s-*$")
   (set (make-local-variable 'fill-paragraph-function) 'python-fill-paragraph)
-  (set (make-local-variable 'require-final-newline) t)
+  (set (make-local-variable 'require-final-newline) mode-require-final-newline)
   (set (make-local-variable 'add-log-current-defun-function)
        #'python-current-defun)
   ;; Fixme: Generalize to do all blocks?