;;; python.el --- silly walks for Python
-;; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Maintainer: FSF
(eval-when-compile
(require 'cl)
(require 'compile)
- (require 'comint))
+ (require 'comint)
+ (require 'hippie-exp))
(autoload 'comint-mode "comint")
"import" "in" "is" "lambda" "not" "or" "pass" "print"
"raise" "return" "try" "while" "yield"
;; Future keywords
- "as" "None")
+ "as" "None"
+ ;; Not real keywords, but close enough to be fontified as such
+ "self" "True" "False")
symbol-end)
;; Definitions
(,(rx symbol-start (group "class") (1+ space) (group (1+ (or word ?_))))
(= (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)))
+ (unless (nth 3 (syntax-ppss))
(eval-when-compile (string-to-syntax "|"))))
;; Otherwise (we're in a non-matching string) the property is
;; nil, which is OK.
See also `\\[python-guess-indent]'"
:group 'python
:type 'integer)
+(put 'python-indent 'safe-local-variable 'integerp)
(defcustom python-guess-indent t
"Non-nil means Python mode guesses `python-indent' for the buffer."
(_ (if (python-comment-line-p)
(python-skip-comments/blanks t)))
(ci (current-indentation))
- (open (python-open-block-statement-p)))
+ (open (python-open-block-statement-p))
+ opoint)
(if (and (zerop ci) (not open))
(not (goto-char point))
(catch 'done
- (while (zerop (python-next-statement))
+ (setq opoint (point))
+ (while (and (zerop (python-next-statement))
+ (not (= opoint (point))))
+ (setq opoint (point))
(when (or (and open (<= (current-indentation) ci))
(< (current-indentation) ci))
(python-skip-comments/blanks t)
is used by `run-python' et al.")
(defvar python-buffer nil
- "*The current python process buffer.
+ "*The current Python process buffer.
Commands that send text from source buffers to Python processes have
to choose a process to send to. This is determined by buffer-local
;; (define-key map "\C-c\C-f" 'python-describe-symbol)
map))
+(defvar inferior-python-mode-syntax-table
+ (let ((st (make-syntax-table python-mode-syntax-table)))
+ ;; Don't get confused by apostrophes in the process's output (e.g. if
+ ;; you execute "help(os)").
+ (modify-syntax-entry ?\' "." st)
+ ;; Maybe we should do the same for double quotes?
+ ;; (modify-syntax-entry ?\" "." st)
+ st))
+
;; Fixme: This should inherit some stuff from `python-mode', but I'm
;; not sure how much: at least some keybindings, like C-c C-f;
;; syntax?; font-locking, e.g. for triple-quoted strings?
\\{inferior-python-mode-map}"
:group 'python
- (set-syntax-table python-mode-syntax-table)
(setq mode-line-process '(":%s"))
(set (make-local-variable 'comint-input-filter) 'python-input-filter)
(add-hook 'comint-preoutput-filter-functions #'python-preoutput-filter
;; Maybe we could be more selective here.
(if (zerop (length res))
(not (bolp))
- (string-match res ".\\'"))))
+ (string-match ".\\'" res))))
;; The need for this seems to be system-dependent:
;; What is this all about, exactly? --Stef
;; (if (and (eq ?. (aref s 0)))
COMMAND should be a single statement."
;; (assert (not (string-match "\n" command)))
;; (let ((end (marker-position (process-mark (python-proc)))))
- (with-current-buffer python-buffer (goto-char (point-max)))
+ (with-current-buffer (process-buffer (python-proc))
+ (goto-char (point-max))
(compilation-forget-errors)
(python-send-string command)
- (with-current-buffer python-buffer
- (setq compilation-last-buffer (current-buffer)))
+ (setq compilation-last-buffer (current-buffer)))
;; No idea what this is for but it breaks the call to
;; compilation-fake-loc in python-send-region. -- Stef
;; Must wait until this has completed before re-setting variables below.
"Evaluate STRING in inferior Python process."
(interactive "sPython command: ")
(comint-send-string (python-proc) string)
- (comint-send-string (python-proc)
- ;; If the string is single-line or if it ends with \n,
- ;; only add a single \n, otherwise add 2, so as to
- ;; make sure we terminate the multiline instruction.
- (if (string-match "\n.+\\'" string) "\n\n" "\n")))
+ (unless (string-match "\n\\'" string)
+ ;; Make sure the text is properly LF-terminated.
+ (comint-send-string (python-proc) "\n"))
+ (when (string-match "\n[ \t].*\n?\\'" string)
+ ;; If the string contains a final indented line, add a second newline so
+ ;; as to make sure we terminate the multiline instruction.
+ (comint-send-string (python-proc) "\n")))
(defun python-send-buffer ()
"Send the current buffer to the inferior Python process."
;; isn't one for `python-buffer'.
(unless (comint-check-proc python-buffer)
(run-python nil t))
- (get-buffer-process (or (if (derived-mode-p 'inferior-python-mode)
- (current-buffer)
- python-buffer))))
+ (get-buffer-process (if (derived-mode-p 'inferior-python-mode)
+ (current-buffer)
+ python-buffer)))
(defun python-set-proc ()
"Set the default value of `python-buffer' to correspond to this buffer.
(orig (point))
(start (nth 8 syntax))
end)
- (cond ((eq t (nth 3 syntax)) ; in fenced string
- (goto-char (nth 8 syntax)) ; string start
- (condition-case () ; for unbalanced quotes
- (progn (forward-sexp)
- (setq end (point)))
- (error (setq end (point-max)))))
+ (cond ((eq t (nth 3 syntax)) ; in fenced string
+ (goto-char (nth 8 syntax)) ; string start
+ (setq end (condition-case () ; for unbalanced quotes
+ (progn (forward-sexp) (point))
+ (error (point-max)))))
((re-search-backward "\\s|\\s-*\\=" nil t) ; end of fenced
; string
(forward-char)
(condition-case ()
(progn (backward-sexp)
(setq start (point)))
- (error nil))))
+ (error (setq end nil)))))
(when end
(save-restriction
(narrow-to-region start end)
(goto-char orig)
- (fill-paragraph justify))))))
- t)
+ (let ((paragraph-separate
+ ;; Make sure that fenced-string delimiters that stand
+ ;; on their own line stay there.
+ (concat "[ \t]*['\"]+[ \t]*$\\|" paragraph-separate)))
+ (fill-paragraph justify))))))
+ t))
(defun python-shift-left (start end &optional count)
"Shift lines in region COUNT (the prefix arg) columns to the left.
\f
;;;; Skeletons
+(defcustom python-use-skeletons nil
+ "Non-nil means template skeletons will be automagically inserted.
+This happens when pressing \"if<SPACE>\", for example, to prompt for
+the if condition."
+ :type 'boolean
+ :group 'python)
+
(defvar python-skeletons nil
"Alist of named skeletons for Python mode.
Elements are of the form (NAME . EXPANDER-FUNCTION).")
(function (intern (concat "python-insert-" name))))
`(progn
(add-to-list 'python-skeletons ',(cons name function))
- (define-abbrev python-mode-abbrev-table ,name "" ',function nil t)
+ (if python-use-skeletons
+ (define-abbrev python-mode-abbrev-table ,name "" ',function nil t))
(define-skeleton ,function
,(format "Insert Python \"%s\" template." name)
,@elements)))))
> _ \n)
(defvar python-default-template "if"
- "Default template to expand by `python-insert-template'.
+ "Default template to expand by `python-expand-template'.
Updated on each expansion.")
(defun python-expand-template (name)
;; . python-font-lock-syntactic-face-function)
))
(set (make-local-variable 'parse-sexp-lookup-properties) t)
+ (set (make-local-variable 'parse-sexp-ignore-comments) t)
(set (make-local-variable 'comment-start) "# ")
(set (make-local-variable 'indent-line-function) #'python-indent-line)
(set (make-local-variable 'indent-region-function) #'python-indent-region)