emacs-devel
[Top][All Lists]
Advanced

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

Re: Deffering redisplay in COMINT


From: Vitalie Spinu
Subject: Re: Deffering redisplay in COMINT
Date: Tue, 25 Dec 2012 12:09:30 +0100
User-agent: Gnus/5.130004 (Ma Gnus v0.4) Emacs/24.2.50 (gnu/linux)

  >> Michael Mauger <address@hidden>
  >> on Thu, 6 Dec 2012 17:08:33 -0800 (PST) wrote:

  > I don't believe this is possible, but I figured I'd run it past the brain 
trust....
  > In sql-interactive-mode, a derivative of comint, I will submit a SELECT
  > statement that returns many very long rows (2000+ characters per line).  The
  > redisplay fireworks that follow are impressive but slow.   As text streams 
to
  > the buffer with `auto-hscroll-mode' enabled the screen flashes as it 
redraws the
  > buffer with more lines of data and scrolled horizontally in different places
  > until all the data stream is complete.  

  > I have figured out how to turn off horizontal scrolling with a
  > comint-preoutput-filter-function' and a `pre-command-hook' for the duration 
of
  > SQL command so the redisplay is limited to a slow march straight down the 
page
  > without the intervening horizontal scrolling but the column number in the 
mode
  > line going crazy.  I've also discovered that if I switch to another buffer 
so
  > that the SQL buffer is not displayed and then switch back, the SQL buffer is
  > populated very quickly.  (That is, Emacs can fetch the results quickly, it 
just
  > can't redraw it quickly a couple of hundred times)

  > So what I'm asking: Is there a way (say by setting `inhibit-redisplay' to 
t) for
  > the duration of the comint command and then restoring redisplay when I am 
at the
  > prompt at the end.  The trick that I use for `auto-hscroll-mode' won't work
  > because I don't find out about the completion until the user causes an 
event.  I
  > understand also that I don't want to universally block redisplay in case I
  > switch to another buffer while the comint command is running and I want to
  > interact with another buffer (i.e., I want to inhibit redisplay in that 
buffer
  > only--buffer-local inhibit-redisplay).  Looking at comint.el and based on my
  > understanding of how processes are handled, I don't believe that it is easy 
to
  > do because I don't know when the output is complete.  (I've noticed in my
  > disable auto-hscroll-mode code that the comint-preoutput-filter-function 
will
  > get called a couple of hundred times with chunks of the output.  I'm 
probably
  > getting a redisplay after
  >  each chunk.)  

  > My only thought is that I could route the output to a temp buffer until I 
see
  > the prompt at the end of a chunk

To the best of my knowledge this is the only way out. But it is not bad
at all. You have to replace comint-output-filter with your own filter
that does that. The filter is triggered each time emacs receives output
from the sub-process (roughly 500 chars last time I counted).  It's
pretty trivial to wait for a prompt at the end of output chunk, and you
will be surprised how reliable this procedure actually is. 

This is how we do it in ESS:

   (defun ess-wait-for-process (proc &optional sec-prompt wait force-redisplay)
     "Wait for 'busy property of the process to become nil.
   If SEC-PROMPT is non-nil return if secondary prompt is detected
   regardless of whether primary prompt was detected or not.  If
   WAIT is non-nil wait for WAIT seconds for process output before
   the prompt check, default 0.001s. When FORCE-REDISPLAY is non-nil
   force redisplay. You better use WAIT >= 0.1 if you need
   FORCE-REDISPLAY to avoid excesive redisplay."
     (unless (eq (process-status proc) 'run)
       (ess-error "ESS process has died unexpectedly."))
     (setq wait (or wait 0.001)) ;;xemacs is stuck if it's 0 here
     (save-excursion
       (while (or (accept-process-output proc wait)
                  (if (and sec-prompt (process-get proc 'sec-prompt))
                      nil
                    (if force-redisplay (redisplay 'force))
                    (process-get proc 'busy))))))
   

The 'busy is set in the process filter by searching for prompt anchored
at the end of output chunk.

    HTH, 
    Vitalie




reply via email to

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