1

Say I have the table:

| TITLE             |
| This is some text |

Can I center align the TITLE like so?

|       TITLE       |
| This is some text |

I've tried using both EasyAlign and Tabular but without much success.

  • Can there be whitespace before the first | or after the last |? I have a simple function that will work if the first and last columns are not whitespace. I can post it if you're desperate. ;) – B Layer Feb 18 '18 at 4:46
  • Hmm.. I guess I can accept that :) Do you mind sharing? – jihupona Feb 18 '18 at 12:45
1

Per the comments I'm offering this as a very rudimentary solution in case no one has a better suggestion. It's limited and hardly production grade. But OP asked to see it after I offered...

This function requires that there be no whitespace before or after the framing characters (| in the first and last columns of your example). And it only works well with padding made up of spaces (!) ... with tabs it might work but only with a fortuitous placement of the tabs. Hey, I'm an expandtabs kind of guy, sorry. :)

func! CenterEmbedText()
    norm! 0
    let sp1 = searchpos('^\S*\zs\s', 'c')[1]
    let wd1 = searchpos('\S', 'z')[1]
    let sp2 = searchpos('\s\+\S\+$', 'zs')[1]
    let wd2 = searchpos('\s\zs\S', 'z')[1]
    let lm = wd1 - sp1
    let rm = wd2 - sp2
    let mm = abs(rm - lm) / 2
    if rm > lm
        exec 'norm! ' . sp2 . '|' . mm . 'x' . sp1 . '|p'
    elseif rm < lm
        let mm =  (mm == 0) ? 1 : mm
        exec 'norm! ' . sp2 . '|' . mm . "i \<ESC>" . sp1 . '|' . mm . 'x'
    endif
endfunc

nnoremap <silent> <leader>c :call CenterEmbedText()<CR>

In the mapping you can replace <leader>c with whatever unused key combo you like.

The function simply counts the spaces to the left and right of the text to center (stored in variables lm and rm) and balances things, if necessary, by deleting mm spaces from one side and adding them to the other side.

To use just put the cursor anywhere on the line to modify and enter the mapped key sequence (Space C for me.)

I tested it with text similar to your example and it works fine. Let me know if you have text for which it doesn't work and I'll take a look.

Update: I noticed that when center falls between two columns this is inconsistent on whether it uses -1 or +1 as the center and I'll fix when I get a chance.

  • Hey man that is great! I do use spaces too and I managed to get around the various limitation by centering the text in a temp line and then moving it and/or adding extra characters afterwards. I see it's not perfect but does the job anyway! Thank you :) – jihupona Feb 18 '18 at 22:25
  • @jihupona Cool. Glad you found it useful. If you see any issue that you think might be straightforward to fix let me know and I'll take a look. – B Layer Feb 18 '18 at 23:39
1

Re-centering with a substitution or "how I learned to abuse regex backtracking"

For giggles you can do this with a :substitution:

:%s/\v\|\zs(\s*)(.{-})(\s*)\ze\|/\=substitute(submatch(1).submatch(3),'\v(\s*)(\1\s=)','\1'.escape(submatch(2),'&~').'\2','')/g

Overview:

Capture the text and the leading and trailing characters, spaces in this case. We use a sub-replace-expression to do another substitution to divide up the spaces in half. This balancing act is done via the regex engine's backtracking because math is hard (let's go shopping).

Notes:

Probably best to make this into a command:

:command! -range -bar CenterCells keeppatterns <line1>,<line2>s/\v\|\zs(\s*)(.{-})(\s*)\ze\|/\=substitute(submatch(1).submatch(3),'\v(\s*)(\1\s=)','\1'.escape(submatch(2),'&~').'\2','')/g

For more help see:

Centering with :Tabularize

You need to set the start and end of the matches with \zs & \ze. Use the c flag for centering.

:Tabularize/|\s*\zs.\{-}\ze\s*|/c1
  • Wow, I've learned multiple things here, thanks! – jihupona Mar 1 '18 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.