Editing Macros

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:

  1. There are extra spaces between the text and the surrounding tags, which we would like to remove, and
  2. 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:

Initial Conditions
Go<Esc>
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
NORMAL
86%
6:1
 

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:

Initial Conditions
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
o<\p>[kO<p>[JJ
NORMAL
88%
7:1
 

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.

Note

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 &#27;, 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:

Initial Conditions
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
o<\p>[kO<p>[JJ
NORMAL
88%
7:1
 
Move the cursor to the first J
fJ
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
o<\p>[kO<p>[JJ
NORMAL
88%
7:13
 
Insert a g
ig
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
o<\p>[kO<p>[gJJ
INSERT
88%
7:14
 
Go back to Normal Mode and move to the end of the line
<Esc>$
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
o<\p>[kO<p>[gJJ
NORMAL
88%
7:15
 
Insert another g
ig
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
o<\p>[kO<p>[gJgJ
INSERT
88%
7:16
 

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:

Initial Conditions
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
o<\p>[kO<p>[gJgJ 
INSERT
88%
7:16
 
Move the Cursor to the end of the line
<Esc>$
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
o<\p>[kO<p>[gJgJ 
NORMAL
88%
7:16
 
Append a j to the line
aj
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
o<\p>[kO<p>[gJgJj
INSERT
88%
7:18
 

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$:

Initial Conditions
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
o<\p>[kO<p>[gJgJj
INSERT
88%
7:18
 
Enter Normal Mode and move the cursor to the beginning of the line
<Esc>0
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
o<\p>[kO<p>[gJgJj
NORMAL
88%
7:1
 
Delete the line and put it into Register a
"ad$
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
 
NORMAL
88%
7:1
 

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:

Initial Conditions
"ad$
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
 
NORMAL
88%
7:1
 
Move the Cursor to line 2
<p>·Beautiful·is·better·than·ugly.·<\p>
Explicit·is·better·than·implicit.
Simple·is·better·than·complex.
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
 
NORMAL
25%
2:1
 
Execute macro by name
@a
<p>·Beautiful·is·better·than·ugly.·<\p>
<p>Explicit·is·better·than·implicit.<\p>
Simple·is·better·than·complex. 
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
 
NORMAL
38%
3:30
 
Repeat previous macro
@@
<p>·Beautiful·is·better·than·ugly.·<\p>
<p>Explicit·is·better·than·implicit.<\p>
<p>Simple·is·better·than·complex.<\p>
Complex·is·better·than·complicated.
Flat·is·better·than·nested.
 
 
NORMAL
50%
4:34
 
Execute macro by name with a Count
2@a
<p>·Beautiful·is·better·than·ugly.·<\p>
<p>Explicit·is·better·than·implicit.<\p>
<p>Simple·is·better·than·complex.<\p>
<p>Complex·is·better·than·complicated.<\p>
<p>Flat·is·better·than·nested.<\p>
 
 
NORMAL
75%
6:1
 

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.