Display the Word Count in the Vim Status Line
Counting Words in Vim
I have recently found myself frequently needing to count
the number of words in a simple ASCII text file as I create it.
Unfortunately, the
Vi editor
does not provide this by default.
Why not?
Continuously maintaining a count of words can require a
surprising amount of work as a file is rapidly
modified through the sweeping methods possible within Vi.
That's fine, it's easy to add the capability.
Let's see what we want to accomplish by using the creation
of this file as an example.
First, notice that the buffer content has been color-coded for
syntax specific to the automatically detected language content.
Second, notice the detailed statusline at the bottom.
It starts with the full path to the file being edited.
The appended flag ,+
indicates that the file
has been modified since it was last written.
Press :w
to write out the buffer and that flag
disappears.
The following [xhtml]
indicates that vim
has automatically determined that the file contains XHTML
data.
You can see that this is not assumed from the
file name, as it ends with .html
and not .xhtml
.
Then we're told that the buffer currently contains 1202 words, and the cursor is on line 43 out of 286, 15% of the way through the file. This looks useful!
That's a lot of detail on the line, and there is very little free space remaining. That's fine, this has been set up so that the long full path to the file will be truncated at its left end as needed to otherwise allow everything to fit. I show how to do that below, it's simple.
To get started, use vim
, not vi
.
With Linux and OS X, you get vim
by default,
and typing vi
really gives you vim
.
But with
OpenBSD,
Solaris and other versions of Unix, you may have to add
a package and explicitly run the vim
command
to get the modernized version.
% uname -sr OpenBSD 5.9 % which vi /usr/bin/vi % which vim /usr/local/bin/vim % pkg_info | grep 'vim' vim-7.4.900-gtk2 vi clone, many additional features % ssh solarisbox 'uname -sr ; which vi ; which vim' SunOS 5.10 /usr/ucb/vi /usr/local/bin/vim
The critical file is ~/.vimrc
.
Modify that file to configure your editor.
If you break your editor by putting errors into this file,
rescue yourself by editing the file without
using it:
% vim -U NONE ~/.vimrc
The easiest way to explain this is to simply show my
.vimrc
file with plenty of comments.
It starts with the basic settings, then it defines
a function for efficient word counting and builds
a complex statusline.
Then there is some standard boilerplate provided with
the distribution for handling compressed files.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Basic settings
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Turn on syntax highlighting, or really color coding.
" This really helps you spot broken syntax as you type.
syntax on" Turn off multi-level undo. Now pressing 'u' will toggle
" the last change off and on, as opposed to rolling back
" undoing all previous changes in reverse order.
" Multi-level undo is NOT helpful for most people!
set undolevels=0" Maintain existing indentation.
set autoindent" Show matches for () [] {}
set showmatch" Default tab spacing = 8 columns
set ts=8" Default backspace like normal
set bs=2" Some option activate by default (remove the no to allow these).
set nobackup set nohlsearch set noincsearch" Some environments set textwidth to force linewrap. Disable this.
set textwidth=0" Display a status-bar.
set laststatus=2""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Here begins my automated wordcount addition.
" This combines several ideas from:
" http://stackoverflow.com/questions/114431/fast-word-count-function-in-vim
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let g:word_count="<unknown>" function WordCount() return g:word_count endfunction function UpdateWordCount() let lnum = 1 let n = 0 while lnum <= line('$') let n = n + len(split(getline(lnum))) let lnum = lnum + 1 endwhile let g:word_count = n endfunction" Update the count when cursor is idle in command or insert mode.
" Update when idle for 1000 msec (default is 4000 msec).
set updatetime=1000 augroup WordCounter au! CursorHold,CursorHoldI * call UpdateWordCount() augroup END" Set statusline, shown here a piece at a time
highlight User1 ctermbg=green guibg=green ctermfg=black guifg=black set statusline=%1*" Switch to User1 color highlight
set statusline+=%<%F" file name, cut if needed at start
set statusline+=%M "modified flag
set statusline+=%y "file type
set statusline+=%= "separator from left to right justified
set statusline+=\ %{WordCount()}\ words, set statusline+=\ %l/%L\ lines,\ %P "percentage through the file
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Below here is just standard content from Mageia installation environment.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" To display color on a vanilla xterm (Use Rxvt luke).
if &term=="xterm" set t_Co=8 set t_AB=<ESC>[%?%p1%{8}%<%t%p1%{40}%+%e%p1%{92}%+%;%dm set t_AF=<ESC>[%?%p1%{8}%<%t%p1%{30}%+%e%p1%{82}%+%;%dm endif" Some macros to manage the buffer of vim
map <F5> :bp<C-M> map <F6> :bn<C-M> map <F7> :bd<C-M>"" Gzip and Bzip2 files support
" Take from the Debian package and the exemple on $VIM/vim_exemples
if has("autocmd")" Set some sensible defaults for editing C-files
augroup cprog" Remove all cprog autocommands
au!" When starting to edit a file:
" For *.c and *.h files set formatting of comments and set C-indenting on.
" For other files switch it off.
" Don't change the order, it's important that the line with * comes first.
autocmd BufRead * set formatoptions=tcql nocindent comments& autocmd BufRead *.c,*.h set formatoptions=croql cindent comments=sr:/*,mb:*,el:*/,:// augroup END" Also, support editing of gzip-compressed files. DO NOT REMOVE THIS!
" This is also used when loading the compressed helpfiles.
augroup gzip" Remove all gzip autocommands
au!" Enable editing of gzipped files
" read: set binary mode before reading the file
" uncompress text in buffer after reading
" write: compress file after writing
" append: uncompress file, append, compress file
autocmd BufReadPre,FileReadPre *.gz set bin autocmd BufReadPre,FileReadPre *.gz let ch_save = &ch|set ch=2 autocmd BufReadPost,FileReadPost *.gz '[,']!gunzip autocmd BufReadPost,FileReadPost *.gz set nobin autocmd BufReadPost,FileReadPost *.gz let &ch = ch_save|unlet ch_save autocmd BufReadPost,FileReadPost *.gz execute ":doautocmd BufReadPost " . %:r autocmd BufWritePost,FileWritePost *.gz !mv <afile> <afile>:r autocmd BufWritePost,FileWritePost *.gz !gzip <afile>:r autocmd FileAppendPre *.gz !gunzip <afile> autocmd FileAppendPre *.gz !mv <afile>:r <afile> autocmd FileAppendPost *.gz !mv <afile> <afile>:r autocmd FileAppendPost *.gz !gzip <afile>:r augroup END augroup bzip2" Remove all bzip2 autocommands
au!" Enable editing of bzipped files
" read: set binary mode before reading the file
" uncompress text in buffer after reading
" write: compress file after writing
" append: uncompress file, append, compress file
autocmd BufReadPre,FileReadPre *.bz2 set bin autocmd BufReadPre,FileReadPre *.bz2 let ch_save = &ch|set ch=2 autocmd BufReadPost,FileReadPost *.bz2 set cmdheight=2|'[,']!bunzip2 autocmd BufReadPost,FileReadPost *.bz2 set cmdheight=1 nobin|execute ":doautocmd BufReadPost " . %:r autocmd BufReadPost,FileReadPost *.bz2 let &ch = ch_save|unlet ch_save autocmd BufWritePost,FileWritePost *.bz2 !mv <afile> <afile>:r autocmd BufWritePost,FileWritePost *.bz2 !bzip2 <afile>:r autocmd FileAppendPre *.bz2 !bunzip2 <afile> autocmd FileAppendPre *.bz2 !mv <afile>:r <afile> autocmd FileAppendPost *.bz2 !mv <afile> <afile>:r autocmd FileAppendPost *.bz2 !bzip2 -9 --repetitive-best <afile>:r augroup END endif " has ("autocmd")
As for color, to be safe you should stick with the
ANSI colors going back to MS-DOS command prompts.
Quoting from :help color
within vim
we see:
*cterm-colors* NR-16 NR-8 COLOR NAME ~ 0 0 Black 1 4 DarkBlue 2 2 DarkGreen 3 6 DarkCyan 4 1 DarkRed 5 5 DarkMagenta 6 3 Brown, DarkYellow 7 7 LightGray, LightGrey, Gray, Grey 8 0* DarkGray, DarkGrey 9 4* Blue, LightBlue 10 2* Green, LightGreen 11 6* Cyan, LightCyan 12 1* Red, LightRed 13 5* Magenta, LightMagenta 14 3* Yellow, LightYellow 15 7* White The number under "NR-16" is used for 16-color terminals ('t_Co' greater than or equal to 16). The number under "NR-8" is used for 8-color terminals ('t_Co' less than 16). The '*' indicates that the bold attribute is set for ctermfg. In many 8-color terminals (e.g., "linux"), this causes the bright colors to appear. This doesn't work for background colors! Without the '*' the bold attribute is removed. If you want to set the bold attribute in a different way, put a "cterm=" argument AFTER the "ctermfg=" or "ctermbg=" argument. Or use a number instead of a color name. The case of the color names is ignored. Note that for 16 color ansi style terminals (including xterms), the numbers in the NR-8 column is used. Here '*' means 'add 8' so that Blue is 12, DarkGray is 8 etc. Note that for some color terminals these names may result in the wrong colors!