Universal Cursor Hotkeys — Emacs & Vim navigation for Markdown tables

Disclaimer

Is this project open source? Yes
Is this project completely free? Yes
Is this project vibe-coded beyond the author’s ability to comprehend how it works? No
Community Directory: Link


Hi everyone,
I’d like to share a plugin I’ve been working on: Universal Cursor Hotkeys.

On macOS, Ctrl+P/N move the cursor naturally up and down everywhere in Obsidian — except at Markdown tables in Live Preview. Approaching from outside, the cursor skips right past the table. Inside a cell, Ctrl+P/N can’t move between rows.

Universal Cursor Hotkeys fixes this — and brings the full set: Ctrl+P/N/B/F for navigation, Ctrl+A/E for Smart Home/End, and Ctrl+K/Y for Kill & Yank, all working seamlessly inside tables. The same shortcuts work universally — inside tables and out, on macOS and Windows alike. Windows users can enable macOS-style (Emacs-style) cursor movement with the same keys.


Enter / Exit Tables
Works with Ctrl+P/N/B/F — no mode switching needed.


Kill & Yank
On paste, pipe characters and newlines are converted automatically — table structure stays intact.


Smart home/end
All steps work inside table cells as well.


Commands

Key Key Repeat Function
Ctrl+P / N Up / Down — enters and exits tables
Ctrl+B / F Left / Right — moves between cells, wraps across rows
Ctrl+A / E Smart Home / End — visual-line-aware, works in tables
Ctrl+K Kill line — table-safe; consecutive kills accumulate
Ctrl+Y Yank — paste anywhere
Ctrl+W Kill region — cut selection
Ctrl+D Delete forward — joins sub-lines at <br>
Ctrl+L Recenter view

No hotkeys are assigned by default — set them in Settings → Hotkeys.

Smart Join (off by default): when joining lines with Ctrl+K, automatically strips blockquote markers, list markers, and indentation from the next line.


Install

Visit the Community Directory: Universal Cursor Hotkeys, click Add to Obsidian, then click Install in Obsidian.

Feedback and questions are welcome — feel free to reply in this thread!

0.6.0 is out!

comparison

What’s new:

  • Ctrl+P/N now enter callout blocks, images, embeds, and thematic breaks — previously these lines were skipped entirely in Live Preview
  • HOME/END are now visual-line-aware inside soft-wrapped table cells — with Visual Line Movement ON, the first press moves to the visual line edge before jumping to the adjacent cell
  • Emacs-style Recenter top-bottom (Ctrl+L): cycles the view to the center, top, or bottom of the screen on successive presses

Full release notes: GitHub Releases

0.6.1 is out!

  • Page Down / Page Up is now significantly faster on notes without tables, callouts, or embeds — it now uses the same mechanism as the physical Page Up/Down keys. Pairs well with the recenter-top-bottom command (Ctrl+L, added in v0.6.0) to reposition the view after scrolling.
  • Verified compatible with Obsidian 1.13.

:tada: 0.7.0 — Settings screen redesign

The Settings screen has been significantly redesigned to make hotkey setup much easier.

Click Apply recommended for each of the three hotkey groups:

  1. Cursor movement
  2. Editing
  3. Other hotkeys

Three clicks and you’re fully set up.

Each row also shows the current assignment status of its recommended hotkey, so you can see exactly what’s set, what’s available, and where conflicts exist before applying anything.

Also new in 0.7.0: A Special key assignments section lets you assign bare Home, End, Page Down, and Page Up keys directly — Obsidian’s hotkeys panel doesn’t support modifier-free keys, so this was previously not possible through normal settings.

:link: Universal Cursor Hotkeys

If it’s been useful, a :star: on GitHub helps others find it — thank you!

:tada: 0.8.0: Vim support (experimental)

If you use Obsidian’s built-in Vim key bindings, this one’s for you.

Vim’s h/l/j/k/w/b/e/gg/G/gj/gk have long had known gaps inside Live Preview tables — miscounting multi-byte characters, refusing to cross rows, landing on the wrong cell, or simply doing nothing. This release fixes them, the same way Ctrl+P/N/B/F/A/E already work in tables.

hjkl, word motion, and gg/G — all working correctly inside the same table.

No special table-navigation commands to learn — your existing hjkl (and friends) just works correctly inside cells, the same as everywhere else in the document.

What’s new:

  • h l x — fixes multi-byte character miscounting and incorrect cell-jumping at line boundaries
  • j k — crosses row boundaries (matching Ctrl+N/P), preserving column position
  • w b e (and W/B/E/ge/gE) — crosses cell/row boundaries the same way word motions already cross line boundaries in plain text
  • gg G — always reaches the note’s actual first/last line, even from inside a table
  • gj gk — fixes inconsistent/no-op display-line movement inside cells
  • $ — sticky end-of-line goal column when followed by j/k or gj/gk
  • ^ I — reuses this plugin’s existing Smart home to reach the real content start
  • J — reuses this plugin’s existing Smart join

Each item is its own toggle under Settings → Universal Cursor Hotkeys → Vim support, off by default.

Being upfront about where this stands: it targets Obsidian’s standard/built-in Vim mode specifically.

Why experimental: it’s newer and less battle-tested than the Emacs-style side of this plugin, and it sits on top of Obsidian’s own Vim engine (codemirror-vim) — which has its own upstream quirks outside this plugin’s control (see below). The core motions have held up well in my own testing, but I’d rather ship early and adjust based on real usage than sit on it longer.

One known limitation worth flagging here — count prefixes don’t fully carry across a gj/gk crossing yet. A few more (all minor) are listed in the README.

One more thing worth knowing regardless of whether you actually type in CJK languages: if you have a CJK (Japanese/Chinese/Korean) input source active while using Vim motions, key handling can get confused — a single g behaving like gg, or j/k moving two lines at once. This traces to an upstream codemirror-vim issue (#178), not something this plugin caused — but worth knowing if that applies to you.

:link: Universal Cursor Hotkeys
:book: GitHub - README

Feedback on what to fix next is very welcome — this is the first cut, not the final word.

1 Like

:tada: 0.9.0: Rounding out the Emacs-side command set

Word commands: Word right / Word left (forward-word / backward-word) and Kill word left / Kill word right (kill-word variants that plug into the existing kill chain) are new.

CJK word segmentation engine: These new commands above are built on a new word-boundary engine that uses real morphological word boundaries instead of just whitespace/punctuation splitting, so Chinese, Japanese, and Korean text is segmented correctly instead of being treated as one long word.

Transpose chars: Also new, and safely handles emoji and other multi-byte characters — no corruption on surrogate pairs.

Other new commands: Uppercase word / Lowercase word / Capitalize word, Copy region, Cursor TOP / Cursor BOTTOM, and Undo / Redo.

Case conversion’s selection-handling mirrors modern Emacs’s own upcase-dwim/downcase-dwim/capitalize-dwim (the actual M-u/M-l/M-c defaults in current Emacs) — unlike the classic upcase-word/downcase-word/capitalize-word, which never look at the region at all.

Undo/Redo were added because Obsidian’s own Ctrl+Z / Ctrl+Shift+Z already work, but aren’t backed by an assignable Command — so they can’t be rebound via Settings → Hotkeys. These thin wrappers make them assignable like everything else in this plugin.

Availability

Hotkeys for all of the above aren’t assigned by default — head to Settings → Universal Cursor Hotkeys to set them up.

Vim support update

The same word-boundary engine also fixes Vim’s own w/b/e for CJK text. And gg/G now apply Smart Home inside table cells too, not just in plain text. Both apply automatically — no setup needed.

Let me know if you run into any issues.

:tada: 0.10.0: Vim leader-key table editing

Universal Cursor Hotkeys makes Obsidian’s built-in Vim mode (and macOS-style Emacs keybindings) actually work inside Live Preview tables. This release adds a leader-key layer for Vim mode — table structure edits and cell navigation, on top of the motion fixes from earlier releases.

Table structure<leader> t + a key, 16 commands wrapping Obsidian’s own built-in table commands (insert/move/delete/duplicate row or column, column alignment, insert table):

  • dd still deletes a line in the cell text; <leader>tdd deletes the whole table row.
  • o still opens a new line in the cell text; <leader>to inserts a new table row below.

Bare dd/o (and the rest of Vim’s own keys) are untouched on purpose — this is an addition, not an override.

Table navigation<leader>th/tj/tk/tl jump straight to the adjacent cell, <leader>tx/tX exit the table. Original logic, not a wrapper around anything native.

Also in this release: CJK-aware (Chinese/Japanese) double-click word selection, and u/Ctrl-R now correctly undo/redo table-structure changes from inside a table cell.

With this, Vim mode now covers tables pretty much end-to-end — the existing motions (h/j/k/l/w/b/e/gg/G) move around them correctly, and the leader-key layer handles structure edits and cell navigation on top.

Full write-up: GitHub - Command Reference

:tada: 0.11.0: :keyboard: Key Upgrades — table-aware & CJK-aware navigation for everyone

Universal Cursor Hotkeys makes Obsidian’s built-in Vim mode (and macOS-style Emacs keybindings) actually work inside Live Preview tables. This release adds Key Upgrades — a new “For everyone” layer where your everyday arrow keys, Home/End, and more now get the same table-aware and CJK-aware fixes Vim mode and Emacs-style keybindings already had, no Vim mode or Emacs-style keybindings required.

Key Upgrades — arrow keys, Home/End, Page Up/Down, and Word right/left, each a plain on/off toggle (or one Apply all):

  • Arrow Up/Down used to lose your column position crossing a table row; now it doesn’t.
  • Ctrl+Left/Right used to treat a whole run of Chinese/Japanese text as one word; now it stops at the real word boundary.

Nothing is hidden — every Key Upgrade is a real, visible entry in Obsidian’s own Hotkeys panel, same as any other command.

Also in this release: a handful of table-cursor edge-case fixes (gj/gk/j/k/w/b/e rendering glitches specific to popout windows, and a goal-column drift when alternating j/gk across the same row boundary), plus settings reorganized into three tabs — For everyone / Vim mode / macOS (Emacs) style — each still with its own one-click setup button.

With this, the table/CJK fixes reach everyone, not just Vim and Emacs users — Key Upgrades covers the plain arrow-key layer, while Vim mode and macOS-style keybindings keep their own deeper motion/editing support on top.

Full write-up: GitHub - For everyone