Gumshoe is a collection of global minor modes that quietly keep tabs on your Point movements so you can retrace your steps if you ever need a reminder of where you’ve been. Each mode keeps a log local to some scope.
(This demonstrates the non-built-in consult-gumshoe-global command I describe below, because it’s the most visual. I usually just use gumshoe–backtrack-back/forward and its variants.)
Gumshoe does not keep track of every move you make, rather, only at increments of some minimum Euclidean distance from the last tracked position, like a leash. It will also automatically log a position if you’ve idled there for a configurable amount of time. This package is very similar to Vim’s jump list, just generalized for Emacs.
I just use straight+use-package like so:
(use-package gumshoe
:straight (gumshoe :type git
:host github
:repo "Overdr0ne/gumshoe"
:branch "master")
:config
;; The minor mode must be enabled to begin tracking
(global-gumshoe-mode 1)
;; Similarly for the perspective-local gumshoe:
(global-gumshoe-persp-mode 1)
;; Similarly for the buffer-local gumshoe:
(global-gumshoe-buf-mode 1)
;; define a command for autocompletion of the gumshoe--global log if you’d like:
(defun consult-gumshoe-global ()
(interactive)
(consult-global-mark (ring-elements (oref gumshoe--global-backlog log))))
;; Similarly, for the persp local gumshoe--persp log, assuming perspectives is installed:
(defun consult-gumshoe-persp ()
(interactive)
(consult-global-mark (ring-elements (oref gumshoe--persp-backlog log))))
;; Similarly, for the buffer local gumshoe--persp log:
(defun consult-gumshoe-buf ()
(interactive)
(consult-global-mark (ring-elements (oref gumshoe--buf-backlog log)))))
And no need to use all of that of course (though I do), just pick what you like.
- Once global-gumshoe-mode is enabled, gumshoe will automatically start recording movements into the gumshoe–log ringbuffer.
- Use gumshoe-backtrack-back and gumshoe-backtrack-forward to jump backwards and forwards in the log.
- Minibuffer autocompletion: Consult supports autocompletion of global(non buffer-local) marks. I’ve decided to remove built-in support for consult, because there are many great autocompletion packages out there. This is the one I use though, so here’s how I use it. You may define a consult function for gumshoe like so:
(defun consult-gumshoe-global ()
(interactive)
(consult-global-mark (ring-elements (oref gumshoe--global log))))
I then just added that to my use-package definition.
- Configure Gumshoe’s euclidean follow distance by customizing the gumshoe–follow-distance variable.
- Configure Gumshoe’s idle time by customizing the gumshoe-idle-time variable.
- Configure the number of locations logged with the gumshoe-log-len variable.
- Horizontal distance is scaled down by a factor of 3 by default, since columns are approximately that much narrower than rows, but you can modify gumshoe-horizontal-scale if you want.
- I have also provided support for perspectives. This class of gumshoe will then maintain a separate log for each perspective. Enable this mode with the global-gumshoe-persp-mode commands. It uses separate commands: gumshoe-persp-backtrack-back and gumshoe-persp-backtrack-forward, such that all logs can be tracked independently.
- Finally, I have also provided support for buffer-local gumshoes. This class of gumshoe will then maintain a separate log for each buffer. Enable this mode with the global-gumshoe-buf-mode commands described above. It uses separate commands: gumshoe-buf-backtrack-back and gumshoe-buf-backtrack-forward, such that all logs can be tracked independently.
If Gumshoe doesn’t suit you, here are some more Point history tracking packages that may.
- https://github.com/blue0513/point-history
- https://github.com/tcw165/history
- https://github.com/dgutov/point-stack/
- https://github.com/rolandwalker/back-button
- https://github.com/gilbertw1/better-jumper
So why do we need gumshoe then? Gumshoe has:
- temporal tracking
- spatial tracking
- extensible scoping: if you can make arbitrary variables local to your scope, you can make a gumshoe mode for that scope. Scoped logs work independently, and don’t interfere with the global-mark-ring.
- integrates well with autocompletion
- works ootb without much configuration or dependency on external packages
Packages above may have one or two of these features, but changes on the order of a complete rewrite would be required to make them work like gumshoe. But comments are totally welcome if you’d like to open an issue.