Revise ch23

pull/63/head
Igor Irianto 3 years ago
parent 988677a7bd
commit 1134f0c3e0

@ -1,12 +1,12 @@
# Ch23. Vim Runtime
In the previous chapters, you learned that Vim automatically looks for special paths like `pack/` (Ch 22) and `compiler/` (Ch 19) inside the `~/.vim/` directory. These are examples of Vim runtime paths.
In the previous chapters, I mentioned that Vim automatically looks for special paths like `pack/` (Ch 22) and `compiler/` (Ch 19) inside the `~/.vim/` directory. These are examples of Vim runtime paths.
Vim has more runtime paths than these two. In this chapter, you will learn a high-level overview of some of these runtime paths. The goal of this chapter is to show you when they are called. Knowing this will allow you to customize Vim further.
Vim has more runtime paths than these two. In this chapter, you will learn a high-level overview of these runtime paths. The goal of this chapter is to show you when they are called. Knowing this will allow you to understand and customize Vim further.
## Runtime Path
In a Unix machine, one of your Vim runtime paths is `$HOME/.vim/` (`~/.vim/`). If you have a different OS (like Windows), your path might be different. To check what the runtime paths for different OS are, check out `:h 'runtimepath'`. In this chapter, I will use `~/.vim/` as the default runtime path.
In a Unix machine, one of your Vim runtime paths is `$HOME/.vim/` (if you have a different OS like Windows, your path might be different). To see what the runtime paths for different OS are, check out `:h 'runtimepath'`. In this chapter, I will use `~/.vim/` as the default runtime path.
## Plugin Scripts
@ -28,7 +28,7 @@ echo "chocolate!"
Now close Vim. The next time you start Vim, you will see both `"donut!"` and `"chocolate!"` echoed. The plugin runtime path can be used for initializations scripts.
## File Type Detection
## Filetype Detection
When you open a new file, Vim usually knows what kind of file it is. If you have a file `hello.rb`, running `:set filetype?` returns the correct response `filetype=ruby`.
@ -42,32 +42,30 @@ File name detection detects a file type using the name of that file. When you op
There are two ways you can do file name detection: using `ftdetect/` runtime directory and using `filetype.vim` runtime file. Let's explore both.
### `ftdetect/`
#### `ftdetect/`
Let's create an obscure (yet tasty) file, `hello.chocodonut`. When you open it and you run `:set filetype?`, since it is not a common file name extension Vim doesn't know what to make of it. It returns `filetype=`.
You need to instruct Vim to set all files ending with `.chocodonut` as a "chocodonut" file type. Create a directory named `ftdetect/` in the runtime root (`~/.vim/`). Inside, create a file and name it `chocodonut.vim` (`~/.vim/ftdetect/chocodonut.vim`). Inside this file, add:
You need to instruct Vim to set all files ending with `.chocodonut` as a "chocodonut" file type. Create a directory named `ftdetect/` in the runtime root (`~/.vim/`). Inside, create a file and name it `chocodonut.vim` (`~/.vim/ftdetect/chocodonut.vim`). Inside this file, add:
```
au BufNewFile,BufRead *.chocodonut set filetype=chocodonut
autocmd BufNewFile,BufRead *.chocodonut set filetype=chocodonut
```
This should look familiar. `BufNewFile` and `BufRead` are triggered whenever you create a new buffer or open a new buffer. `*.chocodonut` means that this event will only be triggered if the opened buffer has a `.chocodonut` filename extension. Finally, `set filetype=chocodonut` command sets the file type to be a chocodonut type.
`BufNewFile` and `BufRead` are triggered whenever you create a new buffer and open a new buffer. `*.chocodonut` means that this event will only be triggered if the opened buffer has a `.chocodonut` filename extension. Finally, `set filetype=chocodonut` command sets the file type to be a chocodonut type.
Restart Vim. Now open `hello.chocodonut` file and run `:set filetype?`. It returns `filetype=chocodonut`
Restart Vim. Now open `hello.chocodonut` file and run `:set filetype?`. It returns `filetype=chocodonut`.
Scrumptious! You can put as many files as you want inside `ftdetect/`. In the future, you can maybe add `ftdetect/strawberrydonut.vim`, `ftdetect/plaindonut.vim`, etc., if you ever decide to expand your donut file types.
There are actually two ways to set a file type in Vim. One is what you just used `set filetype=chocodonut`. The other way is to run `setfiletype chocodonut`.
There are actually two ways to set a file type in Vim. One is what you just used `set filetype=chocodonut`. The other way is to run `setfiletype chocodonut`. The former command `set filetype=chocodonut` will *always* set the file type to chocodonut type, while the latter command `setfiletype chocodonut` will only set the file type if no file type was set yet.
The former command `set filetype=chocodonut` will *always* set the file type to chocodonut type, while the latter command `setfiletype chocodonut` will only set the file type if no file type was set yet.
### `filetype.vim`
#### Filetype File
The second file detection method requires you to create a `filetype.vim` in the root directory (`~/.vim/filetype.vim`). Add this inside:
```
au BufNewFile,BufRead *.plaindonut set filetype=plaindonut
autocmd BufNewFile,BufRead *.plaindonut set filetype=plaindonut
```
Create a `hello.plaindonut` file. When you open it and run `:set filetype?`, Vim displays the correct custom file type `filetype=plaindonut`.
@ -80,13 +78,11 @@ if exists("did_load_filetypes")
endif
augroup donutfiletypedetection
au! BufRead,BufNewFile *.plaindonut setfiletype plaindonut
autocmd! BufRead,BufNewFile *.plaindonut setfiletype plaindonut
augroup END
```
`finish` is a Vim command to stop running the rest of the script. The `"did_load_filetypes"` expression is *not* a built-in Vim function. It is actually a global variable from inside `$VIMRUNTIME/filetype.vim`.
If you're curious, run `:e $VIMRUNTIME/filetype.vim`. You will find these lines inside:
`finish` is a Vim command to stop running the rest of the script. The `"did_load_filetypes"` expression is *not* a built-in Vim function. It is actually a global variable from inside `$VIMRUNTIME/filetype.vim`. If you're curious, run `:e $VIMRUNTIME/filetype.vim`. You will find these lines inside:
```
if exists("did_load_filetypes")
@ -96,17 +92,13 @@ endif
let did_load_filetypes = 1
```
When Vim calls this file, it defines `did_load_filetypes` variable and sets is to 1. Recall that 1 is truthy in Vim. You should read the rest of the `filetype.vim` too. See if you can understand what it does and when Vim calls it.
When Vim calls this file, it defines `did_load_filetypes` variable and sets is to 1. 1 is truthy in Vim. You should read the rest of the `filetype.vim` too. See if you can understand what it does when Vim calls it.
### File Type Script
Let's learn how to detect and assign a file type based on the file content. Suppose you have a collection of files without an agreeable extension. The only thing these files have in common is that they all start with this word on the first line:
```
donutify
```
Let's learn how to detect and assign a file type based on the file content.
You want to assign these files to a `donut` file type. Create new files named `sugardonut`, `glazeddonut`, and `frieddonut` (without extension). Inside each file, add this line:
Suppose you have a collection of files without an agreeable extension. The only thing these files have in common is that they all start with the word "donutify" on the first line. You want to assign these files to a `donut` file type. Create new files named `sugardonut`, `glazeddonut`, and `frieddonut` (without extension). Inside each file, add this line:
```
donutify
@ -126,19 +118,17 @@ if getline(1) =~ '^\\<donutify\\>'
endif
```
The function `did_filetype()` is a Vim built-in function. It will return true when a file type related event is triggered at least once. It is used as a guard to stop re-running file type event.
The function `getline(1)` returns the text on the first line. It checks if the first line starts with the word "donutify". The function `did_filetype()` is a Vim built-in function. It will return true when a file type related event is triggered at least once. It is used as a guard to stop re-running file type event.
Open the `sugardonut` file and run `:set filetype?`, Vim now returns `filetype=donut`.
If you open another donut files (`glazeddonut` and `frieddonut`), Vim also identifies their file types as `donut` types.
Open the `sugardonut` file and run `:set filetype?`, Vim now returns `filetype=donut`. If you open another donut files (`glazeddonut` and `frieddonut`), Vim also identifies their file types as `donut` types.
Note that `scripts.vim` is only run when Vim opens a file with an unknown file type. If Vim opens a file with a known file type, `scripts.vim` won't run.
## File Type Plugin
Earlier you learned that Vim automatically runs all scripts inside the plugin directory. What if you want Vim to automatically execute specific scripts when you open a chocodonut file and not when opening plaindonut file?
What if you want Vim to run chocodonut-specific scripts when you open a chocodonut file and to not run those scripts when opening plaindonut file?
You can do this with ftplugin runtime path (`~/.vim/ftplugin/`). Vim looks inside this directory for a file with the same name as the file type you just opened. Create a `chocodonut.vim` (`~/.vim/ftplugin/chocodonut.vim`):
You can do this with file type plugin runtime path (`~/.vim/ftplugin/`). Vim looks inside this directory for a file with the same name as the file type you just opened. Create a `chocodonut.vim` (`~/.vim/ftplugin/chocodonut.vim`):
```
echo "Calling from chocodonut ftplugin"
@ -152,36 +142,32 @@ echo "Calling from plaindonut ftplugin"
Now each time you open a chocodonut file type, Vim runs the scripts from `~/.vim/ftplugin/chocodonut.vim`. Each time you open a plaindonut file type, Vim runs the scripts from `~/.vim/ftplugin/plaindonut.vim`.
One warning: these files are run each time a buffer's file type is set (`set filetype=chocodonut` for example). If you open 3 different chocodonut files, the scripts will be run a *total* of three times.
One warning: these files are run each time a buffer file type is set (`set filetype=chocodonut` for example). If you open 3 different chocodonut files, the scripts will be run a *total* of three times.
## Indent Files
Vim has an indent runtime path that works similar to ftplugin, where Vim looks for a file named the same as the opened file type.
If you have a script inside `~/.vim/indent/chocodonut.vim`, it will be executed only when you open a chocodonut file type.
Vim has an indent runtime path that works similar to ftplugin, where Vim looks for a file named the same as the opened file type. The purpose of these indent runtime paths is to store indent-related codes. If you the file `~/.vim/indent/chocodonut.vim`, it will be executed only when you open a chocodonut file type. You can store indent-related codes for chocodonut files here.
## Colors
Vim has a colors runtime path (`~/.vim/colors/`) to store color schemes. Any file that goes inside the directory will be displayed in the `:color` command-line command.
If you have a `~/.vim/colors/beautifulprettycolors.vim` file, when you run `:color` and press `<tab>`, you will see `beautifulprettycolors` as one of the color options. If you prefer to customize your own color scheme, this is the place to go.
If you have a `~/.vim/colors/beautifulprettycolors.vim` file, when you run `:color` and press tab, you will see `beautifulprettycolors` as one of the color options. If you prefer to add your own color scheme, this is the place to go.
If you want to check out the color schemes other people made, a good place to visit is [vimcolors](https://vimcolors.com/).
## Syntax Highlighting
Vim has a syntax runtime path (`~/.vim/syntax/`) to define syntax highlighting. In the syntax directory, file name matters.
Vim has a syntax runtime path (`~/.vim/syntax/`) to define syntax highlighting.
Suppose inside `hello.chocodonut`, you have the following expressions:
Suppose you have a `hello.chocodonut` file, inside it you have the following expressions:
```
(donut "tasty")
(donut "savory")
```
Although Vim now knows the correct file type, all texts have the same color. Let's create a highlight for the "donut" keyword.
Create a new chocodonut syntax file, `~/.vim/syntax/chocodonut.vim`. Inside it add:
Although Vim now knows the correct file type, all texts have the same color. Let's add a syntax highlighting rule to highlight the "donut" keyword. Create a new chocodonut syntax file, `~/.vim/syntax/chocodonut.vim`. Inside it add:
```
syntax keyword donutKeyword donut
@ -215,7 +201,7 @@ Now if you run `:h chocodonut` and `:h plaindonut`, you will find these new help
## Lazy Loading Scripts
All of the runtime scripts that you've learned in this chapter are run automatically. There may be a time when you want to manually load these scripts. For this, use the autoload runtime path.
All of the runtime paths that you learned in this chapter were run automatically. If you want to manually load a script, use the autoload runtime path.
Create an autoload directory (`~/.vim/autoload/`). Inside that directory, create a new file and name it `tasty.vim` (`~/.vim/autoload/tasty.vim`). Inside it:
@ -227,7 +213,7 @@ function tasty#donut()
endfunction
```
Note that the function name is `tasty#donut`, not `donut()`. The pound sign (`#`) is a must when using the autoload feature. The function naming convention for the autoload feature is:
Note that the function name is `tasty#donut`, not `donut()`. The pound sign (`#`) is required when using the autoload feature. The function naming convention for the autoload feature is:
```
function fileName#functionName()
@ -237,19 +223,17 @@ endfunction
In this case, the file name is `tasty.vim` and the function name is (technically) `donut`.
Recall that you can invoke any function with the `call` command-line command. Let's call that function with `:call tasty#donut()`.
To invoke a function, you need the `call` command. Let's call that function with `:call tasty#donut()`.
The first time you call the function, you should see *both* echo messages ("tasty.vim global" and "tasty#donut"). When you call the `tasty#donut` function again, it will only display "testy#donut" echo.
The first time you call the function, you should see *both* echo messages ("tasty.vim global" and "tasty#donut"). The subsequent calls to` tasty#donut` function will only display "testy#donut" echo.
When you open a file in Vim, unlike the previous runtime paths, autoload scripts aren't loaded automatically. Only when you explicitly call `tasty#donut()`, Vim looks for the `tasty.vim` file and loads everything inside it, including the `tasty#donut()` function. Autoload is the perfect mechanism for functions that use extensive resources but you don't use often.
You can add as many nested directories with autoload as you want. If you have the runtime path `~/.vim/autoload/one/two/three/tasty.vim`, you can call the function with `:call one#two#three#tasty#donut()`.
Keep in mind that the function inside `tasty.vim` now must be named `function one#two#three#tasty#donut()` to follow the new nested paths.
## After Scripts
Vim has an after runtime path (`~/.vim/after/`) that mirrors the structure of `~/.vim/`. This is a good place to put override scripts.
Vim has an after runtime path (`~/.vim/after/`) that mirrors the structure of `~/.vim/`. Anything in this path is executed last, so developers usually use these paths for script overrides.
For example, if you want to overwrite the scripts from `plugin/chocolate.vim`, you can create `~/.vim/after/plugin/chocolate.vim` to put the override scripts. Vim will run the `~/.vim/after/plugin/chocolate.vim` *after* `~/.vim/plugin/chocolate.vim`.
@ -261,11 +245,11 @@ The structure should look familiar. It contains many runtime paths you learned i
Recall in Chapter 21, you learned that when you open Vim, it looks for a vimrc files in seven different locations. I said that the last location Vim checks is `$VIMRUNTIME/default.vim`. If Vim fails to find any uservimrc files, Vim uses a `default.vim` as vimrc.
Have you ever tried running Vim without syntax plugin like vim-polyglot and yet your file is still syntatically highlighted? That is because when Vim fails to find a syntax file (let's assume for the `hello.rb` file) from the runtime path, Vim looks for a syntax file from `$VIMRUNTIME` syntax directory.
Have you ever tried running Vim without syntax plugin like vim-polyglot and yet your file is still syntatically highlighted? That is because when Vim fails to find a syntax file from the runtime path, Vim looks for a syntax file from `$VIMRUNTIME` syntax directory.
To learn more, check out `:h $VIMRUNTIME`.
## `'runtimepath'`
## Runtimepath Option
To check your runtimepath, run `:set runtimepath?`
@ -275,7 +259,9 @@ If you use Vim-Plug or popular external plugin managers, it should display a lis
runtimepath=~/.vim,~/.vim/plugged/vim-signify,~/.vim/plugged/base16-vim,~/.vim/plugged/fzf.vim,~/.vim/plugged/fzf,~/.vim/plugged/vim-gutentags,~/.vim/plugged/tcomment_vim,~/.vim/plugged/emmet-vim,~/.vim/plugged/vim-fugitive,~/.vim/plugged/vim-sensible,~/.vim/plugged/lightline.vim, ...
```
One of the things plugin managers does is adding each plugin into the runtime path. Each runtime path can have its own directory structure similar to `~/.vim/`. If you have an arbitrary directory `~/box/of/donuts/` and you want to add that directory to your runtime path, you can add this to your vimrc:
One of the things plugin managers does is adding each plugin into the runtime path. Each runtime path can have its own directory structure similar to `~/.vim/`.
If you have a directory `~/box/of/donuts/` and you want to add that directory to your runtime path, you can add this to your vimrc:
```
set rtp+=$HOME/box/of/donuts/
@ -287,6 +273,4 @@ Try this yourself: create an arbitrary path and add it to your runtimepath. Add
## Learn Runtime The Smart Way
This is a long chapter. Take your time reading it and play around with these runtime paths. To see how runtime paths are being used in the wild, go to the repository of one of your favorite Vim plugins and study its directory structure. You should be able to understand most of them now. Try to follow along and discern the big picture. You are one step closer from being able to create your own Vim plugin. What you are missing is the Vim scripting language.
Let's learn Vimscript.
Take your time reading it and play around with these runtime paths. To see how runtime paths are being used in the wild, go to the repository of one of your favorite Vim plugins and study its directory structure. You should be able to understand most of them now. Try to follow along and discern the big picture. Now that you understand Vim directory structure, you're ready to learn Vimscript.

Loading…
Cancel
Save