6

I am currently working on an elisp function that moves to another location, executes a function, then returns to the position. My only problem is that if the function inserts text, the position that I saved is no longer where I want to be. For example, say I have the following string:

Hello World

And let's say I'm at the 'W' at position 6. And let's say I want to insert another "Hello" to the beginning like this:

Hello Hello World

The way I'm doing it now, I would store 6 in a variable, insert the hello, then return to position 6. However, now the second hello is at position 6 and I'm returning to the wrong place!

Right now I'm doing something like this:

(setq my-retloc (point))
(move-function)

Then in the end hook of move-function:

(do-stuff)
(goto-char my-retloc)

Unfortunately, doing this in the end hook isn't really avoidable. Is there a way in elisp to make sure that I would return to the correct position?

user1539179
  • 1,835
  • 2
  • 16
  • 28

2 Answers2

11

This is a pretty common need in elisp, so, there's a special form that does it automatically: save-excursion. Use it like this:

 (save-excursion
   ;; move about and modify the buffer 
   (do-stuff))
 ;; position restored
ataylor
  • 64,891
  • 24
  • 161
  • 189
  • Thanks for the answer! However, this doesn't quite solve my problem since I have to do the returning in another function. I'm trying to use ace-jump to move the cursor, but for some reason it refuses to execute in order. As a result, I have to save my position in one function and restore my position in another function (ace-jump's end hook). I really don't know why, but ace-jump doesn't play nice with save-excursion. – user1539179 Feb 21 '14 at 23:05
1

If you cannot use save-excursion, as @ataylor suggested, then do something like the following. (Presumably you cannot use unwind-protect either, if the return is not from within a function called by the original function.)

  1. Save point in a global variable. Save point as a marker, in case the current buffer changes or the buffer text is modified, making a saved integer position useless.

  2. If possible, wrap the code saving point with a catch, and restore the original position in all cases (as with an unwind-protect).

  3. Use throw when done with your excursion, to get back to that restoring code (which goes to the marker).

Drew
  • 29,895
  • 7
  • 74
  • 104
  • Hi @user1539179, if an answer solves your issue(s), please consider marking it as an answer. –  Feb 22 '14 at 03:01
  • @Drew How do you save `point` as a marker? `mark`, `set-mark`, `push-mark`? – Kaushal Modi May 06 '16 at 20:22
  • Thanks. That's an alias to `set-marker` right? I just got something working as I needed with `push-mark` and `pop-up-mark-command`. – Kaushal Modi May 06 '16 at 23:08
  • If you have chance to [review it](https://github.com/kaushalmodi/.emacs.d/commit/87b6981df1872217247815558bd9f19327b4fe4a). I needed to preserve the point in the org capture indirect buffer, but the basic-save-buffer moved to the point to that in the base buffer. I'm not sure if that's by design. – Kaushal Modi May 06 '16 at 23:11
  • @KaushalModi: Sorry, I don't have the time to review lots of code. If you have a specific question about something, I can try to answer it. I also know nothing particular about Org. – Drew May 06 '16 at 23:18
  • No, `copy-marker` is not an alias to `set-marker`. `C-h f` is your friend. – Drew May 06 '16 at 23:20