For example I have this file:

abc line1
def line2
ghijk line3
lmno line4
pqrstu line5
vwxyz line6

I want to format the file to look like this:

abc    line1
def    line2
ghijk  line3
lmno   line4
pqrstu line5
vwxyz  line6

and all that without external tools please, only pure vim/neovim. So this is not allowed:

:%!column -t
  • 4
    "So this is not allowed" - why not? Do I also have to be blindfolded and have my arms tied behind my back?
    – Friedrich
    Commented Jan 25 at 15:03
  • That’s my go-to solution! It may not work on Windows without some effort, though, which would be a reasonable restriction. Please clarify.
    – D. Ben Knoble
    Commented Jan 25 at 16:11
  • My earlier comment may have been slightly sarcastic. Let me explain: by disqualifying some answers beforehand, you're making your question less useful for future readers who may not have the same restrictions. You are free to accept an answer that does not use external tools.
    – Friedrich
    Commented Jan 25 at 18:41
  • 1
    Do you still have something open in your question? How can we help you further? Otherwise maybe could you accept one of the solution using the v button next to the arrow voting buttons. It allow the question to rest :-) Commented Jan 29 at 9:23
  • 1
    No problem. I'm patient but I'm fighting against the unresolved questions :-) Commented Jan 29 at 17:42

2 Answers 2


I would do:

%s/\v^(\S*)\s/\=submatch(1) . "       "[1:7 - strcharlen(submatch(1))]/


  • \= makes that the substitution is an expression and not a 'literal'
  • The expression submatch(1) . " "[1:7 - strcharlen(submatch(1))] is
    • submatch(1) the first word
    • " "[1:7 - strcharlen(submatch(1))] a string of 7 white spaces from which we take only 7 - strcharlen(submatch(1)) characters to fill the gap knowing that the first word takes strcharlen(submatch(1)) characters


%s/\v^(\S*)\s/\=submatch(1) . join(map(range(7 - strcharlen(submatch(1))), {key -> ' '}), '')/

But of course there are popular plugins to format columns:

  • 1
    Love the way you solved it. But can you please explain it a little further, for example what is this ` " "[1:7 - strcharlen(submatch(1))]/` part? ^^
    – Bog
    Commented Jan 29 at 17:30
  • I have added some explanations. Feel free to ask for more ;-) Commented Jan 29 at 17:52
  • 1
    Ahhh of course how couldn't I understand yesterday^^ Beautiful way to solve it :) Also the Plugins are really cool, I am gonna have a look at them when I have more time. One last question: You seem to are really good at vim, what are your top 3 Plugins you use all the time? :)
    – Bog
    Commented Jan 30 at 8:43
  • I'm using a lot of plugin (52 at the moments). But there are three that I advice to use when you start Vim would be vim-highlightedyank, traces, vim-wilder the first help you to yank without using the visual mode, the second help you with substitute and the third help you using the commands. Commented Jan 30 at 10:31
  • 1
    It is my pleasure :-) Commented Jan 30 at 15:05

Are Ex commands "allowed"?

If expandtab is on:

:[range]s/ /\t/ | retab

If it is off:

:set et | [range]s/ /\t/ | retab | set et!

See :help 'expandtab', :help :retab, :help :s, :help :range, and :help :set-!.

  • This is also a nice answer, quick and easy. But it wouldn't work if one of your lines are longer, lets say 10 characters, wouldn't it?^^
    – Bog
    Commented Jan 30 at 8:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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