sheetdown.nvim turns a visually selected local file containing CSV or TSV
data in a Markdown buffer into a Markdown table.
This plugin is still an ongoing effort.
- Turn a visually selected local file containing CSV or TSV data into a Markdown table.
- Detect CSV or TSV data from file content instead of requiring a specific filename extension.
- Use an optional
snacks.nvim-backed UI for searchable column selection and merged table options. - Lifecycle-aware minimize and resume for the UI session.
- Fall back to the original
vim.ui.input()/vim.ui.select()flow when thesnacks.nvimbackend is unavailable. - Insert below the containing paragraph for plain text and inline code paths.
- Replace the entire fenced code block for fenced path selections.
- Select columns by name or index, with input order controlling output order.
- Support
head N,tail N, andstart:endrow modes. - Support left, center, and right alignment.
{
"svm-zhang/sheetdown.nvim",
cmd = { "TableFromFile" },
ft = { "markdown" },
config = function()
require("sheetdown").setup()
end,
}If snacks.nvim is installed, sheetdown.nvim will use the richer
snacks.nvim-backed UI automatically by default.
{
"svm-zhang/sheetdown.nvim",
cmd = { "TableFromFile" },
ft = { "markdown" },
dependencies = {
{
"folke/snacks.nvim",
opts = {
input = { enabled = true },
picker = { enabled = true },
},
},
},
config = function()
require("sheetdown").setup()
end,
}If snacks.nvim is not installed, sheetdown.nvim keeps using the previous
prompt flow through vim.ui.input() and vim.ui.select().
The sheetdown.nvim workflow is:
- Write a local path in Markdown
- Visually select the path
- Run
:TableFromFileor a visual mapping - Choose columns, alignment, and rows
- Insert the generated table
Run the command from visual mode:
:TableFromFileIf you want a visual mapping, use the normal visual command-line form:
:xnoremap <leader>mt :<C-U>TableFromFile<CR>Do not use a visual <Cmd>... mapping here. This command depends on the
current visual selection marks.
When snacks.nvim is available, sheetdown.nvim opens a single picker-based
screen that keeps search, column selection, current options, and key hints
visible together:
- searchable column selection
- visible alignment choices
- visible row-render choices
- selected-column summary
Columns start unchecked in the snacks.nvim-backed UI. The order you toggle them on
becomes the output column order.
In this snacks.nvim-backed UI:
- the search field opens focused with a placeholder.
- type immediately to filter columns.
- repeated
:TableFromFilehides the current session. - running
:TableFromFileagain restores the hidden session for the same path. <C-j>/<Down>moves from the search input into the list.<i>returns from the list to the search input.<Tab>toggles the current column.<c>selects all columns.<u>clears all columns.<a>cycles alignment.<d>sets eitherNorstart:end.<m>cycleshead/tailwhen the current row detail is numeric.<r>resets the picker state back to configured defaults.<CR>confirms.<Esc>closes the UI and discards the current session.
Minimize-and-resume only applies to the snacks.nvim backend. The fallback
vim.ui.* flow keeps the earlier one-shot prompt behavior.
Without snacks.nvim, the first prompt controls both column inclusion and
output order.
Examples:
name,email,id
1,3,2
Rules:
- Tokens are comma-separated
- Each token may be a header name or a 1-based numeric index
- Token order becomes output order
- An empty input keeps all columns in source order
Supported row selection modes:
head Ntail Nstart:end
Before:
Quarterly results:
`./results.csv`After:
Quarterly results:
`./results.csv`
| quarter | revenue | margin |
| :------ | :------ | :----- |
| Q1 | 120 | 34% |
| Q2 | 128 | 36% |The config surface is intentionally small.
require("sheetdown").setup({
default_alignment = "left",
default_rows = {
mode = "head",
count = 5,
},
ui = {
backend = "auto",
},
notifications = {
enabled = true,
},
})Supported options:
default_alignment:"left","center", or"right"default_rows.mode:"head","tail", or"range"default_rows.count: default row count forheadandtailui.backend:"auto": usesnacks.nvimwhen available, otherwise fall back tovim.ui.*"snacks": require thesnacks.nvimbackend"fallback": force the originalvim.ui.*prompt flow
notifications.enabled:true: show informational notices such as hide/resume messagesfalse: suppress informational notices while still showing errors