Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Do you want to know more about how to use macros in Vim? In this talk, learn tips and tricks for mastering macros in Vim with an example project.
This talk was presented by Camilo Payan at VimConf 2021 on October 29, 2021.
[00:00] (techno music)
[00:04] - Hi, my name is Camilo Payan
[00:07] and thank you for coming to this talk,
[00:08] Mastering the Macro-Machine.
[00:10] You can find me online at cam.bio,
[00:12] and let's go right into it.
[00:14] I work for a company called Test Double,
[00:16] where we work to make software better,
[00:17] and as an aside, we're hiring,
[00:21] but as part of my work as a consultant at Test Double,
[00:23] I maintain a library that we have, called Standard RB,
[00:27] which helps Ruby developers get started
[00:28] with a baseline for the popular Ruby linting tool, RuboCop.
[00:32] So for this talk, I went ahead
[00:33] and made myself some silly little tasks.
[00:35] We're gonna disable every cup, and we're going
[00:37] to create a table of contents for the readme file,
[00:40] and I wanna do this all in Vim
[00:42] with the power of movements and macros.
[00:45] So what do I mean by movements?
[00:47] Movements are the building blocks of text editing in Vim.
[00:50] There are commands in normal mode
[00:52] that will move you somewhere else.
[00:53] The most basic, which you probably already know,
[00:55] are H, J, K and L, and what's really great is
[00:58] you can combine those movements by prefixing them
[01:00] with a number to have it more than once.
[01:03] So let's go ahead and demo that
[01:05] by opening up our base config file,
[01:07] and, you know, J goes down, K goes up.
[01:09] If we go over here, L goes
[01:11] to the right, and H goes to the left.
[01:13] Now, if we do 5J, it takes us down five lines,
[01:18] and what do we mean by macros?
[01:20] So a macro is, basically, a recording of the keystroke.
[01:24] So you start one by using Q and the letter
[01:28] that you wanna name your macro.
[01:29] You can also use numbers,
[01:30] but I recommend you use letters for a reason
[01:33] that'll become more obvious later,
[01:35] then you do all your keystrokes, and Vim is recording them,
[01:39] and then you can finish your recording with Q,
[01:42] then you can repeat your with at
[01:44] and the letter that you gave your macro.
[01:49] So let's get to work on disabling every cup in this file,
[01:54] and if we take a look at the config,
[01:57] all these cups are enabled or disabled using this kind
[01:59] of line here where it says enabled true or enabled false.
[02:02] So let's start our macro.
[02:04] I wanna call it A and, first thing's first,
[02:09] we're going to search for the word enabled,
[02:12] then we're gonna hit L a bunch of times
[02:13] to get to where we wanna be, and then we'll change the rest.
[02:17] We'll just put an F for now,
[02:19] and then once we're back in normal mode,
[02:21] we hit Q to finish recording.
[02:24] So now, if I go down to line 17,
[02:26] and I run @A, it runs it again.
[02:29] So this is the general idea of macros.
[02:32] I don't have to redo all of the keystrokes
[02:35] by hand over and over again.
[02:36] Saves to you a bunch of time.
[02:38] Now, F is for respect, but we actually want
[02:41] the whole word false, and we're gonna do that
[02:43] by appending to the end of the macro.
[02:45] So I made my macro QA.
[02:49] So I'm going ahead and, at the same spot
[02:51] where my macro ends, use Q, capital A,
[02:54] and you can see, it now says "recording @A,"
[02:57] and let's append to the end of the line
[03:01] and finish recording our macro with Q
[03:04] and now, even if I change this
[03:05] to something really cool, it works.
[03:10] I didn't have to re-record my macro
[03:11] from scratch, and the reason that
[03:12] that works is because of Vim's registers.
[03:16] So your macros are stored, just
[03:19] like everything else in Vim's registers.
[03:21] So if you run the registers command,
[03:22] you can take a look at them.
[03:23] There's a bunch of them around here.
[03:25] They are named after letters and numbers
[03:27] and there are some special names too
[03:29] but in this case, we chose the name A, for our macro,
[03:32] and you can see here, these are all the keystrokes
[03:34] that I was doing to make the macro work,
[03:38] even the part that we appended
[03:39] to the end of the macro is still there.
[03:43] Now, the cool part about this is
[03:44] because we know where this is,
[03:47] we can start manipulating our macro by taking it out
[03:53] of the register, and we can change it
[03:57] and in this way, we can go ahead and improve our macro
[03:59] by using some more interesting movements than HJKL.
[04:04] So, you know, one kind
[04:06] of low-hanging fruit here is all these Ls.
[04:09] We wanna replace those with something
[04:11] a little more elegant, a little smaller.
[04:14] So let me go ahead and introduce you to these movements.
[04:17] W takes you to the beginning of the next word.
[04:19] So to the slash, to the capital G,
[04:21] and to the colon on this line.
[04:24] E actually goes to the end of the word
[04:26] that you are currently on.
[04:27] So instead of going to the slash, you're gonna go to the R.
[04:30] Slash is considered a word and for the next one,
[04:33] it's gonna go to this T, instead of going to the G.
[04:36] So that's a useful thing, especially if you need
[04:38] to append to the end of the word.
[04:40] B goes backward a word.
[04:42] So it's kind of the opposite of W,
[04:45] and I really like using these a lot, in my day-to-day.
[04:49] F forward-searches on a letter.
[04:52] So if I do F to the colon, that goes to the end.
[04:55] Let's do FE, and then you can use a semicolon
[04:58] to keep searching forward for the next E that happens
[05:01] and similarly, there's a reverse version
[05:02] with the capital F, capital FE, and you can use colon
[05:06] and go backward to wherever the next E is.
[05:10] So I'm looking at this line.
[05:12] I'm thinking we go ahead and use F;
[05:14] to get to the colon and use W to get
[05:16] to the beginning of the next word,
[05:17] and that should do great, and it's actually a pattern
[05:20] that you can use a lot in YAML files like this.
[05:23] So let's change all these Ls and hit F;W.
[05:31] Now, we can yank all of this into our A-register,
[05:37] and I can show you, right?
[05:39] Those Ls are gone.
[05:40] F;W, that's what we've got now,
[05:44] and let's go ahead and change this to some really cool name
[05:47] that I just made up and run it again,
[05:50] and we get exactly what we were expecting
[05:53] 'cause, you know, nothing actually changed,
[05:54] but we did make this macro a little smaller,
[05:56] a little more easy to read, if we need
[05:57] to keep changing it, which we are going to.
[06:00] So one handy tip is to go ahead and prefix your macros.
[06:03] This helps a lot with consistency.
[06:05] So sometimes your macro, especially if you're working
[06:07] with a less structured document like this,
[06:09] like code or a text document, you don't know exactly
[06:12] where your macros going to end up.
[06:14] So it would be who of you to make sure
[06:16] your macro always starts in the same kind of spot.
[06:19] So these movements will help you a lot with that.
[06:21] You can use zero to get to the zeroth character,
[06:24] which will always be the very first character
[06:26] on the line, or you can use caret to get
[06:28] to the first non-white-space character on the line.
[06:31] Those are both pretty useful for this.
[06:32] I'm going to go ahead and use zero,
[06:36] and let's yank that back into our register.
[06:40] Make sure it's there.
[06:41] All right, there's a zero that we wanted
[06:44] and now, even if I'm at the end of the line,
[06:50] I run my macro with @A, and because it goes back
[06:53] to the beginning of the line, and make sure
[06:54] to change it right there, instead of, you know,
[06:56] maybe going to the line like the search would've.
[06:59] Another thing you can do is suffix your macros.
[07:02] So you wanna suffix your macro in order
[07:04] to set up the next one of the macro,
[07:06] and then you can repeat it like we did with 5J
[07:09] and really unlock the repetition of your macro.
[07:14] Now, these are different movements that you could be using.
[07:17] So Plus takes you to the beginning of the next line.
[07:21] So here it goes to the dash.
[07:22] Over there, went to the capital E,
[07:25] and it's basically the same as using J
[07:27] and then the caret key, but, you know, it's only one key.
[07:29] So that's nice.
[07:31] Another thing that you could use
[07:32] for suffixing is N, which takes you
[07:35] to the next instance of your search,
[07:36] and that could be useful here because, actually,
[07:38] we are search for the word enabled,
[07:41] and another thing that you could do is use star,
[07:44] which takes you to the next instance
[07:45] of the word under your cursor, which is really useful,
[07:48] depending on what you're doing,
[07:49] but it's worth remembering that it does replace your search.
[07:53] So now, if you hit N, it's gonna be looking
[07:55] for bundler and not enabled.
[07:58] For the purposes of this macro,
[08:00] I'm gonna go ahead and add a plus.
[08:02] Let's go ahead and yank it back into our A-register,
[08:05] which we won't actually be able to see that
[08:08] and now, I can go ahead, and let's go
[08:11] to number 10, hit @A, and it works,
[08:15] and it takes us to the next line,
[08:16] which means I could do something like 20@A,
[08:19] and it's just gonna keep running without having any problem.
[08:23] This is a long file.
[08:24] So we could let it run for quite a while,
[08:25] but since we suffixed it with something
[08:27] that sets up the next run, we can take advantage
[08:29] of this and look how little typing I'm doing,
[08:33] but a lot of work got done.
[08:36] All right, so the next task that I gave myself was creating
[08:39] a table of contents for reading use.
[08:41] So when a reading file gets pretty long
[08:43] for an open source project like this,
[08:45] I really like for there to be some kind
[08:48] of table of contents.
[08:49] That way I can go straight to information
[08:50] that I want without having to, like, kind
[08:52] of read through the whole file
[08:54] and since this is a Markdown file, we can kind of guess
[08:57] that every heading is gonna start with a hash.
[09:00] There's actually a Ruby comment here,
[09:02] but it looks like we're starting with two hashes anyway.
[09:06] So that's how we're gonna get our information,
[09:09] and I want to create this table
[09:10] of contents using marks and jumps.
[09:16] So here we are starting at the top.
[09:17] I think after the intro would be a good place
[09:19] for the table of contents,
[09:24] and what is a mark?
[09:25] So a mark is a way that Vim keeps track
[09:28] of a spot that you tell it
[09:32] and in this case, we're gonna do
[09:33] that with the command M and Z
[09:36] to set a mark called Z right here on line 38.
[09:38] Now, no matter where I am, I can use the jump command,
[09:41] which is a single quote and in this case,
[09:43] a Z to go back to the same spot.
[09:45] As a matter of fact, at the beginning
[09:46] of the document or at the end, I can always go back
[09:48] to the same spot as long as I remember the name.
[09:52] So let's get to work on our macro.
[09:55] We're gonna go ahead and record it in A again,
[09:58] and we'll prefix it with a zero.
[09:59] Start with searching forward for the next heading.
[10:04] Let's go forward a word and into our S-register.
[10:08] I'm gonna go ahead and yank all of this.
[10:11] Now, let's go to the next line,
[10:12] and I want to start thinking ahead
[10:14] and set up the next run of this
[10:15] by creating a mark right here.
[10:17] We're gonna call it X.
[10:19] Now, let's jump back to where we want our table of contents.
[10:23] That's not great. We'll get rid of that in a second.
[10:29] Go to INSERT
[10:33] and put in our stuff.
[10:35] Gonna make a markdown link.
[10:37] I give it anchor.
[10:39] I'm really not sure if GitHub will accept just
[10:42] the text like that, but, you know,
[10:44] we can figure that out some other time.
[10:48] Now, I wanna create a new mark here.
[10:51] That's gonna be our new Z mark,
[10:53] and let's go back to our X mark, and that's it.
[10:57] That's our macro.
[10:59] Now, I already remember that there was actually
[11:04] a problem in my macro.
[11:08] I'm not really sure where that was,
[11:09] but let's see if it works.
[11:12] Now, the next heading, I think, is usage.
[11:16] So let's see if that works. Yeah.
[11:18] See, I have an error in the middle of my macro.
[11:21] So this is when I started putting this stuff together.
[11:27] This looks good. This is.
[11:33] All of that must go.
[11:43] Cool. Now, we have a macro that works.
[11:50] Now, if you run it again, we should get usage.
[11:53] Let's take a look for our table of contents.
[11:55] Yeah, we have usage going up here
[11:58] and now, if you run it, you know, like five more times,
[12:00] that's gonna be fun to watch, 10 more times.
[12:03] I don't actually know how many headers there are here.
[12:05] Let's try another five. I think that takes us.
[12:08] Let's do another one and now, we have a problem.
[12:10] We went to the beginning of the document again.
[12:13] So let's take a look at a table of contents.
[12:16] We have everything that we expect
[12:17] but now, we have the title.
[12:19] We don't want that. How can we solve this?
[12:21] We can do it using a recursive macro, and let's go ahead
[12:27] and get rid of the table of contents that we've created.
[12:30] Make a new mark.
[12:31] Now, recursive macros will we'll go ahead
[12:33] and run the macro inside your macro.
[12:34] So then it just keeps running,
[12:36] but in this case, since we're relying on a search,
[12:39] Vim we'll go ahead and wrap to the beginning
[12:40] of the document if you are still searching at that point,
[12:44] and you're at the end of the document,
[12:45] but we wanna get rid of that because a recursive macro
[12:47] won't stop unless there's an error,
[12:49] which is actually why I had to fix that out of the macro
[12:51] 'cause it was gonna stop in the middle of it.
[12:53] So how are we gonna get it to error out?
[12:55] We're gonna use this setting, nowrapscan.
[12:58] So if you hit nowrapscan, what happens is,
[13:02] even if you're at the end
[13:03] of the document and you keep searching.
[13:05] So we wanna search for table of contents.
[13:07] It's not gonna keep going past the end of the document.
[13:11] So that will be useful in this case
[13:14] because now, if I finish my macro
[13:17] by hitting @A and yank that back into my register
[13:25] and let it run, it's just gonna run itself over
[13:29] and over, but when it gets to the end
[13:30] of the document, it's going to stop.
[13:32] So code of conduct is the last one that we were looking at.
[13:35] Let's take a look at table of contents.
[13:36] Yeah, it goes all the way from the rules to code of conduct.
[13:39] Looks great. Mission accomplished.
[13:44] Now, one more thing that we could take a look
[13:45] at is this setting here, lazyredraw.
[13:48] It's really fun, and it's cool for demos
[13:49] to watch your macro run but with lazyredraw,
[13:54] you can skip all of that and, you know,
[13:57] not just sit here and watching your computer work.
[13:59] It's going to wait until all of the commands are finished,
[14:03] and then that's when it's going
[14:06] to actually redraw your file.
[14:12] So there we go.
[14:16] It can be useful, but I kind of like watching macros.
[14:20] Anyways, thank you so much for coming to this talk.
[14:22] I hope you enjoy the rest of the conference.
[14:24] You can find me online at cam.bio.
[14:26] I'm Cam on the discord and also a reminder,
[14:30] Test Double is hiring and, you know, if you'd like
[14:33] to come work, just go ahead and ask any questions
[14:35] that you have, and there's also of information at that link.
[14:39] All right, let me see where my thingy is.
[14:44] (hands clapping)
[14:45] Cool.
[14:48] That's it. Thank you so much, everybody.
[14:55] (Camilo laughs)
[15:16] I guess I can stop screen-sharing
[15:17] - [Moderator 1] Mic's all the way down.
[15:18] - [Moderator 2] Yeah, I turned the mic down.
[15:19] I see that. - Okay.
[15:20] Yeah, we've been talking for 30 seconds now.
[15:22] Yep, they can bang, scuffed in the chat.
[15:24] - [Moderator 2] Bang, scuffed, great streamer here.
[15:26] - [Moderator 1] (laughs) That talk was awesome.
[15:29] Super cool, really Vimy. I love it.
[15:31] Chat? Does anyone have any questions
[15:33] they'd like to give to Camilo quick?
[15:39] - [Moderator 2] I mean, I, personally,
[15:40] have something I would like to say which is,
[15:44] I mean, you were doing a lot of macros there,
[15:46] yet I didn't see any macro pressure.
[15:48] You seem to be breezing.
[15:50] How does one master macro so well
[15:52] that you don't feel macro pressure?
[15:54] - Yeah. (Camilo laughs)
[15:55] How do you move from just being a normy macro user.
[15:57] - [Moderator 2] Yeah, I'm a normy.
[15:58] - [Moderator 1] To sort of this no pressure,
[16:00] never cracks under pressure macro master?
[16:03] - [Moderator 2] Macroception, macro master?
[16:04] - Oh, my God. (laughs)
[16:08] For these macros, practicing, maybe,
[16:10] like 30, 40 times before this talk,
[16:12] but, generally, you know, the more you use 'em,
[16:14] the more you'll end up with like patterns that you go back
[16:16] to a bunch of times, you know, like prefixing, suffixing,
[16:19] all that stuff is gonna end up coming naturally
[16:21] as long as you're intentional about doing it
[16:25] and then yeah, repetition just like learning Vim.
[16:28] As long as you keep repeating it,
[16:31] you'll end up figuring it out.
[16:34] - Okay, I mean, I'm shocked. (Camilo laughs)
[16:37] Okay, I tried that.
[16:39] I thought I tried that, but it-
[16:41] - [Moderator 1] I thought a good question was asked
[16:42] in the chat about running macros over multiple files.
[16:46] Do you have any tricks for that?
[16:48] - Oh yeah.
[16:49] So actually, one thing that you can do
[16:51] that I find makes that easier is creating a function,
[16:53] and then you can kind of slam your macro
[16:55] into that by using the normal command,
[16:57] and then you can use something like.
[17:00] I find it easier to go ahead and do that
[17:02] with, you know things like the arg list,
[17:04] and I forget what the other list is called
[17:07] to have like a function that you call,
[17:09] but I do remember doing it with just macros in the past.
[17:12] I just don't remember (laughs) how I did it.
[17:15] - [Moderator 2] Yeah that seems like magic to me.
[17:17] - [Moderator 1] I don't know about any of that.
[17:19] Yeah, I guess the only other way I could think
[17:21] of would be if you tried to do something like, maybe,
[17:24] run it over your quick-fix list or something like that.
[17:27] If you added all of them to the quick-fix list.
[17:30] - What's that for? - You could try
[17:30] and run something with like cdo or something like that.
[17:32] - Yeah. I've see done. - I always laugh
[17:34] when I say cdo 'cause I imagine myself riding
[17:36] around on a Sea-Doo in the water using Vim,
[17:39] and it's just kind of a hilarious mental picture for myself.
[17:42] - [Moderator 2] I like cdo because sea stands for quick,
[17:45] and it makes me really happy.
[17:47] (Moderator 1 laughs)
[17:48] - I'm pretty sure that you could do something
[17:50] like cdo and normal and then whatever
[17:54] your macro is here. - Yeah, I think so.
[17:55] - Which you probably get out of the register
[17:57] by doing something like Control A.
[18:00] Yeah, there's a macro. (laughs)
[18:02] - [Moderator 1] Cool. Awesome.
[18:03] Well, thanks a bunch, Camilo and-
[18:05] - [Moderator 2] We do have one more question.
[18:06] - Oh, okay. - It's a good question.
[18:07] How do you edit an existing macro?
[18:10] - Yeah, so it's kind of hard to demo.
[18:13] So I kind of glossed over it,
[18:14] but the idea is you just want to kind of put it somewhere.
[18:18] So I have a little scratch buffer here,
[18:20] and then you can do whatever edits that you want to it,
[18:23] then the next step is to yank it back
[18:26] into the register that you had it in in the first place,
[18:28] and so that would be the same way
[18:31] that you yank anything else.
[18:32] You use a double quote and the register that you want
[18:34] and then why and however you wanna do that.
[18:37] Just make sure you don't use, you know,
[18:39] YY to get the whole line because
[18:41] you'll end up with a carriage return at the end
[18:42] of your macro, and that will definitely mess up the macro.
[18:46] So you wanna use Y, usually,
[18:47] to dollar sign the end of the line.
[18:49] - [Moderator 1] So what you're trying to tell me is
[18:51] that when you yank into a register,
[18:54] it's the same thing as recording a macro to a register.
[18:57] That's where the macros go?
[18:58] - Yeah, yeah.
[18:59] So once you look at your register,
[19:01] these are the key strokes that you did,
[19:03] and so it just runs 'em over and over again,
[19:05] then it's cool.