Revise ch13

This commit is contained in:
Igor Irianto 2021-01-22 15:45:40 -06:00
parent cca85716bd
commit 1ca05c9247

View file

@ -2,13 +2,13 @@
So far you have learned how to repeat the last change with the dot command (`.`), to replay actions with macros (`q`), and to store texts in the registers (`"`). So far you have learned how to repeat the last change with the dot command (`.`), to replay actions with macros (`q`), and to store texts in the registers (`"`).
In this chapter, you will learn how to repeat a command-line command with the global command. Run once, apply everywhere (in a buffer). In this chapter, you will learn how to repeat a command-line command with the global command.
## Global Command Overview ## Global Command Overview
Vim's global command is used to running a command-line command on multiple lines simultaneously. Vim's global command is used to run a command-line command on multiple lines simultaneously.
By the way, you may have heard of the term "Ex Commands" before. In this guide, I refer them as command-line commands, but both Ex commands and command-line commands are the same. They are the commands that start with a colon (`:`). In the last chapter, you learned about the substitute command. It was an example of an Ex command. They are called Ex because they originally came from the Ex text editor. I will continue to refer to them as command-line commands in this guide. For a full list of Ex commands, check out `:h ex-cmd-index`. By the way, you may have heard of the term "Ex Commands" before. In this guide, I refer them as command-line commands. Both Ex commands and command-line commands are the same. They are the commands that start with a colon (`:`). The substitute command in the last chapter was an example of an Ex command. They are called Ex because they originally came from the Ex text editor. I will continue to refer to them as command-line commands in this guide. For a full list of Ex commands, check out `:h ex-cmd-index`.
The global command has the following syntax: The global command has the following syntax:
@ -49,7 +49,7 @@ const three = 3;
The global command executes the delete command (`d`) on all lines that match the "console" pattern. The global command executes the delete command (`d`) on all lines that match the "console" pattern.
When running the `g` command, Vim makes two scans across the file. On the first run, it scans each line and marks the line that matches the `/console/` pattern. Once all the matching lines are marked, it makes the second run, where it executes the `d` command on the marked lines. When running the `g` command, Vim makes two scans across the file. On the first run, it scans each line and marks the line that matches the `/console/` pattern. Once all the matching lines are marked, it goes for the second time and executes the `d` command on the marked lines.
If you want to delete all lines containing "const" instead, run: If you want to delete all lines containing "const" instead, run:
@ -135,7 +135,6 @@ To match the lines containing between three to six zeroes, run:
## Passing A Range ## Passing A Range
You can pass a range before the `g` command. Here are some ways you can do it: You can pass a range before the `g` command. Here are some ways you can do it:
- `:1,5g/console/d` matches the string "console" between lines 1 and 5 and deletes them. - `:1,5g/console/d` matches the string "console" between lines 1 and 5 and deletes them.
- `:,5g/console/d` if there is no address before the comma, then it starts from the current line. It looks for the string "console" between the current line and line 5 and deletes them. - `:,5g/console/d` if there is no address before the comma, then it starts from the current line. It looks for the string "console" between the current line and line 5 and deletes them.
- `:3,g/console/d` if there is no address after the comma, then it ends at the current line. It looks for the string "console" between line 3 and the current line and deletes them. - `:3,g/console/d` if there is no address after the comma, then it ends at the current line. It looks for the string "console" between line 3 and the current line and deletes them.
@ -162,21 +161,22 @@ console.log("two: ", two)
const three = 3 const three = 3
console.log("three: ", three) console.log("three: ", three)
``` ```
To add a ";" to the end of each line, run: To add a ";" to the end of each line, run:
``` ```
:g/./normal A; :g/./normal A;
``` ```
Let's break it down: Let's break it down:
- `:g` is the global command. - `:g` is the global command.
- `/./` is a pattern for "non-empty lines". Recall that the dot (`.`) in regex represents *any character*. It matches the lines with at least one character, so it matches the lines with "const" and "console". It does not match empty lines. - `/./` is a pattern for "non-empty lines". It matches the lines with at least one character, so it matches the lines with "const" and "console" and it does not match empty lines.
- `normal A;` runs the `:normal` command-line command. `A;` is the normal mode command to insert a ";" at the end of the line. - `normal A;` runs the `:normal` command-line command. `A;` is the normal mode command to insert a ";" at the end of the line.
## Executing A Macro ## Executing A Macro
You can also execute a macro with the global command. A macro is just a normal mode operation, so it is possible to execute a macro with `:normal`. If you have the expressions: You can also execute a macro with the global command. A macro can be executed with the `normal` command. If you have the expressions:
``` ```
const one = 1 const one = 1
@ -192,7 +192,7 @@ console.log("three: ", three);
Notice that the lines with "const" do not have semi-colons. Let's create a macro to add a comma to the end of those lines in the register "a: Notice that the lines with "const" do not have semi-colons. Let's create a macro to add a comma to the end of those lines in the register "a:
``` ```
qa0A;<esc>q qa0A;<Esc>q
``` ```
If you need a refresher, check out the chapter on macro. Now run: If you need a refresher, check out the chapter on macro. Now run:
@ -214,11 +214,13 @@ const three = 3;
console.log("three: ", three); console.log("three: ", three);
``` ```
If you followed this step-by-step, you will have two semi-colons on the first line. To avoid that, run the global command on line two onward, `:2,$g/const/normal @a`.
## Recursive Global Command ## Recursive Global Command
The global command itself is a type of a command-line command, so you can technically run the global command inside a global command. The global command itself is a type of a command-line command, so you can technically run the global command inside a global command.
Given the expressions: Given the following expressions, if you want to delete the second `console.log` statement:
``` ```
const one = 1; const one = 1;
@ -237,7 +239,7 @@ If you run:
:g/console/g/two/d :g/console/g/two/d
``` ```
First, `g` will look for the lines containing the pattern "console" and find 3 matches. Then the second `g` will look for the line containing the pattern "two" from those three matches. Finally, it will delete that match. First, `g` will look for the lines containing the pattern "console" and will find 3 matches. Then the second `g` will look for the line containing the pattern "two" from those three matches. Finally, it will delete that match.
You can also combine `g` with `v` to find positive and negative patterns. For example: You can also combine `g` with `v` to find positive and negative patterns. For example:
@ -287,13 +289,11 @@ By the way, here is one interesting fact. Because the default command used by th
- `re` = the regex pattern - `re` = the regex pattern
- `p` = the print command - `p` = the print command
It spells *"grep"*, the same `grep` from the command line. This is **not** a coincidence. The `g/re/p` command originally came from the Ed Editor, one of the first line text editors. The `grep` command got its name from Ed. It spells *"grep"*, the same `grep` from the command line. This is **not** a coincidence. The `g/re/p` command originally came from the Ed Editor, one of the original line text editors. The `grep` command got its name from Ed.
Your computer probably still has the Ed editor. Run `ed` from the terminal (hint: to quit, type `q`). Your computer probably still has the Ed editor. Run `ed` from the terminal (hint: to quit, type `q`).
## More Examples ## Reversing The Entire Buffer
## Reverse The Entire Buffer
To reverse the entire file, run: To reverse the entire file, run:
@ -301,7 +301,7 @@ To reverse the entire file, run:
:g/^/m 0 :g/^/m 0
``` ```
`^` is a pattern for the "beginning of a line". Use `^` to match all lines, including empty lines. `^` is a pattern for the beginning of a line. Use `^` to match all lines, including empty lines.
If you need to reverse only a few lines, pass it a range. To reverse the lines between line five to line ten, run: If you need to reverse only a few lines, pass it a range. To reverse the lines between line five to line ten, run:
@ -313,7 +313,7 @@ To learn more about the move command, check out `:h :move`.
## Aggregating All TODOs ## Aggregating All TODOs
When I code, sometimes I think of a random brilliant ideas. Not wanting to lose concentration, I usually write them down in the file I am editing, for example: When coding, sometimes I would write TODOs in the file I'm editing:
``` ```
const one = 1; const one = 1;
@ -359,7 +359,7 @@ console.log("three: ", three);
Now I can review all the TODOs I created, find a time to do them or delegate them to someone else, and continue to work on my next task. Now I can review all the TODOs I created, find a time to do them or delegate them to someone else, and continue to work on my next task.
Another alternative is to use `m`: If instead of copying them you want to move all the TODOs to the end, use the move command, `:m`:
``` ```
:g/TODO/m $ :g/TODO/m $
@ -382,8 +382,6 @@ console.log("three: ", three);
// TODO: create a startup selling an automatic puppy feeder // TODO: create a startup selling an automatic puppy feeder
``` ```
I can just delete the list once I decided what to do with it.
## Black Hole Delete ## Black Hole Delete
Recall from the register chapter that deleted texts are stored inside the numbered registers (granted they are sufficiently large ). Whenever you run `:g/console/d`, Vim stores the deleted lines in the numbered registers. If you delete many lines, you can quickly fill up all the numbered registers. To avoid this, you can always use the black hole register (`"_`) to *not* store your deleted lines into the registers. Run: Recall from the register chapter that deleted texts are stored inside the numbered registers (granted they are sufficiently large ). Whenever you run `:g/console/d`, Vim stores the deleted lines in the numbered registers. If you delete many lines, you can quickly fill up all the numbered registers. To avoid this, you can always use the black hole register (`"_`) to *not* store your deleted lines into the registers. Run:
@ -392,7 +390,7 @@ Recall from the register chapter that deleted texts are stored inside the number
:g/console/d _ :g/console/d _
``` ```
By passing `_` after `d`, Vim won't save the deleted lines into any registers. By passing `_` after `d`, Vim won't use up your scratch registers.
## Reduce Multiple Empty Lines To One Empty Line ## Reduce Multiple Empty Lines To One Empty Line
@ -440,7 +438,7 @@ With that in mind, let's break down the command `:g/^$/,/./-1j` according to `:g
- `/pattern2/` is `/./` with `-1` line modifier. `/./` represents a non-empty line (a line with at least one character). The `-1` means the line above that. - `/pattern2/` is `/./` with `-1` line modifier. `/./` represents a non-empty line (a line with at least one character). The `-1` means the line above that.
- `command` is `j`, the join command (`:j`). In this context, this global command joins all the given lines. - `command` is `j`, the join command (`:j`). In this context, this global command joins all the given lines.
By the way, if you want to reduce multiple empty lines into no lines, instead of using `,/./-1` as the range for `j` command, just use `,/./` as the range instead: By the way, if you want to reduce multiple empty lines to no lines, run this instead:
``` ```
:g/^$/,/./j :g/^$/,/./j
@ -475,7 +473,7 @@ e
c c
``` ```
You can sort them by running `:sort`. If you give it a range, it will sort only the lines within that range. For example, `:3,5sort` sorts only between lines three and five. You can sort them by running `:sort`. If you give it a range, it will sort only the lines within that range. For example, `:3,5sort` only sorts lines three and five.
If you have the following expressions: If you have the following expressions:
@ -510,6 +508,7 @@ If you need to sort the elements inside the arrays, but not the arrays themselve
``` ```
Result: Result:
``` ```
const arrayB = [ const arrayB = [
"a", "a",
@ -534,27 +533,20 @@ const arrayA = [
] ]
``` ```
This is great! But the command looks complicated. Let's break it down. The command consists of three main parts: the global command pattern, the sort command range, and the sort command. :g/\[/+1,/\]/-1sort
This is great! But the command looks complicated. Let's break it down. This command also follows the form `:g/pattern1/,/pattern2/command`.
`:g/\[/` is the global command pattern. `:g/\[/` is the global command pattern.
- `:g` is the global command. - `/\[/+1` is the first pattern. It matches a literal left square bracket "[". The `+1` refers to the line below it.
- `/\[/` is the pattern used by the global command. `\[` looks for a literal "[" string. - `/\]/-1` is the second pattern. It matches a literal right square bracket "]". The `-1` refers to the line above it.
- `/\[/+1,/\]/-1` then refers to any lines between "[" and "]".
`+1,/\]/-1` is the range for the sort command. - `sort` is a command-line command to sort.
- A range can have a starting and an ending addresses. In this case, `+1` is the starting address and `/\]/-1` is the ending address.
- `+1` represents the line after the current line, which is the line that matches the pattern "[" from the global command. `+1` offsets the current line by one line. So in the first match, the range actually starts one line *after* the `const arrayB = [` text.
- `/\]/-1` is the ending address. `\]` represents a literal closing square bracket "]". `-1` offsets it by one line. The ending address is the line above the "]".
`sort` is the sort command-line command. It sorts everything within the given range. Everything after the "[" to the line above "]" is getting sorted.
If you are still confused by the command, do not worry. It took me a long time to grasp it. Take a break, leave the screen, and come back again with a fresh mind.
## Learn The Global Command The Smart Way ## Learn The Global Command The Smart Way
The global command executes the command-line command against all matching lines. With it, you only need to run a command once and Vim will do the rest for you. To become proficient at the global command, two things are required: a good vocabulary of command-line commands and a knowledge of regular expressions. As you spend more time using Vim, you will naturally learn more command-line commands. A regular expression knowledge will require a more active approach. But once you become comfortable with regular expressions, you will be ahead of many. The global command executes the command-line command against all matching lines. With it, you only need to run a command once and Vim will do the rest for you. To become proficient at the global command, two things are required: a good vocabulary of command-line commands and a knowledge of regular expressions. As you spend more time using Vim, you will naturally learn more command-line commands. A regular expression knowledge will require a more active approach. But once you become comfortable with regular expressions, you will be ahead of many.
Some of the examples here are complicated. Do not be intimidated. Really take your time to understand them. Learn to read the patterns. Make sure you know what each letter in each command represent. Do not give up. Some of the examples here are complicated. Do not be intimidated. Really take your time to understand them. Learn to read the patterns. Do not give up.
Whenever you need to apply a command in several locations, pause and see if you can use the `g` command. Look for the best command for the job and write a pattern to target as many things at once. Then repeat it until you can do it without thinking. The next time, see if there is even a faster and more efficient way to do it. Whenever you need to run multiple commands, pause and see if you can use the `g` command. Identify the best command for the job and write a pattern to target as many things at once.
Now that you know how powerful the global command is, let's learn how to use the external commands to increase your tool arsenals. Now that you know how powerful the global command is, let's learn how to use the external commands to increase your tool arsenals.