Update vimrc chapter content

pull/59/head
Igor Irianto 3 years ago
parent 40a3f69985
commit f39a1c4e22

@ -4,15 +4,13 @@ metaTitle: "Vimrc"
metaDescription: "Learn about vimrc structure."
---
In the previous chapters, you learned how to use Vim. From now on, you will learn how to customize Vim to fit your coding style.
In this chapter, you will learn how to configure and organize vimrc.
In the previous chapters, you learned how to use Vim. In this chapter, you will learn how to orgnize and configure vimrc.
## How Vim Finds Vimrc
The conventional wisdom to configure vimrc is to add a `.vimrc` dotfile in the root directory of your computer (`~/.vimrc`).
The conventional wisdom for vimrc is to add a `.vimrc` dotfile in the root directory (`~/.vimrc`).
Behind the scene, Vim looks at multiple places for a vimrc file, not only the root directory. Here are the places that Vim checks:
Behind the scene, Vim looks at multiple places for a vimrc file. Here are the places that Vim checks:
- `$VIMINIT`
- `$HOME/.vimrc`
@ -22,42 +20,51 @@ Behind the scene, Vim looks at multiple places for a vimrc file, not only the ro
- `$HOME/.vim/exrc`
- `$VIMRUNTIME/default.vim`
When you start Vim, it will check the above seven locations in that order for a "vimrc" file (in this chapter, I will refer to the runtime command file Vim uses at start-time as vimrc, regardless what the file is actually named). The first vimrc file found will be used and the rest is ignored. First Vim will look for `$VIMINIT`. If there is nothing there, Vim checks for `$HOME/.vimrc`. If there is nothing there, Vim checks for `$HOME/.vim/vimrc`. If Vim finds it, it will stop looking and use `$HOME/.vim/vimrc`. Let's break down what each path means.
When you start Vim, it will check the above seven locations in that order for a vimrc file. The first vimrc file found will be used and the rest is ignored. First Vim will look for a `$VIMINIT`. If there is nothing there, Vim will check for `$HOME/.vimrc`. If there is nothing there, Vim will check for `$HOME/.vim/vimrc`. If Vim finds it, it will stop looking and use `$HOME/.vim/vimrc`. Let's break down what each path means.
The first, `$VIMINIT`, is an environment variable. By default it is undefined. If you want to use `~/dotfiles/hellovim` as your `$VIMINIT` value, you can define it as follows:
The first, `$VIMINIT`, is an environment variable. By default it is undefined. If you want to use `~/dotfiles/hellovim` as your `$VIMINIT` value, you can create an environment variable containing the path of that vimrc. After you run `export VIMINIT='let $MYVIMRC="$HOME/dotfiles/hellovim" | source $MYVIMRC'`, Vim will now use `~/.dotfiles/hellovim` as your vimrc file.
1. Create a `~/.dotfiles/hellovim` and inside it have:
The second, `$HOME/.vimrc`, is the conventional path for many Vim users. `$HOME` in most cases is your root directory (`~`). If you have a `~/.vimrc` file, Vim will use this as your vimrc file.
```
set nocompatible
set relativenumber number
```
The third, `$HOME/.vim/vimrc`, is located inside the `~/.vim` directory. You might have the `~/.vim` directory already for your plugins, custom scripts, or View files. Note that there is no dot in vimrc file name (`$HOME/.vim/.vimrc` won't work, but `$HOME/.vim/vimrc` will).
The fourth, `$EXINIT` works similar to `$VIMINIT`.
2. In the terminal, run `export VIMINIT='let $MYVIMRC="$HOME/dotfiles/hellovim" | source $MYVIMRC'`
The fifth and sixth, `$HOME/.exrc` and `$HOME/.vim/exrc` work also similar to `$HOME/.vimrc` and `$HOME/.vim/vimrc`.
Now when you run Vim from the terminal, it will use `~/dotfiles/hellovim` as a vimrc file.
The seventh, `$VIMRUNTIME/defaults.vim` is the default vimrc that comes with your Vim build. In my case, I have Vim 8.2 installed using Homebrew, so my path is (`/usr/local/share/vim/vim82`). If Vim does not find any of the previous six vimrc files, it will use this file.
The second, `$HOME/.vimrc`, is the conventional path for many Vim users. `$HOME` in most cases is your root directory (`~`). If you drop the vimrc in this path, `~/.vimrc`, Vim will use this file.
For the remaining of this chapter, I am assuming that the vimrc uses the `~/.vimrc` path.
The third, `$HOME/.vim/vimrc`, is located inside the `~/.vim` directory. You might have the `~/.vim` directory already for your plugins, custom scripts, or View files. Note that there is no dot in `vimrc` file name (`$HOME/.vim/.vimrc` doesn't work, but `$HOME/.vim/vimrc` does).
## What To Put In My Vimrc?
The fourth, `$EXINIT` is similar to `$VIMINIT`. The fifth and sixth, `$HOME/.exrc` and `$HOME/.vim/exrc` are also similar to `$HOME/.vimrc` and `$HOME/.vim/exrc`.
A question I asked when I started to use Vim seriously was, "What should I put in my vimrc?"
The seventh, `$VIMRUNTIME/defaults.vim` is the default vimrc that comes with your Vim build. In my case, I have Vim 8.2 installed, so my path is (`/usr/local/share/vim/vim82`). If Vim does not find any of the previous six vimrc file, it will use this file.
The answer is, "anything you want". The temptation to copy-paste other people's vimrc is real, but you should resist it. If you insist to use someone else's vimrc, make sure that you know what it does, why and how s/he uses it, and most importantly, if it is relevant to you. Everyone has a different coding style. The person you copy it from might have a different workflow from you.
## Installing Plugins
## Basic Vimrc Content
For the remaining of this chapter, I am assuming that the vimrc follows the `~/.vimrc` path. Regardless where you actually put your vimrc, you should be able to follow along.
In the nutshell, a vimrc is a collection of:
- Plugins
- Settings
- Custom Functions
- Custom Commands
- Mappings
There are other things not mentioned above,but in general, this covers most use cases.
### Plugins
In the previous chapters, I have ocassionally mentioned different plugins, like [fzf.vim](https://github.com/junegunn/fzf.vim), [vim-mundo](https://github.com/simnalamburt/vim-mundo), and [vim-fugitive](https://github.com/tpope/vim-fugitive).
Let's talk about different ways to install plugins. Ten years ago, managing plugins was a nightmare. However, with the emergence of modern plugin managers, installing plugins can now be done within seconds. I am currently using [vim-plug](https://github.com/junegunn/vim-plug) as my plugin manager, so I will use it in this section. The concept should be similar with other popular plugin managers. I would strongly recommend you to check out different ones, such as:
Ten years ago, managing plugins was a nightmare. However, with the rise of modern plugin managers, installing plugins can now be done in seconds. I am currently using [vim-plug](https://github.com/junegunn/vim-plug) as my plugin manager, so I will use it in this section. The concept should be similar with other popular plugin managers. I would strongly recommend you to check out different ones, such as:
- [vundle.vim](https://github.com/VundleVim/Vundle.vim)
- [vim-pathogen](https://github.com/tpope/vim-pathogen)
- [dein.vim](https://github.com/Shougo/dein.vim)
There are more plugin managers than the ones listed above. To install vim-plug, if you have a Unix machine, run:
There are more plugin managers than the ones listed above, feel free to look around. To install vim-plug, if you have a Unix machine, run:
```
curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
@ -76,31 +83,150 @@ Save the changes, source it (`:source %`), and run `:PlugInstall` to install the
In the future if you need to remove unused plugins, you just need to remove the plugin names from the `call` block, save and source, and run the `:PlugClean` command to remove it from your machine.
Vim 8 has its own built-in package managers. You can check out `:h packages` for more information. In a later chapter, I will show you how to use it.
Vim 8 has its own built-in package managers. You can check out `:h packages` for more information. In the next chapter, I will show you how to use it.
## Modifying Vimrc
### Settings
A vimrc is nothing but a collection of command-line commands. For example, to display `number` and `relativenumber` settings, you can run `:set relativenumber number` command from the current buffer. But this command is not permanent, you will lose it when you close Vim. You need to add them to your vimrc:
It is common to see a lot of `set` options in any vimrc. If you run the set command from the Command-line mode, it is not permanent. You will lose it when you close Vim. For example, instead of running `:set relativenumber number` from the Command-line mode each time you run Vim, you could just put these inside vimrc:
```
set relativenumber
set number
```
Alternatively, you can also put them in one line:
You can also put them as a one-liner:
```
set relativenumber number
```
Both do the same thing. It comes down to your personal preference.
Some settings require you to pass it a value, like `set tabstop=2`.
You can also use a `let` instead of `set` (make sure to prepend it with `&`). With `let`, you can use an expression as a value. For example, to set the `dictionary` option to a path only if the path exists:
```
let s:english_dict = "/usr/share/dict/words"
if filereadable(s:english_dict)
let &dictionary=s:english_dict
endif
```
You will learn about Vimscript assignments and conditionals in later chapters.
For a list of all possible options in Vim, check out `:h E355`.
### Custom Functions
Vimrc is a good place for custom functions. You will learn how to write your own Vimscript functions in a later chapter.
### Custom Commands
You can create a custom Command-line command with `command`.
To create a basic command `GimmeDate` to display today's date:
```
:command! GimmeDate echo call("strftime", ["%F"])
```
When you run `:GimmeDate`, Vim will display a date like "2021-01-1".
To create a basic command with an input, you can use `<args>`. If you want to pass to `GimmeDate` a specific time/date format:
```
:command! GimmeDate echo call("strftime", [<args>])
:GimmeDate "%F"
" 2020-01-01
:GimmeDate "%H:%M"
" 11:30
```
If you want to restrict the number of arguments, you can pass it `-nargs` flag. Use `-nargs=0` to pass no argument, `-nargs=1` to pass one argument, `-nargs=+` to pass at least one argument, `-nargs=*` to pass any number of arguments, and `-nargs=?` to pass 0 or one arguments. If you want to pass nth argument, use `-nargs=n` (where `n` is any integer).
`<args>` has two variants: `<f-args>` and `<q-args>`. The former is used to pass arguments to Vimscript functions. The latter is used to automatically convert user input to strings.
Using `args`:
```
:command! -nargs=1 Hello echo "Hello " . <args>
:Hello "Iggy"
" returns 'Hello Iggy'
:Hello Iggy
" Undefined variable error
```
Using `q-args`:
```
:command! -nargs=1 Hello echo "Hello " . <q-args>
:Hello Iggy
" returns 'Hello Iggy'
```
Using `f-args`:
```
:function! PrintHello(person1, person2)
: echo "Hello " . a:person1 . " and " . a:person2
:endfunction
It is common to put mappings in your vimrc. I personally like to use `<space>` as the leader key instead of Vim's default. To change your leader key to a backslash, you can add this in your vimrc:
:command! -nargs=* Hello call PrintHello(<f-args>)
:Hello Iggy1 Iggy2
" returns "Hello Iggy1 and Iggy2"
```
To learn more, check out `:h command` and `:args`.
### Mappings
If you find yourself repeatedly performing the same complex task, it is a good indicator that you should create a mapping for that task.
For example, I have these two mappings in my vimrc:
```
nnoremap <silent> <C-f> :GFiles<CR>
nnoremap <Leader>tn :call ToggleNumber()<CR>
```
On the first one, I map `Ctrl-F` to [fzf.vim](https://github.com/junegunn/fzf.vim) plugin's `:Gfiles` command (quickly search for Git files). On the second one, I map `<Leader>tn` to call a custom function `ToggleNumber` (toggles `norelativenumber` and `relativenumber` options). The `Ctrl-F` mapping overwrites Vim's native page scroll. Your mapping will overwrite Vim controls if they collide. Because I almost never used that feature, I decided that it is safe to overwrite it.
By the way, I personally like to use `<space>` as the leader key instead of Vim's default. To change your leader key, add this in your vimrc:
```
let mapleader = "\<space>"
```
The `nnoremap` command indicates three things:
- `map` is the map command.
- `n` represents the Normal mode.
- `nore` means non-recursive.
You could have used `nmap` instead of `nnoremap`. However, it is a good practice to use the non-recursive variant to avoid inifinite loop. Here's what could happen if you don't map non-recursively. Suppose you want to add a mapping to `B` to add a semi-colon at the end of the line, then go back one WORD (recall that `B` n Vim is a Normal-mode navigation key to go backward one WORD).
```
nmap B A;<esc>B
```
When you press `B`... oh no! Vim adds `;` uncontrollably (interrupt it with `Ctrl-C`). Why did that happen? Because in the mapping `A;<esc>B`, the `B` does not refer to Vim's native `B` function (go back one WORD), but it refers to the mapped function. What you have is actually this:
```
A;<esc>A;<esc>A;<esc>A;esc>...
```
To solve this problem, you need to add a non-recursive map:
```
nnoremap B A;<esc>B
```
Now try calling `B` again. This time it successfully adds a `;` at the end of the line and go back one WORD. The `B` in this mapping represents Vim's original `B` functionality.
I find myself opening, editing, and sourcing vimrc quite often in the middle of a programming session. Having to manually find vimrc can take a lot of effort, so I add this in my vimrc:
```
@ -108,14 +234,24 @@ nnoremap <Leader>ve :vsplit $MYVIMRC<CR>
nnoremap <Leader>vs :source $MYVIMRC<CR>
```
Recall that `nnoremap` adds a non-recursive Normal-mode mapping. Vim has the environment variable `$MYVIMRC` to store the path of your vimrc. I can quickly open my vimrc file with `<leader>ve` ("vimrc edit" mnemonic) and source it with `<leader>vs` ("vimrc source" mnemonic).
Vim has the environment variable `$MYVIMRC` to store the path of your vimrc. I can quickly open my vimrc file with `<Leader>ve` ("vimrc edit" mnemonic) and source it with `<leader>vs` ("vimrc source" mnemonic).
Vim has different maps for different modes. If you want to create a map for Insert mode to exit Insert mode when you press `jk`:
```
inoremap jk <esc>
```
The other map modes are: `map` (Normal, Visual, Select, and Operator-pending), `vmap` (Visual and Select), `smap` (Select), `xmap` (Visual), `omap` (Operator-pending), `map!` (Insert and Command-line), `lmap` (Insert, Command-line, Lang-arg), `cmap` (Command-line), and `tmap` (terminal-job). I won't cover them in detail here. To learn more, check out `:h map.txt`.
Create a mapping that's most intuitive, consistent, and easy-to-remember.
## Organizing Vimrc
Over time, your vimrc will grow large and start to become convoluted. There are two ways to keep your vimrc to look clean:
Over time, your vimrc will grow large and become convoluted. There are two ways to keep your vimrc to look clean:
- Split your vimrc into several files.
- Fold your vimrc file based on categories.
- Fold your vimrc file.
### Splitting Your Vimrc
@ -144,11 +280,13 @@ call plug#begin('~/.vim/plugged')
Plug 'mattn/emmet-vim'
Plug 'preservim/nerdtree'
call plug#end()
```
Inside `~/.vim/settings/configs.vim`:
```
set nocompatible
set relativenumber
set number
```
@ -158,17 +296,16 @@ Inside `~/.vim/mappings.vim`:
```
nnoremap <Leader>vs :source $MYVIMRC<CR>
nnoremap <Leader>ve :vsplit $MYVIMRC<CR>
nnoremap <silent> <C-f> :GFiles<CR>
```
Your vimrc should works as usual, but now it is only three lines long!
With this setup, you easily know where to go. If you need to add more mappings, simple head to the `/mappings.vim` file. In the future, you can always add more directories as your vimrc grows. For example, if you have many custom functions, you can store them inside `/functions.vim`.
With this setup, you easily know where to go. If you need to add more mappings, add them to the `/mappings.vim` file. In the future, you can always add more directories as your vimrc grows. For example, to store custom functions like `ToggleNumber`, you can store them inside `/functions.vim`.
### Keeping One Vimrc File
You may prefer to keep one vimrc file to keep it portable but your vimrc file is growing uncontrollably large. How do you manage this?
You use marker folds. Add this at the top of your vimrc:
If you prefer to keep one vimrc file to keep it portable, you can use the marker folds to keep it organized. Add this at the top of your vimrc:
```
" setup folds {{{
@ -207,6 +344,7 @@ set number
" mappings {{{
nnoremap <Leader>vs :source $MYVIMRC<CR>
nnoremap <Leader>ve :vsplit $MYVIMRC<CR>
nnoremap <silent> <C-f> :GFiles<CR>
" }}}
```
@ -219,7 +357,7 @@ Your vimrc should look like this:
+-- 5 lines: configs ---------
+-- 4 lines: mappings --------
+-- 5 lines: mappings --------
```
## Running Vim With Or Without Vimrc And Plugins
@ -242,16 +380,12 @@ If you need to run Vim with vimrc but without plugins, run:
vim --noplugin
```
If you need to run Vim with a *different* vimrc, say `~/.vimrc-extra`, run:
If you need to run Vim with a *different* vimrc, say `~/.vimrc-backup`, run:
```
vim -u ~/.vimrc-extra
vim -u ~/.vimrc-backup
```
## Configure Vimrc The Smart Way
In the beginning, there is a strong temptation to copy other people's vimrc. Resist it. By copying other people's vimrc, you might not always know what you're copying. It doesn't matter if other developer has over 1000 lines of vimrc while yours only have 10. As long as you get the job done, that's all that matters.
Vimrc is an important component of Vim customization. It should be tailored to fit your thinking framework and editing style.
Whenever you find that you are doing the same thing repeatedly, it is a good indication that you need a new mapping or function in your vimrc. To do that, you will need to learn how to create your own Vimscript functions and that's what the rest of this book is for.
Vimrc is an important component of Vim customization. A good way to start building your vimrc is by reading other people's vimrcs and gradually build it over time. The best vimrc is not the one that developer X uses, but the one that is tailored exactly to fit your thinking framework and editing style.

Loading…
Cancel
Save