38

Sometimes I find myself frequently alternating between two functions that I am editing in conjunction with each other. In these situations, it is tedious and painful to keep on doing a C-s <functionname> to switch to the other function and then to find the exact place I was editing previously.

How do I set markers and then jump back and forth between two locations in the buffer with ease?

  • 3
    You're doing it wrong. You should have a vertical split view so you see both functions at the same time. – CaptainCodeman Nov 12 '14 at 11:36
  • 8
    I disagree that OP is "doing it wrong." While a split window would be helpful, OP is still going to need to jump back and forth between windows when editing both functions. Besides that, the question is more general than the specific use case: OP wants to be able to jump around to different locations in a buffer quickly. Lots of answers below give a number of useful ways to do it. – Dan Nov 12 '14 at 13:06
  • @Dan That's cool man, and I agree with you, but my response is not intended to solve his problem -- only to point out that there is an alternate way. – CaptainCodeman Nov 12 '14 at 13:39
  • 4
    @CaptainCodeman, that's fine, although T. Vernon's answer below does provide the split-window alternative. Please treat my comment as a more general request for proactive language in posts. – Dan Nov 12 '14 at 13:47
  • 1
    @CaptainCodeman You're absolutely right. I was not aware that emacs supported a vertical split view. As such, I have accepted the answer that details the usage of these vertical split views. – Vedaad Shakib Nov 12 '14 at 19:36

12 Answers 12

20

Emacs windows

C-x 2 will open another window (=split the frame) below the current one, attached to the same buffer. You can move point in either window without affecting the other.

You can move from one window to the other using C-x o. The built-in windmove library provides some function that makes navigating between windows easier.

If this method suits you, you may also want to have a look at indirect buffers.

enter image description here

  • Maybe you should add a few more lines about using indirect buffers: it really is more useful (and just a bit more complex) than using just another window. – Francesco Nov 12 '14 at 15:38
  • @Francesco I see what you mean now (with the other answer about indirect buffers), indeed that's a very easy to use option too. That's not the usage that I had in mind: my use of indirect buffers doesn't replace using a different window, but it allows for changing the view with narrowing, for example. I'll add a few words to the answer when I find the time. – T. Verron Nov 13 '14 at 12:12
56

Registers:

C-xrSPC runs point-to-register
C-xrj runs jump-to-register

Type any character to specify a register when prompted.1

Bookmarks:

C-xrm runs bookmark-set
C-xrb runs bookmark-jump

Mark ring:

C-SPCC-SPC pushes the current position to the mark ring (without leaving it active).
C-uC-SPC pops the mark ring, jumping to the previous position. You can use this repeatedly to navigate through the entire ring.

Note that some commands (especially ones which are liable to move you an an unknown or arbitrary distance from your original location) will automatically push to the mark ring so that you can use C-uC-SPC to return afterwards. This includes isearch, so after using C-s to go somewhere, you can easily jump back again.

Exchange point and mark:

And as Tu Do comments, C-xC-x runs exchange-point-and-mark which is very useful for jumping between two locations. It also activates the mark/region, but you can use C-SPC to clear the highlighting.


1 If you're taking advantage of register functionality in elisp, use some non-conflicting symbol for the name, rather than a char, so that you can't conflict with interactively-set registers (unless, of course, you want to do that).

  • 2
    You should add C-x C-x as well, since it can jump back and forth between two positions. C-u C-SPC pops the mark ring and execute again will move point elsewhere. – Tu Do Nov 12 '14 at 6:11
18

In addition to phils's answer, there are some more options:

  • helm-all-mark-rings: It allows you to view the content of the both the local and global mark rings in a friendly interface, so you can always jump back to where you were. You can push mark with C-SPC C-SPC. Demo:

helm-all-mark-rings

  • helm-semantic-or-imenu: List all available definitions in the current file. If cursor is inside a definition, when activating the highlighter preselects that definition.

  • sr-speedbar: A file browser that lists its definitions in each file. It is similar to outline tree in IDE.

9

Besides registers and markers (see @phils's answer about both and my other, Icicles answer about markers), bookmarks, particularly either autonamed or temporary bookmarks, can be helpful for this. You need library Bookmark+ for these special bookmark types.

  • An autonamed bookmark is one that you do not need to name. It is quick to create and delete: just hit a key. The same key creates or deletes a bookmark at point. (By default, this is bound to C-x p RET, but you can of course use any key.)

  • Autonamed bookmarks are, like bookmarks in general, persistent. But you can optionally have them be deleted automatically.

  • You can also create temporary bookmarks or make any existing bookmarks temporary. You can, for example, choose to make autonamed bookmarks be temporary automatically.

  • You can quickly cycle among a given set of bookmarks. For example, to cycle among autonamed bookmarks, use commands bmkp-next-autonamed-bookmark-repeat and bmkp-previous-autonamed-bookmark-repeat (binding them to keys).

  • You can highlight bookmarked locations in different ways, so it is easy to spot them.

7

With regard to indirect buffers mentioned in the accepted answer...

M-x clone-indirect-buffer will create an indirect buffer for the current buffer. The name of the new buffer will have '<2>' added to it (or a greater number if you've already got duplicate buffer names). The new buffer is opened in a new window. You can switch back to a single window using C-x 0 or C-x 1.

With M-x winner-mode you can easily switch between the two locations. C-c <left> / M-x winner-undo and C-c <right> / M-x winner-redo switches between window configurations. In this case the configurations will be positions in the two buffers viewing the one file.

Note: the winner-undo and winner-redo functions work on a list of configurations. If the configuration is changed, e.g. moving point, then the current configuration becomes the head of the list and winner-redo is invalid, in this case winner-undo will bring back the previous position.

For the OP's situation this leads to the following process;

  1. Turn on winner mode M-x winner-mode
  2. Visit file (filename: File1.txt, buffer name: File1.txt)
  3. M-x clone-indirect-buffer (new indirect buffer name: File1.txt<2>)
  4. Make current window the only window C-x 1
  5. Find first edit location, make changes.
  6. Switch to original buffer visiting file, C-x b (default will be original buffer unless a switch to another buffer took place since step 3). This creates a new configuration for winner to switch back to.
  7. Find alternative edit location, make changes.

A switch to the previous edit location (window configuration) depends on whether a change is made to the window configuration between switches;

  • If a change is made switch using C-c <left> / M-x winner-undo.
  • If no change is made switch using C-c <left> / M-x winner-undo for back and C-c <right> / M-x winner-redo for forward.

A change is anything other than another winner-undo or winner-redo.

3

if you use evil-mode, the vim layer, then C-o and C-i will work the same.

They run the commands evil-jump-backward / forward. C-o jumps to the older position in the jump list, which is set automatically (marks are set on motion commands). C-i goes in reverse. We can also use TAB after a C-o instead of C-i. So using both functions will take you back and forth in your current buffer.

If you want this feature to be cross-buffers, check out evil-jumpers: http://melpa.org/#/evil-jumper

«
evil-jumper is an add-on for evil-mode which replaces the implementation of the jump list such that it mimics more closely with Vim's behavior. Specifically, it will jump across buffer boundaries and revive dead buffers if necessary. The jump list can also be persisted to a file and restored between sessions. »

Note: I learnt it on this wiki

  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. – Dan Nov 12 '14 at 13:40
  • 1
    D'oh, and by that automated comment, I actually mean that the answer looks like it was intended to be a comment on another answer. If you intended this to be an answer in its own right, could you expand a little bit on what C-o and C-i do? – Dan Nov 12 '14 at 13:51
  • You're right ! done. – Ehvince Nov 12 '14 at 14:05
2

If you use Icicles then you can quickly navigate among the markers in the mark-ring of each buffer or the global-mark-ring (which has a single marker in each buffer).

You do this using multi-command C-- C-SPC (for a buffer's mark-ring) or C-- C-x C-SPC (for the global-mark-ring). After hitting the key once, you use the usual Icicles cycling keys etc., to move among the markers of the ring.

(The same keys without a prefix arg set the mark (set-mark-command) and pop the global mark (pop-global-mark), respectively, just as they do in vanilla Emacs.)

The text of the line of each marker is used as a completion candidate. As you type, your minibuffer input narrows the candidates to those that match (e.g., substring or regexp matching). You can quickly cycle among matching markers or visit any of them directly. You can even change the sort order (C-,) for cycling.

2

A minimimal but often helpful possibility - when you just want to peek the other function - is setting

(setq scroll-preserve-screen-position t)

which brings you back to your exact starting cursor position when switching between C-v and M-v.

1

evil-mode implements Vim-style markers. You can set markers with (m, that is, evil-set-marker) and jump to the mark with the backtick ` (evil-goto-mark) or to the mark's line ' (evil-goto-mark-line).

Hence, you could create mark "a" at the first location with ma, create mark "b" at the second location with ma, and then 'a to jump to mark "a" and 'b to jump to mark "b".

1

use imenu and below code

(defvar rimenu-position-pair nil "positions before and after imenu jump")
(add-hook 'imenu-after-jump-hook
          (lambda ()
            (let ((start-point (marker-position (car mark-ring)))
                  (end-point (point)))
              (setq rimenu-position-pair (list start-point end-point)))))

(defun rimenu-jump ()
  "jump to the closest before/after position of latest imenu jump"
  (interactive)
  (when rimenu-position-pair
    (let ((p1 (car rimenu-position-pair))
          (p2 (cadr rimenu-position-pair)))

      ;; jump to the far way point of the rimenu-position-pair
      (if (< (abs (- (point) p1))
             (abs (- (point) p2)))
          (goto-char p2)
          (goto-char p1))
      )))
1

For the past 20 years or so, I've been using these two gems:

(defun ska-point-to-register ()
  "Store cursorposition _fast_ in a register. Use ska-jump-to-register
to jump back to the stored position."
  (interactive)
  (point-to-register 8))

(defun ska-jump-to-register ()
  "Switches between current cursorposition and position
that was stored with ska-point-to-register."
  (interactive)
  (let ((tmp (point-marker)))
    (jump-to-register 8)
    (set-register 8 tmp)))

I bind them to C-. and C-, respectively and use them constantly without realizing it anymore.

Yes, registers and markers and such are much more flexible and powerful, but still, this is one of those tiny, quick helpers that make it impossible for me to switch to other editors.

  • 1
    Wow, you've been using this longer than I've been alive. – Vedaad Shakib May 17 '18 at 21:56
  • I guess this won't happen in the Node or Visual Studio Code world just yet, but who knows... :-) Glad to see young and smart folks still picking up Emacs. Oh, and, I'm not yet 50 ;-) – Stefan Kamphausen May 17 '18 at 22:07
  • This is pretty awesome. I've been trying to find a way to switch between two arbitrary locations with transient-mark-mode enabled, and this solves the problem really well :) Thank you. – PlagueHammer Nov 11 '18 at 19:21
0

You can also take advantage of macros, since they can be quickly bound to convenient keys.

For example, record a jump to position N using <F3> M-g g N <F4> and assign it to key F5 with C-x C-k b <F5>. Then do the same with position M and F6. From now on you can simply alternate F5 and F6 to jump between N and M.

Even simpler, since <F4> executes last recorded macro and <C-u> F4 the next to last one, you can skip the key binding step and simply alternate positions using <F4> and <C-u> F4.


Another rather radical possibility is to create an indirect buffer in another window with <C-x> 4 c. This buffer has the same contents but may have a different point position. Now simply alternate between windows with <C-x> o the usual way.

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.