A powerful Neovim plugin to convert between various formats
ascii, bin, dec, hex, oct, b64, sha256, md5, morse, braille, natoB, KB, MB, GB, TB (SI), KiB, MiB, GiB, TiB (IEC)bps, kbps, mbps, gbps, tbpspx, em, rem, pt, pica, mm, cm, m, km, in, ft, yd, mi, barleycorn, bolt, cable, chain, clothyard, cubit, ell, fathom, finger, furlong, hand, league, line, link, megalithicyard, nail, nmi, palm, poppyseed, pyramidinch, rod, shackle, span, thou, angstrom, ls, au, ly, pcmm2, cm2, m2, km2, in2, ft2, yd2, mi2, ha, acreml, cl, dl, l, m3, tsp, tbsp, floz, cup, pint, qt, galdeg, rad, grad, turnns, us, ms, s, min, h, day, week, fortnightmps, kmh, mph, fps, knmg, g, kg, t, oz, lb, stPa, kPa, bar, atm, psi, mmHg, torrJ, kJ, cal, kcal, Wh, kWh, BTUW, kW, MW, GW, hpcelsius, fahrenheit, kelvinHz, kHz, MHz, GHz, THzhex, rgb, hsl, tailwind{
"necrom4/convy.nvim",
cmd = { "Convy", "ConvySeparator" },
opts = {}
}
{
opts = {
-- default configuration
notifications = true,
separator = " ",
window = {
position = "left", -- "left" or "right"
width = 36,
},
formats = {
-- custom formats, see section below
},
},
keys = {
-- example keymaps
{
"<leader>cc",
":Convy<CR>",
desc = "Convert (interactive selection)",
mode = { "n", "v" },
silent = true,
},
{
"<leader>cd",
":Convy auto dec<CR>",
desc = "Convert to decimal",
mode = { "n", "v" },
silent = true,
},
{
"<leader>cs",
":ConvySeparator<CR>",
desc = "Set conversion separator (visual selection)",
mode = { "v" },
silent = true,
},
}
}
:Convy <input_format> <output_format>
:Convy " open interactive selection window
:'<,'>Convy <<input_format> <output_format>> " visual selection as string to work on
lua require("convy").convert("auto", "<output_format>") -- `auto` guesses the format of the input
lua require("convy").convert("<input_format>", "<output_format>", true) -- boolean indicates use of visual selection
lua require("convy").show_selector() -- open interactive selection window
:ConvySeparator ", " " sets the separator to `, `
:ConvySeparator \", \" " sets the separator to `", "`
:ConvySeparator | - | " spaces are not ignored, this sets the separator to `| - |`
:'<,'>ConvySeparator " visual selection as selector
lua require("convy.utils").set_separator(", ") -- sets the separator to `, `
Interactive window keymaps:
Up/Down/j/k/Tab/gg/GEnter/Space/Right/lEsc/BSEnter/Spaceza/iExamples:
|represents the cursor's position,[ ... ]represents a visual selection.
" 72 1|01 108 108 111
:Convy auto ascii
" Converts hovered word from decimal to ascii
" Result: 72 e 108 108 111
" [72 101 108 108 111]
:Convy auto ascii
" Converts selection from decimal to ascii
" Result: Hello
" [Hello]
:Convy
" Opens the split-window selector
" Navigate the tree with `j/k`, open a group with `l`/`right`, search with `/`
" Select the input format (or `auto`) with `<CR>`/`<Space>`
" Then select a compatible output format to apply and close
" Result: 72 101 108 108 111
Add your own units or conversions through setup({ formats = { ... } }).
Each entry either extends a built-in group or defines a new key/kind
group. New formats appear in the selector, tab-completion and :Convy.
length is a linear group, so a new unit is just a suffix and a
factor relative to the group's base (meters):
require("convy").setup({
formats = {
{ extend = "length", formats = {
{ name = "smoot", suffix = "smoot", factor = 1.7018 },
}},
},
})
-- :Convy smoot m -> 1smoot becomes 1.7018m
A custom group converts through a shared base: each format provides
decode(text) -> base and encode(base) -> text. Conversion is
out.encode(in.decode(text)), so N formats only need N function pairs.
This example treats a uint32 as a Unix timestamp (epoch seconds) and converts between the raw integer, hex, and an ISO 8601 UTC date:
require("convy").setup({
formats = {
{
key = "epoch",
label = "Epoch Date",
kind = "custom",
formats = {
{
name = "unix",
decode = function(text) return tonumber(text) end,
encode = function(secs) return tostring(math.floor(secs)) end,
},
{
name = "hex32",
decode = function(text) return tonumber(text, 16) end,
encode = function(secs) return string.format("%08X", secs) end,
},
{
name = "iso",
display = "ISO date",
-- optional: makes `auto` recognise ISO dates
detect = function(text) return text:match("^%d%d%d%d%-%d%d%-%d%dT") ~= nil end,
decode = function(text)
local y, mo, d, h, mi, s = text:match("(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+)")
if not y then return nil end
local utc_offset = os.time(os.date("!*t", 0))
return os.time({
year = tonumber(y), month = tonumber(mo), day = tonumber(d),
hour = tonumber(h), min = tonumber(mi), sec = tonumber(s), isdst = false,
}) - utc_offset
end,
encode = function(secs) return os.date("!%Y-%m-%dT%H:%M:%SZ", secs) end,
},
},
},
},
})
-- :Convy unix iso -> 1700000000 becomes 2023-11-14T22:13:20Z
-- :Convy auto unix -> 2023-11-14T22:13:20Z becomes 1700000000