Update vimrc chapter

pull/62/head
Igor Irianto 3 years ago
parent 443dafba1f
commit e6f9cb80b7

@ -1,13 +1,13 @@
# Ch21. Vimrc
In the previous chapters, you learned how to use Vim text editor. This is great, but not the whole thing. To use Vim more effectively, you will need to learn how to configure it. The best place to start is your vimrc. TBC
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 for vimrc is to add a `.vimrc` dotfile in the root directory (`~/.vimrc`).
The conventional wisdom for vimrc is to add a `.vimrc` dotfile in the root directory `~/.vimrc` (it might be different depending on your OS).
Behind the scene, Vim looks at multiple places for a vimrc file. Here are the places that Vim checks:
- `$VIMINIT`
- `$HOME/.vimrc`
- `$HOME/.vim/vimrc`
@ -16,17 +16,19 @@ Behind the scene, Vim looks at multiple places for a vimrc file. Here are the pl
- `$HOME/.vim/exrc`
- `$VIMRUNTIME/default.vim`
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.
When you start Vim, it will check the above seven locations in that order for a vimrc file. The first found vimrc file 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`.
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.
The first location, `$VIMINIT`, is an environment variable. By default it is undefined. If you want to use `~/dotfiles/testvimrc` 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/testvimrc" | source $MYVIMRC'`, Vim will now use `~/dotfiles/testvimrc` as your vimrc file.
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.
The second location, `$HOME/.vimrc`, is the conventional path for many Vim users. `$HOME` in many cases is your root directory (`~`). If you have a `~/.vimrc` file, Vim will use this as your vimrc file.
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`.
The fifth and sixth, `$HOME/.exrc` and `$HOME/.vim/exrc` work also similar to `$HOME/.vimrc` and `$HOME/.vim/vimrc`.
The fifth and sixth, `$HOME/.exrc` and `$HOME/.vim/exrc` work similar to `$HOME/.vimrc` and `$HOME/.vim/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 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.
@ -34,28 +36,26 @@ For the remaining of this chapter, I am assuming that the vimrc uses the `~/.vim
## What To Put In My Vimrc?
A question I asked when I started to use Vim seriously was, "What should I put in my vimrc?"
A question I asked when I started was, "What should I put in my vimrc?"
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.
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. Just because someone uses it doesn't mean you'll use it too.
## Basic Vimrc Content
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.
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).
In the previous chapters, I have 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).
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)
@ -83,22 +83,15 @@ Vim 8 has its own built-in package managers. You can check out `:h packages` for
### Settings
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
```
You can also put them as a one-liner:
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 number
```
Some settings require you to pass it a value, like `set tabstop=2`.
Some settings require you to pass it a value, like `set tabstop=2`. Check out the help page for each setting to learn what kind of values it accepts.
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:
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"
@ -176,9 +169,11 @@ Using `f-args`:
" returns "Hello Iggy1 and Iggy2"
```
To learn more, check out `:h command` and `:args`.
The functions above will make a lot more sense once you get to the Vimscript functions chapter.
### Mappings
To learn more about command and args, check out `:h command` and `:args`.
### Maps
If you find yourself repeatedly performing the same complex task, it is a good indicator that you should create a mapping for that task.
@ -192,18 +187,20 @@ 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:
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:
The `nnoremap` command used above can be broken down into three parts:
- `map` is the map command.
- `n` represents the Normal mode.
- `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).
At minimum, you could have used `nmap` instead of `nnoremap` (`nmap <silent> <C-f> :Gfiles<CR>`). However, it is a good practice to use the non-recursive variant to avoid potential infinite 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
@ -223,29 +220,19 @@ 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:
```
nnoremap <Leader>ve :vsplit $MYVIMRC<CR>
nnoremap <Leader>vs :source $MYVIMRC<CR>
```
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`:
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`.
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. To learn more, check out `:h map.txt`.
Create a mapping that's most intuitive, consistent, and easy-to-remember.
Create a map that's most intuitive, consistent, and easy-to-remember.
## Organizing Vimrc
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.
@ -256,7 +243,6 @@ You can split your vimrc to multiple files using Vim's `source` command. This co
Let's create a file inside the `~/.vim` directory and name it `/settings` (`~/.vim/settings`). The name itself is arbitrary and you can name it whatever you like.
You are going to split it into three components:
- Third-party plugins (`~/.vim/settings/plugins.vim`).
- General settings (`~/.vim/settings/configs.vim`).
- Key mappings (`~/.vim/settings/mappings.vim`) .
@ -266,6 +252,7 @@ Inside `~/.vimrc`:
```
source $HOME/.vim/settings/plugins.vim
source $HOME/.vim/settings/configs.vim
source $HOME/.vim/settings/functions.vim
source $HOME/.vim/settings/mapppings.vim
```
@ -287,17 +274,30 @@ set relativenumber
set number
```
Inside `~/.vim/mappings.vim`:
Inside `~/.vim/settings/functions.vim`:
```
function! ToggleNumber()
if(&relativenumber == 1)
set norelativenumber
else
set relativenumber
endif
endfunc
```
Inside `~/.vim/settings/mappings.vim`:
```
nnoremap <Leader>vs :source $MYVIMRC<CR>
nnoremap <Leader>ve :vsplit $MYVIMRC<CR>
inoremap jk <esc>
nnoremap <silent> <C-f> :GFiles<CR>
nnoremap <Leader>tn :call ToggleNumber()<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, 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`.
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, if you need to create a setting for your colorschemes, you can add a `~/.vim/settings/themes.vim`.
### Keeping One Vimrc File
@ -337,10 +337,20 @@ set relativenumber
set number
" }}}
" functions {{{
function! ToggleNumber()
if(&relativenumber == 1)
set norelativenumber
else
set relativenumber
endif
endfunc
" }}}
" mappings {{{
nnoremap <Leader>vs :source $MYVIMRC<CR>
nnoremap <Leader>ve :vsplit $MYVIMRC<CR>
inoremap jk <esc>
nnoremap <silent> <C-f> :GFiles<CR>
nnoremap <Leader>tn :call ToggleNumber()<CR>
" }}}
```
@ -353,6 +363,8 @@ Your vimrc should look like this:
+-- 5 lines: configs ---------
+-- 9 ilnes: functions -------
+-- 5 lines: mappings --------
```

Loading…
Cancel
Save