Vim
Command line, ubiquitous text editor
If you have terminal access, you generally are going to have vim. That means learning it as a powerful command line text editing, searching and manipulation tool is always going to be useful.
There are different versions, ranging from vi
through to modern vim
.
Vim can be extended with various plugins though it is suggested you learn the basics before looking to extend it. Plugins are not likely to be available on a server so it is important you know how to get the most out of the core functionality.
Learning¶
There are a few ways to learn vim.
Vimtutor¶
Simply open a terminal and type vimtutor
and it will open vim with a text file loaded. You should read through this text file and work through the steps.
This will give you a basic introduction to vim
Useful Links¶
Modes¶
There are two main modes in Vim:
See:
- http://vimdoc.sourceforge.net/htmldoc/intro.html#vim-modes-intro
- https://alvinalexander.com/linux/vim-vi-mode-editor-command-insert-mode
(Normal|Command) Mode¶
This is the mode you start with when you open Vim. You can move around and can issue commands
Insert Mode¶
In this mode, you are actually editing text, you have a few ways of entering insert mode:
[i]
will enter insert mode at the current cursor position[o]
will create a new line under the cursor position and enter insert on that new line[c]
+[e]
will delete the word under the cursor and put you into insert mode
To exit insert mode, simply hit [escape]
(Command-line|Cmdline|Last Line) Mode:source ~/.vimrc¶
In this mode you enter commands in the last line of vim. You enter this from normal mode by typing :
This is how you quit vim, amongst other things
Configuration¶
Vim is very configurable. Some basic configuration is likely to be the same for all of us. Other items are going to be more personal preference.
On the Fly Configuration¶
You can adjust configuration on the fly by typing : set
followed by some configuration options
Persistent Configuration¶
To make persistent configuration changes, you should edit your .vimrc
file.
As standard, the .vimrc
file live in your home directory, eg cd ~
i
Global Persistent Configuration¶
To have one set of vim configuration that you share between users (eg root, you), then you can create a file called /etc/vimrc
If this file already exists, then you probably want to back it up first: sudo bash -c "mv /etc/vimrc /etc/vimrc.bak"
This should be automatically brought in however you can also source this global configuration into each user .vimrc
file using source
Some Suggested Configuration¶
Here are some basic .vimrc
configuration options that you are probably going to want to implement:
Tabs to 4 Spaces¶
Indents to 4 spaces, entered by pressing the tab key
set tabstop=8 softtabstop=0 expandtab shiftwidth=4 smarttab
Suggested Full Basic Configuration¶
As far as I'm concerned each of these are require to make vim more useful, you may disagree
" Use Vim settings, rather then Vi settings (much better!).
" This must be first, because it changes other options as a side effect.
set nocompatible
" ================ General Config ====================
set number "Line numbers are good
set backspace=indent,eol,start "Allow backspace in insert mode
set history=1000 "Store lots of :cmdline history
set showcmd "Show incomplete cmds down the bottom
set showmode "Show current mode down the bottom
set gcr=a:blinkon0 "Disable cursor blink
set visualbell "No sounds
set autoread "Reload files changed outside vim when you run an external command
set ruler "Show the cursor position at all time
set cursorline "Adds a line under the cursor
set ignorecase "Set ignorecase on.
set showmatch "showmatch: Show the matching bracket for the last ')'?
set ve=all "allow the cursor to go beyond the end of the line
set hidden "open a new buffer without saving the current one
" case insensitive tab completion, if enabled
if exists("&wildignorecase")
set wildignorecase
endif
"turn on syntax highlighting
syntax on
sytax sync fromstart
sytax sync fromstart
" ================ Turn Off Swap Files ==============
" Only do this if you also use the Persistent Undo Below
set noswapfile
set nobackup
set nowb
" ================ Persistent Undo ==================
" Keep undo history across sessions, by storing in file.
" Only works all the time.
silent !mkdir ~/.vim/backups > /dev/null 2>&1
set undodir=~/.vim/backups
set undofile
" ================ Indentation ======================
set autoindent
set smartindent
set smarttab
set shiftwidth=4
set softtabstop=4
set tabstop=4
set expandtab
filetype plugin on
filetype indent on
" Display tabs and trailing spaces visually
set list listchars=tab:\ \ ,trail:ยท
" ================ Folds ============================
set foldmethod=manual "Only fold when told to - see here http://vim.wikia.com/wiki/Folding
" ================ Completion =======================
set wildmode=list:longest
set wildmenu "enable ctrl-n and ctrl-p to scroll thru matches
set wildignore=*.o,*.obj,*~ "stuff to ignore when tab completing
set wildignore+=*vim/backups*
set wildignore+=*sass-cache*
set wildignore+=*DS_Store*
set wildignore+=vendor/rails/**
set wildignore+=vendor/cache/**
set wildignore+=*.gem
set wildignore+=log/**
set wildignore+=tmp/**
set wildignore+=*.png,*.jpg,*.gif
" ================ Scrolling ========================
set scrolloff=8 "Start scrolling when we're 8 lines away from margins
set sidescrolloff=15
set sidescroll=1
" This will open the current file in PHPStorm when you press <Ctrl>F
" You will need this plugin installed https://plugins.jetbrains.com/plugin/6027-remote-call
nmap <silent> <C-F> :!curl localhost:8091?message=%:p<CR><CR>
"Use <Ctrl> J,K,L,H to move around split windows
nnoremap <C-J> <C-W>J<CR>
nnoremap <C-K> <C-W>K<CR>
nnoremap <C-L> <C-W>L<CR>
nnoremap <C-H> <C-W>H<CR>
" type cd in normal mode to switch the pwd to that of the file
nmap <silent> cd :cd %:h<CR>
" For some reason vim doesn't recognise md files as markdown. Lets correct that
au BufNewFile,BufRead *.md set filetype=markdown
" And add syntax highlighting for code blocks
let g:markdown_fenced_languages = ['bash=sh', 'css', 'django', 'javascript', 'js=javascript', 'json=javascript', 'perl', 'php', 'python', 'ruby', 'sass', 'xml', 'html']
" =============== Spelling ==========================
set spelllang=en_gb
" Create and use spelling directory
silent !mkdir -p ~/.vim/spell > /dev/null 2>&1
set spellfile=~/.vim/spell/en.utf-8.add
" Enable spelling automatically for markddown and git commits
autocmd BufRead,BufNewFile *.md setlocal spell
autocmd FileType gitcommit setlocal spell
" Allow speling based completion
set complete+=kspell
" Ignore CamelCase words when spell checking
fun! IgnoreCamelCaseSpell()
syn match CamelCase /\<[A-Z][a-z]\+[A-Z].\{-}\>/ contains=@NoSpell transparent
syn cluster Spell add=CamelCase
endfun
autocmd BufRead,BufNewFile * :call IgnoreCamelCaseSpell()
Suggested Extra Configuration - still recommended¶
These are more optional, and may not be needed
" If we want to use encryption, lets use the latest version
" see here for details http://vim.wikia.com/wiki/Encryption
set cm=blowfish2
" Change leader to a comma because the backslash is too far away
" That means all \x commands turn into ,x
" The mapleader has to be set before vundle starts loading all
" the plugins.
let mapleader=","
set nowrap "Don't wrap lines
set linebreak "Wrap lines at convenient points if manually told to
" ====== Use Alt-arrow to move around windows ======
nmap <silent> <A-Up> :wincmd k<CR>
nmap <silent> <A-Down> :wincmd j<CR>
nmap <silent> <A-Left> :wincmd h<CR>
nmap <silent> <A-Right> :wincmd l<CR>
" The keys `jj` don't really appear in english, so use this as a quick way to
" simulate esc
imap jj <esc>
vmap jj <esc>
" Press `sf` to format SQL need this installed first
" https://github.com/vim-scripts/SQLUtilities
vmap <silent>sf <Plug>SQLUFormatter<CR>
nmap <silent>sf <Plug>SQLUFormatter<CR>
Vim with Mouse¶
To use your mouse more fluently with vim, add the following to your ~/.vimrc
file
" ====== Enable Mouse ===
se mouse+=a
Once this is enabled, you can do things like:
- use your mouse to select words, lines and blocks of text
- place the cursor at a specific point
However it does cause some issues which you need to work around.
Copying/Pasting Outside Vim¶
If you want to select some text in order to copy/paste it somewhere outside of vim (i.e. not yanking in vim but using standard Linux clipboard), then simply:
- hold down the
[shift]
key - highlight desired text to copy
- use middle mouse button to paste text elsewhere
Alternatively, you can get vim to use the X clipboard. This requires that vim has been compiled with clipboard. You can check if this is the case be running the following
vim --version | grep clipboard
If this is empty then you need to download a version of vim that has it. The easiest way of doing this is install gvim
which will install a CLI version that supports this
You then have access to the +
(the XA_SECONDARY clipboard) and *
(the XA_PRIMARY clipboard) registers, see here for more details
If you want you can even add the following to your ~/.vimrc
file, or set it manually, and get vim to use the same clip board as CTRL+V
set clipboard=unnamedplus
Warning
This uses the X clipboard, and has not been tested when using Wayland
Tip
If you are using Wayland, don't
Changing Colour Schemes¶
Vim comes with a selection of colour schemes built in as standard.
Selecting a built in colour scheme¶
To see all available, use:
:colo [TAB]
To select and use one, use:
:colo torte
To permanently use one, just put the above command in your ~/.vimrc
file
Helpful config that doesn't live in your vimrc¶
Spell¶
When working on a file, you may want to make sure it is spelt correctly, i.e. when working on handbook entries
To do this, enter the following in normal mode :set spell
This will highlight works that are spelt incorrectly, as well as some grammatical mistakes.
To jump to the next mistake press ]s
, to jump to the previous one press [s
When hovering over a misspelt word press z=
to bring up a list of suggestions. Simply press the number to to
the correct word and it will be updated
See :help spell
for more
Clear search highlights¶
Vim should have been configured to highlight what you have searched for. Sometimes you may want to get rid of this, but still keep the search term in the register.
To do this simply run :set nohighlight
, or :set noh
for short, and the highlights will be cleared until you run another search.
Diffing files¶
Sometimes you may want to visually diff two files. To do this quickly do the following
- Open the first file
- Open the second file in a vertical split
:v /path/to/file
- Tell vim to diff the two open buffers
:windo diffthis
- Jump around the diffs using
[c
and]c
- Copy changes between the files using
do
(diff obtain) anddp
(diff put) - Leave diff mode by running
:windo diffoff
See :help diff
for more
Changing the current working directory¶
Vim will set the working directory to the one that you ran it from. If you want to use the gf
command to jump
to relative files this may not always be the right one
To change this, type the following cd /path/to/dir
I often use this when working with nginx files. The files that I'm editing are in the conf.d/
directory, but
the path to the includes is /etc/nginx
Switching to the directory allows you to move the cursor over any include file and press gf
to jump to it
Helpful commands¶
Insert File Paths¶
In insert mode, if you want to complete a path you can hit [ctrl]+[x] [ctrl]+[f]
to get a neat little drop down that lets you pick the file.
Reload the file¶
If you know that the currently open buffer has been changed on disk, you may want to reload it to see what has changed.
This can be done by running :e
, or :e!
if there are changes that you want to discard
Jumping between buffers¶
Vim is able to open multiple files at once, these open files are called buffers. This can happen if you run vim
file1 file2 ... fileN
, if you open files after starting vim :e file
, :vs file
, or create new files :enew
,
:vnew
. You can use the following commands to move between these open files
:bn
This will move you to the next buffer:bp
This will move you to the previous buffer:ls
This will give you a numbered list of all open buffers along with some information about their state:b
This will open a buffer by number or name. You can type a couple of letters and press tab to get the name
Text Manipulation¶
The following commands are used for basic text manipulation
Yank¶
The y
key is used to yank text into the register. This leaves the text in the document, and allows you to paste is later on
Delete¶
The d
key is used to delete the text from the document and place it into the register
Paste¶
The p
key is used to paste the register into the document. By default this will paste the 0
register onto the
page, but it is possible to paste others by pressing " + <reg> + p
Here are some useful registers that you may want to use
/
The last search term:
The last command*
and+
The xclipboard - will explain this further down%
The current filename#
The last opened buffer filename0
The last yanked / deleted text - this is useful if you are using the register in the search / command line.
Tip
To use the registers in the search / command line press <Ctrl> + r + <reg>
To see all of you registers type :reg
Movement¶
Blocks¶
You can use the {
to jump up a block, and the }
to jump down a block.
A block is considered to be any block of text that doesn't start with a blank line, i.e.
test test test test test test test test test test
test test test test test test test test test test
All of this is one block
test test test test test
This is a new block
Start of Line¶
You can use ^
to jump to the start of a line, or <Shift> + i
to start editing at the start of it, both of
these will take you to the first non space character of the line. If you need to jump to the very first character
of the line, then you can press 0
End of Line¶
Press $
to jump to the end of the line, or <Shift> + a
to start editing.
Jump to last edit¶
If you are in the middle of editing something, and then move to a different location and edit there, you can jump
back the first place by pressing `` (two backticks)
Making a mark¶
The last edit is a special type of mark that vim uses. You can set your own marks by pressing m
and then a single
character, either upper or lower case, for example z
Once this is done you can then return to either the start of that line by pressing 'z
or the exact place by
pressing `z
, (backtick + z)
Start of a file¶
Press gg
to jump to the very start of a file
End of a file¶
Press G
to jump to the last line of a file
Forward a word¶
Press w
to jump forward to the next bit of a word, i.e. a /
or W
to jump to the next space
Backwards a word¶
Press b
to jump to the previous bit of a word, or B
to jump to the previous space
Searching¶
Press f + <character>
to search for the next instance of the character. After that press ;
to jump to the next
one and ,
to jump to the previous one
Use F
to search in reverse, i.e. backwards
Combining Movement and Commands¶
One of the most useful things that vim offers is the ability to combine commands. To explore this we will look at different ways to delete a block of text.
Let's consider the following block of text and the different ways that we could delete it
text text text text text text text text text text text text text text text text text text text text text text text
text text text text text text text text __your cursor is here __text text text text text text text text text text
text text text text text text text text text
Hold down delete and then backspace¶
This will work, but you should feel bad about yourself if you use it
Special delete command¶
Typing dd
will delete the entire line. You could type this several times, to remove the lines one by one.
Delete lots of words¶
You are able to add the number of times that you want an action to be carried out. This means that you could type
25dW
and we would delete 25 words from the cursor. This is useful if you know the exact number of times you want
to carry out the action, but in this case we would be guessing.
Alternatively, you could type the following k3dd
, which would move you up one line, and then delete the next three lines
Jump to the start of the block and delete a block¶
You could run, {d}
which will go to the start of the block and delete one entire block.
Delete inside or around the paragraph¶
Running dip
will delete inside the paragraph, whilst dap
will delete around the paragraph. The inside / around
movements can be combined with lots of helpful modifiers, these are some of the ones I use the most
{
or}
curly braces[
or]
square braces(
or)
brackets'
single quotes"
double quotes<
or>
angle bracketst
and XML tagw
andW
words
Using Visual Mode¶
Pressing <Ctrl> + v
will put you into visual mode. This will allow you to move around and select exactly what
you want. You can then press d
, or x
to delete the selected text
Using Visual Block Mode¶
You could also press <Ctrl> + <Shift> + v
to enter visual block mode. This lets you draw rectangles to select
rather than following the sentence structure. This is very useful when you want to remove columns of data
Shell Commands¶
Vim allows you to run shell commands over blocks of text. This can be entered into a range on the command line,
or you can combine the !
key with a movement, which is what I use.
In addition to the inside / around commands, and the up and down blocks, you can also press ! + left / right arrow
to select the current line.
This will change the command line to the following, :.!
. You can then type in a bash command and it will be run on the line.
For example consider the following log entry
[2017-10-16 14:27:32] INFO: With this body {"products":[{"qty":1,"id":"6","configurable_options":[{"code":"colour","value":"9"},{"code":"size","value":"8"}],"custom_options":[]}],"customer_details":{"email_address":"test_order@example.com","customer_identifier":"any_unique_random_string","first_name":"John","last_name":"Smith","has_loyalty_card":1,"loyalty_card_number":"123456789"},"address_details":{"street_1":"123 Main Street","street_2":"","city":"Leeds","region":"West Yorkshire","country":"United Kingdom","post_code":"LS1 2AB"},"appId":"test,"merchantId":"4"} []
We want to be able to read the JSON that has been sent through, but it has been minified onto one line.
Combining what we have learn above, we can run the following commands - assuming that we are on the first character of the line
f{
- this will move the character to the opening curly braceya{
- this will yank everything inside the curly braces into the registerenew
- this will open a new bufferp
- paste the register into the new file! + left arrow
- tells vim we want to run a command on the current linejson_reformat
- a bash command that will prettify JSONset filetype=json
- tells vim that the file contains JSON and syntax highlights it.
In additon to the json_reformat
toll, I find the following commands helpful
xmllint¶
Like json_reformat
this is used to format XML. The following is the standard command that I use
xmllint --format -
Which will validate and format any XML that is passed to it.
fmt¶
Useful to ensure that the width of a document doesn't exceed a set amount. Splits intelligently on word breaks, and can either reflow an entire document, or keep the existing line breaks
fmt -w 140 -s
column¶
Used to create text tables from deliminated data. The deliminater can be set, which makes it easier to read and edit CSV files. Use this in combination with visual block mode to easily add, move, or remove columns
column -s ',' -t
sort¶
There are other options available, but this is still the one that I turn to. Quickly sort a set of data, I use this a lot in combination with the inside braces / tags to keep definitions in alphabetically order
sort
uniq¶
Only output the unique values in a sorted list, can be used to count them as well
uniq (-c)
Still to do¶
- Other useful bash commands
- Folding
- Search / replace
- Global command
- Read command
- Macros
- Indentation
- Helpful shortcuts
- History commands i.e. undo / redo
- Encryption
- Running commands on the file
- The clipboard and how to use it