all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* (save-excursion (other-window 1)) leaves me in the other window
@ 2010-03-05 20:33 Sean McAfee
  2010-03-05 22:21 ` Joe Fineman
  2010-03-07  6:55 ` Tim X
  0 siblings, 2 replies; 9+ messages in thread
From: Sean McAfee @ 2010-03-05 20:33 UTC (permalink / raw
  To: help-gnu-emacs

A native reimplementation of scroll-other-window doesn't work as I'd
expect:

  (save-excursion
    (other-window 1)
    (scroll-up))

The problem is that the current window isn't restored, which surprised
me considerably.  Why doesn't this work, and how would I write a
function to go do some stuff in the other window and then come back?


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: (save-excursion (other-window 1)) leaves me in the other window
  2010-03-05 20:33 (save-excursion (other-window 1)) leaves me in the other window Sean McAfee
@ 2010-03-05 22:21 ` Joe Fineman
  2010-03-07  6:55 ` Tim X
  1 sibling, 0 replies; 9+ messages in thread
From: Joe Fineman @ 2010-03-05 22:21 UTC (permalink / raw
  To: help-gnu-emacs

Sean McAfee <eefacm@gmail.com> writes:

> A native reimplementation of scroll-other-window doesn't work as I'd
> expect:
>
>   (save-excursion
>     (other-window 1)
>     (scroll-up))
>
> The problem is that the current window isn't restored, which
> surprised me considerably.  Why doesn't this work, and how would I
> write a function to go do some stuff in the other window and then
> come back?

I believe save-excursion should be save-window-excursion.
-- 
---  Joe Fineman    joe_f@verizon.net

||:  Everything you do costs money, dissipates heat, and makes  :||
||:  crumbs.                                                    :||


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: (save-excursion (other-window 1)) leaves me in the other window
  2010-03-05 20:33 (save-excursion (other-window 1)) leaves me in the other window Sean McAfee
  2010-03-05 22:21 ` Joe Fineman
@ 2010-03-07  6:55 ` Tim X
  2010-03-08  3:09   ` Sean McAfee
  1 sibling, 1 reply; 9+ messages in thread
From: Tim X @ 2010-03-07  6:55 UTC (permalink / raw
  To: help-gnu-emacs

Sean McAfee <eefacm@gmail.com> writes:

> A native reimplementation of scroll-other-window doesn't work as I'd
> expect:
>
>   (save-excursion
>     (other-window 1)
>     (scroll-up))
>
> The problem is that the current window isn't restored, which surprised
> me considerably.  Why doesn't this work, and how would I write a
> function to go do some stuff in the other window and then come back?

As emacs already has the command to scroll the other window, I'm
assuming your example is a simplification of what you really want to do.
However, if you were writing your own version as a learning exercise,
the best soruce of help is to look at the source for
scroll-other-window. That will probably give you more valuable insight
than any of the responses you will get here and you can be fairly
confident that the information you get is correct!

I'd highly recommend reading the Introduction to Emacs Lisp book that
comes with emacs.

You will also benefit by doing a high level scan and skim reading of the
elisp reference manual.

A couple of things to consider. 

Windows are really the interface for us humans and not necessary the
right abstraction to work at if you just want to do non-interactive
manipulation of data using elisp. 

Have a look at buffers. This is where you will generally focus. Often
the general approach is

1. Save important data
2. switch to a buffer
3. Do stuff in that buffer
4. Possibly make that buffer *visible* by showing it or just return to
wehre you were. 

The point is, you don't have to do stuff only in a visible buffer. More
often than not, you will do stuff in the buffer and either return to
where you were, never making what you did visible right then or maybe
you will make the work you have done visible once you hve finished doing
it. 

You usually only make the buffer visible prior to doing som eprocessing
if you need that to be interactive and the user needs to see what your
doing or you are making interface changes, such as scrolling.

Also, in addition to save-excursion, have a look at unwind-protect,
save-match-data, save-window-excursion, with-current-buffer,
with-temp-buffer, set-buffer, current-buffer etc

I would also be careful about using constructs like (other-window 1) in
elisp code - you don't know what that other window is as it will be
different depending on what you are doing. Usually best to work with
buffer names when you can. 

Tim

-- 
tcross (at) rapttech dot com dot au


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: (save-excursion (other-window 1)) leaves me in the other window
  2010-03-07  6:55 ` Tim X
@ 2010-03-08  3:09   ` Sean McAfee
  2010-03-08  7:26     ` Tim X
  0 siblings, 1 reply; 9+ messages in thread
From: Sean McAfee @ 2010-03-08  3:09 UTC (permalink / raw
  To: help-gnu-emacs

Tim X <timx@nospam.dev.null> writes:

> Sean McAfee <eefacm@gmail.com> writes:
>> A native reimplementation of scroll-other-window doesn't work as I'd
>> expect:
>>
>>   (save-excursion
>>     (other-window 1)
>>     (scroll-up))
>>
>> The problem is that the current window isn't restored, which surprised
>> me considerably.  Why doesn't this work, and how would I write a
>> function to go do some stuff in the other window and then come back?
>
> As emacs already has the command to scroll the other window, I'm
> assuming your example is a simplification of what you really want to do.

True.  The situation is this:

I have a frame, split horizontally into two windows.  One window shows
text that came from an OCR process; the other window, in image-mode,
shows the (large) image that was the input to that OCR process.  What I
want to do is work in the text window, shifting the image in the other
window around as I check it against the text.  I assumed I could do
something like this:

(defmacro in-other-window (&rest body)
  `(save-excursion (other-window 1) ,@body))

And then:

(global-set-key [(shift down)]
  (lambda () (interactive) (in-other-window (image-next-line))))

...and similarly for the other three directions.

Although the documentation for save-excursion says that it saves and
restores the current buffer, it doesn't in this case.  I still don't
really know why.  I tried using save-window-excursion instead as Joe
Fineman suggested, but while that worked for image-next-line and
image-previous-line, it doesn't for image-forward-hscroll, which I need
for scrolling horizontally.  I guess the horizontal scroll amount is
something that's saved and restored by save-window-excursion.  So I
finally settled on this:

(defmacro in-other-window (&rest body)
  `(progn
     (other-window 1)
     (unwind-protect
         (progn ,@body)
       (other-window -1))))

I just have to be careful not to alter the window configuration from
within in-other-window.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: (save-excursion (other-window 1)) leaves me in the other window
  2010-03-08  3:09   ` Sean McAfee
@ 2010-03-08  7:26     ` Tim X
  2010-03-08 16:55       ` Sean McAfee
  0 siblings, 1 reply; 9+ messages in thread
From: Tim X @ 2010-03-08  7:26 UTC (permalink / raw
  To: help-gnu-emacs

Sean McAfee <eefacm@gmail.com> writes:

> Tim X <timx@nospam.dev.null> writes:
>
>> Sean McAfee <eefacm@gmail.com> writes:
>>> A native reimplementation of scroll-other-window doesn't work as I'd
>>> expect:
>>>
>>>   (save-excursion
>>>     (other-window 1)
>>>     (scroll-up))
>>>
>>> The problem is that the current window isn't restored, which surprised
>>> me considerably.  Why doesn't this work, and how would I write a
>>> function to go do some stuff in the other window and then come back?
>>
>> As emacs already has the command to scroll the other window, I'm
>> assuming your example is a simplification of what you really want to do.
>
> True.  The situation is this:
>
> I have a frame, split horizontally into two windows.  One window shows
> text that came from an OCR process; the other window, in image-mode,
> shows the (large) image that was the input to that OCR process.  What I
> want to do is work in the text window, shifting the image in the other
> window around as I check it against the text.  I assumed I could do
> something like this:
>
> (defmacro in-other-window (&rest body)
>   `(save-excursion (other-window 1) ,@body))
>
> And then:
>
> (global-set-key [(shift down)]
>   (lambda () (interactive) (in-other-window (image-next-line))))
>
> ...and similarly for the other three directions.
>
> Although the documentation for save-excursion says that it saves and
> restores the current buffer, it doesn't in this case.  I still don't
> really know why.  I tried using save-window-excursion instead as Joe
> Fineman suggested, but while that worked for image-next-line and
> image-previous-line, it doesn't for image-forward-hscroll, which I need
> for scrolling horizontally.  I guess the horizontal scroll amount is
> something that's saved and restored by save-window-excursion.  So I
> finally settled on this:

Note that the docs as you noted say that they restore the buffer, not
the window. This was part of the point I was tyring to make. Buffers and
windows are not the same thing. 

For example, you might use save-excursion in a command that needs to
jump to another point in the buffer, perform some calculation, maybe put
the results in a temp buffer or variable and then return to where things
were at before the command executed. Essentially, your saving state of
the buffer (not the window!) going off and doing something else and then
once done, returning to where you were. In many cases, the user won't
even realise this has occured. 

If on the other hand, you wanted to do something like display another
window with some data, maybe a status message and then after the user
hits a particular key, restore the window as it was, then
save-window-excursion is probably what you want. 

In your current situation, you want to switch to the window displaying
the buffer with the image in it, scroll it up/down or left/right and
then return to where you were in the text buffer? I think you could
either just use an unwind-protect or a save-excursion, but I'm a little
confused regarding what the issue is with restoration. 

Strongly suggest you have a look at the sources to simple.el as it
contains some examples of convenience commands related to scrolling. 

I also did an apropos-command with the search term 'scroll' and found
the following which you might find useful -

image-backward-hscroll        M-x ... RET
   Scroll image in current window to the right by N character widths.
image-forward-hscroll         M-x ... RET
   Scroll image in current window to the left by N character widths.
image-scroll-down             M-x ... RET
   Scroll image in current window downward by N lines.
image-scroll-up               M-x ... RET
   Scroll image in current window upward by N lines.

It would be fairly trivial to write two commands that would scroll the
image up/down or left/right. It could take a prefix argument to
determine the distance with positive arguments meaning donw/right and
negative meaning up/left etc. 

I don't see there is any need to make it a macro unless you want to be
able to execute arbitrarily complex forms. Maybe just write functions
and later do a macro if justified.

Tim

-- 
tcross (at) rapttech dot com dot au


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: (save-excursion (other-window 1)) leaves me in the other window
  2010-03-08  7:26     ` Tim X
@ 2010-03-08 16:55       ` Sean McAfee
  2010-03-08 17:02         ` Sean McAfee
  2010-03-09  6:45         ` Tim X
  0 siblings, 2 replies; 9+ messages in thread
From: Sean McAfee @ 2010-03-08 16:55 UTC (permalink / raw
  To: help-gnu-emacs

Tim X <timx@nospam.dev.null> writes:
> Sean McAfee <eefacm@gmail.com> writes:
>> Although the documentation for save-excursion says that it saves and
>> restores the current buffer, it doesn't in this case.

> Note that the docs as you noted say that they restore the buffer, not
> the window. This was part of the point I was tyring to make. Buffers and
> windows are not the same thing. 

If the current buffer is restored, then I would expect this expression:

(eq (current-buffer) (save-excursion arbitrary-forms (current-buffer)))

...to always evaluate to t regardless of what arbitrary-forms is, but it
returns nil if I replace arbitrary-forms with (other-window 1).


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: (save-excursion (other-window 1)) leaves me in the other window
  2010-03-08 16:55       ` Sean McAfee
@ 2010-03-08 17:02         ` Sean McAfee
  2010-03-08 17:24           ` David Kastrup
  2010-03-09  6:45         ` Tim X
  1 sibling, 1 reply; 9+ messages in thread
From: Sean McAfee @ 2010-03-08 17:02 UTC (permalink / raw
  To: help-gnu-emacs

Sean McAfee <eefacm@gmail.com> writes:
> If the current buffer is restored, then I would expect this expression:
>
> (eq (current-buffer) (save-excursion arbitrary-forms (current-buffer)))
>
> ...to always evaluate to t regardless of what arbitrary-forms is, but it
> returns nil if I replace arbitrary-forms with (other-window 1).

Argh.  Of course the expression I meant to write was:

(eq (current-buffer) (progn (save-excursion arbitrary-forms) (current-buffer)))

This actually does return t in the presence of multiple windows even if
arbitrary-forms is (other-window 1), and yet the cursor still ends up in
a different window than the one it was in before evaluating the
expression.  I still don't get it.  I guess maybe other-window doesn't
switch windows immediately, but defers the switch until after the
expression has been fully evaluated?


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: (save-excursion (other-window 1)) leaves me in the other window
  2010-03-08 17:02         ` Sean McAfee
@ 2010-03-08 17:24           ` David Kastrup
  0 siblings, 0 replies; 9+ messages in thread
From: David Kastrup @ 2010-03-08 17:24 UTC (permalink / raw
  To: help-gnu-emacs

Sean McAfee <smcafee@palantirtech.com> writes:

> Sean McAfee <eefacm@gmail.com> writes:
>> If the current buffer is restored, then I would expect this expression:
>>
>> (eq (current-buffer) (save-excursion arbitrary-forms (current-buffer)))
>>
>> ...to always evaluate to t regardless of what arbitrary-forms is, but it
>> returns nil if I replace arbitrary-forms with (other-window 1).
>
> Argh.  Of course the expression I meant to write was:
>
> (eq (current-buffer) (progn (save-excursion arbitrary-forms) (current-buffer)))
>
> This actually does return t in the presence of multiple windows even if
> arbitrary-forms is (other-window 1), and yet the cursor still ends up in
> a different window than the one it was in before evaluating the
> expression.  I still don't get it.  I guess maybe other-window doesn't
> switch windows immediately, but defers the switch until after the
> expression has been fully evaluated?

other-window changes the current window, not the current buffer.  When
Emacs returns to the command loop, the current buffer is set to the
window-buffer of the current window.

-- 
David Kastrup


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: (save-excursion (other-window 1)) leaves me in the other window
  2010-03-08 16:55       ` Sean McAfee
  2010-03-08 17:02         ` Sean McAfee
@ 2010-03-09  6:45         ` Tim X
  1 sibling, 0 replies; 9+ messages in thread
From: Tim X @ 2010-03-09  6:45 UTC (permalink / raw
  To: help-gnu-emacs

Sean McAfee <eefacm@gmail.com> writes:

> Tim X <timx@nospam.dev.null> writes:
>> Sean McAfee <eefacm@gmail.com> writes:
>>> Although the documentation for save-excursion says that it saves and
>>> restores the current buffer, it doesn't in this case.
>
>> Note that the docs as you noted say that they restore the buffer, not
>> the window. This was part of the point I was tyring to make. Buffers and
>> windows are not the same thing. 
>
> If the current buffer is restored, then I would expect this expression:
>
> (eq (current-buffer) (save-excursion arbitrary-forms (current-buffer)))
>
> ...to always evaluate to t regardless of what arbitrary-forms is, but it
> returns nil if I replace arbitrary-forms with (other-window 1).

I suspect your assuption is incorrect. 

The documentation for save-excursion does not explicitly state what its
return value is. However, it does say that @body is executed 'just like
progn'. 

The documentation for progn states that its return value is the return
value of the last command executed. 

Documentation for other-window states that it returns nil, which would
support the assumption that save-excursion returns values similar to
progn, which in the case of other-window would be nil.

There is certainly nothing I can see that would indicate save-excursion
returns the same value as current-buffer i.e. a buffer object. 

Tim

-- 
tcross (at) rapttech dot com dot au


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2010-03-09  6:45 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-03-05 20:33 (save-excursion (other-window 1)) leaves me in the other window Sean McAfee
2010-03-05 22:21 ` Joe Fineman
2010-03-07  6:55 ` Tim X
2010-03-08  3:09   ` Sean McAfee
2010-03-08  7:26     ` Tim X
2010-03-08 16:55       ` Sean McAfee
2010-03-08 17:02         ` Sean McAfee
2010-03-08 17:24           ` David Kastrup
2010-03-09  6:45         ` Tim X

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.