[Top][All Lists]
[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