I've seen many ways of creating vim Tabular patterns for a specific predetermined pattern. For example, in this answer I see a mapping for:
AddTabularPattern 1= /^[^=]*\zs=
Which allows you to do:
:Tabularize 1=
The regex above is hardcoded to match on the first equals character. Is there any way to define an arbitrary character instead, so that I could create a pattern that matches any character?
For example, I'd like to be able to do the following to match on the first "|" or the first "}" without having to create a separate predefined pattern for each.
:Tabularize 1|
:Tabularize 1}
I don't believe this is possible directly via Tabular. However, you can define a wrapper command that accepts the desired string as an argument:
command! -nargs=1 First exec 'Tabularize /^[^' . escape(<q-args>, '\^$.[?*~') . ']*\zs' . escape(<q-args>, '\^$.[?*~')
You can then execute First
with any character, e.g. :First =
and :First |
, or even longer strings, e.g. :First ||
and :First &&
.
In case this better suits your use case, you can also define mappings that use the current selection (in normal mode, the character under the cursor) as the argument:
vnoremap <F3> y \| :exec 'Tabularize /^[^' . escape(getreg('"'), '\^$.[?*~') . ']*\zs' . escape(getreg('"'), '\^$.[?*~')<CR>
nnoremap <F3> yl \| :exec 'Tabularize /^[^' . escape(getreg('"'), '\^$.[?*~') . ']*\zs' . escape(getreg('"'), '\^$.[?*~')<CR>
Edit: In order to allow for ranges, add the -range
attribute to the command definition and pass <line1>
(beginning) and <line2>
(end) on to Tabularize
:
command! -nargs=1 -range First exec <line1> . ',' . <line2> . 'Tabularize /^[^' . escape(<q-args>, '\^$.[?*~') . ']*\zs' . escape(<q-args>, '\^$.[?*~')