# HG changeset patch # User Stefan Monnier # Date 1156546154 0 # Node ID 9d3a9b609c0464f6fc2af92e1d3db01a4e6a7e5a # Parent 8885920493337c75a77eb7b1d80e2325271045fe (python-preoutput-skip-next-prompt): New var. (python-preoutput-continuation): Remove. (python-preoutput-filter): Simplify correspondingly. Remove handling of _emacs_ok. Make sure we skip _emacs_out's prompts. Loop around to catch embedded _emacs_out output. (run-python): Send the import&print command on a single line. (python-send-command): Send command&print on a single line. (python-send-string): Only add double \n if needed. (python-send-receive): Loop until the result comes. (python-mode-running): Defvar it. (python-setup-brm): Remove unused var `menu'. Only bind py-mode-map and `features' around brm-init. (python-calculate-indentation): Remove unused var `point'. (python-beginning-of-defun): Remove unused var `def-line'. diff -r 888592049333 -r 9d3a9b609c04 lisp/ChangeLog --- a/lisp/ChangeLog Fri Aug 25 22:01:34 2006 +0000 +++ b/lisp/ChangeLog Fri Aug 25 22:49:14 2006 +0000 @@ -1,36 +1,56 @@ +2006-08-25 Stefan Monnier + + * progmodes/python.el (python-preoutput-skip-next-prompt): New var. + (python-preoutput-continuation): Remove. + (python-preoutput-filter): Simplify correspondingly. + Remove handling of _emacs_ok. Make sure we skip _emacs_out's prompts. + Loop around to catch embedded _emacs_out output. + (run-python): Send the import&print command on a single line. + (python-send-command): Send command&print on a single line. + (python-send-string): Only add double \n if needed. + (python-send-receive): Loop until the result comes. + (python-mode-running): Defvar it. + (python-setup-brm): Remove unused var `menu'. + Only bind py-mode-map and `features' around brm-init. + (python-calculate-indentation): Remove unused var `point'. + (python-beginning-of-defun): Remove unused var `def-line'. + 2006-08-25 Richard Stallman * kmacro.el (kmacro-repeat-on-last-key): Doc fix. 2006-08-25 Michael Kifer - - * viper.el (viper-set-hooks): use frame bindings for + + * viper.el (viper-set-hooks): Use frame bindings for viper-vi-state-cursor-color. - (viper-non-hook-settings): don't set default + (viper-non-hook-settings): Don't set default mode-line-buffer-identification. - - * viper-util.el (viper-set-cursor-color-according-to-state): new - function. - (viper-set-cursor-color-according-to-state, - viper-get-saved-cursor-color-in-replace-mode, - viper-get-saved-cursor-color-in-insert-mode): make conditional on + + * viper-util.el (viper-set-cursor-color-according-to-state): New fun. + (viper-set-cursor-color-according-to-state) + (viper-get-saved-cursor-color-in-replace-mode) + (viper-get-saved-cursor-color-in-insert-mode): Make conditional on viper-emacs-state-cursor-color. - - * viper-cmd.el (viper-envelop-ESC-key): bug fix. - (viper-undo): use point if undo-beg-posn is nil. - (viper-insert-state-post-command-sentinel,viper-change-state-to-emacs, - viper-after-change-undo-hook): don't use + + * viper-cmd.el (viper-envelop-ESC-key): Bug fix. + (viper-undo): Use point if undo-beg-posn is nil. + (viper-insert-state-post-command-sentinel, viper-change-state-to-emacs) + (viper-after-change-undo-hook): Don't use viper-emacs-state-cursor-color by default. - (viper-undo): more sensible positioning after undo. - - * viper-ex.el (ex-splice-args-in-1-letr-cmd): got rid of caddr. - (viper-emacs-state-cursor-color): default to nil, since this feature + (viper-undo): More sensible positioning after undo. + + * viper-ex.el (ex-splice-args-in-1-letr-cmd): Get rid of caddr. + (viper-emacs-state-cursor-color): Default to nil, since this feature doesn't work well yet. - * ediff-mult.el (ediff-intersect-directories, - ediff-get-directory-files-under-revision, ediff-dir-diff-copy-file): + * ediff-mult.el (ediff-intersect-directories) + (ediff-get-directory-files-under-revision, ediff-dir-diff-copy-file): always expand filenames. - + +2006-08-24 Stefan Monnier + + * tumme.el: Remove * in defcustoms's docstrings. + 2006-08-24 Chong Yidong * emacs-lisp/timer.el (timer-set-idle-time, run-with-idle-timer): diff -r 888592049333 -r 9d3a9b609c04 lisp/progmodes/python.el --- a/lisp/progmodes/python.el Fri Aug 25 22:01:34 2006 +0000 +++ b/lisp/progmodes/python.el Fri Aug 25 22:49:14 2006 +0000 @@ -65,6 +65,7 @@ ;;; Code: (eval-when-compile + (require 'cl) (require 'compile) (require 'comint)) @@ -547,40 +548,39 @@ ((looking-at (rx (0+ space) (syntax comment-start) (not (any " \t\n")))) ; non-indentable comment (current-indentation)) - (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)))))))) + (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))))))) ;;;; Cycling through the possible indentations with successive TABs. @@ -755,13 +755,13 @@ (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) @@ -773,7 +773,7 @@ ;; 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))) @@ -1250,47 +1250,57 @@ (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)) - (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: - ;; What is this all about, exactly? --Stef - ;; (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))) + (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))))) (autoload 'comint-check-proc "comint") @@ -1342,9 +1352,8 @@ ;; 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 ()'") + (python-send-receive "import emacs; 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 @@ -1358,13 +1367,14 @@ ;; commands having set up such a state. (defun python-send-command (command) - "Like `python-send-string' but resets `compilation-shell-minor-mode'." + "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 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 ()'") + (python-send-receive (concat command "; print '_emacs_out ()'")) (with-current-buffer python-buffer (set-marker compilation-parsing-end end) (setq compilation-last-buffer (current-buffer))))) @@ -1409,7 +1419,11 @@ "Evaluate STRING in inferior Python process." (interactive "sPython command: ") (comint-send-string (python-proc) string) - (comint-send-string (python-proc) "\n\n")) + (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"))) (defun python-send-buffer () "Send the current buffer to the inferior Python process." @@ -1561,14 +1575,15 @@ (defun python-send-receive (string) "Send STRING to inferior Python (if any) and return result. -The result is what follows `_emacs_out' in the output (or nil)." +The result is what follows `_emacs_out' in the output." (let ((proc (python-proc))) (python-send-string string) - (setq python-preoutput-result nil) + (set (make-local-variable 'python-preoutput-result) nil) (while (progn (accept-process-output proc 5) - python-preoutput-leftover)) - python-preoutput-result)) + (null python-preoutput-result))) + (prog1 python-preoutput-result + (kill-local-variable 'python-preoutput-result)))) ;; Fixme: Is there anything reasonable we can do with random methods? ;; (Currently only works with functions.) @@ -2078,36 +2093,35 @@ (unless (fboundp 'brm-rename) (pymacs-load "bikeemacs" "brm-") ; first line of normal recipe (let ((py-mode-map (make-sparse-keymap)) ; it assumes this - (features (cons 'python-mode features)) ; and requires this - menu) - (brm-init) ; second line of normal recipe - (remove-hook 'python-mode-hook ; undo this from `brm-init' - '(lambda () (easy-menu-add brm-menu))) - (easy-menu-define - python-brm-menu python-mode-map - "Bicycle Repair Man" - '("BicycleRepairMan" - :help "Interface to navigation and refactoring tool" - "Queries" - ["Find References" brm-find-references - :help "Find references to name at point in compilation buffer"] - ["Find Definition" brm-find-definition - :help "Find definition of name at point"] - "-" - "Refactoring" - ["Rename" brm-rename - :help "Replace name at point with a new name everywhere"] - ["Extract Method" brm-extract-method - :active (and mark-active (not buffer-read-only)) - :help "Replace statements in region with a method"] - ["Extract Local Variable" brm-extract-local-variable - :active (and mark-active (not buffer-read-only)) - :help "Replace expression in region with an assignment"] - ["Inline Local Variable" brm-inline-local-variable - :help - "Substitute uses of variable at point with its definition"] - ;; Fixme: Should check for anything to revert. - ["Undo Last Refactoring" brm-undo :help ""])))) + (features (cons 'python-mode features))) ; and requires this + (brm-init)) ; second line of normal recipe + (remove-hook 'python-mode-hook ; undo this from `brm-init' + '(lambda () (easy-menu-add brm-menu))) + (easy-menu-define + python-brm-menu python-mode-map + "Bicycle Repair Man" + '("BicycleRepairMan" + :help "Interface to navigation and refactoring tool" + "Queries" + ["Find References" brm-find-references + :help "Find references to name at point in compilation buffer"] + ["Find Definition" brm-find-definition + :help "Find definition of name at point"] + "-" + "Refactoring" + ["Rename" brm-rename + :help "Replace name at point with a new name everywhere"] + ["Extract Method" brm-extract-method + :active (and mark-active (not buffer-read-only)) + :help "Replace statements in region with a method"] + ["Extract Local Variable" brm-extract-local-variable + :active (and mark-active (not buffer-read-only)) + :help "Replace expression in region with an assignment"] + ["Inline Local Variable" brm-inline-local-variable + :help + "Substitute uses of variable at point with its definition"] + ;; Fixme: Should check for anything to revert. + ["Undo Last Refactoring" brm-undo :help ""]))) (error (error "Bicyclerepairman setup failed: %s" data)))) ;;;; Modes. @@ -2131,6 +2145,8 @@ (add-hook 'post-command-hook 'python-abbrev-pc-hook nil t)) (modify-syntax-entry ?/ "w" python-abbrev-syntax-table) +(defvar python-mode-running) ;Dynamically scoped var. + ;;;###autoload (define-derived-mode python-mode fundamental-mode "Python" "Major mode for editing Python files.