Revise ch17

pull/62/head
Igor Irianto 3 years ago
parent dc23c6857a
commit 5f2f07fc93

@ -1,14 +1,14 @@
# Ch17. Fold
When you read a file, often there are many irrelevant text that hinders you from understanding what that file does. To hide this unnecessary information, you can use Vim fold.
When you read a file, often there are many irrelevant texts that hinder you from understanding what that file does. To hide the unnecessary noise, use Vim fold.
In this chapter, you will learn how to use different folding methods.
In this chapter, you will learn different ways to fold a file.
## Manual Fold
Imagine that you are folding a sheet of paper to cover some text. The actual text does not go away, it is still there. Vim fold works the same way. It *folds* a range of text, hiding it from display without actually deleting it.
Imagine that you are folding a sheet of paper to cover some text. The actual text does not go away, it is still there. Vim fold works the same way. It folds a range of text, hiding it from display without actually deleting it.
The fold operator is `z`. When you fold a paper, the fold looks like the letter "z" too.
The fold operator is `z` (when a paper is folded, it is shaped like the letter z).
Suppose you have this text:
@ -24,17 +24,16 @@ Type `zfj`. Vim folds both lines into one. You should see something like this:
```
Here is the breakdown:
- `zf` `zf` is the fold operator.
- `j` is the motion for the fold operator.
You can open a folded text with `zo`. To close the fold, use `zc`.
Vim fold follows the grammar rule. You can pass the fold operator with a motion or text object. To fold an outer paragraph, run `zfap`. To fold to the end of a file, run `zfG`. To fold the texts between `{` and `}`, run `zfa{`.
Fold is an operator, so it follows the grammar rule (`verb + noun`). You can pass the fold operator with a motion or text object. To fold an inner paragraph, run `zfip`. To fold to the end of a file, run `zfG`. To fold the texts between `{` and `}`, run `zfa{`.
You can fold from the visual mode. Highlight the area you want to fold (`v`, `V`, or `Ctrl-v`), then run `zf`.
A Vim operator is not complete without the command-line mode version. You can execute a fold from the command-line mode with the `:fold` command. To fold the current line and the line after it, run:
You can execute a fold from the command-line mode with the `:fold` command. To fold the current line and the line after it, run:
```
:,+1fold
@ -92,7 +91,7 @@ With indent fold, Vim looks at how many spaces each line has at the beginning an
:set shiftwidth?
```
Vim's default `'shiftwidth'` value is 2. On the text above, there are two spaces between the start of the line and the text "Two" and "Two again". When Vim sees the number of spaces *and* that the `'shiftwidth'` value is 2, Vim considers that line to have an indent fold level of one.
Vim's default `'shiftwidth'` value is 2. On the text above, there are two spaces between the start of the line and the text "Two" and "Two again". When Vim sees the number of spaces and that the `'shiftwidth'` value is 2, Vim considers that line to have an indent fold level of one.
Suppose this time you only one space between the start of the line and the text:
@ -102,13 +101,15 @@ One
Two again
```
Right now if you run `:set foldmethod=indent`, Vim does not fold the indented line because there isn't sufficient space on each line. However, if you change the `'shiftwidth'` to 1:
Right now if you run `:set foldmethod=indent`, Vim does not fold the indented line because there isn't sufficient space on each line. One space is not considered an indentation. However, if you change the `'shiftwidth'` to 1:
```
:set shiftwidth=1
```
The text is now foldable. Restore the shiftwidth back to two and the spaces between the texts to two again. In addition, add:
The text is now foldable. It is now considered an indentation.
Restore the `shiftwidth` back to 2 and the spaces between the texts to two again. In addition, add two additional texts:
```
One
@ -136,7 +137,7 @@ One
What's this? A fold within a fold?
You can have nested folds. The text "Two" and "Two again" have fold level of one. The text "Three" and "Three again" have fold level of two. If you have a foldable text with a higher fold level within a foldable text, you can have multiple fold layers.
Nested folds are valid. The text "Two" and "Two again" have fold level of one. The text "Three" and "Three again" have fold level of two. If you have a foldable text with a higher fold level within a foldable text, you will have multiple fold layers.
## Marker Fold
@ -171,10 +172,10 @@ Vim sees `{{{` and `}}}` as fold indicators and folds the texts between them. Wi
:set foldmarker?
```
By default, Vim uses `{{{` and `}}}` as indicators. If you want to change the indicator to another texts, like "foo1" and "foo2":
By default, Vim uses `{{{` and `}}}` as indicators. If you want to change the indicator to another texts, like "coffee1" and "coffee2":
```
:set foldmarker=foo1,foo2
:set foldmarker=coffee1,coffee2
```
If you have the text:
@ -182,54 +183,44 @@ If you have the text:
```
hello
foo1
coffee1
world
vim
foo2
coffee2
```
Now Vim uses `foo1` and `foo2` as the new folding markers. As a side note, an indicator must be a literal string and cannot be a regex.
Now Vim uses `coffee1` and `coffee2` as the new folding markers. As a side note, an indicator must be a literal string and cannot be a regex.
## Syntax Fold
Vim has a syntax system to customize the text syntax (highlight, weight, color, etc). This chapter won't discuss how the syntax system works, but you can use this to indicate which text to fold. To use a syntax fold, run:
Syntax fold is determined by syntax language highlighting. If you use a language syntax plugin like [vim-polyglot](https://github.com/sheerun/vim-polyglot), the syntax fold will work right out of the box. Just change the fold method to syntax:
```
:set foldmethod=syntax
```
Suppose you have this text and you want to fold everything between the square brackets:
Let's assume you are editing a JavaScript file and you have vim-polyglot installed. If you have an array like the following:
```
[
"one",
"two",
"three"
const nums = [
one,
two,
three,
four
]
```
You need to define the proper syntax definition to capture the characters between the square brackets:
It will be folded with a syntax fold. When you define a syntax highlighting for a particular language (typically inside the `syntax/` directory), you can add a `fold` attribute to make it foldable. Below is a snippet from vim-polyglot JavaScript syntax file. Notice the `fold` keyword at the end.
```
:syn region testFold start="\\[" end="\\]" transparent fold
syntax region jsBracket matchgroup=jsBrackets start=/\[/ end=/\]/ contains=@jsExpression,jsSpreadExpression extend fold
```
You should see:
```
+-- 5 lines: [ -----
```
Here is the breakdown:
- `:syn` is the syntax command.
- `region` constructs a syntax region that can span several lines. For more info, check out `:h syntax.txt`
- `start="\\[" end="\\]"` defines the starting and ending of a region. You have to escape (`\\`) the square-brackets because they are considered special characters.
- `transparent` to prevent highlights.
- `fold` increases the fold level when the syntax matches the starting and ending characters.
This guide won't cover the `syntax` feature. If you're curious, check out `:h syntax.txt`.
## Expression Fold
Expression folding allows you to define an expression to match for a fold. After you define the fold expressions, Vim scans each line for the value of `'foldexpr'`. This is the variable that you have to configure to return the appropriate value. If the `'foldexpr'` returns 0, then the line is not folded. If it returns 1, then that line has a fold level of 1. If it returns 2, then that line has a fold level of 2. There are more values other than integers, but I won't go over them. If you are curious, check out `:h fold-expr`.
Expression fold allows you to define an expression to match for a fold. After you define the fold expressions, Vim scans each line for the value of `'foldexpr'`. This is the variable that you have to configure to return the appropriate value. If the `'foldexpr'` returns 0, then the line is not folded. If it returns 1, then that line has a fold level of 1. If it returns 2, then that line has a fold level of 2. There are more values other than integers, but I won't go over them. If you are curious, check out `:h fold-expr`.
First, let's change the foldmethod:
@ -254,13 +245,12 @@ Next, change the `foldexpr` to capture the expressions starting with "p":
:set foldexpr=getline(v:lnum)[0]==\\"p\\"
```
The expression above looks intimidating. Let's break it down:
The expression above looks complicated. Let's break it down:
- `:set foldexpr` sets up the `'foldexpr'` option to accept a custom expression.
- `getline()` is a Vimscript function that returns the content of any given line. If you run `:echo getline(5)`, it will return the content of line 5.
- `v:lnum` is Vim's special variable for the `'foldexpr'` expression. Vim scans each line and at that moment stores each line's number in `v:lnum` variable.
- `v:lnum` is Vim's special variable for the `'foldexpr'` expression. Vim scans each line and at that moment stores each line's number in `v:lnum` variable. On line 5, `v:lnum` has value of 5. On line 10, `v:lnum` has value of 10.
- `[0]` in the context of `getline(v:lnum)[0]` is the first character of each line. When Vim scans a line, `getline(v:lnum)` returns the content of each line. `getline(v:lnum)[0]` returns the first character of each line. On the first line of our list, "donut", `getline(v:lnum)[0]` returns "d". On the second line of our list, "pancake", `getline(v:lnum)[0]` returns "p".
- `==\\"s\\"` is the second half of an equality expression. It checks if the expression you just evaluated is equal to "s". If it is true, it returns 1. If it is false, it returns 0. In Vim, 1 is truthy and 0 is falsy. So on the lines that start with an "s", it returns 1. Recall at the beginning of this section, if a `'foldexpr'` has a value of 1, then it has a fold level of 1.
- `==\\"p\\"` is the second half of the equality expression. It checks if the expression you just evaluated is equal to "p". If it is true, it returns 1. If it is false, it returns 0. In Vim, 1 is truthy and 0 is falsy. So on the lines that start with an "p", it returns 1. Recall if a `'foldexpr'` has a value of 1, then it has a fold level of 1.
After running this expression, you should see:
@ -354,17 +344,16 @@ Then when you open up `count.txt`, run:
:loadview
```
Your folds are restored. However, you have to manually run `mkview` and `loadview`. I know that one of these days, I will forget to run `mkview` before closing the file and I will lose all the folds. Wouldn't it be nice if you can automate this?
Your folds are restored. However, you have to manually run `mkview` and `loadview`. I know that one of these days, I will forget to run `mkview` before closing the file and I will lose all the folds. How can we automate this process?
Definitely! To automatically run `mkview` when you close a `.txt` file and run `loadview` when you open a `.txt` file, add this in your vimrc:
To automatically run `mkview` when you close a `.txt` file and run `loadview` when you open a `.txt` file, add this in your vimrc:
```
autocmd BufWinLeave *.txt mkview
autocmd BufWinEnter *.txt silent loadview
```
You have seen the `autocommand` from the previous chapter. It is used to execute a command on an event trigger. There are two events to accomplish this:
Recall that `autocmd` is used to execute a command on an event trigger. The two events here are:
- `BufWinLeave` for when you remove a buffer from a window.
- `BufWinEnter` for when you load a buffer in a window.
@ -374,8 +363,8 @@ By default, Vim saves the fold information when running `mkview` inside `~/.vim/
## Learn Fold The Smart Way
When I first started Vim, I would skip learning Vim fold because I didn't think it was useful. However, the longer I code, the more useful I find folding is. Strategically placed folds can give you a better overview of the text structure, like a book's *table of content*.
When I first started Vim, I neglected ot learn fold because I didn't think it was useful. However, the longer I code, the more useful I find folding is. Strategically placed folds can give you a better overview of the text structure, like a book's table of content.
When you learn fold, start with the manual fold because that can be used on-the-go. Then gradually learn different tricks to do indent and marker folds. Finally, learn how to do syntax and expression folds. You can even use the latter two to write your own Vim plugins.
Now that you know how to do fold, let's learn something different: version control with git.
Next, let's version control with git.

Loading…
Cancel
Save