Introduction
Vim Motions provides comprehensive support for Markdown tables, including structural navigation, cell-level text objects, manipulation commands, and native table editor integration for Live Preview that preserves Vim’s editing power.
Cell navigation
Table navigation
Navigate Markdown table cells without leaving Vim mode.
Link to original
Keybinding Description ]|or]cMove to the next table cell [|or[cMove to the previous table cell ]rMove to same column in next row [rMove to same column in previous row
Table navigation commands allow you to move between cells horizontally and vertically.
- Wrapping: Horizontal navigation (
]|,[|,]c,[c) wraps around to the next or previous row when reaching the end or beginning of a row. - Separator-skip: Vertical navigation (
]r,[r) automatically skips over table separator rows (the|---|lines) to land on the same column in the next or previous content row.
Warning
On many non-US keyboard layouts, the pipe character (
|) requires a modifier key (like AltGr) that may conflict with Vim’s key capture. If]|or[|do not work on your keyboard, use the alternative]cand[cbindings.
Table text objects
Table text objects
Operate on table cells with standard Vim operators.
Link to original
Keybinding Description i|Inside table cell (content between pipes) a|Around table cell (content plus trailing pipe)
Table text objects allow you to operate on the content of individual cells using standard Vim operators:
di|: Delete the content of the current cell.ci|: Change the content of the current cell (delete and enter insert mode).yi|: Yank (copy) the content of the current cell.vi|: Visually select the content of the current cell.
The a| variant includes the surrounding pipes and padding.
Tip
Escaped pipes (
\|) inside table cells are treated as cell content, not boundaries. For example,| foo \| bar | baz |is a two-column table where the first cell containsfoo \| bar.\\|(escaped backslash followed by pipe) is treated as a real boundary.
Table manipulation
Table manipulation
Manage table structure using the
<leader>tprefix.Link to original
Keybinding Description <leader>tmInsert table <leader>toAdd row below <leader>tOAdd row above <leader>tJMove row down <leader>tKMove row up <leader>tddDelete row <leader>tiLAdd column to the right <leader>tiHAdd column to the left <leader>tLMove column right <leader>tHMove column left <leader>tdcDelete column <leader>trRealign table columns
A suite of manipulation commands is available under the <Leader>t prefix for structural changes to the table:
<Leader>to: Add a row below the current row.<Leader>tO: Add a row above the current row.<Leader>tj: Move the current row down.<Leader>tk: Move the current row up.<Leader>tdd: Delete the current row.<Leader>tiL: Add a column to the right.<Leader>tiH: Add a column to the left.<Leader>tL: Move the current column to the right.<Leader>tH: Move the current column to the left.<Leader>tdc: Delete the current column.<Leader>tr: Realign the entire table.
Note
These manipulation commands call Obsidian’s internal table commands. In
nativemode, they work when the cursor is inside the table. Inrawmode, use Source mode or manual Markdown editing.
Table auto-formatting
Vim Motions includes built-in auto-formatting for tables:
- Format-on-exit: When you edit a table in raw Markdown and move the cursor outside the table, the table columns are automatically realigned. No formatting happens while you are typing inside the table, so the cursor stays where you expect it.
- Separator generation: Typing
||on a new line immediately below a table header row generates a correctly formatted separator row matching the header’s column count. - Manual realignment: Use
<Leader>tror:tablerealignto realign at any time.
Table widget in Live Preview
Vim Motions integrates with Obsidian’s native table editor in Live Preview. Two rendering modes are available via set tablewidget:
native(default): Obsidian’s native table widget renders in Live Preview. Cell editors are native Obsidian editors with vim injected viaregisterEditorExtension(). The native editor handles wikilinks, pipe escaping (|→\|), cursor positioning, and<br>conversion automatically.raw: Always shows raw markdown table syntax. No widget rendering. Useful for users who prefer source-style editing in Live Preview. The vim cursor remains fully visible in raw mode — cursor suppression only activates when a native table widget is visible.
In source mode, tables are always rendered as raw markdown regardless of the tablewidget setting. The cursor behaves normally — no cursor suppression occurs.
The tablenav setting (on by default) controls whether the table-nav overlay activates on top of the native editor. With tablenav off, the native table editor still provides full vim cell editing with cross-cell h/j/k/l navigation — just without the overlay UI.
| Configuration | Experience |
|---|---|
native + tablenav (default) | Full table-nav overlay with cell highlighting and structural commands |
native + notablenav | Native table editor with vim cell editing and cross-cell navigation |
raw | Raw markdown tables |
Table-nav mode
When the cursor enters a table in Live Preview with tablenav enabled, a navigation overlay activates. This mode allows you to navigate between cells and perform structural changes without entering the cell editor.
Keybindings
| Key | Action |
|---|---|
h / j / k / l | Navigate between cells |
i / a / c / s / Enter | Start editing the active cell |
Escape | Exit table-nav and return to the main editor |
o | Add a row below |
O | Add a row above |
dd | Delete the current row |
dc | Delete the current column |
J | Move the current row down |
K | Move the current row up |
H | Move the current column to the left |
L | Move the current column to the right |
I | Add a column to the left |
A | Add a column to the right |
= | Realign the table |
Fork-only feature
Table-nav mode requires the bundled vim engine (fork mode). If you are using Obsidian’s built-in vim mode, the plugin falls back to standard cell editing.
Tip
The native mode provides the best vim editing experience for tables. Obsidian’s native table widget handles rendering while vim is injected into cell editors. Structural commands let you add, delete, and move rows and columns without leaving the table. Notes with multiple tables are fully supported — each table is independently navigable.
Viewport scrolling
When navigating through a table taller than the viewport, the editor scrolls to keep the highlighted cell visible. This works even with tables that extend well beyond the screen.
Native mode vim navigation
In native mode, h/j/k/l in normal mode cross cell boundaries automatically:
| Key | In cell | At boundary |
|---|---|---|
l | Move right within cell | Move to next cell (same row) |
h | Move left within cell | Move to previous cell (same row) |
j | Move down within cell | Move to same column in next data row (skip separator) |
k | Move up within cell | Move to same column in previous data row (skip separator) |
j at last row | — | Exit table downward |
k at header | — | Exit table upward |
Operator-pending (dj, yl) and visual mode motions are confined to the current cell — they do not trigger cross-cell navigation.
Vim modality in cell editors
Cell editors are Obsidian’s native editors with vim injected via registerEditorExtension(). Full Vim modality is supported: Normal, Insert, and Visual modes all work within a single table cell.
Tab/Shift-Tabnavigate between cells (handled by the native table editor).- When table-nav is enabled:
Escapein normal mode returns to table-nav.h/j/k/lin normal mode move the cursor within the cell; only when the cursor reaches a cell boundary do they exit to table-nav and navigate to the adjacent cell. This lets you use standard vim cursor movement inside cells after pressing Escape from insert mode. - When table-nav is disabled:
Escapein normal mode stays in the cell;h/j/k/lcross cell boundaries directly via motion overrides. - Register sharing: Vim registers are shared between cell editors and the main document.
- Which-key: Which-key popups work in cell editors.
Cell editors use Live Preview
Cell editors use Obsidian’s Live Preview rendering. Markdown syntax like wikilink brackets (
[[]]) and formatting marks are hidden during editing, but the underlying text is preserved.
Animated cursor in cells
When the animated cursor is enabled, table cell editors use the native vim cursor as the steady-state renderer. The canvas-based animated cursor cannot reliably render above table cell content due to CSS stacking contexts. Cross-cell navigation (
h/j/k/l) snaps the cursor to the destination cell. Within a single cell, the native cursor renders normally.
Multi-line cell content
Pressing
Enterinside a cell editor creates a line break. The native editor automatically handles<br>↔ newline conversion so the table structure stays valid.
Table row text objects
In raw Markdown mode, you can operate on entire table rows using the ir and ar text objects:
ir: Selects the inner row content (everything between the first and last|pipes, excluding the pipes themselves).ar: Selects the around row content (the entire line including the leading and trailing pipes).
These text objects are useful for quickly deleting, changing, or yanking whole rows while editing the Markdown source.
Info
You can configure the table widget mode in Settings → Vim Motions → Table widget in live preview, or via
set tablewidget=native/set tablewidget=rawin your vimrc.
Ex commands
The following Ex commands are available for table manipulation:
| Command | Short | Description |
|---|---|---|
:tablerowbefore | :tablerowb | Add row above |
:tablerowafter | :tablerowa | Add row below |
:tablerowup | :tablerowu | Move row up |
:tablerowdown | :tablerowd | Move row down |
:tablerowdelete | :tablerowde | Delete row |
:tablecolbefore | :tablecolb | Add column left |
:tablecolafter | :tablecola | Add column right |
:tablecolleft | :tablecoll | Move column left |
:tablecolright | :tablecolr | Move column right |
:tablecoldelete | :tablecold | Delete column |
:tablealignleft | :tablealignl | Align column left |
:tablealigncenter | :tablealignc | Align column center |
:tablealignright | :tablealignr | Align column right |
:tableinsert | :tablei | Insert a new table |
:tablerealign | :tablerea | Realign the table |
See known-limitations > Tables for detailed technical limitations.