Vim allows you to run all (or some) of your content through an external program. In this case, we want to use Python to format (i.e. pretty print) our JSON with python -m json.tool
.
The Goal
Before
{"data":{"attributes":{"name":"sal"}}}
After
{
"data": {
"attributes": {
"name": "sal"
}
}
}
Using Vim Filters
A Vim filter allows us to run a selection a text through an external filter (see :help filter
).
JSON Format the Entire File
Running the following command will try to JSON pretty print format the entire file.
:%!python -m json.tool
Explanation
The command starts with :
because it is entered in command-line mode (see :help Cmdline-mode
).
The %
indicates the range to operate on is the entire file (see :help :%
).
The !
indicates this is a filter to apply to the selected text (see :help filter
).
The python -m json.tool
is the command line tool. We pass the selected text to the command line tool and replace the selected text with the output we receive.
Other Ranges
We can replace the range %
(the entire file) with any other range (see :help range
). e.g.
.
the current line3,5
lines 3 to 5'<,'>
the current visual selection
JSON Format the Current Line
:.!python -m json.tool
JSON Format Lines 3 to 5
:3,5!python -m json.tool
JSON Format the Current Visual Selection
Highlight the desired lines using Visual Mode (v
, see :help visual-mode
) or Linewise Visual Mode (V
, see :help linewise-visual
).
:'<,'>!python -m json.tool
Neovim (lua) Custom Command
My problem with all of these solutions is that I don’t remember the commands and I have to look these up each time.
My ideal solution would be a custom Vim command (e.g. :JSONFormat
), which would allow me to type :JSO<tab>
and get the command autocompleted. Additionally, the command should operate on a given range (e.g. :%JSONFormat
or :'<,'>JSONFormat
) or the current line if no range is given.
vim.api.nvim_create_user_command(
'JSONFormat',
'<line1>,<line2>!python -m json.tool',
{
range = true,
}
)
Vimscript Custom Command
command! -range JSONFormat <line1>,<line2>!python -m json.tool
This is the solution I came up with and added to my .vimrc
(see PR 182 Add :JSONFormat to pretty print format JSON).
How it Works
The line in our .vimrc
begins with command
because it is a user defined command (see :help user-commands
).
The exclamation mark !
allows this command to be redefined. If the !
is omitted and you try to reload your .vimrc
, you’ll get an error because the command is already defined. By including the !
we prevent this error (see :help E182
).
The -range
attribute allows our user defined command to accept a range (by default user defined commands do not accept ranges). See :help command-range
.
We are naming our command JSONFormat
When our command is executed it does the following <line1>,<line2>!python -m json.tool
, where
<line1>
is the starting line of the command range (see ‘:help <line1>`)<line2>
is the final line of the command range (see ‘:help <line2>`)!
here indicates this is a filter to apply to the selected text (see :help filter)- The python -m json.tool is the command line tool. We pass the selected text to the command line tool and replace the selected text with the output we receive.
Leave a Reply