How can I get (g)Vim to display the character count of the current file?

87

23

I like to write tutorials and articles for a programming forum I frequent. This forum has a character limit per post. I've used Notepad++ in the past to write posts and it keeps a live character count in the status bar. I'm starting to use gVim more and I really don't want to go back to Notepad++ at this point, but it is very useful to have this character count. If I go over the count, I usually end up pasting the post into Notepad++ so I can see when I've trimmed enough to get by the limit.

I've seen suggestions that :set ruler would help, but this only gives the character count via the current column index on the current line. This would be great if I didn't use paragraph breaks, but I'm sure you'd agree that reading several thousand characters in one paragraph is not comfortable.

I read the help and thought that rulerformat would work, but after looking over the statusline format it uses I didn't see anything that gives a character count for the current buffer.

I've seen that there are plugins that add this, but I'm still dipping my toes into gVim and I'm not sure I want to load random plugins before I understand what they do. I'd prefer to use something built in to vim, but if it doesn't exist it doesn't exist.

What should I do to accomplish my goal? If it involves a plugin, do you use it and how well does it work?

OwenP

Posted 2010-06-07T16:26:01.123

Reputation: 1 400

Answers

142

Press g CTRL-G in normal mode to display some statistics on the cursor and the file.

If you are in linux you can use wc -m to get the character count in the current file

:!wc -m %

Since it is not updated in real-time, maybe you want to map this command to something like:

map <F4> :!wc -m %<CR>

mrucci

Posted 2010-06-07T16:26:01.123

Reputation: 8 398

21g CTRL-G I didn't know this existed. Nice! – Jason Down – 2012-06-13T18:50:24.430

Nice I keep forgetting to use !bang commands in Vim – Eddie B – 2013-01-16T01:38:47.237

3g <c-g> works cross-platform which is nice. – AndrewPK – 2014-01-17T18:39:24.187

Where can I find more info about the use of ! [...] %? – Wok – 2014-02-14T20:59:35.537

Help is here: http://vimdoc.sourceforge.net/htmldoc/various.html#:%21cmd . If you make heavy use of shell commands, check also this plugin: http://stevelosh.com/projects/clam/ .

– mrucci – 2014-02-15T08:10:12.297

24

:help count-items

suggests, that you could either do a dry-run of a replace ala

:%s/./&/gn

(which then reports back the number of matched chars) or that you do a fancy strlen() on the visually selected text:

:echo strlen(@")

(" is the unnamed register)

since you can call an expression in your statusline like %{myfunc()} that might be a good starting point. counting all the time could be a bit time consuming since you would have to select the whole text and then yank it, but maybe showing the number of bytes in the "-register is ok for you already. if you really want to know the number of chars in the buffer: just visually select ALL the text in the buffer and yank it. so, the solution would be:

 :set statusline=%{strlen(@")}

which gives you the number of chars in the "-register (which is identical to the number of bytes if you select and yank the current buffer).

akira

Posted 2010-06-07T16:26:01.123

Reputation: 52 754

Solution works also on Windows (which bash commands won't). – dastrobu – 2017-08-11T12:12:09.387

I like that the count doesn't disappear after a second like the g<CTRL-g> method in the accepted answer. – Chester – 2017-10-09T14:57:23.107

9

An enhancement to the answer of mrucci:

You can use wc on linux without having to save the file first by directing the :w command output as follows:

:w !wc -m

and you can map it to something as mentioned by mrucci.

architectonic

Posted 2010-06-07T16:26:01.123

Reputation: 191

For the those less familiar with vimscript foo, I did :command! Chars :w !wc -m to make it a command (ie. run :Chars to get the character count). Note the command must be uppercase (requirement for non-default commands). – James Wright – 2019-12-26T15:17:06.750

6

:help statusline

gives you

o N   Byte number in file of byte under cursor, first byte is 1.
      Mnemonic: Offset from start of file (with one added)

which is also a good workaround for your problem. just go to the end of the buffer with G and the byte number shown in your statusline is the number of chars (not true with multi-byte chars of course). go back to where you came from with ctrlo.

akira

Posted 2010-06-07T16:26:01.123

Reputation: 52 754

http://vimdoc.sourceforge.net/htmldoc/options.html#%27statusline' – Tyler Szabo – 2016-10-25T01:52:57.700

1Since the docs are vague and confusing, it's worth noting that the specific command one need to execute is set statusline+=\ %o\ %N (interestingly, it doesn't work for e.g. "t S" item). Then if you see the statusline unchanged, it's because you gotta execute set laststatus=2. For me it replaced the existing transparent statusline with the new one, being solid black, and only having "byte count" item. – Hi-Angel – 2018-05-09T17:42:28.323

1This is problematic with multi-byte characters. I found this question after putting %o in my statusline :) – Matt – 2013-02-01T02:53:23.353

@Matt: so, whats the solution? – akira – 2013-02-01T07:02:36.923

1mrucci's solution "g^g" in normal mode was good enough for me. I needed it for a quick debug, so I haven't taken the time to try and get that information in the statusline. – Matt – 2013-02-01T07:13:39.433

3

You can append an expression to display the buffer's bytecount in the statusline with:

:set statusline+=\ %{\ line2byte(line(\"$\")+1)-1\ }B

Or you can change the option variable directly to avoid all that escaping:

:let &statusline .= ' %{ line2byte(line("$")+1)-1 }B'

akira

Posted 2010-06-07T16:26:01.123

Reputation: 52 754

When I try this, gVim complains about an unclosed expression sequence. I noticed you are missing a parenthesis, but fixing that doesn't help either. Here's what I rewrote it to:

:set statusline=%{ line2byte(line("$")) } – OwenP – 2010-06-07T17:51:58.313

@OwenP: should be fixed now – akira – 2010-06-08T04:55:50.323

1Probably you want ...%{ line2byte(line(\"$\")+1))-1 } so that it includes the last line's characters in the count. This approach won't count multibyte characters correctly, though. – intuited – 2010-06-08T05:29:16.077

1Also I think you need to escape the spaces, or just get rid of them. – intuited – 2010-06-08T06:04:29.957

Edited to include @intuited's suggestions, also appended to the statusline rather than overwrite it. – joeytwiddle – 2014-06-14T21:40:51.550

3

If you're in the habit of using :w to save the file, each time you do this the status reports back the number of characters written. For instance, at the end of this sentence I did a :w (yes I'm using gvim to write this note) and it reported: 245C written.

Erin Thomas

Posted 2010-06-07T16:26:01.123

Reputation: 47

This golfs beautifully for one time usage. – Ciro Santilli 新疆改造中心法轮功六四事件 – 2015-06-04T15:29:30.240

0

If you keep a file copy of your text, just write your text to disk - the character count is displayed by default.

If you do not want to keep a file, just save your text to /dev/null: :w!/dev/null.

You can also let wc count your characters: :%!wc -c - but don't forget to hit U to restore your text.

If you need this often, just map these commands to a key sequence: :map #wc :w!/dev/null^[ - note that the ^[ must be entered as Ctrl+V Esc.

As a first indicator of text size, just turn on line numbers; admitted: this needs some mental arithmetics ;-)

kdo

Posted 2010-06-07T16:26:01.123

Reputation: 367

0

Workaround I've been using until I accepted mrucci's answer:

I found out by accident that when I :w to save the file, the command outputs the number of bytes written. This is more or less a character count, so that's been close enough so far. I do like mrucci's answer as well, possibly more than this one because it has a word count too.

OwenP

Posted 2010-06-07T16:26:01.123

Reputation: 1 400

0

After having this question and reading the answers (thanks mrucci) I added these lines to my .vimrc initialization file.

# get full statistics on the current buffer (not perfect, may redraw screen)
map ;gg           G$g<C-G>''
# get full statistics on the current position in the buffer
map ;gh           g<C-G>

I leave it to vim :help users to figure out what they do.

Personally I find it useful to start Vim mappings with ; or , since I rarely use them as the first character of a command.

David E.

Posted 2010-06-07T16:26:01.123

Reputation: 51