alazarte

[home]

Vim command line integration

Vim integrates really well with command line tools, such as jq, sort and uniq. Here I list a few examples.

Formatting jsons with jq

In cases where I need to work with json files, I tend to check whether is well formatted, or "pretty-print" it's contents. For example, I have a file with only the following line:

{"asd":"qwe","bool":false}

If I run :w ! jq ., vim prints that to jq . and replaces the current contents of the file with the output of that command; so I get this:

{
  "asd": "qwe",
  "bool": false
}

But it also works with ranges and visual selections. So for example, if the contents of the file are these (imagine a project's readme file):

# introduction

something important, here's a json:

{"some": "json"}

something else

I usually jump to the line with the json snippet and run this: :.,.! jq .; the range .,. selects the current line as the start, and also the finish of the range, and is used as the input of the command jq.

If I had a multi-line json that I need to format, I can visual select all lines and run w ! jq . on it. The full command looks like this: '<,'>w ! jq .. That '<,'> is also a range that selects the start and finish of the visual selection.

sort, uniq and some neat regex

I had to add a list of string values to a json key not long ago, and thought that is a nice example for this post. The input I had looked something like this:

Tree Cat Keyboard Tree Dog Cellphone Cat Monitor Keyboard Car Car Cellphone

What I wanted to do was remove the duplicates and sort alphabetically asc. With vim I can paste that list directly inside the json file and work with ranges so I don't change the rest of the file. What I usually do is to keep blank lines around the lines I want to edit, like this:

...
  "string-list": [

# list of strings to edit

  ],
...

Then I can just use this range: .,/^$/. If the cursor is in the first blank line, then that range will include all lines until the next blank line, which in this case contains all those string values.

Now, the end result that I want is a valid json, with the string values without duplicates and also ordered. The first command that I run is this:

.,/^$/-1! sort | uniq

Which sorts and removes duplicates from the lines included by the range. Note the -1 in this range, meaning don't include the last line matched by it ([a,b)). The second command is this:

.,/^$/s/\([A-Za-z]\+\)/"\1",

Which almost formats those strings as a valid json string list, with only one error: the last line contains a comma. Removing that makes it a valid json. In this case I want to include the last line, and I think the regex part needs it's own post. But regex in vim is super simple and useful.