Andrew
Andrew

Reputation: 4418

How do I dynamically set textwidth to suit the current file?

For a long time I have written prose text files using textwidth:80. I want to start using textwidth:72, for Reasons.

If I just change my .vimrc to use 72, I run into a problem. Either I have to re-wrap any old files I touch (making for extra proofreading and large, semantically useless git commits), or I end up with blocks of 72-column text in files that are otherwise 80-column, which is ugly.

I would like to have vim figure out the appropriate textwidth when I open the file. Something like "make textwidth 72 columns or the maximum common line length in this file, whichever is longer." I include 'common' because I don't want a few overlength lines -- perhaps long URLs -- to affect textwidth.

How do I do this?

Upvotes: 0

Views: 703

Answers (1)

Ingo Karkat
Ingo Karkat

Reputation: 172510

Getting the lengths

You can get a List of the (ascending) lengths of all lines of the current buffer via:

let lengths = sort(map(getline(1, '$'), 'strdisplaywidth(v:val)'), 'n')

Then, maybe remove the longest 1% to account for any outliers (or apply even more elaborate statistics here), and obtain the maximum of the rest:

let max = max(lengths[0: (len(lengths) * 99 / 100)])

And use that to detect legacy files which wrap at column 80:

let isLegacyWidth = max > 72 && max <= 80

Setting textwidth

This can be done via :autocmd. The most important question here is how to discriminate your "prose text files". If you have a custom filetype (e.g. text), you can use

autocmd FileType text ...

If these are stored in certain location(s):

autocmd BufReadPost /path/to/prose/* ...

Assuming you've put the above length checks into a IsLegacyWidth() function, you can set the local 'textwidth' value with:

let &l:textwidth = (IsLegacyWidth() ? 80 : 72)

Upvotes: 2

Related Questions