I'd like to be able to show the number of spelling errors in a buffer in my status line. Is there a vimscript way of getting a count of the number of spelling errors? I could write some code to count them using ]S, keeping track of the cursor position, but that seems pretty clumsy. Is there a better way? A simple piece of code would be fine, but a plugin is also OK.


I should add that I have written some code, which looks like this:

function! Statusline_SpellingErrorCount()
    if &spell
        if !exists('b:spelling_warning')
            let l:view = winsaveview()

            let l:mycount = 0
            call cursor(1, 1)

            let l:lastline = 0
            while 1
                let l:lastline = line('.')
                let l:lastcol = col('.')
                normal! ]S
                if (!(line('.') > l:lastline || (line('.') == l:lastline && col('.') > l:lastcol)))
                let l:mycount = l:mycount + 1

            call winrestview(l:view)
            if l:mycount > 0
                let b:spelling_warning = '[splerr ' . l:mycount . ']'
                let b:spelling_warning = ''
        let b:spelling_warning = ''

    return b:spelling_warning

set statusline+=%{Statusline_SpellingErrorCount()}

autocmd CursorHold,BufWritePost * unlet! b:spelling_warning

This works, but as I mentioned in my question, it's pretty clumsy as it involves iterating through the entire buffer (potentially very slow if there are lots of errors), and when it loops from the end to the beginning, there's a nasty sideeffect of a wraparound 'start from beginning' warning in the status line too.

I would be interested if there are better ways than this.

Update: per @filbranden's comment, I've added:

 let l:oldwrapscan = &wrapscan
 set nowrapscan

before saving the view, and...

 let &wrapscan = l:oldwrapscan

after saving the view, as well as simplifying the if condition to:

 if line('.') == l:lastline && col('.') == l:lastcol

This removes the nasty wraparound, but it still means counting the errors manually.

  • 1
    Temporarily using set nowrapscan should help with the issue of wrapping around to the start... (Even though you still need to scan the whole buffer...)
    – filbranden
    May 21 '20 at 7:42
  • 1
    @filbranden that's a good call, I wasn't aware of that option. I'll adapt my code accordingly. May 21 '20 at 7:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.