emacs-evil / evil

The extensible vi layer for Emacs.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

(evil-goto-definition) somehow erases the last jump

Hi-Angel opened this issue · comments

Usually when (evil-goto-definition) takes me someplace in the same file I want to be able to get back with C+o. So I have a wrapper that basically executes a (evil--jumps-push) before going to definition. Unfortunately it was sporadically not working and I just found that (evil-goto-definition) somehow nullifies its effects.

Issue type

  • Bug report

Environment

Emacs version: GNU Emacs 30.0.50 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.24.41, cairo version 1.18.0) of 2024-02-21
Operating System: Archlinux
Evil version: 1.15.0
Evil installation type: MELPA
Graphical/Terminal: Graphical
Tested in a make emacs session (see CONTRIBUTING.md): Yes

Reproduction steps

  1. make emacs in Evil repo
  2. Once *scratch* buffer appears paste the following code:
    (setq evil-goto-definition-functions '(evil-goto-definition-search))
    (defun my-goto-definition ()
      (interactive)
        (evil--jumps-push)
        (evil-goto-definition))
    
    ;; DO NOT EVALUATE BELOW
    (my-goto-definition)
  3. Evaluate it up to DO NOT EVALUATE line.
  4. Press C+o repeatedly till the jumps stack is exhausted.
  5. Put caret over the (my-goto-definition) call and execute M+x my-goto-definition
  6. Now that the caret went to the definition, press C+o

Expected behavior

Caret gets back to the location it was at in point 5. That should happen because the my-goto-definition executed evil--jumps-push prior going to definition to make sure position is saved.

Actual behavior

The caret goes elsewhere.

Before I try to repro, why do you need to wrap evil-goto-definition in a function that calls evil--jumps-push? :jump t has been set for evil-goto-definition for years. Surely this does what you want without needing the wrapper? As a side note, evil-- functions (i.e. with a double dash) are usually not for public use. I would think that evil-set-jump would be more appropriate anyway. Happy to investigate once I get a better understanding of what you're trying to fix that evil isn't doing.

Before I try to repro, why do you need to wrap evil-goto-definition in a function that calls evil--jumps-push? :jump t has been set for evil-goto-definition for years. Surely this does what you want without needing the wrapper? As a side note, evil-- functions (i.e. with a double dash) are usually not for public use. I would think that evil-set-jump would be more appropriate anyway. Happy to investigate once I get a better understanding of what you're trying to fix that evil isn't doing.

Ooooh, you are right on all points! As for "why do I have it", I tried git-blame to see when this line appeared in my config and it goes all the way back to the initial import of evil-related config in 2019. So no description what made me add this.

And thank you for mentioning evil-set-jump, I have 4 more occasions of evil--jumps-push in my config which I should replace then. Yeah, I was guessing it's likely internal judging by two dashes, but I couldn't find the public version because I thought it would be called a evil-jumps-push (with one dash), which it wasn't 😊

Sorry for the noise and thank you

Ooooh, you are right on all points! As for "why do I have it", I tried git-blame to see when this line appeared in my config and it goes all the way back to the initial import of evil-related config in 2019. So no description what made me add this.

Oh yeah, to clarify: I tried experimenting to see if I can make returning back to the location break, and everything seems fine. Basically, the wrapper with evil--jumps-push was breaking it if anything (I presume because I should've used evil-set-jump which has more code besides just calling evil--jumps-push).

…and just as I wrote it I realized why it was there in the first place 😊

It doesn't matter at this point because evil-set-jump works as I just tested. But for the record: for the bugreport I kind of simplified the situation around the wrapper purpose. It's this function and it solves the following problem: I usually have at least 4 windows in a Emacs frame (may be more depending on the monitor at hand) and let's say I have had a file foo.cpp opened in some window. Then using "goto-definition" in some bar.cpp might show this foo.cpp in yet another window. IOW, after "goto definition" I've been ending up with two windows showing foo.cpp simultaneously.

So what the wrapper does is it basically scans currently existing windows and if it finds that the definition belongs to a buffer that is already visible, then it goes in there instead of having the buffer shown in two places.

As for why :jump t doesn't work: apparently it is interactive-only, i.e. jump is not saved when such function is called from ELisp.

As for why :jump t doesn't work: apparently it is interactive-only

Ah, yes, that's basically correct. evil-set-jump is conditionally called as part of the pre-command-hook (https://github.com/emacs-evil/evil/blob/master/evil-jumps.el#L293-L303) and a function is only a command if called interactively. I'm glad the issue is resolved :)