emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: python-mode: make sure output is not eaten


From: Slawomir Nowaczyk
Subject: Re: python-mode: make sure output is not eaten
Date: Fri, 25 Aug 2006 11:03:41 +0200

On Wed, 23 Aug 2006 00:04:40 -0400
Stefan Monnier <address@hidden> wrote:

#> > Also, "\n\n" in python-send-string still needs to be changed into a
#> > single "\n" in order to avoid spurious prompts.
#> 
#> Yes, of course.  BTW do you have any idea why the current code uses "\n\n"?

Not, not really -- it looks to me like an attempt to fix some prompt
problems which didn't quite work. Or it may be an attempt to have 
C-c C-s work for indented blocks, as Steven suggested.

#> > Finally, when you test this patch, make sure you also try enabling
#> > eldoc-mode (it doesn't work too well, a patch to improve it a bit is
#> > forthcoming, but even now it works for built-in functions like "apply"
#> > or "map"). It is important to make sure no extra ">>>"s get added to
#> > the inferior buffer when eldoc is talking to Python process.
#> 
#> Would it be because eldoc ends up sending commands to the
#> underlying process while some other command is still being
#> processed? Maybe we'd need a "python-process-busy" variable to
#> prevent eldoc from interfering.

Not really, at least not in my testing... the problems I am seeing
come from the fact that when eldoc sends commands, Python responds
with line that looks like "_emacs_out reload(module)\n>>> " and the
comint filter needs to remove the trailing prompt as well.

OTOH, it seems possible that we might need a "python-process-busy"
variable, as I do not know what will happen if I eldoc tries sending
commands to busy Python interpreter... but maybe there is something in
comint mode which we can test to check if subprocess is busy?

It is not related to current problems, though.

#> > This is -- partially -- the reason why it is important to save
#> > whatever text exists in front of "_emacs_out"... For example,
#> > when I python-send-buffer I can get output like "\nTest!\n>>>
#> > _emacs_out ()\n>>> "... and the ">>>" after "Test!" must show in
#> > the buffer. On the other hand, after eldoc asks Python about
#> > argument list, the output may look like this: "_emacs_out
#> > apply(object[, args[,kwargs]])\n>>> " and it is important that
#> > *nothing* is shown in the inferior buffer.
#> 
#> The handling of the prompt looks pretty messy, indeed. I think we
#> should never send a command followed by "\n" followed by "print
#> _emacs_out ()", but instead we should send the command augmented
#> with "; print _emacs_out ()\n". This should avoid those nasty
#> intermediate prompts.

I am not sure about that. It's not the intermediate prompts that are a
problem, it's rather the trailing one: which is always present, but
shouldn't really be shown.

An alternative, which I think might be a good one, would be to have
the caller specify what to do with the prompt... after all, it is not
the filter function, but the one which sends something to Python, that
really knows if prompt should be shown or not.

We could have variable python-inhibit-print which could be let-bound
by functions such as python-eldoc-function which *know* they should
never print anything...

OTOH, I like your solution of printing prompt only if there is some
other output -- seems clean to me.

#> How 'bout the patch below which also removes the _emacs_ok and
#> preoutput continuation stuff which doesn't seem to be used any
#> more.

You have misspelled command as "comand" in 
    (defun python-send-command (command)

Other than that, your patch looks OK to me. Please install, it's
definitely an improvement.

However, if you change the
   (string-match "\\`_emacs_out \\(.*\\)\n\\'" line)
to
   (string-match "\\`\\(?:>>> \\)?_emacs_out \\(.*\\)\n\\'" line)

then you do not need to do the trick of augmenting commands with ";
print" statement: things work just fine if you do python-send-string
followed by python-send-receive. 

I think this is cleaner, because adding ";" causes syntax error if the
command ends with an indented block (try C-c C-s if 1: C-q C-j    print 1
RET). As Steven pointed out, this is probably not an important use case,
but still... syntax error is a bit too much :)

If you agree, here is a patch, to be applied over yours:

--- m:/EmacsCVS/EmacsCVS/lisp/progmodes/python.el       2006-08-25 
10:41:46.370473600 +0200
+++ c:/Emacs/lisp/progmodes/python.el   2006-08-25 10:47:42.112004800 +0200
@@ -1264,7 +1264,7 @@
     ;; First process whole lines.
     (while (string-match "\n" s start)
       (let ((line (substring s start (setq start (match-end 0)))))
-        (if (string-match "\\`_emacs_out \\(.*\\)\n\\'" line)
+        (if (string-match "\\`\\(?:>>> \\)?_emacs_out \\(.*\\)\n\\'" line)
             (setq python-preoutput-result (match-string 1 line))
           (setq res (concat res line)))))
     ;; Then process the remaining partial line.
@@ -1341,7 +1341,8 @@
   ;; 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 ()'")
+  (python-send-string "import emacs")
+  (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
@@ -1360,7 +1361,8 @@
     (with-current-buffer python-buffer (goto-char (point-max)))
     (compilation-forget-errors)
     ;; Must wait until this has completed before re-setting variables below.
-    (python-send-receive (concat comand "; print '_emacs_out ()'"))
+    (python-send-string command)
+    (python-send-receive "print '_emacs_out ()'")
     (with-current-buffer python-buffer
       (set-marker compilation-parsing-end end)
       (setq compilation-last-buffer (current-buffer)))))


-- 
 Best wishes,
   Slawomir Nowaczyk
     ( address@hidden )

If at first you dont succeed, destroy all evidence that you tried.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]