jq is a very powerful command-line tool designed to manipulate JSON data. One of its great features is that it automatically formats JSON output for better readability:
$ echo '{"is_jq_awesome": true}' | jq
{
"is_jq_awesome": true
}
But in Vim?
Can we utilize this inside of Vim? Of course!
In Vim, there’s a feature called filter commands that enables us to use external applications to modify our buffers. Filter commands take a range, which is a set of contiguous lines, and a command that processes these lines. This feature is exactly what we need for our purpose.
Whole buffer
:%!jq
Here we pass the whole buffer range (%
) to jq
:
Selected range
It even works with visual selection!
:'<,'>!jq
Here we pass instead pass the range of the visual selection ('<,'>
) to jq
:
Minified JSON
You can also pass --compact-output
to get a minified JSON structure back:
:%!jq --compact-output
Mappings
Let’s add some mappings. I use the abbreviations fj
for “format JSON” and
fcj
for “format compact JSON”, but feel free to choose any abbreviations
that works best for you.
Vim
" Whole buffer
nnoremap <silent> <Leader>fj <Cmd>%!jq<CR>
nnoremap <silent> <Leader>fcj <Cmd>%!jq --compact-output<CR>
" Visual selection
vnoremap <silent> <Leader>fj :'<,'>!jq<CR>
vnoremap <silent> <Leader>fcj :'<,'>!jq --compact-output<CR>
Neovim using Lua
local opts = { noremap = true, silent = true }
-- Whole buffer
vim.keymap.set("n", "<Leader>fj", "<Cmd>%!jq<CR>", opts)
vim.keymap.set("n", "<Leader>fcj", "<Cmd>%!jq --compact-output<CR>", opts)
-- Visual selection
vim.keymap.set("v", "<Leader>fj", ":'<,'>!jq<CR>", opts)
vim.keymap.set("v", "<Leader>fcj", ":'<,'>!jq --compact-output<CR>", opts)
Resources
- Vim help docs:
:h range
,:h filter
- jq
Discuss on Hacker News