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.

KeybindingDescription
]| 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
Link to original

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 ]c and [c bindings.

Table text objects

Table text objects

Operate on table cells with standard Vim operators.

KeybindingDescription
i|Inside table cell (content between pipes)
a|Around table cell (content plus trailing pipe)
Link to original

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 contains foo \| bar. \\| (escaped backslash followed by pipe) is treated as a real boundary.

Table manipulation

Table manipulation

Manage table structure using the <leader>t prefix.

KeybindingDescription
<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
Link to original

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 native mode, they work when the cursor is inside the table. In raw mode, 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>tr or :tablerealign to 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 via registerEditorExtension(). 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.

ConfigurationExperience
native + tablenav (default)Full table-nav overlay with cell highlighting and structural commands
native + notablenavNative table editor with vim cell editing and cross-cell navigation
rawRaw 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

KeyAction
h / j / k / lNavigate between cells
i / a / c / s / EnterStart editing the active cell
EscapeExit table-nav and return to the main editor
oAdd a row below
OAdd a row above
ddDelete the current row
dcDelete the current column
JMove the current row down
KMove the current row up
HMove the current column to the left
LMove the current column to the right
IAdd a column to the left
AAdd 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:

KeyIn cellAt boundary
lMove right within cellMove to next cell (same row)
hMove left within cellMove to previous cell (same row)
jMove down within cellMove to same column in next data row (skip separator)
kMove up within cellMove to same column in previous data row (skip separator)
j at last rowExit table downward
k at headerExit 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-Tab navigate between cells (handled by the native table editor).
  • When table-nav is enabled: Escape in normal mode returns to table-nav. h/j/k/l in 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: Escape in normal mode stays in the cell; h/j/k/l cross 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 Enter inside 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=raw in your vimrc.

Ex commands

The following Ex commands are available for table manipulation:

CommandShortDescription
:tablerowbefore:tablerowbAdd row above
:tablerowafter:tablerowaAdd row below
:tablerowup:tablerowuMove row up
:tablerowdown:tablerowdMove row down
:tablerowdelete:tablerowdeDelete row
:tablecolbefore:tablecolbAdd column left
:tablecolafter:tablecolaAdd column right
:tablecolleft:tablecollMove column left
:tablecolright:tablecolrMove column right
:tablecoldelete:tablecoldDelete column
:tablealignleft:tablealignlAlign column left
:tablealigncenter:tablealigncAlign column center
:tablealignright:tablealignrAlign column right
:tableinsert:tableiInsert a new table
:tablerealign:tablereaRealign the table

See known-limitations > Tables for detailed technical limitations.