Vim

Published on 30 December 2022

Vim Ain’t Faster

Editing could be editing in Vim, but most of developer’s time is spent on reading the code. More importantly, using keyboard gives a wrong impression that you’re quick. I believe this happens because with keyboard we’re occupied performing the action.

Personal Wiki

i denotes insert and puts caret before the character on which it is hovering over. a instead, i don’t know acts like an append and will put caret right after the block. <s-i> will put caret at end of the line and <s-a> will put at first non-whitespace character of the line.

While <cr> autocompletes stuff, <c-y> should do it too. <c-e> to exit out of completion.

https://www.youtube.com/watch?v=CN8p9iL7PPI. One nice thing that I found that I can use gq<motion> or visual select and then use gq to fold/wrap the lines. Very useful for folding comments.

:s/old/new/g replaces all occurrences of “old” with “new” in the line where your cursor is at. Doing :g& will do it for the whole file. These two steps are equal to doing :%s/old/new/g .

To substitute word under cursor, have cursor on the word and do :s/<c-r><c-w>/new/g.

Using local arglist in your workflow https://reddit.com/r/vim/comments/n3ywch/_/gwx36kx/?context=1

Using :buf <partial name of file> is also a nice way to switch to another file. It also does autocomplete!

In Vim using Fish, top open files in a specified order you can use vim (cat .toc) where .toc list those files. For Bash/POSIX, brackets are replaced by backticks. Inside Vim for example, you’ll need to use

:args `cat .toc`

Backticks work too. See https://vimcasts.org/episodes/populating-the-arglist

]} to go to parent end block. Esp. useful when in middle of React component and I need to go to its return/render method. Let’s say you are in a function definition which is inside useEffect. I’ll type 3]} to go to closing component block and then k to get inside return block and then I’ll press %.

yip yanks paragraph but if you are in middle of a para and you want to delete till end of paragraph you’ll use d}.

Opposite of join (J) could be :s/ /^M/g where ^M is Enter and is entered using <c-v><cr>.

commands to read from sources apart from :read https://www.reddit.com/r/vim/comments/ae0t7b/how_can_i_save_messages_to_a_file_or_to_a_text/

:put =execute('messages') is basically equal to <c-r> + = then typing execute cmd.

https://teukka.tech/vimloop.html and an application here https://youtu.be/futay9NjOac. More at here https://reddit.com/r/neovim/comments/n1r9tt/access_to_libuv_is_one_of_the_best_things_about/

Use :args %:h<tab>* or args %:h/* to load all files in buffer which are present in same dir as current buffer. :n works the same way.

<c-g> shows current file path.

<c-d> is used for de-indent and <c-t> for indent in insert mode
<c-x> then press <c-e> as many times to scroll window up, see :h insert_expand for more

read <filename> to insert contents of that file. read !ls to insert content of ls. <c-r> then =expand("%h:t") to insert filename.

%bd deletes all buffers and gives you a clean slate to start your workspace. enew creates a new buffer (remember tabnew?). ls + to list modified buffers. file <name> changes buffer name.

if used / command, gn select closest next occurrence found on or after the cursor. So you can use cgn which is better than ciw if you’ve typed the whole word in search and want to replace it as the latter might select a word that contains chars more than you typed in search. And because gn is selecting next match I can spam . to repeat the changes in subsequent selection and n to skip.

On the same note, [//e](//e) or /word-to-search/e will put cursor at the end of the word.

2dd is equivalent to dj.

<c-v><tab> in insert mode to insert an actual tab if you are using spaces (soft tabs) for tab spaces.

<c-r>= in insert mode to type an arithmetic operation and press enter to evaluate and insert.

note to self: remove keymaps from here which you think you won’t use

o for new line and O for opening new line above.

There is :x but I don’t see any benefit over :wq. See also :cq , :s vs :cl .

w denotes small word and W denotes big word. Big words can contain separators in between; - is one, _ isn’t. Separators/delimiters include ., !, etc.

<c-i> is alt + bksp of VS Code and <c-o> is forwards. <g-i> is useful too, if you are navigating around using normal or any other mode it will bring the cursor back where you made your last insert.

A register is an storage area, a buffer, which is generally used to copy and insert or execute the content which is in it.

Next step would be to use a way to retain a position by marking it. We use mark for this. To add one use m + [any key you want] (m key will work too, so we we’ll put mark in m register) and going it using ` + [that key] . Small-cased mark like a will persist within file, so multiple files can have their own a marks while upper-cased like A are shared across files. Rather than using ` + some-key , you can use ' + that-key to go to first non-whitespace character of that marked line. This is useful for example, to y'a to to copy till a mark.

H, M and L are for going top, middle and bottom of the viewport respectively. Mnemonics for that is high, middle and low.

zt and zb moves current line to top and bottom of the screen respectively. zz moves current line to the middle of the screen. However with title bar, menu bar, tab bar and task bar on screen makes the line to appear at somewhat lower than its desired position. For that use <c-e> and <c-y>. As always numbers can be used so using 2 + <c-e> will scroll down by two lines.

For half-page movements use <c-d> and <c-u>. For full-page movements use <c-f> and <c-b>.

0, $, ^ and g_ are used for moving to line ends. g_ is rarely used. ^ / g_ moves caret to first/last non-whitespace character of the line.

- and + to go to prev and next line first non-whitspace char.

* goes to next occurrence of the word and then you can keep using either * or n to keep navigating to next occurrence of word or N to go backwards. Conversely, # does the opposite. Either of these work quite like find / command and so :noh can clear the search.

. is a register which repeats last command. This commands could be anything that have performed text manipulation, deleting two words, inserting a text, etc.

There is f and t. df, will find comma after cursor and delete words till and including comma, t won’t include comma. Use c instead of d to replace instead (so df,).

w, e, b and their capital forms exist for word navigation. I wonder what e’s equivalent for backward is. Ans: It is ge.

o jumps to the ends of visual selection.

Selecting (usuing visual mode) and replacing (by pasting) works in Vim too.

You can go from visual mode to visual line mode while having a selection.

% is to toggle between bracket pair. It basically forwards the cursor until it finds a bracket and when it finds one it jumps to its matching pair. V%d can delete a whole fn for example. ci{ will delete inside code block, respects indentation, and goes into insert mode.

If x is to delete a character, s deletes the character and puts caret into insert mode.

y which is to yank/copy, yw copies a word. 2dw deletes two words.

<c-o> temporarily escapes you to normal mode while you are in insert mode to issue an command and come back. alt+some key will send esc and that key (if it is not sending then you can configure in terminal settings). So rather than pressing <c-o> then O for example, you can press alt + O which presses esc, creates a new line and as O automatically brings you to insert mode, this will too.

di[ will delete content inside square brackets while da[ deletes square brackets too. dat will delete tags and text inside it.

c in substitution mode asks for confirmation.

For copying and pasting from system clipboard, see this. In short, use "*y to copy and "*p to paste. Rather than using * one can use + too. _ is void/black hole register.


Visual selection works this way:


ctrl+n/p is used go to next/previous item in list. It could be autosuggestion or quick open. This is kind of useless if your keyboard has layers and you have mapped hjkl as arrow keys in one of the layer. Not entirely sure but <c-e> should invoke suggest box.

:-12,-10co. means from 12th line to 10th line above where caret is, copy here (here means at caret position). For lines below the caret, use +.

q + any key records a macro, @ + that key executes it. These macro recordings can be yanked and saved as plugins. (See this link). You can call a macro from another macro.

A valid combination of normal and g command is :ldo g/func/norm! Ilocal . This means find occurence of func in location list items (using g) and for each ooccurence of func, go to normal mode then insert at start (using I) and put word local there. Also see how regex capture group work to use in :g/ and esp. in :s/ command.

rx replaces the character at the cursor with x. R opens replace mode.


Substitute command:


To go to a line number, one can either:

Either way, <c-g> is useful to show file and line info.


You can run commands using :!command --even-with-args . For eg. :!ls.

:w can take a filename, so :w testfile will work. You can also select a piece of text and write/save which will save all lines which include that text. Vim will save the whole line even if you select only a word in it.

To retrieve and insert contents of a file, use :r filename . Use :r ls to insert contents of the command ls.

f, F, t, T where capitals denote backwards movement. ; denotes next find and , does the same but backwards.

Because of the way pasting works, if the content you want to paste has newline at the end, you need to go up one line before pasting else it will paste on the line below. Same for pasting a word, as it will paste at right side of the caret. You might want to do P which pastes before.

yaw selects whole word and yanks it. if caret is on s of apostrophe and yw is done it will only copy strophe. daw deletes word with the space and diw will delete only word. dip is delete inner paragraph.

:set ic ignores case while finding. Set :set noic to revert (prepending with no disables settings). To ignore only for a search, use /txt to srch\c .

Multiple set can be done at a time. For eg :set hls is. hls highlights matching phrases and is shows partial matches for a search phrase. Similarly, different commands can be combined. Use :wq to save and quit.

:e filename to start editing a file. :e! discards all changes.

Completion works for many commands. Just try pressing CTRL-D and

<TAB>. It is especially useful for :help .

ctrl+w ctrl+w swtiches between windows (which I think are splits). ctrl + w + something like h or l or w or other perform window operations.

When you say dd or cc it is deleting or changing the line respectively. It is actually alias of _ . So dd is d_.

>> is used for indenting and << outdenting. So 3>> or >3> will indent current and next 2 lines. >ip indents paragraph.

=ip is for formatting a para. Need to explore more.

Capital case versions of many commands apply action to end of line.

Use { and } to jump between paragraphs. However, it does saves it in your jumplist. d} might be similar to dap.

You can toggle set by appending ! at the end. You can also hook into Vim’s process (like before opening a file do something) using Vim’s autocmd. See this to understand how these are used.

There is set and leader but there is setlocal and localleader and <buffer> too.

There is a nice way to copy content of a file into system clipboard without moving your cursor or using cat. TLDR; :%y+

cl is equivalent to s, and cc is equivalent to S. (Use c equivalents.)

The command :bd (delete current buffer) appears to close an active file explorer without closing Vim. (Basically closing last window without closing Vim). If current window has changes, append with !.

Fish has fuzzy find search for files with shift+tab

To cut and paste to system clipboard, use "+3dd. "+ Means selecting + or say system register.

How to paste in command? TLDR; <c-r> + register key.

If you have a tab heavy workflow then this post is very useful. Esp. :tab ball (and this link), :tabonly , {i}gt, and “Switching to another buffer” section.

To go to a line and column, use :call cursor(row, col).

While there are many good ways to debug error in vimrc (look up on google), the easiest way to get started is to source the vimrc file.

To go to a line and column, use :call cursor(18,2)

See changelist, undo list and earlier/later here and here and in OneTab group about undo branches.

In visual (block) mode, use I to insert.

To yank letter on which caret is sitting. use yl or vy.

Read later: https://www.xspdf.com/resolution/50073724.html

Indent a line using ==. See more here. Vim indentation does not behaves well with TypeScript comments.

<c-w>= will put splits back into equal blocks. <c-w>o to only keep the active window and hide others.

A goes to end of line but I inserts cursor before first non-whitespace character of the line

Ctrl+d in command mode shows all autosuggestion in a grid manner and ctrl+f will show a history of commands which is useful to yank or to edit a command and run it. Even better, use q: in normal mode to activate the same. q/, q? are same as q:, except for searches. If you are in the middle of command line/search, you can use <c-f> to drop into history mode.

See https://www.hillelwayne.com/post/intermediate-vim/

Ctrl+w o will close all splits except the current one on which you are on

In command line mode :so % will source the file of current buffer

When using f F t or T, semicolon ; goes to next and comma to previous

Use marks and recording macros, marks can be used to mark, location and then yank to that location.

Jumplist (ctrl o and ctrl i) is cool but registers contain current file in % and last file in #. So Ctrl+6 can be used to hop between files. This is great for hopping between code file and its test file for example. Another way could be bp or bprevious and bn (bnext) to move b/w next and prev buffers but these cycle b/w buffers and includes all buffers across all windows so it ain’t that good.

gi goes to last insert position, gv goes to last visual selection. g' or g` to go to mark.

g; prev pos in changelist (insertion point) and g, to next.

There is `1 / '1 , '2, '3 and so on. https://vi.stackexchange.com/a/8717

D (and C) will delete from caret pos to the end of the line (and will put your cursor in insert mode). S deletes whole line, respects indentation, and goes into insert mode (cc doesn’t necessarily put the indentation, esp. if there is no indented code before change)

w jumps to next non whitespace char, so all contiguous whitespaces will be skipped if you are on any of them.

o jumps to ends of visual selection

To restart nvim lang server use e or e!. Courtesy of reddit.

Ctrl A or Ctrl X will increment or decrement number. 5 Ctrl+A will increment number 5 times.

Press * to go to next occurrence of word that is on cursor.

To paste into command line use <c-r> + register, to copy from it use <c-f> to open command line window. Read more here.

Ctrl+pg up/down can be used switched b/w tabs instead of gT/t and there is a selection mode when you type gh to give a selection mode similar to conventional editors. But you should not do either of these.

dn deletes till next occurence, d} to del just before next para.

gd will take you to the local declaration, to the import for example.

From https://vim.fandom.com/wiki/Cut/copy_and_paste_using_visual_selection :

Instead of inserting the block, it is also possible to replace (paste over) the destination. To do this, move to the target location then press 1vp (1v selects an area equal to the original, and p pastes over it).

Here “original” means the text stored in the register.

If you have some yanked text, pressing ‘p’ or ‘P’ while in Visual mode will replace the selected text with the already yanked text. After this, the previously selected text will be yanked.

Not always, but selecting to replace the text from yank is better than deleting in normal mode, pasting the deleted text and then changing it to the actual one needed.

After searching, typing n searches forward from the current position to find the next match. Typing gn does the same thing, and selects the match. Using gn, the current match is found if the cursor is at a search hit. If an operator is pending, typing gn operates on the selected match. For example, dgn would delete the next match, and cgn would change the next match. After moving the cursor, for example by pressing n to search again, use . to repeat the last operation. More at here.

Change tag contents using cit and tag themselves using ci< or ci> . With vim-sandwich, srt is also available.

/ for forward and ? for backward search.

:23 or 23G to go to line 23.

You can use uppercase letter of a register for subsequent deletes/yanks to be appended to it.

Delete all lines containing a pattern. See even more on this. See also power of g. Also normal command.

To yank buffer content without moving the cursor, use :%y.

Use :cq to exit vim with non-zero exit code. Use :x or ZZ to write and close, but only trigger write if the buffer is modified (:wq will write it anyways).

After pressing :ls to list all buffers, press buffer number then <c-6> to go to that buffer.

@: to replay last command, useful after typing :cn for example

<c-r> then register will literally type in the text. So, this could be slow for large text.

In insert mode, using arrow keys will act as if you left insert mode to go to normal mode and came back to insert mode. In other words you’ll lose dot command repeatability.

:te to open terminal and <c-\><c-n> to get back to normal mode. To create a new terminal in vertical split, use :vsp | terminal or just :vsp | te.

You can insert content from shell commands using system. Here for example using <c-j>d in insert mode will insert a UUID generated from python code:

^ I don’t know how :put can be used here (if it could be used). (:read is used for getting content from file if I’m right.) Video here: https://vimeo.com/4446843

command line

(p and P) gp and gP https://github.com/svermeulen/vim-yoink/issues/27#issue-875481116

apparently one can use ^, $, \n for during line substitutions using :s/ https://news.ycombinator.com/item?id=22132842

still have other nice stuff apart from these notes in vim dotfiles (init.vim). Do refer to it. like i found '[ and '] (`[ and `]) to go start/end of pasted text (one of them (tick/backtick) goes to correct column pos link in m/M marks).

not sure when i could use it, but in insert mode, using c-y copies chars from above

]}V%0%0 (last 0 is optional) if on top block of fn definition this would select whole fn block
another way would be ]}V[{{
lol, ]] [[ do exactly the same (see also, [] or ][)
there’s also ( and )

while using / and ? to type there is a way to navigate in search without hitting enter. Useful for peeking
^ probably this https://stackoverflow.com/questions/62459247/go-to-search-result-without-having-to-press-enter-in-vim


in go code (doom emacs):

^^ ]] and [[ and works for org mode to to jump b/w headings/list items


on navigating first non blank char below/above: -/+ to go up and down to first non-blank char

you can edit a macro, you can append stuff to a macro.

https://www.youtube.com/watch?v=rD2eyB9oMqQ

ways to enter the word under the cursor https://stackoverflow.com/questions/48642/how-do-i-specify-the-word-under-the-cursor-on-vims-commandline

https://jnrowe.github.io/articles/evil_emacs_steals_my_heart.html

on using vim with frontend https://www.youtube.com/watch?v=dXMHf57xs5M
setting up lsp in new https://www.youtube.com/watch?v=puWgHa7k3SY

https://old.reddit.com/r/neovim/comments/sn8lt7/how_can_i_find_across_files_using_telescope/hw27ocx/

in insert mode, typing c-v followed by char (like brace bracket), is useful as to skip bracket pair

https://blog.sanctum.geek.nz/vim-command-window/

there’s e, E and ge


to append colons the end of line do:


if you aren’t using surround plugin, you can still surround stuff easily, see https://stackoverflow.com/a/32758226/7683365, or just use insert two times at ends to add brackets

while i have added <leader>f/ you can also search using slash and then navigate using <c-g> or <c-t> (you don’t have to press enter for this)


search for :h :substitute. There are many shortcuts if you’d scroll down other interesting ones:


do r<cr> in normal mode if you want to break a line in mid

g; vs <c-o> vs gi
:h object-motions

quit+error code/abort https://stackoverflow.com/a/29419286/7683365
there’s also :update and (( :x and ZZ ))

:%bd to remove buffers and reset vim to clean slate
:saveas %:h/newfilename.ext to duplicate the file to same dir with name newfilename.ext
:lv txt % to put search results for current buf in location list where txt is search pattern

http://vimcasts.org/episodes/search-multiple-files-with-vimgrep/

use \zs to do :s/github\.\zsorg/com to replace github.org with github.com (notice whole github.com is not used as replace text)
see :h \zs for details (there’s \ze too)
there’s e flag :s/a/b/e to not show error when there’s no match found
and \a is used for alphabets, not \w (see :h \w)
with /search-term if you append it with /e, you would do an inclusive motion. This means, if there’s text “There’s no way.” and you do d/no/e it would delete “There’s no”. Without it, by default, only “There’s “ is deleted.

because of the way ]} work (others being [{, [(, ])) you can press 9]} to basically go to end of the function. ]} makes you go a level higher to enclosing {} pair (even though it is described as going to unmatched pair).
It probably says unmatched in docs because at cursor pos opening bracket is at left/above and the closing one at right/below. Resulting in unmatched pair if I move to the right for example.

combine :h :move with the global command. For example to move all the matching lines at the end of the buffer:
:g/PATTERN/move $

g<tab> switches to alternate tab

P in visual mode replaces the text but doesn’t yank the deleted stuff into unnamed register

gf resolution typescript javascript https://damien.pobel.fr/post/configure-neovim-vim-gf-javascript-import/
https://stackoverflow.com/a/70575996 or https://stackoverflow.com/a/51272987
https://stackoverflow.com/questions/33093491/vim-gf-with-file-extension-based-on-current-filetype
https://phelipetls.github.io/posts/making-vim-understand-typescript-path-mapping/
in suffixesadd+= you’d need to add index.{js,ts,tsx} too

time based undo/redo acting on all trees: https://leebyron.com/til/vim-time-travel/

1v selects same range that you used earlier. For selecting last yanked you already have a shortcut in vimrc (<leader>=) so 1v would be useful in other places.

If using Comment.nvim, you can use gcic to uncomment a set of lines

{ and } to jump b/w paragraph, and d} to delete till end of paragraph similarly d]} will delete till when an outer } is encountered. To delete till the most outermost scope, 33]} might work