;;; 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
(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
;; 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.
(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))))))
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.
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 ()
(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,
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.)"
;; (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
(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."
"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."
(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.
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?
;; 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
(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?