Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Soft wrap at 80 characters in Vim in window of arbitrary width

Tags:

vim

word-wrap

People also ask

How do I set 80 characters per line in Vim?

As of vim 7.3, you can use set colorcolumn=80 ( set cc=80 for short).

How do I wrap text in Vim?

If you want to wrap lines in a specific area, move the cursor to the text you want to format and type gq followed by the range. For example, gqq wraps the current line and gqip wraps the current paragraph.

What is Nowrap in Vim?

To wrap lines visually, i.e. the line is still one line of text, but Vim displays it on multiple lines. Use :set nowrap. To display long lines as just one line (i.e. you have to scroll horizontally to see the entire line).


You could

  • set a large minimum width for the line numbers column via :set numberwidth=6 and
  • then you could resize your window with :set columns=86 (or with the mouse) to the proper size.

If you edit a file with a million lines in it, you may have trouble, but that's unlikely. You're wasting 6 columns of screen real estate this way too. So there are still all kinds of problems.

You can highlight past the 80th column using :match like it says here and here.

Beyond that I can't see any way to do this. Seems like it'd be a nice feature though.


Try this:

set columns=80
autocmd VimResized * if (&columns > 80) | set columns=80 | endif
set wrap
set linebreak
set showbreak=+++

You can remove the if (&columns > 80) | if you always want 80 columns.


I don't have a solution to the soft wrap, but as for marking a column, as of Vim 7.3 (released 2010-08-15) :set colorcolumn=80 will highlight column 80. The color will depend on your syntax file.

See Vim 80 column layout concerns, :h colorcolumn.


Have you tried 'linebreak'?

        *'linebreak'* *'lbr'* *'nolinebreak'* *'nolbr'*
  'linebreak' 'lbr' boolean (default off)
        local to window
        {not in Vi}
        {not available when compiled without the  |+linebreak|
        feature}
If on Vim will wrap long lines at a character in 'breakat' rather
than at the last character that fits on the screen.  Unlike
'wrapmargin' and 'textwidth', this does not insert <EOL>s in the file,
it only affects the way the file is displayed, not its contents.  The
value of 'showbreak' is used to put in front of wrapped lines.
This option is not used when the 'wrap' option is off or 'list' is on.
Note that <Tab> characters after an <EOL> are mostly not displayed
with the right amount of white space.

Combining eborisch's answer with some other answers I found here and things I had to work around, I came up with the following two-part solution:

This first part makes it easier to edit text with long lines:

" Allow enabling by running the command ":Freeform", or <leader>sw
command! Softwrap :call SetupSoftwrap()
map <Leader>sw :call SetupSoftwrap() <CR>

func! SetupFreeform()
  " Use setlocal for all of these so they don't affect other buffers

  " Enable line wrapping.
  setlocal wrap
  " Only break at words.
  setlocal linebreak
  " Turn on spellchecking
  setlocal spell

  " Make jk and 0$ work on visual lines.
  nnoremap <buffer> j gj
  nnoremap <buffer> k gk
  nnoremap <buffer> 0 g0
  nnoremap <buffer> $ g$

  " Disable colorcolumn, in case you use it as a column-width indicator
  " I use: let &colorcolumn = join(range(101, 300), ",")
  " so this overrides that.
  setlocal colorcolumn=

  " cursorline and cursorcolumn don't work as well in wrap mode, so
  " you may want to disable them. cursorline highlights the whole line,
  " so if you write a whole paragraph on a single line, the whole
  " paragraph will be highlighted. cursorcolumn only highlights the actual
  " column number, not the visual line, so the highlighting will be broken
  " up on wrapped lines.
  setlocal nocursorline
  setlocal nocursorcolumn
endfunc

With this alone you can get decent text wrapping for writing something like markdown, or a Readme.

As noted in other answers, getting wrapping at an exact column width requires telling vim exactly how many columns there are, and overwriting that each time vim gets resized:

command! -nargs=? Draft :call SetupDraftMode(<args>)
func! SetupDraftMode()
  " I like 80 columns + 4 for line numbers
  set columns=84
  autocmd VimResized * if (&columns > 84) | set columns=84 | endif

  :Softwrap
endfunc

There are still a couple of problems with this:

  • vim won't clear the screen outside of the columns you specify after calling set columns, and I can't figure out how to tell it to, so ideally you should call this immediately after opening vim
  • vim shows a prompt with the version number and some helpful commands when you open it, so these won't be cleared. You can add set shm+=I to disable that prompt
  • You can't open any vertical splits, because then both splits will be ~40 column. You would need to set columns to 2x your desired width and then always have a split open.
  • My vimscript is awful, but ideally someone could modify the Draft function above to take a column width as an argument, or use a global variable (g:explicit_vim_width?) that can be set manually if your window size changes.