[Top][All Lists]

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

Re: *shell*: annoying behavior with long output

From: Michael Slass
Subject: Re: *shell*: annoying behavior with long output
Date: Mon, 17 May 2004 23:35:12 GMT
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3

bill <address@hidden> writes:

>I'm a big fan of the Emacs shell, but one thing that really annoys
>me is its behavior when a lot of output is sent to stdout.  The
>cursor ends up at the very bottom of the output, even though,
>invariably I'm more interested in looking at the top first and then
>work my way down, which means that I end up having to search
>backwards for the shell prompt to see the beginning of the output.
>I have not found a satisfactory solution to this.  When I'm not in
>the Emacs shell, the solution is simple: I pipe the output through
>/usr/bin/less.  But the Emacs shell can't handle less too well.
>Another thing I've tried is to set the mark before executing a
>command, and then C-x C-x after executing it.  The problem with
>this is that the top of the output gets placed in the middle of
>the screen, so I have to do C-u 0 C-l to see the top screenful of
>output.  Besides, this works only when I know ahead of time that
>the output will be long.
>Is there a way to tell the Emacs shell to keep the cursor at the
>top of the output in such a way that the top screenful of output
>is what is visible of the *shell* buffer immediately after executing
>a command?
>       -bill

You'd think that frobbing this variable would do it:
| comint-scroll-to-bottom-on-output's value is nil
| Documentation:
| *Controls whether interpreter output causes window to scroll.
| If nil, then do not scroll.  If t or `all', scroll all windows showing buffer.
| If `this', scroll only the selected window.
| If `others', scroll only those that are not the selected window.
| The default is nil.
| See variable `comint-scroll-show-maximum-output' and function
| `comint-postoutput-scroll-to-bottom'.  This variable is buffer-local.
| You can customize this variable.
| Defined in `comint'.

But I can't get any effects by changing it at all.

So, I hacked this together, which will return you to your starting
point if a prompt shows up in the shell N lines after your last
prompt, where N is your screen height.  I tried the more elegant
solution of using around-advice, and a (let ...) form to set the value
of my-comint-process-start-point:

| (defadvice comint-send-input (around my-comint-send-input)
|   "go to beginning after comint-send-input"
|   (let ((my-comint-process-start-point (point)))
|     ad-do-it))

but the filter function was always seeing
my-comint-process-start-point as undefined, so I've gone with the
uglier (because more global) setq.

Criticisms from gurus welcomed as always.

(defadvice comint-send-input (before my-comint-send-input)
  "Set starting point variable for use in `my-comint-return-to-start-maybe'"
  (setq my-comint-process-start-point (point)))

(ad-activate 'comint-send-input)

(defun my-comint-return-to-start-maybe (output)
  "Return to start of shell-output if it has scrolled off-screen.
Depends on advising `comint-send-input' to set the value of
`my-comint-process-start-point' before running.

This can be done with this advice form:
\(defadvice comint-send-input (before my-comint-send-input)
  \"go to beginning after comint\"
  (setq my-comint-process-start-point (point)))
  (if (and (bound-and-true-p my-comint-process-start-point)
           (string-match comint-prompt-regexp output)
           (> (count-screen-lines my-comint-process-start-point (point))
              (cdr (assoc 'height (frame-parameters)))))
      (goto-char (1+ my-comint-process-start-point))))

Mike Slass

reply via email to

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