Highlight yanked region in Emacs
OK, so I recently switched over to Emacs just becuse I woke up one day and got the itch to write some lisp. It has been pretty fun so far.
Now with that out of the way, let me tell you about what I was actually planning to write about. The idea is to show you a small example of how I am able to hack together stuff in Emacs.
I know someone will ask for it, so here are my dotfiles. Steal away.
Before switching to Emacs I have been a very heavy (neo)vim user for a long time. And at some point I had the following snippet added from some reddit thread to my vimrc.
autocmd TextYankPost * silent! lua vim.highlight.on_yank({higroup="IncSearch", timeout=200})
What this script did was to highlight the region that I just yanked. This was pretty useful in my transition from doing viwy
to yiw
.
Just a way to verify that I yanked the correct thing. Let me show you what I am talking about.
In the above GIF, I yank the word under the cursor with yiw
and so it highlights that. I have tweaked word
to mean symbol
in evil mode.
That is why it is selecting the full symbol and not just -
which would have been the case in vim.
So, ever since I switch to Emacs, I have wanted to recreate this.
Recenly I came accross an article by Karthinks which introduced me to pulse.el
.
This was pretty much what I was looking for. Now I just need to make this do the highlight on yank thing.
OK, so here is how I approached it.
In the blog, he mentions about pulse-momentary-highlight-one-line
and I knew there had to be a pulse region command.
I started typing pulse-momentary-
and by then Emacs had shown me pulse-momentary-highlight-region
as as autocomplete option.
Cool, that looks like what I want. I opened up the documentation for that I saw that it takes a begin
and end
and an optional face
in case you wanna change that.
(pulse-momentary-highlight-region START END &optional FACE)
Now with that figured out, I had to find how evil figures out the start and end location when I do a yank. I started off with checking out what command gets called when do something with yank.
Hit C-hky and there you go.
This told me that the function that I need to use is evil-yank
and the params for that are as follows.
(evil-yank BEG END &optional TYPE REGISTER YANK-HANDLER)
Cool, looks like I can just add an advice to it. For those who don't know what an advice
is, it pretty much just lets you wrap aroud a function with another.
Kinda like a python wrapper function.
Let me show you what the idea behind an advice is. First you create a function which you use to add as an advice.
(defun my-advice-fun (orig-fn arg1 arg2)
;; Do things you wanna do before calling the function
(apply orig-fn arg1 arg2) ;; Call the original function
;; Do things you wanna do after calling the function
)
Now you ask the function to be added as an advice to some other function using advice-add
.
(advice-add the-function :around #'my-advice-fun)
This will add my-advice-fun
as an advice to the-function
.
OK, with that out of the way, let me show you what we need to do to get a highlight on yank.
First we create the function to be added as an advice.
(defun meain/evil-yank-advice (orig-fn beg end &rest args)
(pulse-momentary-highlight-region beg end)
(apply orig-fn beg end args))
Here we create an function called meain/evil-yank-advice
which first calls pulse-momentary-highlight-region
with the begin
and end
params
and after that calls the orig-fn
with the same begin
and end
. One other thing we have here is &rest args
which pretty much means you collect everything that is not orig-fn
, beg
or end
to rest
.
This way we can easily pass all those optional arguments that evil-yank
will need to it without being aware of them explicitly.
Now to add this advice:
(advice-add 'evil-yank :around 'meain/evil-yank-advice)
Voilà, you have highlight on yank.