Easily aligning characters after whitespace in vim
Asked Answered
L

4

11

I would like to create a mapped vim command that helps me align assignments for variables across multiple lines. Imagine I have the following text in a file:

foo                     = 1;
barbar            = 2;
asdfasd    = 3;
jjkjfh                = 4;
baz              = 5;

If I select multiple lines and use the regex below, noting that column 10 is in the whitespace for all lines, stray whitespace after column 10 will be deleted up to the equals sign.

:'<,'>s/^\(.\{10}\)\s*\(=.*\)$/\1\2/g

Here's the result:

foo       = 1;
barbar    = 2;
asdfasd   = 3;
jjkjfh    = 4;
baz       = 5;

Is there a way to get the current cursor position (specifically the column position) while performing a visual block selection and use that column in the regular expression?

Alternatively, if it is possible to find the max column for any of the equals signs on the selected lines and insert whitespace so all equals signs are aligned by column, that is preferred to solving the previous problem. Imagine quickly converting:

foo = 1;
barbar = 2;
asdfasd = 3;
jjkjfh = 4;
baz = 5;

to:

foo     = 1;
barbar  = 2;
asdfasd = 3;
jjkjfh  = 4;
baz     = 5;

with a block selection and a key-combo.

Lavinialavinie answered 26/1, 2013 at 16:49 Comment(1)
One thing you can do is delete the whitespace at the beginning of a visual block like this: :'<,'>s/\%V *//Isologous
B
5

There are two plugins for that: Either the older Align - Help folks to align text, eqns, declarations, tables, etc, or Tabular.

Broadcloth answered 26/1, 2013 at 17:48 Comment(2)
Tabular is excellent: For your example all you need to do is :Tab /= on any line of the block.Manthei
That's exactly what I needed. Any idea how to make it align each token in the two lines "final int foo = 3;" and "public boolean bar = false"? I poked around but didn't have much luck.Lavinialavinie
P
10

Without plugins

In this case

foo = 1
fizzbuzz = 2
bar = 3

You can add many spaces with a macro:

0f=10iSPACEESCj

where 10 is an arbitrary number just to add enough space.

Apply the macro M times (for M lines) and get

foo           = 1
fizzbuzz           = 2
bar           = 3

Then remove excessive spaces with a macro that removes all characters till some column N:

0f=d12|j

where 12 is the column number you want to align along and | is a vertical bar (SHIFT + \). Together 12| is a "go to column 12" command.

Repeat for each line and get

foo        = 1
fizzbuzz   = 2
bar        = 3

You can combine the two macros into one:

0f=10iSPACEESCd11|j

Pelota answered 30/5, 2020 at 0:53 Comment(0)
T
7

Not completely satisfied with Tabular and Align, I've recently built another similar, but simpler plugin called vim-easy-align.

Check out the demo screencast: https://vimeo.com/63506219

For the first case, simply visual-select the lines and enter the command :EasyAlign= to do the trick.

If you have defined a mapping such as,

vnoremap <silent> <Enter> :EasyAlign<cr>

you can do the same with just two keystrokes: Enter and =

The case you mentioned in the comment,

final int foo = 3;
public boolean bar = false;

can be easily aligned using ":EasyAlign*\ " command, or with the aforementioned mapping, Enter, *, and space key, yielding

final  int     foo = 3;
public boolean bar = false;
Tequilater answered 2/5, 2013 at 10:19 Comment(0)
B
5

There are two plugins for that: Either the older Align - Help folks to align text, eqns, declarations, tables, etc, or Tabular.

Broadcloth answered 26/1, 2013 at 17:48 Comment(2)
Tabular is excellent: For your example all you need to do is :Tab /= on any line of the block.Manthei
That's exactly what I needed. Any idea how to make it align each token in the two lines "final int foo = 3;" and "public boolean bar = false"? I poked around but didn't have much luck.Lavinialavinie
A
0

A regex based solution is:

:%g/^.*/norm f=15i this add 15 blank spaces in between =

followed by:

:%s/\%>8c.*=/=/g this replace exceeding spaces from column line 8

You can also perform multiple column alignment with:

:%s/\s/ /g followed by:

:%s/\([^,]\{10}\)\(\s\+\)/\1/g

Example:

foo =1; barbar
barbar =2; asdasd
asdfasd =3; baz
jjkjfh =4; foo
baz =5; jjjasd

transform to:

foo       =1;       barbar
barbar    =2;       asdasd
asdfasd   =3;       baz
jjkjfh    =4;       foo
baz       =5;       jjjasd
Annabel answered 8/7, 2023 at 13:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.