evil-easymotion
evil-easymotion copied to clipboard
goto mark
it would be great to have a way to jump to a mark. basically it would be evil-goto-mark
with an overlay showing the actual mark characters. so when i create marks a
and b
using m a
and m b
and both are visible in the current window, SPC `` (backtick) would show an
avyoverlay with
aand
bat the right positions. similarly,
SPC '` (single quote) would show the overlay with the marks at the beginning of the lines.
just for reference: https://github.com/roman/evil-visual-mark-mode is similar but not quite the same.
Are there motions that traverse the marks?
not that i know of, there's (evil-goto-mark "a")
so perhaps some code around it can do that, but i do not have the elisp skills for it.
also, the overlay characters should match exactly the mark names (which are also single characters), otherwise this feature is not useful at all.
In retrospect, I really should have renamed this package evil-avy
.
As far as I can tell, this would require a lot of new code. If I were to implement it, it would dramatically increase the scope of this package. I'm not entirely opposed to this, but let me think about it for a bit.
I think it would be easier to traverse evil-markers-alist
and collect the items where the cdr satisfies markerp
. This should make a evil-next-mark
function relatively short.
Here's a quick example of getting all marker positions in the current buffer:
(defun evil-all-marks ()
(let (marks)
(dolist (cons evil-markers-alist)
(let ((maybe-marker (cdr-safe cons)))
(when (and (markerp maybe-marker)
(eq (marker-buffer maybe-marker) (current-buffer)))
(push (marker-position maybe-marker) marks))))
marks))
One thing to note is that this will include the point (which should be removed). It would be pretty simple to make a motion out of this that sorted them and jumped to the first. I'm not sure where the best place to add this new motion would be though.
Edit: To clarify, you would add another check to ensure that the position was greater than the point and then sort them or just choose the min.
@noctuid I guess the hard part is ensuring the mark targets match the mark letters. I'd need to think about how to achieve that.
I don't think avy has a way of specifically matching letters for every target. Maybe just override avy-keys
with the mark characters in the order they appear?
Here's a quickly written example (could definitely be improved but seems to work):
(defun evil--marker-sort (a b)
(< (marker-position (cdr a))
(marker-position (cdr b))))
(defun evil-avy-forward-marks ()
(let (marks
positions
chars)
(dolist (cons evil-markers-alist)
(let ((maybe-marker (cdr-safe cons)))
(when (and (markerp maybe-marker)
(eq (marker-buffer maybe-marker) (current-buffer))
(< (point) (marker-position maybe-marker) (1+ (window-end))))
(push cons marks))))
(setq marks (sort marks #'evil--marker-sort))
(setq positions (cl-map 'list (lambda (a) (marker-position (cdr a)))
marks))
(setq chars (cl-map 'list #'car marks))
(let ((avy-keys chars))
(avy--process positions (avy--style-fn avy-style)))))
thanks for looking into this. i think the "after point" check should be "is currently visible", i.e. both backward and forward as long as it's visible in the current window.
Sure, that would probably be the most useful. It was just an example. Another thing worth noting is that the implicit marks are included (such as [
and ]
). Like with evil-visual-mark-mode, this would probably be most useful if there was an option to not include certain marks.
This is definitely interesting. I haven't had a chance to test it out, and I don't know when my next free moment will come, but I'd definitely be interested in adding something like this.