Intelligent paragraph reflowing in vim?

I'm not sure whether this is an appropriate question for tex.SE. If you think questions like this should not be asked here, please voice you concern. If necessary I'll open a question on meta.

For readability I like to keep line lengths in my source files at about 80 characters. Vim has the nice shortcut gqap that reflows the current paragraph to fit within 80 characters without wasting space with lines that are too short. It even keeps indentation. Unfortunately it considers paragraphs to be marked by empty lines and considers everything that is not separated by an empty line to be in the same paragraph. In particular any equations (started with $ or \begin{...}) are always considered to be part of the paragraph and reflowed. Is there any way to have vim handle LaTeX syntax more intelligently in this respect? Are there any other text editors which can to that? (I know that I can highlight only the text and then use gq, but if possible I'd like to have a single command to reflow a paragraph without the need to manually mark what a paragraph is.) - If I understood correctly, does gqq do what you need? (or Vgq). It's line-wise, ie. if you type-in text without manual line-breaks. – morbusg May 25 '11 at 3:11 Emacs does this out-of-the-proverbial-box ;-D (although, no TeX–Emacs experience is complete without AUCTeX.) (Edit: didn't realize how old this post was—must have been bumped by an edit—but Emacs is definitely "another editor".) – Sean Allred Aug 14 '13 at 3:42 @SeanAllred: Actually the question is so old that I stopped doing the 80 characters/line thing a long time ago (I now find one sentence per line much more useful for editing). – Caramdir Aug 14 '13 at 15:20 5 Answers I have the following function in my VIM/ftplugin/context.vim file to format ConTeXt paragraphs (same as LaTeX: the environments are enclosed in \start... and \stop... instead of \begin{...} and \end{...}. It should be easy to adapt this to LaTeX (In fact, I think that I copied it originally from someone who had written it for LaTeX and adapted it to ConTeXt). " Reformat lines (getting the spacing correct) {{{ fun! TeX_fmt() if (getline(".") != "") let save_cursor = getpos(".") let op_wrapscan = &wrapscan set nowrapscan let par_begin = '^$$%D$$\=\s*$$\|\\start\|\\stop\|\\Start\|\\Stop\|\\\(sub$$*section\>\|\\item\>\|\\NC\>\|\\blank\>\|\\noindent\>\)' let par_end = '^$$%D$$\=\s*$$\|\\start\|\\stop\|\\Start\|\\Stop\|\\place\|\\\(sub$$*section\>\|\\item\>\|\\NC\>\|\\blank\>\)' try exe '?'.par_begin.'?+' catch /E384/ 1 endtry norm V try exe '/'.par_end.'/-' catch /E385/  endtry norm gq let &wrapscan = op_wrapscan call setpos('.', save_cursor) endif endfun nmap Q :call TeX_fmt()<CR>  - Thank you, this works really well. For LaTeX one needs only needs to replace \\start\|\\stop\|\\Start\|\\Stop\| by |\\begin\|\\end\|\\[\|\$\|. (Also the {{{ should be ended by a " }}} after the last line.) –  Caramdir Aug 11 '10 at 17:35
I'm not having success with the pattern \$ and \$. In my case, Vim seems to simply ignore display math that starts and ends with $ and $. I'm no expert in Vim regular expressions but I found that escaping the square brackets does the trick, i.e., replacing \$ with \\\[ and \$ with \\\]. –  Dominique Jan 2 '12 at 22:49

The following solution only applies to paragraph formatting, it will properly work depending on the LaTeX styling settings.

Another possible solution would be to set a hard wrap of 80 characters.

http://vimcasts.org/episodes/hard-wrapping-text/

formatoptions:

t - Auto-wrap text using textwidth

c - Auto-wrap comments using textwidth, inserting the current comment leader automatically.

a - Automatic formatting of paragraphs.

Here are some of the commands to set it up:

:set formatoptions=tc
:set fo+=a
:set textwidth=80


Tip: Use the autocmd or ftplugin folder to setup these settings automatically according to filetype. Run help: ftplugin in vim for more info.

http://vimdoc.sourceforge.net/htmldoc/change.html#fo-table

-
With this method, you can't end lines with a comment. –  sappjw Dec 13 '12 at 16:12

I know it's against policy to answer commenting on other answers, but in this case -- given I lack the 50 reputation needed to comment directly on the relevant answer -- I think it's worth it.

The function provided by Aditya functions perfectly for LaTeX, mutatis mutandis, except for one detail: often after beginning an environment, or a section, the very next line will be a \label{}. The original TeX_fmt() function wrongly considers this line to be a part of the paragraph. To fix this, modify the line that sets par_begin, to this:

let par_begin = '^$$%D$$\=\s*$$\|\\label\|\\begin\|\\end\|\$\|\$\|\\\(sub$$*section\>\|\\item\>\|\\NC\>\|\\blank\>\|\\noindent\>\)'


Basically, you add a \label before the \begin.

Profit!!

-
This would be too long for a comment as it stands, and extends functionality in some sense. Nice catch!! –  Sean Allred Aug 14 '13 at 3:47

Sorry to barge in, but just don't. I'll give several reasons, each one of them good enough for me on its own.

First, I got into the habit of splitting source lines at punctuation, and otherwise to keep a (vaguely defined) phrase/idea together on a line. I.e., keep the article and the subject together, etc. And cut lines into short(ish) pieces when writing.

• It makes searching for mistakes, like "an wrong article" or repeated repeated words easy
• Most of the time editing gets to be shuffling lines around, erasing/adding lines. This is natural with the editor's commands, whatever it might be.
• Last in my personal history, but overwhelming today: by the second point above, differences from one version to the next will be restricted to only the "real" changes, no "this line and most of the rest of the paragraph got reflowed" noise because a word got added. This makes version control keep smaller differences (nice), but more importantly makes differences understandable.

But that can't be automated in any reasonable way (unless you want to add full text understanding to your editor, and that is definitely emacs' territory, not vi's... ;-)

-

I came into the same problem. Here is solution that worked for me. I've wrote an external script to handle the formatting of latex text (https://github.com/elmanuelito/par-latex). I usually reformat the entire document at once, but it can be done paragraph-wise.

Example of usage in vim:

• Select some text (e.g. Vj or ggVG)
• type ":!par-latex" (vim command-line looks like: '<,'>!par-latex)
• type enter

You can customize the script (it's based on some regexp) and change some parameters at the beginning.

-