Markdown & CSV table editor for Neovim — structural editing, pure text, always valid.
Supports Markdown and CSV out of the box, and can be extended to other formats via custom parsers.

Edit Markdown tables structurally.
Raw → aligned → edit → back to raw (lossless).

Raw → aligned → edit → back to raw (lossless).
Markdown and CSV are text — but they represent structure.
Tirenvi lets you edit tabular data structurally, while staying in Vim’s native editing model.
You edit text. Tirenvi preserves structure.
At the center is: TIR — Tabular Intermediate Representation
flat (gfm markdown, csv, tsv, ...)
↓ external parser
TIR (intermediate representation)
↓ tirenvi
tir-buf (structured buffer view)
Editing happens in tir-buf format.
On save:
tir-buf → TIR → original flat format
Key principles:
Edit tables directly in Vim while preserving a structured internal model.
Tirenvi maintains a structured internal table model while allowing temporary buffer inconsistencies.
In deferred repair mode:
:Tir repair synchronizes the buffer with the internal modelIn immediate repair mode:
Tirenvi respects Vim’s undo tree.
Historical undo states are not rewritten, even if they contain temporary structural inconsistencies.
{
"kibi2/tirenvi.nvim",
dependencies = {
"tpope/vim-repeat", -- optional: enables '.' repeat for column width operations
},
config = function()
require("tirenvi").setup {}
end,
}
Plug 'kibi2/tirenvi.nvim'
" Optional: enables '.' repeat for column width operations
Plug 'tpope/vim-repeat'
Install parsers:
pip install tir-gfm-lite
pip install tir-csv
pip install tir-pukiwiki
Automatically activates based on filetype (via parser_map):
csvtsvmarkdownpukiwikiCustom parser mapping:
require("tirenvi").setup({
parser_map = {
csv = { executable = "tir-csv", required_version = "0.1.4" },
tsv = { executable = "tir-csv", options = { "--delimiter", "\t" }, required_version = "0.1.4" },
markdown = { executable = "tir-gfm-lite", allow_plain = true, required_version = "0.1.6" },
pukiwiki = { executable = "tir-pukiwiki", allow_plain = true, required_version = "0.1.1" },
}
})
| Command | Description |
|---|---|
:Tir repair |
Repair and reformat dirty tables |
:Tir repair enable |
Enable automatic structural repair |
:Tir repair disable |
Disable automatic structural repair |
:Tir repair toggle |
Toggle automatic structural repair |
:Tir toggle |
Switch raw ↔ structured table view |
:Tir width[=+-][count] |
Adjust column width by count (=: set, +/-: increment/decrement) |
:Tir redraw |
Deprecated. Will be removed in v0.5.Use :Tir repair instead |
All native Vim editing works.
dd, yy, p, D, o, R, J, and moreNo special editing mode.
Columns are structural units.
To modify a column:
vil, val, v3al)d, p, etc.)require("tirenvi").setup({
textobj = {
column = "l",
},
})
Operations that would break structure are automatically corrected.
Column width operations support . repeat when
vim-repeat is installed.
Fast horizontal navigation across cells.
vim.keymap.set({ 'n', 'o', 'x' }, '<leader>tf', require('tirenvi').motion.f, { expr = true })
vim.keymap.set({ 'n', 'o', 'x' }, '<leader>tF', require('tirenvi').motion.F, { expr = true })
vim.keymap.set({ 'n', 'o', 'x' }, '<leader>tt', require('tirenvi').motion.t, { expr = true })
vim.keymap.set({ 'n', 'o', 'x' }, '<leader>tT', require('tirenvi').motion.T, { expr = true })
They behave like Vim’s f/F/t/T,
but target table separators.
; and , continue to repeat as usual.
Note: There are two types of pipes (continuation and non-continuation), so motions may behave differently across lines.
It is a structured text editor layer.
| Feature | Tirenvi | csv.vim | Spreadsheet tools |
|---|---|---|---|
| Native Vim editing | ✅ | ⚠️ | ❌ |
| Always structurally valid | ✅ | ❌ | ⚠️ |
| No file format change | ✅ | ❌ | ❌ |
| No custom buffer type | ✅ | ❌ | ❌ |
| Toggle raw view | ✅ | ❌ | ❌ |
| Markdown | ✅ | ❌ | ❌ |
| Automatic wrapping | ✅ | ❌ | ⚠️ |
| Grid-aware join | ✅ | ❌ | ❌ |
Tirenvi prioritizes structural safety with Vim purity.
The architecture centers around:
Large changes should respect this separation.
Please open an issue before major design proposals.
MIT License.