Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get live word count for document in vim

Tags:

vim

word-count

I would like vim to display the total document word count in the status bar (where the current line and character number are displayed). I have come across similar questions on SO, and have tried all the suggestions mentioned here and here --- and none of them had any effect whatsoever on my status bar.

To explicitly name a few, I tried to paste any of the following in my ~/.vimrc (and ofc subsequently restarted vim):

function! CountNonEmpty()
    let l = 1
    let char_count = 0
    while l <= line("$")
        if len(substitute(getline(l), '\s', '', 'g')) > 3   
            let char_count += 1 
        endif
        let l += 1
    endwhile
    return char_count
endfunction

function WordCount()
  let s:old_status = v:statusmsg
  exe "silent normal g\<c-g>"
  let s:word_count = str2nr(split(v:statusmsg)[11])
  let v:statusmsg = s:old_status
  return s:word_count
endfunction  

" If buffer modified, update any 'Last modified: ' in the first 20 lines.
" 'Last modified: ' can have up to 10 characters before (they are retained).
" Restores cursor and window position using save_cursor variable.
function! LastModified()
  if &modified
    let save_cursor = getpos(".")
    let n = min([15, line("$")])
    keepjumps exe '1,' . n . 's#^\(.\{,10}LOC:\).*#\1' .
          \ ' ' . CountNonEmpty() . '#e'
    keepjumps exe '1,' . n . 's#^\(.\{,10}Word Count:\).*#\1' .
          \ ' ' . WordCount() . '#e'
    call histdel('search', -1)
    call setpos('.', save_cursor)
  endif
endfun 

OR

function WordCount()
  let s:old_status = v:statusmsg
  exe "silent normal g\<c-g>"
  let s:word_count = str2nr(split(v:statusmsg)[11])
  let v:statusmsg = s:old_status
  return s:word_count
endfunction
set statusline=wc:%{WordCount()}

OR

function! WordCount()
   let s:old_status = v:statusmsg
   let position = getpos(".")
   exe ":silent normal g\<c-g>"
   let stat = v:statusmsg
   let s:word_count = 0
   if stat != '--No lines in buffer--'
     let s:word_count = str2nr(split(v:statusmsg)[11])
     let v:statusmsg = s:old_status
   end
   call setpos('.', position)
   return s:word_count 
endfunction
set statusline=wc:%{WordCount()}

OR

let g:word_count="<unknown>"
fun! WordCount()
    return g:word_count
endfun
fun! UpdateWordCount()
    let s = system("wc -w ".expand("%p"))
    let parts = split(s, ' ')
    if len(parts) > 1
        let g:word_count = parts[0]
    endif
endfun

augroup WordCounter
    au! CursorHold * call UpdateWordCount()
    au! CursorHoldI * call UpdateWordCount()
augroup END

" how eager are you? (default is 4000 ms)
set updatetime=500

" modify as you please...
set statusline=%{WordCount()}\ words

or many many more. And as I said there wa no efect. No error message, no visually perceptible change. I guess there may be a common issue which I am missing, but what is it?

like image 266
TheChymera Avatar asked Aug 21 '18 14:08

TheChymera


2 Answers

Assuming your status line is enabled (set laststatus=2), the following:

set statusline+=%{wordcount().words}\ words

does exactly what you want in Vim version 7.4.1042 and above:

wc

See :help wordcount().


If you absolutely need backward compatibility, the following is pretty much guaranteed to work in Vim 7.x, and will probably also work in earlier versions:

function! WC()
    return len(split(join(getline(1,'$'), ' '), '\s\+'))
endfunction
set statusline+=%{WC()}\ words

Some of the answers from those old threads may be faster or smarter, though.


Your comments about those functions from those old threads not changing anything to your status line make me wonder if the problem is in all those old answers or elsewhere. Maybe… you don't have a status line to begin with?

like image 183
romainl Avatar answered Sep 20 '22 23:09

romainl


Word count in vim-airline

Word count is provided standard by vim-airline for a number of file types, being at the time of writing: asciidoc, help, mail, markdown, org, rst, tex ,text

If word count is not shown in the vim-airline, more often this is due to an unrecognised file type. For example, at least for now, the compound file type markdown.pandoc is not being recognised by vim-airline for word count. This can easily be remedied by amending the .vimrc as follows:

let g:airline#extensions#wordcount#filetypes = '\vasciidoc|help|mail|markdown|markdown.pandoc|org|rst|tex|text'
set laststatus=2    " enables vim-airline.

The \v statement overrides the default g:airline#extensions#wordcount#filetypes variable. The last line ensures vim-airline is enabled.

In case of doubt, the &filetype of an opened file is returned upon issuing the following command:

:echo &filetype

Here is a meta-example:

vim-airline word count

like image 33
Serge Stroobandt Avatar answered Sep 21 '22 23:09

Serge Stroobandt