Vim Tips Wiki
Tag: sourceedit
Tag: sourceedit
Line 63: Line 63:
 
<code>fold</code> is more aggressive: it will chop lines even inside of words.
 
<code>fold</code> is more aggressive: it will chop lines even inside of words.
   
In addition, Vim itself provides the command <code>gqq</code> to format the current line, so something like:
+
In addition, Vim itself provides the command <code>gqq</code> to format the current line, so typing something like <code>999gqq</code> (with maybe hitting <code>.</code> a few times if that's not enough to format the whole buffer) in normal mode will format the buffer according to the value of <code>'textwidth'</code>.
 
<pre>
 
:%normal! gqq
 
</pre>
 
 
will format the buffer according to the value of <code>'textwidth'</code>.
 
   
 
If the original linebreak locations must be preserved, one can leave a unique character in place of linebreaks. Below, the character '↵' (typed using <code>&lt;C-V&gt;u21B5</code>) is provided as a suggestion, but it must not appear in the file itself.
 
If the original linebreak locations must be preserved, one can leave a unique character in place of linebreaks. Below, the character '↵' (typed using <code>&lt;C-V&gt;u21B5</code>) is provided as a suggestion, but it must not appear in the file itself.

Revision as of 07:27, 8 February 2017

This page explains several strategies for dealing with long lines. Vim does not handle long lines well; there are restrictions on when a long line can partially be displayed, and commands like <C-E> act on logical lines rather than visual lines. Part of the reason for this is that Vim is a descendant of line-based editors that only acted on logical lines. The upshot is that Vim will often feel "jumpy" when scrolling and moving in a buffer with long lines, especially ones that fill up the entire window.

One may encounter files with long lines in various situations:

  • Conventions can require it; e.g. the English Wikipedia, which uses the MediaWiki markup language, favors single-line paragraphs so lines tend to be long
  • Some data files (JSON, CSVs, etc.) use long lines
  • Content on the web is often presented in minified form, leading to long lines

At a high level, the strategies for dealing with long lines can be grouped in the following way:

  • Making use of Vim's built-in capabilities for navigating long lines (i.e. work around long lines without modifying them)
  • Preprocessing the file to use shorter lines, and then possibly converting back to using long lines after the editing task in Vim is done; the two strategies here are "chopping" and pretty-printing
  • Increasing the terminal window size or decreasing the terminal font size so that more text can fit in
  • Taking steps to prevent long lines (rewriting code to use shorter lines, enforcing a manageable text width, etc.)
  • Giving up on Vim for these files and using editors and pagers that work fine with long lines (less, gedit, GNU Emacs, etc.); it's important to keep in mind that there is no single best tool for every task

This article will cover the first two points.

Navigating long lines with Vim's built-in capabilities

Vim can attempt to show long lines with :set wrap (on by default). With :set linebreak, Vim will wrap the lines at characters in 'breakat'; this generally makes the text easier to read (in older versions of Vim, one will also have to :set nolist). Also very useful is :set display+=lastline, which will try to show as much as possible of the last line in the window (rather than a column of "@", which is the default behavior).

The normal mode movements j and k move by logical lines, but these have the analogous gj and gk for moving by visual lines. Similarly, g0, g^, and g$ all work. In addition, gm will move the cursor to the middle of the visual line.

Search-to-navigate is another useful way to move. It's advisable to :set incsearch so that one can see the cursor move as one types, and then hit enter when one gets to the desired location.

Note that the commands f, t, F, T, ;, and , are even more powerful within long lines: they can cover more ground.

If the buffer contains prose, the sentence motions ) and ( also work well.

Using :set scrolloff=99999 (or any large number instead of 99999) will try to keep the cursor in the middle of the screen, providing more context even within very long lines. This will allow one to type something like 5gj to simulate 5<C-E>.

Note that when using commands like :vimgrep and :clist, Vim uses a more-like pager that can display partial lines even when using j and k.

The following provides the maps gH, gM, and gL to emulate H, M, and L even when very long lines are present. Note that Vim already defines the normal mode command gH (:help gH), although this is to enter Select mode, which is rarely used.

nnoremap <silent> <expr> gH winline() - 1 - &scrolloff > 0
      \ ? ':normal! ' . (winline() - 1 - &scrolloff) . 'gkg^<CR>'
      \ : 'g^'
nnoremap <silent> <expr> gM winline() < (winheight(0)+1)/2
      \ ? ':normal! ' . ((winheight(0)+1)/2 - winline()) . 'gjg^<CR>'
      \ : winline() == (winheight(0)+1)/2
      \         ? 'g^'
      \         : ':normal! ' . (winline() - (winheight(0)+1)/2) . 'gkg^<CR>'
nnoremap <silent> <expr> gL winheight(0) - winline() - &scrolloff > 0
      \ ? ':normal! ' . (winheight(0) - winline() - &scrolloff) . 'gjg^<CR>'
      \ : 'g^'

Preprocessing long lines

Generic formatting tools

Most UNIX-like programming environments offer generic tools for formatting text. These include fmt, fold, sed, perl, and par. From inside Vim, one can invoke:

:%!fmt -80 -s

to format the current buffer. The -80 specifies 80 columns as the desired width and the -s tells fmt to split lines only (i.e. to not join short lines together, called "refilling").

fold is more aggressive: it will chop lines even inside of words.

In addition, Vim itself provides the command gqq to format the current line, so typing something like 999gqq (with maybe hitting . a few times if that's not enough to format the whole buffer) in normal mode will format the buffer according to the value of 'textwidth'.

If the original linebreak locations must be preserved, one can leave a unique character in place of linebreaks. Below, the character '↵' (typed using <C-V>u21B5) is provided as a suggestion, but it must not appear in the file itself.

" Use :ShortLines or :ShortLinesAtSpace to convert the document to use
" short lines with hard linebreaks, and use :LongLines to convert back.
command! ShortLines :%s/.\{71}/&↵\r/g | 1
command! ShortLinesAtSpace :%s/.\{70,79} /&↵\r/g | 1
command! LongLines :%s/↵\n// | 1

Note that this sort of regex replacement will be slow on large files.

Filetype-specific tools

Instead of generic tools, one can sometimes do better by using a tool suited to a particular filetype.

If one is working with JSON files and have Python installed (note: this is just the system binary rather than Python support being compiled into Vim):

:%!python -m json.tool

will convert the buffer into pretty-printed JSON. There are also plugins like jdaddy.vim that are designed to make work with JSON easier.

For HTML and XML, there are tools like tidy (e.g. :%!tidy -utf8 -i) and xmllint; see Cleanup your HTML for the main article.

In some cases, gg=G might make things nicer.

Some plugins that try to unify this sort of pretty-printing/tidying are:

Languages like Go have strong source formatting requirements and provide tools like gofmt.

See also

External links