shichishima892 downloadsFull cursor navigation for Markdown — whether in tables or out, either on macOS or Windows, be it Emacs keybindings or Vim mode.
Emacs keybindings (Ctrl+P/N/B/F/A/E), Kill & Yank, and Vim key bindings — all finally working inside Obsidian's Live Preview tables, for macOS and Windows.
Obsidian's Live Preview breaks cursor behavior inside Markdown tables. This plugin fixes cursor navigation around tables — whether you use Emacs keybindings (macOS-style) or Obsidian's built-in Vim mode.
On macOS, cursor shortcuts — Ctrl+P (up), Ctrl+N (down), Ctrl+B/F (left/right), Ctrl+A/E (home/end), and Page Down/Up — work natively in Obsidian. This plugin restores them inside tables too, giving you seamless navigation just as physical cursor keys would — and Shift+Ctrl+P/N/B/F/A/E extend the selection the same way.
Windows users can enable the full set of macOS-style cursor shortcuts throughout Obsidian. The Quick setup assistant assigns all recommended hotkeys in three clicks.
Kill & Yank (Ctrl+K / Ctrl+Y) and Kill Region (Ctrl+W) bring the full Emacs editing workflow to Obsidian — and all three work seamlessly inside table cells, automatically handling newlines and pipe characters. Recenter-top-bottom (Ctrl+L) rounds out the workflow.
If you use Obsidian's built-in Vim mode, this plugin fixes a set of well-known Live Preview table gaps: h/l/j/k/w/b/e/gg/G/gj/gk now work correctly inside table cells, instead of miscounting characters, refusing to cross rows, or landing in the wrong place. See Vim support (experimental) below.
No hotkeys are assigned by default.
Quick setup (recommended): Open Settings → Universal Cursor Hotkeys and click Apply recommended for each of the three command groups — Cursor movement, Editing, and Other hotkeys. Three clicks and you're done.
Manual setup: Go to Settings → Hotkeys, search for "Universal Cursor Hotkeys", and assign keys individually.
For detailed behavior of each command, see Command Details below.
| Command Name | Recommended Hotkey |
Function Summary | Key Repeat |
|---|---|---|---|
| UP | Ctrl + P | Smart UP: Text/Cell movement, Table & callout entry (from below) & exit (from top). | ✓ |
| DOWN | Ctrl + N | Smart DOWN: Text/Cell movement, Table & callout entry (from above) & exit (from bottom). | ✓ |
| LEFT | Ctrl + B | Smart LEFT: Move by character or jump to the previous cell. | ✓ |
| RIGHT | Ctrl + F | Smart RIGHT: Move by character or jump to the next cell. | ✓ |
| HOME | Ctrl + A | Smart HOME: Moves to the visual line edge, content start, or line start in steps; jumps to the previous cell inside a table. | ✓ |
| END | Ctrl + E | Smart END: Moves to the visual line edge or line end in steps; jumps to the next cell inside a table. | ✓ |
| Kill line | Ctrl + K | Kill from cursor to line end. Consecutive kills accumulate in the kill cache and clipboard. | ✓ |
| Kill region | Ctrl + W | Cut the selected region to the kill cache. Table-aware: single-cell only; no-op for multi-row or cross-cell selections. | — |
| Yank | Ctrl + Y | Paste from the OS clipboard. Table-aware: converts newlines and pipes automatically. | ✓ |
| Delete char | Ctrl + D | Forward-delete one character. Stops at cell boundary; joins sub-lines at <br> in Live Preview. |
✓ |
| Recenter-top-bottom | Ctrl + L | Cycle the view so the cursor appears at the center, top, or bottom of the screen on successive presses. Resets on any other action. | — |
| Recenter | (None) | Scroll the view so the cursor line is centered on screen. | — |
| Page down | (None) | Scroll down one page; the cursor stays at the same screen position. Bare PageDown can be set in the plugin's Settings. | ✓ |
| Page up | (None) | Scroll up one page; the cursor stays at the same screen position. Bare PageUp can be set in the plugin's Settings. | ✓ |
| Select all | (None) | Windows replacement for Select all when Ctrl+A is reassigned to HOME. | — |
Open Settings → Universal Cursor Hotkeys to assign hotkeys without leaving the settings screen.
Apply recommended: Each command group has an Apply recommended button that assigns all recommended hotkeys at once.
Live status: Each row shows the current state of its hotkey:
| Status | Meaning |
|---|---|
| ✅Set | Recommended hotkey is assigned. |
| 🟢Custom | A non-recommended hotkey is assigned, with no conflict. |
| 🔵Available | Recommended hotkey is free to assign. |
| 🔵Used | Recommended hotkey is taken; applying it will not displace any command. |
| 🟡Used | Recommended hotkey is taken; applying it will displace one command. |
| 🔴Conflict | A conflict exists: a hotkey is currently assigned to more than one command. |
Displaced commands: Lists commands that would lose their only hotkey when recommended keys are applied. Each entry has an Assign button to reassign it via the hotkeys panel, and a Restore button to undo the displacement and return the key to its original command.
Special key assignments: Set bare Home, End, Page Down, and Page Up keys — Obsidian's hotkeys panel does not support modifier-free keys.
| Setting | Default | Description |
|---|---|---|
| Visual line movement | ON | ON: the first HOME / END moves to the visual line edge. OFF: moves directly to the logical line start / end. |
| Smart home (standard) | ON | ON: HOME skips leading Markdown syntax (lists, ordered lists, checkboxes, indents, blockquotes) to reach content start — Windows Home / macOS Cmd+← style. OFF: HOME moves directly to the start of the line — macOS / Emacs Ctrl+A style. |
| Smart home (advanced) | ON | ON: also skips past headings (# ), footnotes ([^1]: ), and callout type markers ([!type]). Requires Smart home (standard) to be ON. |
| Smart join | OFF | ON: Kill Line join lands at the next line's content start, removing blockquote markers, list markers, and indentation. Pairs with Smart home (advanced) for headings and footnotes. Requires Smart home (standard) to be ON. OFF: joins the next line as-is. |
| Cross-row navigation | ON | ON: LEFT / HOME at the first cell and RIGHT / END at the last cell wrap to the adjacent row. OFF: stops at the boundary. |
No Word-Level Navigation: Movement by word (macOS: Option+Left/Right; Windows: Ctrl+Left/Right; Emacs: Meta-F/B) is currently not supported.
Range selection stops at table cell boundaries: Shift+Ctrl+P/N/B/F/A/E extend the selection normally within plain text and within a single table cell. At a cell boundary, they neither cross into the adjacent cell (unlike plain Ctrl+B/F) nor extend the selection across cells (unlike Shift+Arrow keys). Use Shift+Arrow keys for cross-cell selection.
Brief scroll when entering a tall wrapped cell in Live Preview (UP): When pressing UP into a cell whose wrapped content exceeds the screen height, the view momentarily scrolls to the cell start before jumping to the bottom visual line. This is an inherent side effect of the two-step navigation used to locate the bottom visual line within Obsidian's Live Preview table widget.
Multi-cell cut, copy, and paste are not supported (Kill Line / Kill Region / Yank): Kill Line, Kill Region, and Yank are text-level operations; inside a table, they work on the text content within individual cells. Selecting multiple cells and attempting to cut or paste with these commands is not supported. For multi-cell cut, copy, and paste operations, use the right-click context menu instead.
Source Mode table detection is heuristic: In Source Mode, table rows are identified by a simple string check (line starts and ends with |). Unlike Live Preview mode, which uses the syntax tree, this approach may produce unexpected behavior on lines that coincidentally match the pattern but are not part of a Markdown table.
Shortcut Conflicts
Note: (*) indicates behaviors specific to Live Preview mode.
![[...]], ), applies when the syntax starts at the beginning of the line. For thematic breaks (---, ***, ___), the cursor lands at the beginning of the break line.> [!type]...). For images and embeds (![[...]], ), applies when the syntax starts at the beginning of the line. For thematic breaks (---, ***, ___), the cursor lands at the beginning of the break line.- , * , + ), checkboxes (- [ ] ), ordered lists (1. or 1) ), and blockquotes (>). With Smart home (advanced) ON, also skips heading markers (# ), footnote indicators ([^1]: ), and callout type markers ([!type]). (→ Smart home settings)<br>): does not move further.<br>): does not move further.<br> tag: Jumps to the right edge of the next in-cell line, skipping the <br> tag.| (ch=0): Snaps to the content start of the first cell.<br> or |).<br>): Deletes the <br> tag, joining the current in-cell line with the next.<br> joins).<br> → \n, \| → |).<br> (Live Preview): The <br> separator is removed along with the selected text, joining the surrounding sub-lines.\n) are converted to <br> and pipe characters (|) are escaped to \| before insertion to prevent breaking the table structure.<br>): Deletes the <br> tag, joining the current sub-line with the next.|).If Obsidian's built-in Vim key bindings are enabled, this plugin fixes several native gaps inside Live Preview table cells by making the affected Vim motions table-aware — the same way Ctrl+P/N/B/F/A/E already are. Off by default; enable individual items under Settings → Universal Cursor Hotkeys → Vim support. If you're using Vim mode, you likely won't need the Quick setup assistant above — that manages this plugin's Emacs-style Ctrl+P/N/B/F/A/E hotkeys instead.
Apply all: Turns on every item below that can currently be turned on in one click — skips ^/I or J if their own Smart home (standard) / Smart join prerequisite is currently off.
| Keys | Fixes |
|---|---|
h l x |
Multi-byte character miscounting and incorrect cell-jumping at line boundaries; x at cell boundaries. |
j k |
Row-boundary crossing (matching Ctrl+N/P), preserving column position throughout. |
w b e (and W/B/E/ge/gE) |
Cell/row-boundary crossing, matching vim's own document-wide word-motion behavior. ASCII words only — see Limitations. |
gg G |
Reaches the note's actual first/last line, including exiting a table cell entirely. |
gj gk |
Visual-line movement inside table cells (matching Ctrl+N/P), tracking the visual column across wrapped lines. |
$ |
Sticky end-of-line goal column when followed by j/k or gj/gk, matching real vim's own behavior. Requires j/k or gj/gk to be enabled. D/C share the same underlying vim.js motion, so this toggle affects them too, but their own behavior is identical either way. |
^ I |
Reuses Smart home to skip Markdown syntax, not just whitespace. Requires Smart home (standard). |
J |
Reuses Smart join to strip blockquote/list markers and indentation on join. Requires Smart join. |
Turning an item off restarts Obsidian to fully restore vim's native behavior (a banner prompts this when needed).
g, j, or k) can occasionally be misread — e.g. a single g behaving like gg, or j/k moving two lines instead of one. This is a known, upstream issue in Obsidian's underlying codemirror-vim engine (issue #178) and reproduces identically in vanilla Obsidian Vim mode with this plugin fully disabled. Workaround: switch to an ASCII/alphanumeric input source before using Vim motions.w/b/e cross only one cell/row boundary per count: A count like 5w isn't fully precise once it needs to cross more than one cell or row boundary.gj/gk do not support count prefixes across a crossing: A count like 5gj correctly steps through multiple visual lines within a single cell, but once the count needs to cross a row boundary or enter/exit a table, it stops consuming the count after that first crossing.$ doesn't cross table rows: 3$ stays within the current table cell rather than reaching the end of a line further down, the way real vim would outside a table.w/b/e and related keys) does not segment CJK text: These reuse Vim's own native word classification, which does not distinguish Japanese word boundaries — a run of Hiragana/Katakana/Kanji is treated as one long "word" rather than split at natural boundaries. ASCII text is unaffected.