4

When I am writting a Latex document I generally like to keep an 80 column line width to keep things easy to read. However I don't like to use text wrapping because it can get in the way of typing equations.

Normally I will type a paragraph without caring how long the lines are, and eventually they gradually get longer, and longer, to the point where if I vsplit two documents the lines run off the end. So I will set textwitdth=80 and highlight an offending section in visual mode, and then use gq to format the selected text. However this is a bit more of a process than I have come accustomed to using vim I prefer to do things with only a few key strokes, or have it automatically done based on the file type.

I am looking for a way to either:

  1. script the application of a particular format (predetermined) to a selection of text
  2. Apply conditional formatting to a file-type based on some of the same identifiers used to conditionally highlight syntax

For those unfamiliar with latex:

A regular text section is by and large free of any syntax. When you
begin an equation  like this, 
\begin{equation}
\hat{H}\Psi = E\Psi
\end{equation}
I wouldn't want the lines inside to be wrapped automatically.

So there is a clear way of identifying math environments ie\begin..\end and Vim's ft plugin recognizes this for syntax highlighting. Can you apply conditional formatting in a similar way?

This (latex) is an example I am working with right now, but for example in general programming I would really like it if multi line comments could be wrapped without automatically wrapping regular code.

Martin Tournoij
  • 62,054
  • 25
  • 192
  • 271
Ajay
  • 219
  • 1
  • 6

2 Answers2

2

This is pretty much the same question as Prevent Vim from breaking up links mid-tag in markdown

For TeX equations it's slightly more involved, but not too much. We assume we're inside an equation if a line in the last 10 lines begins with \begin{equation}.

au CursorMovedI,CursorMoved *.tex let b:tex_textwidth = 80 | let b:tex_last_line = 0 | call ModifyTextWidth()

fun! ModifyTextWidth()
        " Only run if the cursor is on another line
        if line('.') == b:tex_last_line | return | endif
        let b:tex_last_line = line('.')

        " Try to find the start of an equation
        let l:eq = 0
        for i in range(1, 10)
                if getline(line('.') - i) =~ '^\\end{equation}' | break | endif

                " We're in an equation
                if getline(line('.') - i) =~ '^\\begin{equation}'
                        set textwidth=0
                        return
                endif
        endfor

        " Reset to original
        let &textwidth = b:tex_textwidth
endfun

I haven't extensively tested this, but it seems to work well with some samples I've found on the internet...

Martin Tournoij
  • 62,054
  • 25
  • 192
  • 271
2

I have a similar setup with respect for writing mails. The idea is, to check the cursor position and depending on the current position set some formatting options.

" Dynamically set format options, depending on where you are in a
" mail, idea from Teemu Likonen:
" http://groups.google.com/group/vim_use/msg/f59e5c1adc6be2b3

let d_fo = &fo
let s:defaults = 'setlocal tw=72 ts=8 sts=4 sw=4 fo='.d_fo
execute s:defaults
let b:MailAreaDetect=1

"nnoremap <buffer> <LocalLeader>ma1 :call <SID>MailAreaDetect_On()
"    \ <bar> echo 'MailAreaDetect On'<CR>
"nnoremap <buffer> <LocalLeader>ma0 :call <SID>MailAreaDetect_Off()
"    \ <bar> echo 'MailAreaDetect Off'<CR>

nnoremap <buffer><silent> <F9> :call <SID>MailAreaDetect_Switch(0)<CR>
inoremap <buffer><silent> <F9> <C-\><C-O>:call <SID>MailAreaDetect_Switch(1)<CR>

function! s:MailAreaDetect_Switch(vmode)
    if b:MailAreaDetect
        silent call <SID>MailAreaDetect_Off()
        let b:MailAreaDetect=0
        echo 'MailAreaDetect Off'
        if a:vmode
            sleep 1
        endif
    else
        silent call <SID>MailAreaDetect_On()
        let b:MailAreaDetect=1
        echo 'MailAreaDetect On'
        if a:vmode
            sleep 1
        endif
    endif
endfu


function! s:MailAreaDetect_On()
    silent autocmd! MailAreaDetect CursorMoved,CursorMovedI
        \ <buffer> call <SID>AreaOptions()
    let b:MailAreaDetect=1
endfunction

function! s:MailAreaDetect_Off()
    silent autocmd! MailAreaDetect
    execute s:defaults
    let b:MailAreaDetect=0
endfunction

augroup MailAreaDetect
    autocmd!
    call <SID>MailAreaDetect_On()
augroup END

function! s:AreaOptions()
    execute s:defaults
    if <SID>CheckArea('\v^From( |: ).*\n','\v^$')
        "echo 'Header'
        setlocal fo-=a fo-=w fo-=t sts=0 sw=8 noet
    elseif getline('.') =~ '\m^\s*>'
        "echo 'Quotation'
        setlocal fo-=a fo-=w
    elseif <SID>CheckArea('\m^--- .*\n^+++ ','\v(^$|\n^-- $)')
        "echo 'Patch'
        setlocal fo-=a fo-=w fo-=t sts=0 sw=8 noet
    elseif <SID>CheckArea('^-- $','^$')
        "echo 'Signature'
        setlocal fo-=a fo-=w fo-=t sts=0 sw=8 noet
    else
        "echo 'My text'
        setlocal fo+=aw et
    endif
endfunction

function! s:CheckArea(start, end)
    return (search(a:start,'bcnW')-line('.')) >
        \ (search(a:end,'bnW')-line('.'))
endfunction
Martin Tournoij
  • 62,054
  • 25
  • 192
  • 271
Christian Brabandt
  • 25,820
  • 1
  • 52
  • 77