Vim is a modal text editor, to learn how to switch modes, start by the section Switch between navigation and editing mode. Large part of this documents have been copied from the vim help accessible through:
:help <topic>
People that I admire use vim.
See also my vimrc file stored in setup/.vimrc. Many configuration options are mentioned throughout this document.
Reload the configuration after editing it:
:so ~/.vimrc
Text colour. Add syntax highlight to your .vimrc
syntax enable
How to add a file extension to vim syntax highlight
au BufNewFile,BufRead *.dump set filetype=sql
I used it to display markdown files as text files:
au BufNewFile,BufRead *.md set filetype=txt
Make a key combination specific to latex files, to insert a citation key using the vimtex plugin. Note: ctrl-space appears as ctrl-@ in my terminal
au BufRead,BufNewFile *.tex inoremap <C-Space> <C-x><C-o> | inoremap <C-@> <C-x><C-o>
Prevent tab expanding to space in make files SO answer:
autocmd FileType make set noexpandtab
I mapped m to the end of line, maybe I should use m instead?
noremap m $
See also mapping below.
Be sure to set terminal colour to 256 as explained in an answer to a question on vi.stackexchange and in the vim wiki 256 colors in vim
set t_Co=256
For a while I used:
set background=dark
colorscheme jellybeans
A command that reuses another command can be entered directly after
the command name, separated by a space. To enter normal and insert mode
command, you need to prefix it with “normal
”. See
:help normal
for more information on executing normal mode
commands typed on the command line.
Sample commands that I have in my .vimrc.
Add the current date
command! Date put =strftime('%Y-%m-%d')
Convert the current line to snake case (1) replace any non alphanumeric characters by underscores (2) convert to lower case.
command! -range=% Snake s/[^a-zA-Z0-9]\+/_/g | normal Vu
Lexplore with a 30 character size buffer only
command! Ll Lexplore | vert res 30
Display a word diff
command! Gwdiff vert term git diff --word-diff
Create a table of content command based on different tools that depend on the file type
augroup Toc
autocmd!
autocmd Filetype markdown command! -buffer Toc Voom
autocmd Filetype rmd command! -buffer Toc Voom
" rnoweb are the Rnw notebooks mixing latex and R code
autocmd Filetype rnoweb command! -buffer Toc Voom
autocmd Filetype tex command! -buffer Toc VimtexTocOpen
augroup END
command! TOc Toc
Title inside a script
autocmd FileType python command! Title normal A #<esc>yyppv$r#kkv$r#
Right align columns in tab separated files generated by Nvim-R. After
pressing the
command! Tt Tabularize /\t/r0
See
:help map
Show all mappings including
:map
How to map the ALT key Explains who to see what key combination is actually seen by the console:
sed -n l
I used this mapping “ALT-;” to insert the pipe “%>%” in R documents:
" The ALT key is mapped to escape in the terminal, remap it
" https://vi.stackexchange.com/questions/2350/how-to-map-alt-key
execute "set <M-;>=\e;"
autocmd FileType r inoremap <M-;> <space>%>%<CR>
autocmd FileType rmd inoremap <M-;> <space>%>%<CR>
This didn’t work because the CTRL-; is seen as ; by the terminal:
" Try to map the CTRL+;
autocmd FileType r inoremap <C-;> <space>%>%<CR>
autocmd FileType rmd inoremap <C-;> <space>%>%<CR>
In the end I changed the mapping > to %>% as explained in NVimR issue 85:
autocmd FileType r inoremap <buffer> > <Esc>:normal! a %>%<CR>a
autocmd FileType rmd inoremap <buffer> > <Esc>:normal! a %>%<CR>a
different mappings for CTRL+A and CTRL+SHIFT+A It’s generally not possible.
You can create a minimal .vimrc and use is by calling vim with
vim -u /tmp/.vimrc
See for example this bug report where I used this minimal vimrc file to investigate an issue with the Vimtex plugin.
set nocompatible
let &runtimepath = '~/.vim/bundle/vimtex,' . &runtimepath
let &runtimepath .= ',~/.vim/bundle/vimtex/after'
filetype plugin indent on
syntax enable
" Use zathura as a PDF viewer
let g:vimtex_view_method = 'zathura'
Or another minimal vimrc to investigate an issue with the nvim-R plugin.
set nocompatible
let &runtimepath = '~/.vim/bundle/Nvim-R,' . &runtimepath
filetype plugin indent on
syntax enable
let maplocalleader = ";"
" enable vim-markdown for .Rmd files too
" This might conflict with the Nvim-R plugin
augroup filetypedetect_markdown
au!
au BufRead,BufNewFile *.Rmd set ft=markdown
augroup END
The solution was to use 2 file types for Rmd files:
set ft=rmd.markdown
.
Show existing values of settings with a question mark at the end
:set updatetime?
:set signcolumn?
:set filetype?
Vim uses a syntax highlight system that changes quotes and backsticks. It prevents copy pasting from vim using the tmux copy mechanism. To turn it off before a copy:
syn off
Convert markdown documents to other formats such as pdf with pandoc.
Convert the current document to html
:Pandoc
Convert the current document to pdf
:Pandoc pdf
Convert the current document to word
:Pandoc docx
Other output -t options from man pandoc
• docx (Word docx) • html or html5 (HTML, i.e. HTML5/XHTML polyglot markup) • latex (LaTeX) • odt (OpenOffice text document) • pptx (PowerPoint slide show)
Add a yaml front matter to specify more parameters
---
title: "Songs of freedom"
author: "Bob Marley"
geometry: margin=0.5cm
---
To use a bibliography with the pandoc extension insert the following in the header of the markdown file:
bibliography: /path/to/bibliography/papers.bib
Then the bibliography file should be added to the vim variable
b:pandoc_biblio_bibs
. You can check it was added correctly
by calling:
:echo b:pandoc_biblio_bibs
Once the bibliography files is activated, autocomplete can be called
by pressing CTRL-X CTRL-O
(or ctrl+space in my case) after
@
. For more see:
:help vim-pandoc-bibliographies-module
Bibliography also works with R markdown documents, see rmarkdown documentation authoring bibliographies and citations.
To edit a whole line:
dd to delete a whole line
yy to copy a whole line
p to paste the copied or deleted text after the current line or
P to paste the copied or deleted text before the current line
You can edit multiple lines simultaneously by inserting text inside a multi-line selection in Vim :
Use Ctrl+V to enter visual block mode
Move down with jj to select the columns of text in the lines you want to comment.
Then hit Shift+I and type the text you want to insert.
Then press Escape, the inserted text will appear on all lines.
Similarly to enter text at the end of multiple lines (vim.wikia)
Use Ctrl+V to enter visual block mode
Move down with jj to select the columns of text in the lines you want to comment.
Then hit **$** to select all lines until the end of the line.
Then press Shift+A and type the text you want to insert.
The press Escape, the inserted text will appear at the end of all lines.
How to add text at the end of each line in Vim?
“Visual select a paragraph
vip
, switch to Visual block modeCTRL V
, append to all lines$A
a comma ,, then press Esc to confirm.”
Delete all lines that contain “pattern”:
:g/pattern/d
Delete all lines that do not contain a pattern:
:g!/pattern/d
:v/pattern/d
See also:
Use the range
command as explained in the vim
wiki:
:put =range(11,15)
Use the auto incrementation g CTRL-A
:help ctrl-a
{Visual}g CTRL-A Add [count] to the number or alphabetic character in
the highlighted text. If several lines are
highlighted, each one will be incremented by an
additional [count] (so effectively creating a
[count] incrementing sequence). {not in Vi}
For Example, if you have this list of numbers:
1. ~
1. ~
1. ~
1. ~
Move to the second "1." and Visually select three
lines, pressing g CTRL-A results in:
1. ~
2. ~
3. ~
4. ~
Other example from the vim wiki:
my_array[0] = 0;
Then copy it using Y6p
(copy the line and paste it six
times). The result is:
my_array[0] = 0;
my_array[0] = 0;
my_array[0] = 0;
my_array[0] = 0;
my_array[0] = 0;
my_array[0] = 0;
my_array[0] = 0;
Then select the lines from the second line onwards and use
g CTRL-A
to get:
my_array[0] = 0;
my_array[1] = 0;
my_array[2] = 0;
my_array[3] = 0;
my_array[4] = 0;
my_array[5] = 0;
my_array[6] = 0;
Filter a file in place (seen in a blog post called Vim Kōans)
:%!awk "/paper/{print $4}"
Select a few lines in visual mode and
:sort
Help sort
With [!] the order is reversed.
:'<,'>sort!
With [i] case is ignored.
:'<,'>sort i
With [u] (u stands for unique) only keep the first of
a sequence of identical lines
Sort outside a pattern
When /{pattern}/ is specified and there is no [r] flag
the text matched with {pattern} is skipped, so that
you sort on what comes after the match.
Instead of the slash any non-letter can be used.
For example, to sort on the second comma-separated
field: >
:sort /[^,]*,/
To sort on the text at virtual column 10 (thus
ignoring the difference between tabs and spaces):
:sort /.*\%10v/
To sort on the first number in the line, no matter
what is in front of it:
:sort /.\{-}\ze\d/
(Explanation: ".\{-}" matches any text, "\ze" sets the
end of the match and \d matches a digit.)
Sort within a pattern
With [r] sorting is done on the matching {pattern}
instead of skipping past it as described above.
For example, to sort on only the first three letters
of each line: >
:sort /\a\a\a/ r
Super User reverse selected lines
Select the paragraph and use the GNU tac
command:
:'<,'>!tac`
To reverse the order of lines in a paragraph, you can use
vip
to select the current paragraph, followed by
!
which automatically inserts :'<,'>!
followed by tac
. In short what you end up tipping to
reverse the current paragraph is vip!tac
.
It’s possible to edit text files inside a zip archive with vim. Open the file as such:
vim file.zip
The tabular plugin provides a Tabular command which can be
abbreviated to :Tab
. To align a latex table with the
tabular package. Select a few lines, then press:
:'<,'>Tab /&
Align tab separated text in the current buffer (to view tsv files generated from data frames by NVim-R for example):
:Tab /\t
Or enter CTRL + V and press the TAB key for a literal tab.
To have numbers right aligned
:Tab /\t/r0
Similarly to align a markdown table, select a few lines, then call:
:'<,'>Tab /|
For more, see help tabular
.
u: undo last change (can be repeated to undo preceding commands)
Ctrl-R: Redo changes which were undone (undo the undos).
Compare to '.' to repeat a previous change, at the current cursor position.
Ctrl-R will redo a previously undone change, wherever the change occurred.
Vim help on search and replace :help :s
[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
For each line in[range]
replace a match of{pattern}
with{string}
.
For example find each occurrence of ‘red’ (in the current line only), and replace it with ‘green’:
:s/red/green/g
The s
command means “substitute”. The g
means “greedy”, it will replace all occurrences of the word on a line
(not just the first occurrence).
When text is visually selected, press : to enter a command. The command line will automatically enter the range:
:'<,'>
Then you can enter a replacement command such as
s/red/green/g
to replace each occurence of “red” with
“green” in all lines of the visual selection. The command will appear
as:
:'<,'>s/red/green/g
Find each occurrence of ‘red’ in all lines (%s
), and
replace it with ‘green’.
:%s/red/green/g
Find each occurence of foo but don’t perform the replacement, only count the number of occurences
:%s/foo/bar/n
To replace by a new line character, use \r
instead of
\n
. For example to insert a new line after each comma in a
selection:
:'<,'>s/,/,\r/g
To replace double line breaks by a single line brake
:%s/\n\n/\r/g
You can use replacement to remove text. For example to remove the last 2 characters of each line in a selection :
:'<,'>s/..$//
In case you have slashes in the pattern, you can use another
separator such as #
:%s#/path/to/file#/new/path#g
See also:
Add a read counter item to a list of papers to read
iabbrev azer - {1}
Vim wiki abbreviations
iabbrev teh the
See :help collection
: “A collection is a sequence of
characters enclosed in brackets.”
Example matches ~
[xyz] any 'x', 'y' or 'z'
[^xyz]" anything but 'x', 'y' and 'z'
[a-zA-Z]$ any alphabetic character at the end of a line
For example to replace all characters but the pipe (to create a separation in a markdown table):
:'<,'>s/[^\|]/-/g
Find and replace with confirmation
:%s/old/new/gc
Press y
or n
to confirm each replacement
individually.
Toggle case "HellO" to "hELLo" with g~ then a movement.
Uppercase "HellO" to "HELLO" with gU then a movement.
Lowercase "HellO" to "hello" with gu then a movement.
For example to convert to lower case from the cursor to the end of the line:
gu$
To change the current line from upper to lower case:
guu
http://vimregex.com/ Grouping and Backreferences
“ou can group parts of the pattern expression enclosing them with
"\(" and "\)"
and refer to them inside the replacement pattern by their special number \1, \2 … \9. Typical example is swapping first two words of the line:
s:\(\w\+\)\(\s\+\)\(\w\+\):\3\2\1:
” where \1 holds the first word, \2 - any number of spaces or tabs in between and \3 - the second word. How to decide what number holds what pair of () ? - count opening
"\("
from the left. ”
A simpler version in the case of character strings only
:'<,'>s/.*\(".*"\).*/\1/g
# Paste ready version
s/.*\(".*"\).*/\1/g
Suggestion and explanation by Chat GPT
:'<,'>s/.*\("\([^"]\+\)"\).*/\1/g
Explanation:
.*
Matches any character zero or more times.\("([^"]\+)"\)
This is the capturing group for the
quoted string. It captures anything between quotes and stores it in
\1..*
Matches any character zero or more times.\1
This replaces the entire line with just the first
capturing group, which is your quoted string.Several search and replace patterns to fix text copied from web pages or pdf files into markdown.
Place quotes around variables that contain a dollar sign (otherwise interpreted as a formula start in markdown):
:'<,'>s/\(\w*\$\)/`\1`/g
Remove hyphenation at the end of lines in a paragraph
:'<,'>s/\(\i\)- /\1/g
I put this into a command in my .vimrc
command! -range=% Hyphen <line1>,<line2>s/\(\i\)- /\1/g
TODO: “the 30- year average” should not be replace but only by a space.
To place quotes around variables that contain a dollar sign (otherwise interpreted as a formula start in markdown):
:'<,'>s/\(\w*\$\)/`\1`/g
add quotes at the start and end of each line
:%s/^\(.*\)$/"\1"/
s/regex/replace/ is vim command for search n replace. % makes it apply throughout the file ^ and $ denotes start and end of the line respectively.
(.*)
captures everything in between. ( and ) needs to be escaped in vim regexes. \1 puts the captured content between two quotes.
Remove bracketed references from text copied from Wikipedia.
:'<,'>s/\[[0-9]\+\]//g
See also patterns below.
See :help character-classes
for a list of classes
accepted in Vim with their equivalent regex pattern, for example
\w
is equivalent to [0-9A-Za-z_]
. Replace all
word characters by a dash (to create a markdown table division see also
collection below)
:'<,'>s/\w/-/g
Note that this only works with ASCII characters and doesn’t work with
accentuated characters. For example smöl
gets replaced by
--ö-
. To replace all identifier characters, use
:'<,'>s/\i/-/g
And then smöl
gets replaced by ----
.
Insert Markdown title marker #
before a number at the
beginning of a line
%s/^\(\d.\)/# \1/g
Note \0
matches the hole pattern. Use backslash-escaped
parenthesis to match a particular pattern. \d
matches any
digit.
Remove bracketed references from text copied from Wikipedia.
:'<,'>s/\[[0-9]\+\]//g
Remove all numbers in a list of authors
:'<,'>s/\d//g
Replace this or that with a dot
:%s/this\|that/./g
Replace opening or closing curly braces by two curly braces
:'<,'>s/{/{{/g | s/}/}}/g
Replace simple list items with a curly braces counter (to count the number of times I want to read a publication or a paper). I have created a shortcut for this substitution.
:'<,'>s/\n- /\r- {1} /g
List files in the present working directory and replace them with a markdown link:
:.!ls
:'<,'>s/.*/[&](&)/g
Vim wiki Remove unwanted spaces:
In a search, finds white space (a space or a tab), and + finds one or more occurrences. Command to replace repeated white spaces by a single white space in a selection:
:'<,'>s/\s\+/ /g
SO vim regex replace multiple consecutive spaces with only one space proposes multiple other solutions, this one derived from Aristotle’s answer keeps indentation white spaces at the beginning of the line:
:'<,'>s/[^\s]\zs\s\+/ /g
Remove all beginnings of line. :%s//, /g replace all end of line by comma + space. This cleans an html list of species for inclusion in a text.
%s/option value=".*"//g
This pattern replaces one or more white spaces with a pipe, to create markdown tables:
:'<,'>s/\s\+/|/g
This pattern removes spaces at the end of the line:
:'<,'>s/\s*$//g
To search and replace in a visual selection, select an area then
press :
. The line will automatically begin with
:'<,'>
, you can then enter the patterns.
:'<,'>s/search/replace/g
For a vertical selection, this doesn’t work automatically and you have to use
:'<,'>s/\%Vsearch/replace/g
To replace a visual selection by inserting new text at the keyboard
in insert mode, use c
for change:
c
Copy
yy The current line
yiw The current word
ye To the end of the current word
yip The current paragraph
yG To the end of the document
Paste with P
(before) or p
(after) the
cursor.
Copy just one character
vy
Copy and paste in visual mode with the following instructions:
Position the cursor where you want to begin cutting.
Press v (or upper case V if you want to cut whole lines).
Move the cursor to the end of what you want to cut.
Press d to cut or y to yank (copy into the `"0` register).
Move to where you would like to paste.
Press P to paste before the cursor, or p to paste after.
Copy to a system register (to be used by other programs)
"+yy
"+yip
See also the section on registers below and :help "+
for
more details on system registers.
Press Y6p
to copy the following line 6 times
- example
When pasting from the system register i.e. with
Ctrl+Shift+V
you need to prevent auto indent otherwise vim
will mess with the indentation. This can be solved with bracketed paste,
see further down below.
As explained in Paste without autoindent You can either read from the shell with:
:r! cat
And then paste CTRL + SHIFT + V
the content, and
CTRL+D
. Also works over SSH.
Or use
:set paste
:set nopaste
Set up a shortcut to toggle paste mode on and off with:
set pastetoggle=<F3>
Note: I don’t use paste toggle any more, bracketed paste works well.
” Registers in Vim let you run actions or commands on text stored within them. To access a register, you type “a before a command, where a is the name of a register. If you want to copy the current line into register k, you can type
"kyy
Or you can append to a register by using a capital letter
"Kyy
You can then move through the document and paste it elsewhere using
"kp
To display the content of all registers:
:registers
For example yank the word “yank”, delete the word “delete” and copy the word “system” outside of vim in any program will give you the following registers:
:registers
--- Registers ---
"" delete
"0 yank
"- delete
"* system
"+ system
". ^@yank^@delete^@
To clean vim registers as explained on a SO answer, enter this at the vim prompt:
for i in range(34,122) | silent! call setreg(nr2char(i), []) | endfor
How can I do a change word in vim using the current paste buffer
Select the current word, then select the word to replace and paste
ye
vep
Or select the current word, then paste and delete the word to replace
ye
Plde
Note this works only for one replacement because the yank register is then replaced with the deleted word.
Copy a single character at the cursor position
vy
xu
Copy a character before the cursor position
Xu
Cut a single character, then paste it later
x
p
From a Stack Exchange question on how to copy a single character in vim
Indentation replaced by spaces, add this to the ~/.vimrc file
set tabstop=4
set expandtab
set softtabstop=4
set shiftwidth=4
filetype indent on
More details on vim indentation in the python wiki. In particular the page How to stop auto indentation explains how to display indentation setting for the current file type:
:verbose set ai? cin? cink? cino? si? inde? indk?
Save the current file
:w
Save under a new name (save as) and edit that file
:sav
:saveas
SO save as a new file and continue editing the original one
To move or rename a file within the vim file explorer:
R
https://vi.stackexchange.com/questions/74/is-it-possible-to-make-vim-auto-save-files/79#79 suggests
One possible way to implement this is to use the CursorHold autocommand event. This event is triggered when the user hasn’t pressed a key for ‘updatetime’ milliseconds.
autocmd CursorHold * update
The :update command only saves the buffer if it is modified. If you also wanted this to happen while insert mode is active, CursorHoldI could be added to the event list.
autocmd CursorHold,CursorHoldI * update
Show the value of the update time
:set updatetime?
https://stackoverflow.com/a/34814520/2641825 says that
“
:update
is better suited than:write
, because it only actually saves when there are unpersisted updates.”
https://stackoverflow.com/questions/6991638/how-to-auto-save-a-file-every-1-second-in-vim suggests
autocmd TextChanged,TextChangedI <buffer> silent write
https://stackoverflow.com/questions/17365324/auto-save-in-vim-as-you-type/55761306#55761306 (duplicate of the previous one)
https://www.reddit.com/r/vim/comments/ywzeu3/autosave_file/?rdt=63220&onetap_auto=true suggests
autocmd CursorHoldI,CursorHold * silent! update
Thoughtbot.com Wrap existing block of text to 80 characters:
:set textwidth=80
Apply automatically to markdown files, by adding this to .vimrc
au BufRead,BufNewFile *.md setlocal textwidth=80
To format the text, select it with v and up or down movements, and press
gq
To disable auto wrapping, call
:set formatoptions=cq
Vim documentation
:help visual-use
Difference between visual and select mode
Various ways to select text in visual mode
vt<char> - till before a given character
vf<char> - till a given character
Select the current paragraph:
vip
Select the current word:
viw
Select what is in the current parenthesis block
vi(
Select what is inside the current quote block
vi"
Select the current line
V
These selection methods can also be used to delete diw
and yank yiw
.
To enter edit mode:
i
To enter command mode:
escape
To exit vim, go in command mode and enter the following command:
:q
To exit without saving the content of the file:
:q!
To save the content of the file:
:w
If you accidentally press CTRL+S the terminal will hang
Press CTRL+Q
to regain control. See also Ctrl-s
hang terminal emulator? which provides a workaround: entering
stty -ixon
in .bashrc.
To save content and exit:
:wq
See also the [debian.html] page. The Arch Linux wiki page on Mutt has a section explaining how to set it up with vim.
:help - vim help
:help commandname - help on a particular command
:h commandname - help on a particular command
CTRL+] - jump to a highlighted topic. I remapped it to `ctrl %`.
CTRL+T - jump backwards
HTML version of the Vim help pages kept up-to-date automatically from the Vim source repository.
Did you see warning messages but they disappeared before you have had time to read them? Type the command |:messages| in Normal mode to see them again. (copied from nvim-r help)
Insert the current file name in VIM In insert mode press:
<c-r>%
In normal mode:
:r! echo %
In normal mode, insert the content of another file:
:read /tmp/newdir/file1.txt
Insert the content of a file from the network:
:Nread https://www.wikipedia.org/
For more, see :help Nread
.
Vim wiki insert date or time
I added the following command to my .vimrc:
command! Date put =strftime('%Y-%m-%d')
:e filename - edit another file
:ls - show current buffers
:b 2 - open buffer #2 in this window
:b filename - open buffer #filename in this window
:bd - close the current buffer (! to forget changes)
:bd filename -close a buffer by name
Reload the file in the current buffer:
:e
Open the quickfix window with:
:copen
The result of some search operation seach as grep can be displayed in the quick fix window.
Why do vim experts prefer buffers over tabs? > ““Vim experts” don’t prefer buffers over tabs: they use buffers as the file > proxies they are and tab pages as the workspaces they are. Buffers and tab > pages have different purposes”
Open a file in a new tab
:tabnew {file}
Move to the next tab
gt
Move to the previous tab
gT
Open the file under the cursor in a new tab
CTRL-W gf Open a new tab page and edit the file name under the cursor.
See |CTRL-W_gf|.
CTRL-W gF Open a new tab page and edit the file name under the cursor
and jump to the line number following the file name.
See |CTRL-W_gF|.
See :help tabpage
for more instructions.
:sp[lit] filename - split window and load another file
:10sp - specify the split height with a number
:vs[plit] - same but split vertically
ctrl-w up arrow - move cursor up a window
ctrl-w ctrl-w - move cursor to another window (cycle)
ctrl-w_ - maximize current window
ctrl-w= - make all equal size
CTRL+z - suspend the process and get back to the shell
fg - get back to vim
nnoremap <C-J> <C-W><C-J>
nnoremap <C-K> <C-W><C-K>
nnoremap <C-L> <C-W><C-L>
nnoremap <C-H> <C-W><C-H>
Natural split opening
set splitbelow
set splitright
Open an existing buffer (from the buffer list) in a new split
:sb buffername
For a vertical split
:vert sb buffername
ViM Stack exchange Open 2 files in 2 horizontal splits
vim -o file1.md file2.md
Limit the number of splits
vim -o2 *.md
Open files in vertical splits
vim -O file1.md file2.md
Set current window height to 10 lines
res 10
Set current window width to 100 characters
vertical res 100
See :help resize
for more commands. There are many
possible key combinations to resize the window.
:res[ize] [N]
CTRL-W CTRL-_ *CTRL-W_CTRL-_* *CTRL-W__*
CTRL-W _ Set current window height to N (default: highest possible).
z{nr}<CR> Set current window height to {nr}.
Change the height of the current window by increments of 10:
:res +10
Change the with of the current window by increments of 10:
:vert res +10
Set the height of the terminal buffer to 10 lines
:set termwinsize=10x0
c-w-| to have window take over (if using vsplits).
c-w-_ for horizontal splits
c-w-= to restore.
See the bash page for the tmux side of the configuration.
I use the vim-tmux-navigator
It doesn’t work in a terminal buffer because of conflicts with fuzzy file search. issue 172
vim-tmux-navigator to use tmux prefix instead of C-[hjkl]
busnag.com tmux and vim > ” like many vim users, I edited my .vimrc to simplify split navigation, so > that I can jump between vim splits using ctrl-j, ctrl-k, etc.
reddit python workflow with terminal using tmux > “Finally, I have Ctrl+[hjkl] setup such that I can navigate seamlessly between vim and tmux panes.”
Plugins are mentioned in diverse section of this document. This section is mostly to list plugins I used and potentially interesting plugins.
Display plugins I currently use with vundle:
:PluginList
Copy of the list from my .vimrc
:
" Colour themes for Vim
Plugin 'morhetz/gruvbox'
Plugin 'nanotech/jellybeans.vim'
" Code structure i.e. table of content of classes, methods and functions
Plugin 'yegappan/taglist'
" Git interface
Plugin 'tpope/vim-fugitive'
" Latex editing
Plugin 'vim-latex/vim-latex'
" Markdown toc navigation
Plugin 'godlygeek/tabular'
Plugin 'plasticboy/vim-markdown'
" Python autocompletion
Plugin 'davidhalter/jedi-vim'
" Python linter
Plugin 'dense-analysis/ale'
" R programming
Plugin 'jalvesaq/Nvim-R'
I also use a spell checker.
Other plugins installed in the default vim repo:
:r ! ls ~/.vim/pack/plugins/start/
indentpython.vim
pytest.vim
vim-slime
vim-tmux-navigator
Potentially useful plugins
:Explore
I’m trying to extract a table of content functionality from a plugin that does many other things I don’t need.
I extracted the function into a plugin called markdown-toc-toc I placed the plugin in ~/.vim/pack/plugins/start/markdown-toc-toc and this fixes my issue. I now have both Nvim-R autocompletion and syntax highlight working correctly in R markdown chunks as well as a table of content for the markdown titles. Later on, I moved to the Voom plugin for the table of content.
To temporarily deactivate a plugin in a session.
How to see which plugins are making Vim slow?
“You can use built-in profiling support: after launching vim do”
:profile start profile.log
:profile func *
:profile file *
" At this point do slow actions
:profile pause
:noautocmd qall!
“If you’re having problems with screen update operations (^L, scrolling, etc) being slow, your problem may be an inefficient syntax highlighting file. You can test this by temporarily disabling syntax highlighting”
:syn off
To profile the syntax file
Open a file that causes syntax highlighting performance issues.
Run :syntime on to start profiling.
Scroll through the file a bit.
Run :syntime report to generate a report. The patterns listed first in the report are the ones which took the most time to process.
The matchparen plugin seemed to be slow on large markdown documents. It’s part of the vim distribution and loaded by default. vi.stackexchange matchpairs makes vim slow. But it was called by the Pandoc syntax highlight file.
Install slime with Vim’s built-in package support (since Vim 7.4.1528):
mkdir -p ~/.vim/pack/plugins/start
cd ~/.vim/pack/plugins/start
git clone https://github.com/jpalardy/vim-slime.git
Install all plugins configured in your .vimrc
.
:PluginInstall
Update the configured plugins. Press ‘u’ after updates to see the change log.
:PluginInstall! " NOTE: bang(!)
# or
:PluginUpdate
Since there is a built-in plugin support, maybe I don’t need Vundle after all?
Edit your .vimrc and add the following at the beginning
set nocompatible " be iMproved, required
filetype off " required
" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
" alternatively, pass a path where Vundle should install plugins
"call vundle#begin('~/some/path/here')
" let Vundle manage Vundle, required
Plugin 'VundleVim/Vundle.vim'
" Navigate markdown toc
Plugin 'godlygeek/tabular'
Plugin 'plasticboy/vim-markdown'
Plugin 'tpope/vim-fugitive'
Plugin 'jpalardy/vim-slime'
" All of your Plugins must be added before the following line
call vundle#end() " required
filetype plugin indent on " required
" To ignore plugin indent changes, instead use:
"filetype plugin on
"
" Brief help
" :PluginList - lists configured plugins
" :PluginInstall - installs plugins; append `!` to update or just :PluginUpdate
" :PluginSearch foo - searches for foo; append `!` to refresh local cache
" :PluginClean - confirms removal of unused plugins; append `!` to auto-approve removal
"
" see :h vundle for more details or wiki for FAQ
" Put your non-Plugin stuff after this line
vim-latex the one I used first.
vimtex is more recent compared to vim-latex
:help compl-omni
with CTRL-X CTRL-OUsage as explained in
̀:help vimtex-default-mappings
:
———————————————————————~ LHS RHS MODE~ ———————————————————————~
n
n
n
———————————————————————~
I mapped <localleader>
to ;
.
Display a table of content:
:VimtexTocOpen
:VimtexTocToggle
Define a shorter command name Toc
, by placing this in
the .vimrc
au BufRead,BufNewFile *.tex command! Toc VimtexTocOpen
I first ran into this error when viewing git diffs or when jumping back to the tex file with Ctrl-O
Error detected while processing BufRead Autocommands for "*.tex":
E174: Command already exists: add ! to replace it: Toc VimtexTocOpen
Because I had the autocommand defined this way:
au BufRead,BufNewFile *.tex command Toc VimtexTocOpen
Compile
:VimtexCompile
Install prerequisite to view pdf files with forward (from vim to the pdf viewer) and backward (from the pdf viewer to vim) search. Note: Forward and backward search are not available for evince issue 179.
sudo apt install zathura
sudo apt install xdotool
This bug report pushed me to learn about xdotool and xprop.
There was a issue with the focus not moving to the zathura viewer. I reported it as issue #1719. The first step was to add client server support to vim. I asked a question on how to install vim with clientserver support. But the issue remained even with client server enabled in vim.
The second step was related to the fact that Debian 10 Buster uses wayland as a window manager. To force the use of x11 for zathura, in debian a zathura wrapper script containing:
#!/usr/bin/bash
GDK_BACKEND=x11 /usr/bin/zathura "$@"
Can be placed under the default user bin located at ~/.local/bin.
This is one of the first element of the $PATH
environment
variable.
Plugins * Python mode * Jedi it’s incompatible with python mode (according to the readme) * more explanations in the Jedi section below * vim ipython * [vim-test] see also the tests section below.
Blog posts
Reddit python workflow with terminal using tmux
“I run my scripts using
ipython -i script.py
That way I drop to an ipython shell whenever it breaks or finishes running. I also insert
from ipython import embed; embed();
Instead of using pdb. Its really neat.”
I use the ALE linter to check the quality of python code.
To copy code it’s preferable to deactivate the 2 characters columns used by ale as explained in Is it possible to disable the column on the left that is created by ALE?
:set signcolumn=no
The 2 characters column can later be shown again with
:set signcolumn=yes
To temporarily disable ALE in a buffer:
:let b:ale_enabled = 0
To enable it:
:let b:ale_enabled = 1
For the python options, see:
:h ale-python-options
I’ve added this option to my .vimrc to show which linter is complaining
let g:ale_echo_msg_format = '[%linter%] %s'
The linters I see most in python code are pylint and flake8.
Pylint complains about variable names that are too short
See the python page for the configuration details of the linters.
Turn off virtual text (added to .vimrc)
let g:ale_virtualtext_cursor = 0
Example exception file .flake8
at the root of the git
repository
[flake8]
ignore = F841, E501, W503, E203
Jedi Installation required enabling python mode in vim, available inside this Debian package:
sudo apt install vim-nox
Autocomplete is turned on to complete a word, press:
Ctrl+Space
To cycle through proposition you can use Ctrl+space
again or:
Ctrl+P
Ctrl+N
Enter for example a module name, then use Ctrl+N and Ctrl+P to choose among the objects and functions in that module.
Show the help of a function or object:
K
Jump to definition:
<leader>d
I remapped the <leader>
key to ,
in
my .vimrc
:let mapleader = ","
See above section on navigation, you can use Ctrl-O
to
jump back and Ctrl-I
to jump forward.
jedi#rename()
To refactor all occurrences of a variable in a file, move to the object you want to rename, then
:call jedi#rename()
There is a default shortcut <leader>r
for this but
it is deactivated on my machine for some reason. Not a big problem since
I don’t use refactor often. Also I prefer not to call this shortcut by
mistake.
The advantage of jedi#rename()
over a simple
:%s/old/new/g
is that it will only replace python objects,
if you have them mentioned in comments, it will not replace those.
See also my refactor with git grep
and perl
in the bash page.
The goal is to open files at the line number specified in a python error trace back message.
Using Vim Dispatch to run pylint on the current script works correctly and returns a quick fix window with errors on the relevant lines:
:Dispatch pylint -f parseable %
Running the current script itself with ipython
:Dispatch ipython %
:Dispatch ipython3 ~/repos/eu_cbm/eu_cbm_hat/scripts/running/run_zz.py
Opens a small tmux pane at the bottom of the tmux window and starts
the script. Upon completion, the output is available in a quickfix
window. One issue is that the files cannot be opened with
gF
. File names in the quickfix window output are not
parseable to jump to them. I get error messages of this form in the
quick fix window:
|| hat/ZZ/0 - INFO - Saving final simulations results to disk.
|| ^[[0;31m---------------------------------------------------------------------------^[[0m
|| ^[[0;31mAttributeError^[[0m Traceback (most recent call last)
|| ^[[0;32m~/repos/eu_cbm/eu_cbm_hat/scripts/running/run_zz.py^[[0m in ^[[0;36m<module>^[[0;34m^[[0m
|| ^[[1;32m 20^[[0m ^[[0;31m# runner.country.base_year = 2020^[[0m^[[0;34m^[[0m^[[0;34m^[[0m^[[0;34m^[[0m^[[0m
Running it with python3 is better because I can actually open the
file with gF
, however still not at the correct line
number
:Dispatch python3 %
Issue 299 with recommended settings
autocmd FileType python let b:dispatch = 'pylint -f parseable %'
Still doesn’t work for me, TODO: make a reproducible example and post on Vi stackexchange.
Other links
Stackexchange Quick Fix support for python tracebacks
Reddit View Python traceback as quickfix
Nvim-R supports knitr and mappings can be defined for example:
RSendChunk RDSendChunk
I mapped the local leader key to “;” by adding the following to my .vimrc:
let maplocalleader = ";"
Start R
Sending code to R:
Object browser
On the code, when the cursor is on a data frame:
Edit code
Help on a function ;rh
Posted this to https://github.com/jalvesaq/Nvim-R/issues/509
One solution based on :help Nvim-R-key-bindings
, is to
use SendCmdToR
as such:
:call g:SendCmdToR("setwd(opts_knit$get()$root.dir)")
I mapped this to <localleader>wd
by editing my
.vimrc
as follows:
map <silent> <LocalLeader>wd :call g:SendCmdToR("setwd(opts_knit$get()$root.dir)")<CR>
To use it, I run the setup chunk with
<localleader>ca
, then I call
<localleader>wd
.
vi.stackexchange Python debugging vimpdb
Once the fugitive plugin is installed the :G
command can
be used run any git command, such as:
:G status
:G pull
:G log
The output of these command may appear in a vim buffer, or it may appear in a terminal, depending on whether or not fugitive has a special way to handle the output of git.
You can also call the command alone to open a fugitive summary buffer:
:G
Within this summary buffer many things can be done with mappings. Move to the next file and expand inline diffs:
i
Expand inline diffs of the file under the cursor :
>
Remove the inline diff of the file under the cursor.
<
Perform a horizontal diff on the file under the cursor.
dd
Perform a vertical diff on the file under the cursor.
dv
Stage (add) or unstage (reset) the file under the cursor:
a
-
Create a commit
cc
Discard the change under the cursor. This uses checkout
or clean
under the hood. A command is echoed that shows how
to undo the change. Consult :messages
to see it again. You
can use this during a merge conflict do discard “our” changes (–theirs)
in the “Unstaged” section or discard “their” changes (–ours) in the
“Staged” section.
X
The powerful X command led me to loose a bunch of changes. A help hint in the message bar says to use the following to recover one file
:Gsplit art/music.md|Gread 124cdf331a4
I managed to recover that test files. How do I find out about the other files deleted previously?
When committing markdown file I like to get a summary of the modified
titles as the long part of the commit message. Search pattern to look
for modified titles of level 2 and more in the diff part of the fugitive
git summary buffer accessible after pressing i
on a file
name:
:g/+##
Blame the current file in a left side split
:G blame
Git log of the current file only
:G log %
Since the word diff provided by fugitive is not colourized, I created an alias to display a word diff
:Gwdiff
It’s defined in .vimrc as:
command! Gwdiff vert term git diff --word-diff
vim slime > “Grab some text and send it to a target, most probably: GNU Screen, tmux or Vim Terminal”
Tmux is not the default, to use it you will have to add this line to your .vimrc:
let g:slime_target = "tmux"
Then add this to configure the sending of commands to a Read Eval Print Loop: in the general use case of vim in a split tmux window with a REPL in the other pane:
let g:slime_default_config = {"socket_name": "default", "target_pane": "{last}"}
Send command to a tmux pane running bash, python or R with:
Ctrl C
I created the shortcut ;w
, ;l
and
;p
to emulate NvimR’s shortcut which send the current word,
the current line or the current paragraph to the latest interactive
shell (ipython)
autocmd FileType python nmap <buffer> <LocalLeader>w viw<Plug>SlimeRegionSend
autocmd FileType python nmap <LocalLeader>l <Plug>SlimeLineSend
autocmd FileType python nmap <LocalLeader>p <Plug>SlimeParagraphSend
Excessive indentation issues can arrise when slime sends indented
lines to the ipython console. For example after a function definition,
such as def function_name():
ipython places the cursor at
the indented place (4 spaces) and slime sends an additional 4 (or more
spaces) to indent the line further. This creates an “IndentationError:
unexpected indent”. This shouldn’t be done when slime is sending intput.
Ipython’s auto indentation behaviour can be turned off by sending the
following command to ipython:
%autoindent off
Turn off syntax highlight
syn off
Start Vim with syntax highlight turned off
vim -c 'syn off'
You can also specify a rule that vim should turn off syntax highlight for large files Stackoverflow question.
Use the shorthand version :set cole=0
to turn off
concealing of markdown bold **
and italic *
marks as well as the replacement of # Title
to
§ Title
. More explanations in How
to prevent vim from hiding symbols in Markdown and JSON
:set cole=0
Or set the file type to text
:set ft=text
Vim Test Works with pytest and other testing suites for many languages. Test results appear in the quick fix window.
pytest vim Run pytest from within vim.
I put the following options in the .vimrc
" Pytest
nmap <silent><Leader>f <Esc>:Pytest file<CR>
nmap <silent><Leader>c <Esc>:Pytest class<CR>
nmap <silent><Leader>m <Esc>:Pytest method<CR>
Keyboard mapping defined in .vimrc
:
nmap <silent> <leader>T :TestFile<CR>
nmap <silent> <leader>a :TestSuite<CR>
Define strategies to send the test output
let test#strategy = "make"
" let test#strategy = "dispatch"
Use :copen
to display a quickfix window.
Use a Bang! to run a command directly, for example to see how many words are in the file, run:
:! wc %
To insert the word count directly in the file, run:
!! wc %
You can copy (y $
) and paste a command in the vim
command line with CTRL + R + "
.
Insert text from a specified file into the current buffer:
:r textfile
You can also read in the output of shell applications. For example, if you wanted to include a list of files from a specific directory, you could include them using a read command:
:r ! ls -1 /home/user/directory
Or simply using the double bang
!! ls
Working with external commands explains how to start a shell:
:shell
Then exit the shell normally with exit
.
See also terminal buffer below.
You can start a terminal inside a vim split by entering the command:
:terminal
To enter the normal mode in a terminal buffer:
CTRL+W+N
Reddit does anybody use terminal instead of tmux and a normal terminal? Some users prefer tmux panes and windows, others prefer vim terminal. I have not used vim terminal buffers enough to know how to use them properly. For example slime is also working with vim’s terminal
To start a vertical terminal:
:vert term
Open a terminal in a new tab:
:tab term
Start a make action:
:term make
Start ipython3:
:vert term ipython3
Change the terminal window size to be 4 lines high (works for all
subsequent opening of a terminal :term
)
:set termwinsize=4x
:set tws=4x
Change the size of the current terminal
:res 10
Word coung: > To count the number of words in the current buffer, press g then Ctrl-g. To > count the number of words in a block, select the block (for example, type V5j > to select 6 lines) or vip to select the current paragraph and again press
g
Ctrl-g
This will also display the character count.
Vim wiki Macros
qn start recording to register n
... your complex series of commands
q stop recording
@n execute your macro
@@ execute your macro again
“Suppose you have a macro which operates on the text in a single line. You can run the macro on each line in a visual selection in a single operation: Visually select some lines (for example, type vip to select the current paragraph). Type :normal @q to run the macro from register q on each line.”
Macro to add a new line below each line
qq " start recording to register q (you could use any register from a to z)
o " insert an empty line below cursor
<Esc> " switch to normal mode
jjj " move the cursor 3 lines downward
q " stop recording
Then just move to the start line and type 1000@q to execute your macro 1000 times.
How
to configure vim spellcheck to use two languages To use the
spellcheck for two languages, add this to your
~/.vimrc
:
set spell spelllang=en_gb,fr
To use the spellcheck only temporary for an additional language (italian in this case):
set spell spelllang=it
set spell spelllang=de
This might require installing addition Debian packages on the system.
On the first use, vim may give a warning that some word lists are missing. How to make vim download missing word lists To solve this issue, turn spell check off
:set nospell
Turn spell check on
:set spell
Then vim will offer to download the missing dictionaries.
Set spell check only in the local buffer:
:setlocal spell spelllang=en_gb
Find alternative for highlighted word:
z=
How to make vim spell check remember a word Mark word as correct, this creates a spell file under /home/user/.vim/spell:
zg
Mark word as incorrect
zw
View differences between file1
and file2
(vim documentation)
vimdiff file1 file2
This page is the continuation of my 2014 blog post on Vim commands.
“Spacemacs is an attempt to improve on both vim and Emacs using the superior modal editing of vim and the nicer configuration language of Emacs.”
“This philosophy of minimalist commands that can be composed together is the fundamental originating philosophy of Unix, and Vim exemplifies it like no other editor.”
5 emacs packages for better productivity: Org mode, magit, evil mode, focus mode, darkroom
VS Code Vim
VS Code NeoVim https://github.com/vscode-neovim/vscode-neovim
“VSCode’s native functionality is used for insert mode and editor commands, making the best use of both editors.”
VS Code Vim https://marketplace.visualstudio.com/items?itemName=vscodevim.vim
https://www.reddit.com/r/vscode/comments/l7r1g8/in_your_opinion_is_it_better_to_use_vscode_vim_or/
“I used Emacs, Vim and now VSCode for many years - I remain not convinced that I’m faster at Vim for most edits - but I admit that using Vim keybindings for some edits feels very cool, fast and smart. In the end I can do most stuff on VSCode very fast, without modality, by abusing multiple cursors and some extensions. Other than that, the Open in Vim command (another extension) is a quick life saver when I need a macro. And I’m betting on VSCode to continue improving faster than Vim.”
https://www.barbarianmeetscoding.com/blog/boost-your-coding-fu-with-vscode-and-vim
“The true magic of Vim is composition. As you go building up this vocabulary of operators and motions you’ll find that you can combine them to your heart’s content. So that, once you know all the c, cl, caw, ciw, ct. from the previous paragraph and you learn how dl works, you’ll not only be able to use dl, you’ll know that you can also combine it with all the motions you already have at your disposal and daw, diw, dt, etc.”
const salute = ‘I salute you oh Mighty Warrior’ You type ci’Hi!
Reddit Python workflow with terminal using tmux I tried slime.
Should I introduce vim to my kid > “Learn to support, not to shoehorn.”
Vim Galore introduction to vim maintained by a group of users
“The project I encountered in Kibaale is completely different. The foreigners who work there are volunteers, they have sponsors themselves to make it possible to live and work there. All the donations for children go to the project and are spent there. Also for staff and vehicles, but that’s local staff that then spend their money in the country, thus indirectly it helps others. And in the end seeing the children grow up, finish their studies and find a job is wonderful.”
“The original code for vi was written by Bill Joy in 1976, as the visual mode for a line editor called ex that Joy had written with Chuck Haley.[3] Bill Joy’s ex 1.1 was released as part of the first Berkeley Software Distribution (BSD) Unix release in March 1978. It was not until version 2.0 of ex, released as part of Second BSD in May 1979 that the editor was installed under the name”vi” (which took users straight into ex’s visual mode),[4] and the name by which it is known today. […] On the free software process
“The core ex commands which relate to search and replace are essential to vi. For instance, the ex command :%s/XXX/YYY/g replaces every instance of XXX with YYY, and works in vi too. The % means every line in the file. The ‘g’ stands for global and means replace every instance on every line (if it was not specified, then only the first instance on each line would be replaced).”