Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make { and } ignore lines containing only whitespace

Tags:

vim

When you navigate by paragraph in vim using { and } it skips lines that contain nothing but whitespace though they are otherwise 'blank'.

How can I convince vim to treat "whitespace only" lines as paragraph breaks so { and } will jump to them?

like image 498
ʞɔıu Avatar asked Dec 05 '09 18:12

ʞɔıu


3 Answers

Here's a modified version that handles counts correctly:

function! ParagraphMove(delta, visual, count)
    normal m'
    normal |
    if a:visual
        normal gv
    endif

    if a:count == 0
        let limit = 1
    else
        let limit = a:count
    endif

    let i = 0
    while i < limit
        if a:delta > 0
            " first whitespace-only line following a non-whitespace character           
            let pos1 = search("\\S", "W")
            let pos2 = search("^\\s*$", "W")
            if pos1 == 0 || pos2 == 0
                let pos = search("\\%$", "W")
            endif
        elseif a:delta < 0
            " first whitespace-only line preceding a non-whitespace character           
            let pos1 = search("\\S", "bW")
            let pos2 = search("^\\s*$", "bW")
            if pos1 == 0 || pos2 == 0
                let pos = search("\\%^", "bW")
            endif
        endif
        let i += 1
    endwhile
    normal |
endfunction

nnoremap <silent> } :<C-U>call ParagraphMove( 1, 0, v:count)<CR>
onoremap <silent> } :<C-U>call ParagraphMove( 1, 0, v:count)<CR>
" vnoremap <silent> } :<C-U>call ParagraphMove( 1, 1)<CR>
nnoremap <silent> { :<C-U>call ParagraphMove(-1, 0, v:count)<CR>
onoremap <silent> { :<C-U>call ParagraphMove(-1, 0, v:count)<CR>
" vnoremap <silent> { :<C-U>call ParagraphMove(-1, 1)<CR>
like image 149
keithr Avatar answered Nov 17 '22 20:11

keithr


As said before, if you run :help paragraph you will see that lines with whitespace are not treated as a boundary.

In the mean time there are two plugin projects which could help:

  • Improved paragraph motion (mirrored as https://github.com/vim-scripts/Improved-paragraph-motion)
  • Vim Paragraph Motion based on the code in the other answers.

If you use Pathogen, simply download from one of the sites mentioned above.

If you use Vundle, put one of the following in your .vimrc:

  • Improved paragraph motion:

    Bundle 'vim-scripts/Improved-paragraph-motion'
    
  • Vim Paragraph Motion:

    Bundle 'dbakker/vim-paragraph-motion'
    

Run :BundleInstall after a reboot and the { } motions should stop on lines containing whitespace characters.

like image 3
JBert Avatar answered Nov 17 '22 21:11

JBert


This is something that's bothered me for a long time. Probably the "right" solution would be to submit a patch to vim itself that would allow you to customize paragraph boundaries with a regex (like :set paragraphs, but actually useful).

In the meantime, I've made a function and a couple of mappings that almost do the right thing:

function! ParagraphMove(delta, visual)
    normal m'
    normal |
    if a:visual
        normal gv
    endif

    if a:delta > 0
        " first whitespace-only line following a non-whitespace character
        let pos1 = search("\\S", "W")
        let pos2 = search("^\\s*$", "W")
        if pos1 == 0 || pos2 == 0
            let pos = search("\\%$", "W")
        endif
    elseif a:delta < 0
        " first whitespace-only line preceding a non-whitespace character
        let pos1 = search("\\S", "bW")
        let pos2 = search("^\\s*$", "bW")
        if pos1 == 0 || pos2 == 0
            let pos = search("\\%^", "bW")
        endif
    endif
    normal |
endfunction

nnoremap <silent> } :call ParagraphMove( 1, 0)<CR>
onoremap <silent> } :call ParagraphMove( 1, 0)<CR>
" vnoremap <silent> } :call ParagraphMove( 1, 1)<CR>
nnoremap <silent> { :call ParagraphMove(-1, 0)<CR>
onoremap <silent> { :call ParagraphMove(-1, 0)<CR>
" vnoremap <silent> { :call ParagraphMove(-1, 1)<CR>

This doesn't correctly handle counts like '4}' or visual mode correctly (uncomment the vnoremap lines at your peril), but seems ok for things like not clobbering the current search pattern and not flickering. Also, 'd}', 'y}', etc. seem to work ok. If anyone has ideas for making counts work or fixing visual mode, please let me know.

like image 2
Mike P Avatar answered Nov 17 '22 21:11

Mike P