In the previous section we looked at a few different ways that we can execute macros, then we identified a few issues with our macro that we would like to fix:
- There are extra spaces between the text and the surrounding tags, which we would like to remove, and
- We want to automatically reposition the cursor after the macro executes so that it executes correctly when used with counts.
Now, let's look at how we can go about doing this. To start, lets jump to the bottom of the buffer with G, then let's add a line so we have some room to work. We can do this with o, and finally hit Esc to get back to normal mode. Our buffer now looks like this:
Let's get editing! We start by executing :put a to insert the contents of the a
register, which is where we stored our macro, into our new line:
Let's take a moment to explain the text that was just inserted into the buffer. When we recorded the macro we followed this sequence of keystrokes:
o<\p><Esc>kO<p><Esc>JJ
However, the text that was pasted into our buffer is slightly different:
o<\p>^[kO<p>^[JJ
what is going on?
While it is convenient for humans to represent keys by their names, such as <Esc>,
terminals represent these keys internally as a sequence of bytes defined by ANSI escape
codes. These codes appear as a sequences of
characters when displayed in a terminal . For example, the bytes representing the escape key
(Esc) are 0x1b, which is rendered in the terminal as ^[ which explains why this is
shown when we insert the macro contents into the buffer.
If you look carefully, the text shown on this page is still slightly different than what you see in your terminal:
o<\p>[kO<p>[JJ
Unfortunately, web browsers sometimes interpret and display bytes differently than terminals,
which can lead to small variations in what is finally displayed. In this case, the browser
interprets the 0x1b byte sequence as text, and renders it as , which is a meaningless
character. In order to keep this page content looking more similar to the terminal, we have
replaced this character with a [.
Now, let's get back to implementing our edits.
The first change that we want to make is to remove the extra spaces that exist between the text and
the surrounding tags. Now, let's look at how the spaces got there to begin with, in order to develop
a plan for removing them. Our original macro used the J command to join lines together,
and when J joins lines it inserts a space between them, which in most cases is exactly what we
would want it to do. However, that isn't what we want to happen in this case. Instead, we should
have used the gJ command , which joins lines like J but does not add a space between
them. We will make this update by first moving the cursor to the first J using fJ, then
insert a g before it by entering insert mode i and typing a g. Next we want to
move to the end of the line and add a g before the second J too, so that we remove the extra
spaces from both the opening and closing tags:
The second change we want to make is to reposition the cursor after the macro executes, which can
be accomplished by simply adding a j to the end of the macro, so that the cursor moves down
one line after execution completes. We implement this change by pressing $ to move to the end of
the line of text, pressing a to move the cursor to the right one space and enter insert mode,
then finally typing the j:
As the final step, after the edits have been completed we need to store the updated macro back into register a and delete it from the buffer. This is done by switching to normal mode (<Esc>) then moving the cursor to the beginning of the line with 0. Finally, we delete all of the text through the end of this line and put it into register a using "ad$:
Finally, let's test the updated macro by first jumping up to the second line, then let's execute the macro using each of the methods that we we learned in the previous section:
At this point our macro is working as expected. The only remaining task is to manually remove the spaces between the text of line 1 and the tags, and we are done.