Commit b7ad691a authored by Stefan Monnier's avatar Stefan Monnier
Browse files

''

parent 28421945
;;; python.el --- silly walks for Python
;;; python.el --- silly walks for Python -*- coding: iso-8859-1 -*-
;; Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
;; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Maintainer: FSF
......@@ -11,7 +11,7 @@
;; GNU Emacs 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, or (at your option)
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
......@@ -65,10 +65,10 @@
;;; Code:
(eval-when-compile
(require 'cl)
(require 'compile)
(require 'comint)
(require 'hippie-exp))
(autoload 'font-lock-fontify-region "font-lock")
(autoload 'info-lookup-maybe-add-help "info-look"))
(autoload 'comint-mode "comint")
......@@ -84,22 +84,21 @@
(add-to-list 'interpreter-mode-alist '("python" . python-mode))
;;;###autoload
(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode))
(add-to-list 'same-window-buffer-names "*Python*")
;;;; Font lock
(defvar python-font-lock-keywords
`(,(rx symbol-start
;; From v 2.4 reference.
;; From v 2.5 reference, § keywords.
;; def and class dealt with separately below
(or "and" "assert" "break" "continue" "del" "elif" "else"
(or "and" "as" "assert" "break" "continue" "del" "elif" "else"
"except" "exec" "finally" "for" "from" "global" "if"
"import" "in" "is" "lambda" "not" "or" "pass" "print"
"raise" "return" "try" "while" "yield"
;; Future keywords
"as" "None" "with"
;; Not real keywords, but close enough to be fontified as such
"self" "True" "False")
"raise" "return" "try" "while" "with" "yield")
symbol-end)
(,(rx symbol-start "None" symbol-end) ; see § Keywords in 2.5 manual
. font-lock-constant-face)
;; Definitions
(,(rx symbol-start (group "class") (1+ space) (group (1+ (or word ?_))))
(1 font-lock-keyword-face) (2 font-lock-type-face))
......@@ -151,7 +150,8 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
(cond
;; Consider property for the last char if in a fenced string.
((= n 3)
(let ((syntax (syntax-ppss)))
(let* ((font-lock-syntactic-keywords nil)
(syntax (syntax-ppss)))
(when (eq t (nth 3 syntax)) ; after unclosed fence
(goto-char (nth 8 syntax)) ; fence position
(skip-chars-forward "uUrR") ; skip any prefix
......@@ -163,8 +163,9 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
(= (match-beginning 1) (match-end 1))) ; prefix is null
(and (= n 1) ; prefix
(/= (match-beginning 1) (match-end 1)))) ; non-empty
(unless (nth 3 (syntax-ppss))
(eval-when-compile (string-to-syntax "|"))))
(let ((font-lock-syntactic-keywords nil))
(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.
)))
......@@ -192,6 +193,8 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
;;;; Keymap and syntax
(autoload 'symbol-complete "sym-comp" nil t)
(defvar python-mode-map
(let ((map (make-sparse-keymap)))
;; Mostly taken from python-mode.el.
......@@ -214,7 +217,7 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
(define-key map "\C-c\C-z" 'python-switch-to-python)
(define-key map "\C-c\C-m" 'python-load-file)
(define-key map "\C-c\C-l" 'python-load-file) ; a la cmuscheme
(substitute-key-definition 'complete-symbol 'python-complete-symbol
(substitute-key-definition 'complete-symbol 'symbol-complete
map global-map)
(define-key map "\C-c\C-i" 'python-find-imports)
(define-key map "\C-c\C-t" 'python-expand-template)
......@@ -267,7 +270,7 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
"-"
["Help on symbol" python-describe-symbol
:help "Use pydoc on symbol at point"]
["Complete symbol" python-complete-symbol
["Complete symbol" symbol-complete
:help "Complete (qualified) symbol before point"]
["Update imports" python-find-imports
:help "Update list of top-level imports for completion"]))
......@@ -348,7 +351,7 @@ comments and strings, or that point is within brackets/parens."
(error nil))))))))
(defun python-comment-line-p ()
"Return non-nil if current line has only a comment."
"Return non-nil iff current line has only a comment."
(save-excursion
(end-of-line)
(when (eq 'comment (syntax-ppss-context (syntax-ppss)))
......@@ -356,7 +359,7 @@ comments and strings, or that point is within brackets/parens."
(looking-at (rx (or (syntax comment-start) line-end))))))
(defun python-blank-line-p ()
"Return non-nil if current line is blank."
"Return non-nil iff current line is blank."
(save-excursion
(beginning-of-line)
(looking-at "\\s-*$")))
......@@ -374,7 +377,7 @@ BOS non-nil means point is known to be at beginning of statement."
(save-excursion
(unless bos (python-beginning-of-statement))
(looking-at (rx (and (or "if" "else" "elif" "while" "for" "def"
"class" "try" "except" "finally" "with")
"class" "try" "except" "finally")
symbol-end)))))
(defun python-close-block-statement-p (&optional bos)
......@@ -404,19 +407,18 @@ The criteria are that the line isn't a comment or in string and
;;;; Indentation.
(defcustom python-indent 4
"Number of columns for a unit of indentation in Python mode.
"*Number of columns for a unit of indentation in Python mode.
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."
"*Non-nil means Python mode guesses `python-indent' for the buffer."
:type 'boolean
:group 'python)
(defcustom python-indent-string-contents t
"Non-nil means indent contents of multi-line strings together.
"*Non-nil means indent contents of multi-line strings together.
This means indent them the same as the preceding non-blank line.
Otherwise preserve their indentation.
......@@ -435,7 +437,7 @@ are always indented in lines with preceding comments."
:group 'python)
(defcustom python-continuation-offset 4
"Number of columns of additional indentation for continuation lines.
"*Number of columns of additional indentation for continuation lines.
Continuation lines follow a backslash-terminated line starting a
statement."
:group 'python
......@@ -461,7 +463,7 @@ Set `python-indent' locally to the value guessed."
(let ((initial (current-indentation)))
(if (zerop (python-next-statement))
(setq indent (- (current-indentation) initial)))
(if (and indent (>= indent 2) (<= indent 8)) ; sanity check
(if (and (>= indent 2) (<= indent 8)) ; sanity check
(setq done t))))))
(when done
(when (/= indent (default-value 'python-indent))
......@@ -552,39 +554,40 @@ Set `python-indent' locally to the value guessed."
((looking-at (rx (0+ space) (syntax comment-start)
(not (any " \t\n")))) ; non-indentable comment
(current-indentation))
(t (if python-honour-comment-indentation
;; Back over whitespace, newlines, non-indentable comments.
(catch 'done
(while t
(if (cond ((bobp))
;; not at comment start
((not (forward-comment -1))
(python-beginning-of-statement)
t)
;; trailing comment
((/= (current-column) (current-indentation))
(python-beginning-of-statement)
t)
;; indentable comment like python-mode.el
((and (looking-at (rx (syntax comment-start)
(or space line-end)))
(/= 0 (current-column)))))
(throw 'done t)))))
(python-indentation-levels)
;; Prefer to indent comments with an immediately-following
;; statement, e.g.
;; ...
;; # ...
;; def ...
(when (and (> python-indent-list-length 1)
(python-comment-line-p))
(forward-line)
(unless (python-comment-line-p)
(let ((elt (assq (current-indentation) python-indent-list)))
(setq python-indent-list
(nconc (delete elt python-indent-list)
(list elt))))))
(caar (last python-indent-list)))))))
(t (let ((point (point)))
(if python-honour-comment-indentation
;; Back over whitespace, newlines, non-indentable comments.
(catch 'done
(while t
(if (cond ((bobp))
;; not at comment start
((not (forward-comment -1))
(python-beginning-of-statement)
t)
;; trailing comment
((/= (current-column) (current-indentation))
(python-beginning-of-statement)
t)
;; indentable comment like python-mode.el
((and (looking-at (rx (syntax comment-start)
(or space line-end)))
(/= 0 (current-column)))))
(throw 'done t)))))
(python-indentation-levels)
;; Prefer to indent comments with an immediately-following
;; statement, e.g.
;; ...
;; # ...
;; def ...
(when (and (> python-indent-list-length 1)
(python-comment-line-p))
(forward-line)
(unless (python-comment-line-p)
(let ((elt (assq (current-indentation) python-indent-list)))
(setq python-indent-list
(nconc (delete elt python-indent-list)
(list elt))))))
(caar (last python-indent-list))))))))
;;;; Cycling through the possible indentations with successive TABs.
......@@ -759,13 +762,13 @@ reached start of buffer."
(let ((ci (current-indentation))
(def-re (rx line-start (0+ space) (or "def" "class") (1+ space)
(group (1+ (or word (syntax symbol))))))
found lep) ;; def-line
found lep def-line)
(if (python-comment-line-p)
(setq ci most-positive-fixnum))
(while (and (not (bobp)) (not found))
;; Treat bol at beginning of function as outside function so
;; that successive C-M-a makes progress backwards.
;;(setq def-line (looking-at def-re))
(setq def-line (looking-at def-re))
(unless (bolp) (end-of-line))
(setq lep (line-end-position))
(if (and (re-search-backward def-re nil 'move)
......@@ -777,7 +780,7 @@ reached start of buffer."
;; Not sure why it was like this -- fails in case of
;; last internal function followed by first
;; non-def statement of the main body.
;;(and def-line (= in ci))
;; (and def-line (= in ci))
(= in ci)
(< in ci)))
(not (python-in-string/comment)))
......@@ -850,7 +853,7 @@ multi-line bracketed expressions."
"Skip out of any nested brackets.
Skip forward if FORWARD is non-nil, else backward.
If SYNTAX is non-nil it is the state returned by `syntax-ppss' at point.
Return non-nil if skipping was done."
Return non-nil iff skipping was done."
(let ((depth (syntax-ppss-depth (or syntax (syntax-ppss))))
(forward (if forward -1 1)))
(unless (zerop depth)
......@@ -883,13 +886,10 @@ On a comment line, go to end of line."
nil)
((eq 'string (syntax-ppss-context s))
;; Go to start of string and skip it.
(let ((pos (point)))
(goto-char (nth 8 s))
(condition-case () ; beware invalid syntax
(progn (forward-sexp) t)
;; If there's a mismatched string, make sure
;; we still overall move *forward*.
(error (goto-char pos) (end-of-line)))))
(goto-char (nth 8 s))
(condition-case () ; beware invalid syntax
(progn (forward-sexp) t)
(error (end-of-line))))
((python-skip-out t s))))
(end-of-line))
(unless comment
......@@ -988,7 +988,7 @@ don't move and return nil. Otherwise return t."
(if (and (zerop ci) (not open))
(not (goto-char point))
(catch 'done
(while (zerop (python-next-statement))
(while (zerop (python-next-statement))
(when (or (and open (<= (current-indentation) ci))
(< (current-indentation) ci))
(python-skip-comments/blanks t)
......@@ -996,16 +996,7 @@ don't move and return nil. Otherwise return t."
(throw 'done t)))))))
(setq arg (1- arg)))
(zerop arg)))
(defvar python-which-func-length-limit 40
"Non-strict length limit for `python-which-func' output.")
(defun python-which-func ()
(let ((function-name (python-current-defun python-which-func-length-limit)))
(set-text-properties 0 (length function-name) nil function-name)
function-name))
;;;; Imenu.
(defvar python-recursing)
......@@ -1025,10 +1016,8 @@ precede it)."
;; _with_ this, imenu doesn't immediately work; I can't figure out
;; what's going on, but it must be something to do with timers in
;; font-lock.
;; This can't be right, especially not when jit-lock is not used. --Stef
;; (unless (get-text-property (1- (point-max)) 'fontified)
;; (font-lock-fontify-region (point-min) (point-max)))
)
(unless (get-text-property (1- (point-max)) 'fontified)
(font-lock-fontify-region (point-min) (point-max))))
(let (index-alist) ; accumulated value to return
(while (re-search-forward
(rx line-start (0+ space) ; leading space
......@@ -1083,13 +1072,15 @@ just insert a single colon."
(defun python-backspace (arg)
"Maybe delete a level of indentation on the current line.
Do so if point is at the end of the line's indentation.
Do so if point is at the end of the line's indentation outside
strings and comments.
Otherwise just call `backward-delete-char-untabify'.
Repeat ARG times."
(interactive "*p")
(if (or (/= (current-indentation) (current-column))
(bolp)
(python-continuation-line-p))
(python-continuation-line-p)
(python-in-string/comment))
(backward-delete-char-untabify arg)
;; Look for the largest valid indentation which is smaller than
;; the current indentation.
......@@ -1110,7 +1101,7 @@ Repeat ARG times."
;;;; pychecker
(defcustom python-check-command "pychecker --stdlib"
"Command used to check a Python file."
"*Command used to check a Python file."
:type 'string
:group 'python)
......@@ -1142,7 +1133,7 @@ See `python-check-command' for the default."
;; Fixme: Make sure we can work with IPython.
(defcustom python-python-command "python"
"Shell command to run Python interpreter.
"*Shell command to run Python interpreter.
Any arguments can't contain whitespace.
Note that IPython may not work properly; it must at least be used
with the `-cl' flag, i.e. use `ipython -cl'."
......@@ -1150,7 +1141,7 @@ with the `-cl' flag, i.e. use `ipython -cl'."
:type 'string)
(defcustom python-jython-command "jython"
"Shell command to run Jython interpreter.
"*Shell command to run Jython interpreter.
Any arguments can't contain whitespace."
:group 'python
:type 'string)
......@@ -1162,7 +1153,7 @@ modified by the user. Additional arguments are added when the command
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
......@@ -1190,6 +1181,10 @@ local value.")
1 2)
(,(rx " in file " (group (1+ not-newline)) " on line "
(group (1+ digit)))
1 2)
;; pdb stack trace
(,(rx line-start "> " (group (1+ (not (any "(\"<"))))
"(" (group (1+ digit)) ")" (1+ (not (any "("))) "()")
1 2))
"`compilation-error-regexp-alist' for inferior Python.")
......@@ -1199,7 +1194,7 @@ local value.")
(define-key map "\C-c\C-l" 'python-load-file)
(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 provided we have a normal prompt,
;; Python process even at the prompt iff we have a normal prompt,
;; i.e. '>>> ' and not '... '. See the comment before
;; python-send-region. Fixme: uncomment these if we address that.
......@@ -1245,13 +1240,13 @@ For running multiple processes in multiple buffers, see `run-python' and
;; Still required by `comint-redirect-send-command', for instance
;; (and we need to match things like `>>> ... >>> '):
(set (make-local-variable 'comint-prompt-regexp)
(rx line-start (1+ (and (repeat 3 (any ">.")) " "))))
(rx line-start (1+ (and (or (repeat 3 (any ">.")) "(Pdb)") " "))))
(set (make-local-variable 'compilation-error-regexp-alist)
python-compilation-regexp-alist)
(compilation-shell-minor-mode 1))
(defcustom inferior-python-filter-regexp "\\`\\s-*\\S-?\\S-?\\s-*\\'"
"Input matching this regexp is not saved on the history list.
"*Input matching this regexp is not saved on the history list.
Default ignores all inputs of 0, 1, or 2 non-blank characters."
:type 'regexp
:group 'python)
......@@ -1274,57 +1269,46 @@ Don't save anything for STR matching `inferior-python-filter-regexp'."
(defvar python-preoutput-result nil
"Data from last `_emacs_out' line seen by the preoutput filter.")
(defvar python-preoutput-continuation nil
"If non-nil, funcall this when `python-preoutput-filter' sees `_emacs_ok'.")
(defvar python-preoutput-leftover nil)
(defvar python-preoutput-skip-next-prompt nil)
;; Using this stops us getting lines in the buffer like
;; >>> ... ... >>>
;; Also look for (and delete) an `_emacs_ok' string and call
;; `python-preoutput-continuation' if we get it.
(defun python-preoutput-filter (s)
"`comint-preoutput-filter-functions' function: ignore prompts not at bol."
(when python-preoutput-leftover
(setq s (concat python-preoutput-leftover s))
(setq python-preoutput-leftover nil))
(let ((start 0)
(res ""))
;; First process whole lines.
(while (string-match "\n" s start)
(let ((line (substring s start (setq start (match-end 0)))))
;; Skip prompt if needed.
(when (and python-preoutput-skip-next-prompt
(string-match comint-prompt-regexp line))
(setq python-preoutput-skip-next-prompt nil)
(setq line (substring line (match-end 0))))
;; Recognize special _emacs_out lines.
(if (and (string-match "\\`_emacs_out \\(.*\\)\n\\'" line)
(local-variable-p 'python-preoutput-result))
(progn
(setq python-preoutput-result (match-string 1 line))
(set (make-local-variable 'python-preoutput-skip-next-prompt) t))
(setq res (concat res line)))))
;; Then process the remaining partial line.
(unless (zerop start) (setq s (substring s start)))
(cond ((and (string-match comint-prompt-regexp s)
;; Drop this prompt if it follows an _emacs_out...
(or python-preoutput-skip-next-prompt
;; ... or if it's not gonna be inserted at BOL.
;; Maybe we could be more selective here.
(if (zerop (length res))
(not (bolp))
(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)))
;; (accept-process-output (get-buffer-process (current-buffer)) 1))
(setq python-preoutput-skip-next-prompt nil)
res)
((let ((end (min (length "_emacs_out ") (length s))))
(eq t (compare-strings s nil end "_emacs_out " nil end)))
;; The leftover string is a prefix of _emacs_out so we don't know
;; yet whether it's an _emacs_out or something else: wait until we
;; get more output so we can resolve this ambiguity.
(set (make-local-variable 'python-preoutput-leftover) s)
res)
(t (concat res s)))))
(cond ((and (string-match (rx string-start (repeat 3 (any ".>"))
" " string-end)
s)
(/= (let ((inhibit-field-text-motion t))
(line-beginning-position))
(point)))
;; The need for this seems to be system-dependent:
(if (and (eq ?. (aref s 0)))
(accept-process-output (get-buffer-process (current-buffer)) 1))
"")
((string= s "_emacs_ok\n")
(when python-preoutput-continuation
(funcall python-preoutput-continuation)
(setq python-preoutput-continuation nil))
"")
((string-match "_emacs_out \\(.*\\)\n" s)
(setq python-preoutput-result (match-string 1 s))
"")
((string-match ".*\n" s)
s)
((or (eq t (compare-strings s nil nil "_emacs_ok\n" nil (length s)))
(let ((end (min (length "_emacs_out ") (length s))))
(eq t (compare-strings s nil end "_emacs_out " nil end))))
(setq python-preoutput-leftover s)
"")
(t s)))
(autoload 'comint-check-proc "comint")
......@@ -1354,59 +1338,48 @@ buffer for a list of commands.)"
;; (not a name) in Python buffers from which `run-python' &c is
;; invoked. Would support multiple processes better.
(when (or new (not (comint-check-proc python-buffer)))
(with-current-buffer
(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-separator path)))
process-environment)))
(apply 'make-comint-in-buffer "Python"
(if new (generate-new-buffer "*Python*") "*Python*")
(car cmdlist) nil (cdr cmdlist)))
(setq-default python-buffer (current-buffer))
(setq python-buffer (current-buffer))
(save-current-buffer
(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-in-buffer "Python"
(generate-new-buffer "*Python*")
(car cmdlist) nil (cdr cmdlist)))
(setq-default python-buffer (current-buffer))
(setq python-buffer (current-buffer)))
(accept-process-output (get-buffer-process python-buffer) 5)
(inferior-python-mode)
;; Load function definitions we need.
;; Before the preoutput function was used, this was done via -c in
;; cmdlist, but that loses the banner and doesn't run the startup
;; file. The code might be inline here, but there's enough that it
;; seems worth putting in a separate file, and it's probably cleaner
;; to put it in a module.
;; Ensure we're at a prompt before doing anything else.
(python-send-receive "import emacs; print '_emacs_out ()'")))
(if (derived-mode-p 'python-mode)
(inferior-python-mode)))
(if (eq 'python-mode major-mode)
(setq python-buffer (default-value 'python-buffer))) ; buffer-local
;; Load function definitions we need.
;; Before the preoutput function was used, this was done via -c in
;; cmdlist, but that loses the banner and doesn't run the startup
;; file. The code might be inline here, but there's enough that it
;; seems worth putting in a separate file, and it's probably cleaner
;; to put it in a module.
(python-send-string "import emacs")
;; Ensure we're at a prompt before doing anything else.
(python-send-receive "print '_emacs_out ()'")
;; Without this, help output goes into the inferior python buffer if
;; the process isn't already running.
(sit-for 1 t) ;Should we use accept-process-output instead? --Stef
(sit-for 1 nil t)
(unless noshow (pop-to-buffer python-buffer t)))
;; Fixme: We typically lose if the inferior isn't in the normal REPL,
;; e.g. prompt is `help> '. Probably raise an error if the form of
;; the prompt is unexpected. Actually, it needs to be `>>> ', not
;; `... ', i.e. we're not inputting a block &c. However, this may not
;; be the place to check it, e.g. we might actually want to send
;; commands having set up such a state.
(defun python-send-command (command)
"Like `python-send-string' but resets `compilation-shell-minor-mode'.
COMMAND should be a single statement."
;; (assert (not (string-match "\n" command)))
;; (let ((end (marker-position (process-mark (python-proc)))))
(with-current-buffer (process-buffer (python-proc))
(goto-char (point-max))
(compilation-forget-errors)
(python-send-string command)
(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.
;; (python-send-receive "print '_emacs_out ()'")
;; (with-current-buffer python-buffer
;; (set-marker compilation-parsing-end end))
) ;;)
"Like `python-send-string' but resets `compilation-shell-minor-mode'."
(when (python-check-comint-prompt)
(let ((end (marker-position (process-mark (python-proc)))))
(with-current-buffer python-buffer (goto-char (point-max)))
(compilation-forget-errors)
(python-send-string command)
;; Must wait until this has completed before re-setting variables below.
(python-send-receive "print '_emacs_out ()'")
(with-current-buffer python-buffer
(set-marker compilation-parsing-end end)
(setq compilation-last-buffer (current-buffer))))))
(defun python-send-region (start end)
"Send the region to the inferior Python process."
......@@ -1448,13 +1421,7 @@ COMMAND should be a single statement."
"Evaluate STRING in inferior Python process."
(interactive "sPython command: ")
(comint-send-string (python-proc) string)
(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")))
(comint-send-string (python-proc) "\n\n"))
(defun python-send-buffer ()
"Send the current buffer to the inferior Python process."
......@@ -1486,7 +1453,7 @@ Then switch to the process buffer."
(python-switch-to-python t))
(defcustom python-source-modes '(python-mode jython-mode)
"Used to determine if a buffer contains Python source code.
"*Used to determine if a buffer contains Python source code.
If a file is loaded into a buffer that is in one of these major modes,
it is considered Python source by `python-load-file', which uses the
value to determine defaults."
......@@ -1529,9 +1496,9 @@ See variable `python-buffer'. Starts a new process if necessary."