How I Align Contents in Neovim
Background
When writing documentation in plain text, I struggled to make the text look better, including Markdown tables, key-value pairs with different lengths, etc.
Who doesn’t want to make a table like this look better?
| header 1 | header 2 | header 3 |
|-|-|-|
| long content 1 | long content 2 | long content 3 |
| 4 | 5 | 6 |
Then I found this plugin. It is quite straightforward to use after understanding how it works. Let’s see how it helps.
mini.align to the Rescue
mini.align is one of the powerful Neovim plugins collected in mini.nvim.
Basically, it aligns contents in 3 steps:
- Split the content into columns with a pattern. Note that the delimiters are preserved.
- Justify the columns, align the contents of each column with paddings.
- Merge the columns back into rows.
Installation
I installed mini.nvim with lazy.nvim:
return {
{
"echasnovski/mini.nvim",
version = "*",
event = 'VeryLazy',
config = function()
require('mini.align').setup { mappings = { start = '', start_with_preview = 'g=' } }
end,
},
}
Note that I set a keymap of g= to start alignment with preview.
Examples
Space Separated Columns
Let’s take an example, to format a crontab file like this:
*/3 * * * * echo 1
* */3 * * * echo 2
* 1,3,5 * * * echo 3
I really hope to see the columns aligned so I can easily tell which time unit each column belongs to and how the command works.
I select the content to be aligned in visual mode, and press g= to start alignment.
If everything goes well, I enter the alignment process and see the prompt in the status bar:
(mini.align) Split: "" | Justify: "left" | Merge: "" | Enter modifier
Now I go through the 3 steps mentioned above.
- Firstly, press
sfor Split, enter the delimiter:%s+, meaning one or more whitespaces. I will see all the whitespaces disappear and everything collapses. - Press
tto trim the columns to remove extra whitespaces before merging. Justify ofleftlooks good to me, so I won’t change it. - Finally press
mand set Merge delimiter as, exactly one whitespace.
Now the content should look like this:
*/3 * * * * echo 1
* */3 * * * echo 2
* 1,3,5 * * * echo 3
Each column is aligned to the left, and separated with exactly one whitespace.
A Markdown Table
Another example is to format Markdown tables, for example:
| header 1 | header 2 | header 3 |
|-|-|-|
| long content 1 | long content 2 | long content 3 |
| 4 | 5 | 6 |
This is a valid Markdown table but it really looks bad in the source. So I am going to format it with mini.align. To demonstrate some advanced features, I am going to align the first column to the left, the second in the center, and the third column to the right.
To make it clear, I will get the following structure after splitting (pseudo-code for better understanding):
[
['|', ' header 1 ', '|', ' header 2 ', '|', ' header 3 ', '|'],
['|', '-', '|', '-', '|', '-', '|'],
['|', ' long content 1 ', '|', ' long content 2 ', '|', ' long content 3 ', '|'],
['|', ' 4 ', '|', ' 5 ', '|', ' 6 ', '|'],
]
Note that the delimiters (|) and whitespaces are all preserved.
Now I will align the first column to the left, using the filter feature.
- Select the table, press
g=to start alignment, presssto set the delimiter to|. - Press
ffor filter, set the expression tocol<4so we only modify the first column, taking the delimiters into account. - Press
tto trim the filtered columns, thenjlto justify the contents to the left. - Press
mand merge the columns with a whitespace.
Then the second column:
- Select the table, press
g=to start alignment, presssto set the delimiter to|. - Press
ffor filter, set the expression tocol>=4 and col<6so we only modify the second column and the following delimiter. - Press
tto trim the filtered columns, thenjcto justify the contents in the center. - Press
mand merge the columns with a whitespace.
Then the third column:
- Select the table, press
g=to start alignment, presssto set the delimiter to|. - Press
ffor filter, set the expression tocol>=6so we only modify the third column and the following delimiter. - Press
tto trim the filtered columns, thenjrto justify the contents to the right. - Press
mand merge the columns with a whitespace.
Here is what I get:
| header 1 | header 2 | header 3 |
| - | - | - |
| long content 1 | long content 2 | long content 3 |
| 4 | 5 | 6 |
Limitations
- The
filteris global. All changes apply to thefiltered columns no matter when thefilteris applied. So if we want to align the columns in 3 ways, we have to go through the process 3 times. - It is not perfect for Markdown table formatting. Here I just use it to demonstrate what we can do. Consider using marksman for better Markdown formatting.
gera2ld.space