Skip to content

Instantly share code, notes, and snippets.

@pedrominicz
Last active February 24, 2026 05:30
Show Gist options
  • Select an option

  • Save pedrominicz/46ac70da5f597e3f3ce130c467128cfa to your computer and use it in GitHub Desktop.

Select an option

Save pedrominicz/46ac70da5f597e3f3ce130c467128cfa to your computer and use it in GitHub Desktop.
-- $ stylua csv-align.lua
-- $ luacheck csv-align.lua
-- $ cp csv-align.lua ~/.config/nvim/plugin/.
local M = {}
local ns = vim.api.nvim_create_namespace("csv-align")
function M.align()
local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
local column_len = {}
-- Calculate maximum width for each CSV column.
for _, line in ipairs(lines) do
local fields = vim.split(line, ",", { plain = true })
for i, field in ipairs(fields) do
-- Add one for the comma.
local len = vim.fn.strdisplaywidth(field) + 1
column_len[i] = math.max(column_len[i] or 0, len)
end
end
-- Clear existing virtual text.
vim.api.nvim_buf_clear_namespace(0, ns, 0, -1)
-- Build virtual text with padding for each line.
for line_number, line in ipairs(lines) do
local fields = vim.split(line, ",", { plain = true })
local col = 0
for i, field in ipairs(fields) do
col = col + #field + 1
if col > #line then
break
end
local len = vim.fn.strdisplaywidth(field) + 1
local padding_len = column_len[i] - len
if padding_len > 0 then
vim.api.nvim_buf_set_extmark(0, ns, line_number - 1, col, {
virt_text = { { string.rep(" ", padding_len), "Comment" } },
virt_text_pos = "inline",
})
end
end
end
end
vim.api.nvim_create_autocmd({ "BufReadPost", "BufWritePost", "TextChanged", "InsertLeave" }, {
pattern = { "*.csv" },
callback = M.align,
})
return M
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment