Reputation:
Is it possible to display the line count in the VIM status bar with thousands separators, preferably custom thousands separators?
Example:
set statusline=%L
should lead to "1,234,567" instead of "1234567".
Upvotes: 4
Views: 317
Reputation: 85827
I've found a way but it looks a bit crazy:
set statusline=%{substitute(line('$')\,'\\d\\zs\\ze\\%(\\d\\d\\d\\)\\+$'\,'\,'\,'g')}
The first round of backslashes is just for set
(I have to escape ,
and \
itself).
What I'm actually setting the option to is this string:
%{substitute(line('$'),'\d\zs\ze\%(\d\d\d\)\+$',',','g')}
As a format string, this line contains one formatting code, which is %{...}
. Everything in ...
is evaluated as an expression and the result substituted back in.
The expression I'm evaluating is (spaces added (if I had added them to the real code, I would've had to escape them for set
again, forcing yet more backslashes)):
substitute(line('$'), '\d\zs\ze\%(\d\d\d\)\+$', ',', 'g')
This is a call to the substitute
function. The arguments are the source string, the regex, the replacement string, and a list of flags.
The string we're starting with is line('$')
. This call returns the number of lines in the current buffer (or rather the number of the last line in the buffer). This is what %L
normally shows.
The search pattern we're looking for is \d(\d\d\d)+$
(special vim craziness removed), i.e. a digit followed by 1 or more groups of 3 digits, followed by the end of the string. Grouping is spelled \%(
\)
in vim, and "1 or more" is \+
, which gives us \d\%(\d\d\d\)\+$
. The last bit of magic is \zs\ze
. \zs
sets the start of the matched string; \ze
sets the end. This works as if everything before \zs
were a look-behind pattern and everything after \ze
were a look-ahead pattern.
What this amounts to is: We're looking for every position in the source string that is preceded by a digit and followed by exactly N digits (where N is a multiple of 3). This works like starting at the right and going left, skipping 3 digits each time. These are the positions where we need to insert a comma.
That's what the replacement string is: ','
(a comma). Because we're matching a string of length 0, we're effectively inserting into the source string (by replacing ''
with ','
).
Finally, the g
flag says to do this with all matches, not just the first one.
TL;DR:
line('$')
gives us the number of linessubstitute(..., '\d\zs\ze\%(\d\d\d\)\+$', ',', 'g')
adds commas where we want them%{
}
lets us embed arbitrary expressions into statusline
Upvotes: 4