alligator's blog

vim tips from well wasted workdays

Apr 25, 2020

contents

Below is a selection of useful bits and pieces taken from my vimrc. I intend for this to be a living document and will add new things as and when I find them.

productivity

Perform common tasks in less time.

use space as your leader

This lets you hit the leader with both of your thumbs.

let mapleader = " "

I believe I learned about this from this article which has some other good tips, namely mapping common command mode commands to leader based key combinations:

nnoremap <Leader>w :w<CR>
nnoremap <Leader>f :NERDTreeToggle<CR>

create ad-hoc build/run mappings

Often all I need as a build tool is an ad-hoc binding to run a shell command. I use <Leader> m for this:

nnoremap <Leader>m :!python %<CR>
nnoremap <Leader>m :!make<CR>
nnoremap <Leader>m :!npm run start<CR>

use a key sequence instead of escape

Escape is a long way away from the home row:

inoremap fd ^[

jj is often used for this, I prefer fd because I tend to keep my left hand on the home row more than my right. The ^[ is inserted via <C-v>escape.

keep the cursor centered when jumping between paragraphs

{ and } are great for hopping around blocks of code, with these mappings the buffer stays centred on what you're looking at while doing so.

nnoremap { {zz
nnoremap } }zz

utility

Useful tidbits I've created or collected.

open windows explorer with the current file highlighted

function! OpenExplorer()
    let path = expand('%:p')
    let path = substitute(path, "/", "\\", "g")
    execute "!start explorer /select," . path . "\r"
endfunction

if has("win32")
    nnoremap <F11> :call OpenExplorer()<CR>
endif

This was surprisingly tricky. It took much longer than it should have to discover I needed to add a trailing carriage return to the path for this to work.

send a command to a terminal in another buffer (neovim only)

In the terminal buffer, run this to find the job id of the terminal:

:echo b:terminal_job_id

Then in any buffer, run this to send text to it:

:call jobsend(<job id>, "text")

Useful when combined with an ad-hoc mapping:

nnoremap <Leader>m :call jobsend(<job id>, "python main.py")<CR>

run a command without changing your view

A very simple but useful function inspired by emacs' excursions:

function! ExcursionExec(cmd)
    let l:winview = winsaveview()
    execute a:cmd
    call winrestview(l:winview)
endfunction

For example, I use this in a mapping that copies the current file to the system clipboard:

nnoremap <Leader>yf :call ExcursionExec('normal gg"+yG')<CR>

format JSON

Format JSON using node:

command! FormatJson %!node -e "var fs = require('fs'); console.log(JSON.stringify(JSON.parse(fs.readFileSync(process.stdin.fd, 'utf-8')), null, 2));"

keep the buffers equal in diff mode

Make vim behave like other diff tools:

if &diff
    set equalalways
    au VimResized * wincmd =
endif

turn off search highlighting when you move

No more :nohlsearch

noremap <expr> <Plug>(StopHL) execute('nohlsearch')
noremap! <expr> <Plug>(StopHL) execute('nohlsearch')

function! StopHL()
  if !v:hlsearch || mode() isnot 'n'
    return
  else
    sil call feedkeys("\<Plug>(StopHL)", 'm')
  endif
endfunction

augroup SearchHighlight
  au!
  au CursorMoved * call StopHL()
  au InsertEnter * call StopHL()
augroup end

There are plugins to do this, but this turns out to be all I need. This is taken from this GitHub issue. You can follow the thread there to understand how and why this works, and why all of it is necessary.

blog index