Shows line/word/char count for current visual selection as virtual text.
- Toggleable with commands or lua API.
- Customizable (fairly) with presets.
- Somewhat flexible in terms of what to count.
-- lazy.nvim
"tzhouhc/virt-counter.nvim"Just including the plugin in this bare minimal way would work, further configuration is optional.
-- Default configuration
opts = {
-- Use existing rendering presets. You can still override these options.
-- options: "default", "pill", "diamond", "forward_angly", "backward_angly"
preset = nil,
-- What highlight group to use for the virtual text. For "button" style
-- using powerline symbols, recommend using HL groups that have colored bg.
highlight_group = "Comment",
-- Location of the virtual text. Can take legal values of `virt_text_pos`.
-- (Note: I don't think `overlay` would work all that well, so you should
-- probably stick to `eol` or `right_align`)
pos = "eol",
-- Minimal amount of time to pass in milli-secs before rerunning.
debounce_ms = 50,
-- Whether to count using bytes or actual characters (e.g. for CJK).
count_bytes = false,
-- Whether to count newline characters or not. Due to neovim native counting
-- mechanisms, probably does not work correctly in blockwise selection.
count_newlines = false,
-- Whether to count white space characters or not.
count_whitespace = true,
-- Whether to create user commands to toggle the above counting settings.
-- Will be named "VirtCounterToggleCountWhitespaces",
-- "VirtCounterToggleCountNewlines", and "VirtCounterToggleCountBytes".
create_toggle_cmds = true,
-- Whether toggling produces a notification via `vim.notify`.
silent_toggle = false,
-- additional spaces to put before the virtual text.
spacing = 0,
-- Configuration for creation a 'pill/button' like virtual text.
-- left: the left edge string for the button
-- right: the right edge string for the button
-- edge_highlight_group: the highlight group for the edges of the button.
-- if not provided, creates a simple reversed hl group using the main
-- highlight_group's fg and "Normal"'s bg.
-- (For best effects, this should be one with colored
-- bg and dark fg.)
button = nil,
-- Custom format function for the count, receives the number of lines, words
-- and chars as 3 integers params, and expects a string (or nil) in return.
-- Alternatively, provide a string with 3 `%d`s, e.g. "%d/%d/%d", for
-- lines, words, chars respectively.
format = function(lines, words, chars)
return string.format("%d lines, %d words, %d chars", lines, words, chars)
end,
}Note
If count_newlines then count_whitespace is automatically true; if
count_whitespace is false then count_newlines is automatically false.
However you can have count_whitespace but not count_newlines.
Sample setup with customized formatting and "pill"-like visuals using powerline symbols:
return {
"tzhouhc/virt-counter.nvim",
opts = {
count_newlines = true,
preset = "pill",
}
},which is equivalent to:
return {
"tzhouhc/virt-counter.nvim",
opts = {
count_newlines = true,
highlight_group = "CurSearch",
spacing = 4,
button = {
left = "\u{E0B6}",
right = "\u{E0B4}",
},
format = function(l, w, c)
return " " .. l .. " " .. w .. " " .. c
end,
}
},In addition to the standard setup method, you can also directly invoke the
lua API with require("virt-counter").refresh(), which will clear the virtual
text if outside of visual mode, or update it without requiring the events.
local vc = require("virt-counter")
-- API to toggle specific options on the fly; takes one parameter for whether
-- to send a notification for current status.
vc.toggle_count_newlines(true)
vc.toggle_count_bytes(true)
vc.toggle_count_whitespace(true)
-- overall plugin status control
vc.enable()
vc.disable()
vc.toggle()Known caveat: does not immediately update selection count when selection updates but the cursor does not move -- Neovim does not provide an event for visual change.
I suppose you can just wobble your cursor a bit...?
My personal solution:
{
"tzhouhc/virt-counter.nvim",
cond = not not vim.g.visual_wordcount,
config = function()
local vt = require("virt-counter")
vt.setup({
...
})
-- make space force a virt-counter update in visual mode.
vim.keymap.set("v", "<space>", vt.refresh, {})
end
},- Customizable counting method?
- ???
local presets = {
default = {
highlight_group = "Comment",
format = function(lines, words, chars)
return string.format("%d lines, %d words, %d chars", lines, words, chars)
end,
},
diamond = {
highlight_group = "CurSearch",
spacing = 4,
button = {
left = "\u{E0B2}",
right = "\u{E0B0}",
},
format = function(l, w, c)
return " " .. l .. " " .. w .. " " .. c .. " "
end,
},
forward_angly = {
highlight_group = "CurSearch",
spacing = 4,
button = {
left = "\u{E0BA}",
right = "\u{E0BC}",
},
format = function(l, w, c)
return " " .. l .. " \u{E0BB} " .. w .. " \u{E0BB} " .. c .. " "
end,
},
backward_angly = {
highlight_group = "CurSearch",
spacing = 4,
button = {
left = "\u{E0BE}",
right = "\u{E08}",
},
format = function(l, w, c)
return " " .. l .. " \u{E0B9} " .. w .. " \u{E0B9} " .. c .. " "
end,
},
pill = {
highlight_group = "CurSearch",
spacing = 4,
button = {
left = "\u{E0B6}",
right = "\u{E0B4}",
},
format = function(l, w, c)
return " " .. l .. " " .. w .. " " .. c
end,
},
}