Instead of using an external
fmt program to format your text by filtering it through the external command, consider using Vim built-in commands
Both commands take a motion or text object to determine which lines of text to act on (by the way, the same is true for the
! command, which also takes a motion, so you can use
!}fmt to format from the current line until the next blank line.)
So you can use
gq} to format from the current line to the next blank line,
gqip to format the current paragraph (block delimited by blank lines),
gqG to format from the current line to the end of the file,
gggqG to format the whole buffer (first
gg jumps to the first line.) Additionally, you can select lines in Visual mode and use just
gq to format the lines in the Visual selection. Finally, there's
gwgw) to format the current line only.
These commands will respect the Vim settings you're using, such as
'textwidth' to determine how long lines can be, and
'expandtab' to determine whether to use tabs or spaces. Since they're built-ins, they can have easy access to the settings you're already using, which is not the case when you're filtering the text through an external command, which will most surely not know about the settings you had inside Vim.
The difference between
gw is that
gq may be customized using Vimscript. You can write your own formatter function and set
'formatexpr' to call that function. This is quite useful when using it to format code, where the
'formatexpr' can be made aware of the language it's formatting and can then wrap it correctly while maintaining the correct syntax.
gq command can also use a
'formatprg' pointing at an external binary to use as a filter. So you could even have it configured to actually use
fmt under the hood if you wanted to!
gw command on the other hand doesn't use any of the customizations, so it will always give you access to Vim's native formatter, even if you have a
'formatprg' set. As a bonus,
gw will preserve the cursor position across formatting the block (which is not often done by the custom formatters, since it's usually hard to do so in a function, and would be virtually impossible when using an external filter, where there's really no protocol to communicate that information of cursor position back to Vim.)
Hopefully you'll find these commands useful and see how they're much superior to filtering through an external
fmt. Not to mention they should easily prevent the issue you're having with
fmt adding tabs to your text.