user1255770
user1255770

Reputation: 1642

How to align several assignments in vim

I have this piece of C code:

options->file_extension = DEFAULT_FILE_EXTENSION;
options->config = "";
options->max_file_bytes = DEFAULT_MAX_FILE_BYTES;
options->msg_sort_type = SORT_TYPE_NONE;
options->msg_sort_buffer_max_size = DEFAULT_SORT_BUFFER_MAX_SIZE;
options->msg_sort_buffer_flush_time = DEFAULT_SORT_BUFFER_FLUSH_TIME;

Is there any easy way in vim to align this so it becomes e.g. ?

options->file_extension             = DEFAULT_FILE_EXTENSION;
options->config                     = "";
options->max_file_bytes             = DEFAULT_MAX_FILE_BYTES;
options->msg_sort_type              = SORT_TYPE_NONE;
options->msg_sort_buffer_max_size   = DEFAULT_SORT_BUFFER_MAX_SIZE;
options->msg_sort_buffer_flush_time = DEFAULT_SORT_BUFFER_FLUSH_TIME;

Or even if I wrote the first line here as

options->file_extension             = DEFAULT_FILE_EXTENSION;
options->config|<--cursor her now

Would there be a quick way to jump the cursor on the 2. line up to the = of the previous line?

Upvotes: 2

Views: 378

Answers (3)

Nathan Chappell
Nathan Chappell

Reputation: 2436

For a quick, non-robust, vimmy, non-plugin way to accomplish this task, consider the following command

.,+6s/\(\S*\)\s*=/\=submatch(1) . repeat(' ', 15 - len(submatch(1))) . '='

Analysis by component:

.,+6s

substitute command over the appropriate range

/\(\S*\)\s*=/

Pattern (regular expression) designed to match LHS of assignment (as many non-space characters as possible followed by as many space characters as possible followed by an assignment operator (=))

\=

Starts the "sub-replace-expression" context. Vim will "evaluate" the expression and use it to replace the matched text.

submatch(1) . 

In the "sub-replace-expression" context, submatch(1) will be replaced with the first submatch (similar to \1). The . is the concatenation operator.

repeat(' ', 15 - len(submatch(1)))

This expression does the "heavy lifting" of alignment. repeat will create a list or string depending on the first argument, the ' ' says "repeat a single space", and 15-len(submatch(1)) says "repeat it that many times." Of course, 15 could be replaced with whatever column + initial nonspace character the assignments should be aligned at.

. '='

Puts the assignment operator back on. Note that we can't just type =, because this is an expression, so to add it we must "concatenate it" with . '='.

I say this is "non-robust," because as is it won't work with definitions (declarations with assignments), which is probably desirable. However, by changing the initial regular expression, a great deal of flexibility can be obtained. It's also worth knowing, because it exposes a pretty powerful tool within vim, and can probably do a lot of good work without having to depend on a plugin.

Further reading:

:help :sub-replace-expression
:help :repeat()

Upvotes: 1

timss
timss

Reputation: 10260

I use Align and I think it does the job:

  • Whole file: :Align =
  • Visual line: <leader>t= or :'<,'>Align = (i.e. : from visual line).

There's also Tabular:

  • Whole file: :Tab /=
  • Visual line: <leader>a=

PS: Tabular seems to be the most popular choice, but I can't tell why. Is there something with it that Align doesn't do?

Upvotes: 3

Kent
Kent

Reputation: 195039

there are alignment plugins. I use the "old?" Align

for your example, you can visual select your lines, and press <leader>t= You will get your expected output.

Upvotes: 1

Related Questions