3

I would like the ability to go back and forth through a series of stored recent cursor positions, say up to 100 of them. Specifically, a position should be recorded when I click somewhere, or when I do a find operation that causes me to jump to a different location in the file. Ideally, I would be able to go back to the previous stored position, then back forward again through the list of positions, if I choose to do so.

Is there some preexisting way to do this? Alternatively, is there a relatively easy way to design a function to do this? Say, to set hooks for a cursor position change, then update some global array when such a hook is activated?

I don't care whether positions are stored per-buffer or per-window or per-frame (although per-buffer would probably be better).

exchange-point-and-mark sort of does this (after a find operation; doesn't pay attention to mouse click position), on a much smaller scale.

8 Answers 8

3

You are describing a use case of bookmarks. For example, have a look at the visual bookmark package at https://github.com/joodland/bm. You get functions to toggle bookmarks at point and move back and forth between them. Bind them to keys that are convenient for you.

2

The simplest option, although it does not keep positions in a ring, is to save positions to registers.

The docstring for the command point-to-register:

It is bound to C-x r SPC, C-x r C-SPC, C-x r C-@.

(point-to-register REGISTER &optional ARG)

Store current location of point in register REGISTER. With prefix argument, store current frame configuration. Use C-x r j to go to that location or restore that configuration. Argument is a character, naming the register.

And the docstring for jump-to-register:

It is bound to C-x r j.

(jump-to-register REGISTER &optional DELETE)

Move point to location stored in a register. If the register contains a file name, find that file. (To put a file name in a register, you must use set-register.) If the register contains a window configuration (one frame) or a frameset (all frames), restore that frame or all frames accordingly. First argument is a character, naming the register. Optional second arg non-nil (interactively, prefix argument) says to delete any existing frames that the frameset doesn't mention. (Otherwise, these frames are iconified.)

1
  • Is there a way to add a hook that will detect the start and end of a find operation, and/or a mouse click? I'm aware of isearch-mode-end-hook, but no matching "isearch-mode-start-hook" or any hook for mouse click events.
    – std_answ
    Dec 16, 2016 at 20:16
1

I was going to suggest helm-all-mark-rings in the Helm package. It has been mentioned here previously, along with some other tips. To me it otherwise sounds like you might be interested in bm, which is a way to manually add locations to a file (by mouse or keyboard), which you can then jump between.

1

The mark-ring is supposed to do just that: use C-u C-SPC to go back one step; repeat as needed. You'll need to increase mark-ring-max if you want to go "up to 100 of them", of course. And it might be the case that some operations fail to "push a mark". If so, please report that as a bug.

1

I realize that this is an old post, but I actually just finished something which I believe does what you're looking for. I didn't realize when I wrote it that anything similar existed, so I'm not sure how it compares to previously mentioned packages.

The package I created is called "footsteps", and it can be found at the following link: https://gitlab.com/jdavisclemson/footsteps.

Summary description:

This package provides a way to quickly retrace your "footsteps" when navigating a project. It maintains a ring of automatically-logged previous locations called "footsteps", or "steps", for short. The steps are logged "intelligently", based on certain settings, which are customizable. The steps are stored in the step-ring, which can be conceptualized as a trail of footsteps.

I would recommend reading the README.md for a more in-depth description of its behavior, but it logs steps automatically as you navigate. The maximum number that it logs is configurable, but it defaults to 100. It has a few mechanisms to prevent the logging of in-transit, or excessively dense locations. One of these is a "minimum distance" criteria, which is partially configurable (some of the criteria would not make sense to change). It also has a configurable list of commands and buffer names which will prevent logging, in an effort to mitigate the logging of in-transit locations. In the event it does log undesired locations, it has a command to unlog the step at the current location.

Lastly, it keeps the step locations up-to-date as lines are added to or removed from buffers.

2
  • I added your summary from the linked page. (Please always summarize what a link leads to. Q&A should be searchable for info and pretty much stand on their own. Thx.)
    – Drew
    Jan 19 at 2:01
  • Okay. I'll make sure to do that in the future. Thanks for the correction and letting me know.
    – jdavis
    Jan 19 at 23:04
1

You don't say whether you want the saved locations to be saved persistently or just for the current Emacs session.

In any case, you can have either or both, with Emacs bookmarks.


If you use Bookmark+ then you can have create bookmarks without bothering to give them names -- just hit C-x x RET (or bind that command to another key). The bookmarks created that way are automatically named with the location.

You can also just turn on automatic bookmarking. There are several ways to automatically create bookmarks.

0

I've recently implemented a package that performs a big chunk of what you desire, specifically, by allowing you to define a set of commands before which the cursor (i.e., point, in Elisp slang) position is saved in a list, in a buffer-local fashion:

Restore Point Package

Originally, the package allows you to restore the last saved cursor position by hitting keyboard-quit, which is usually bound to C-g or ESC, or by explicitly calling rp/restore-point-position.

The list of commands to be considered for saving the point position in advance can be configured by modifying rp/restore-point-commands.

What's currently missing is the ability to cycle through the list of saved positions, but this can be (without much effort) implemented by looping through the list rp/point-ring in your desired fashion. Perhaps an interesting integration that would make it shine would be to have an interface similar to what ivy-mark-ring does.

Cheers!

0

The library pointhistory stores all positions after reasonable large point changes caused by commands.

The only caveat is that sometimes it stores more than you want and you have to skim through some intermediate positions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.