0.12.7 (Aug, 15 2026)
Added
- 1b66afd Pan viewport horizontally to follow the cursor in edit mode by @erikjuhani
Long source lines are shown raw (unwrapped) while editing, so the cursor
could move past the right edge and disappear. Track a horizontal scroll
offset and pan the document so the cursor stays visible, mirroring the
existing vertical follow logic.When the document pans, full-width fills must extend with it or they stop
short of the right edge. Thread the scroll offset through the render path
so code-block backgrounds, heading underlines, and the title rule span
width + offset, covering every visible block, not just the one being
edited.
- 51d9f92 Add markdown table rendering to the note editor by @erikjuhani
Tables were parsed away as paragraphs and never drawn. The note editor
now renders GFM tables as bordered boxes in reading view. Columns size
to their content and, when the table is too wide to fit, share the spare
width in proportion to each column's demand the way browsers lay out
tables, so a long column takes the most slack without starving the
others, and cell text wraps to fit.While editing, a table renders as the same box but reveals the row under
the cursor as raw markdown so its pipes stay editable, and every row
including the delimiter is reachable. The box is only drawn while the
buffer still parses as a table, so the moment the syntax breaks the block
falls back to raw line by line editing and a half broken table never
hides itself.A thematic break is now kept as a plain paragraph instead of being
dropped, because a table whose pipes are deleted degrades into a bare
dash row that would otherwise vanish from the document.
- 00430a8 Add vim visual selection with clipboard yank by @erikjuhani
Add vim-style visual selection to the note editor: v (charwise) and V
(linewise) select text, y yanks the selection to the clipboard and esc
cancels. A brief flash highlights the yanked range to acknowledge the
copy.The selection is highlighted per character and clipped to the editor
viewport. Clipboard writes go through a native utility (pbcopy, wl-copy,
xclip, xsel or clip) with an OSC 52 fallback for SSH and tmux, adding no
new dependencies.
- 8f58061 Render callout block quotes by @erikjuhani
Render Obsidian and GitHub callouts (
> [!note]) with a per-kind
coloured bar and an icon + title header above the body, keeping the
accent colour while editing.Support the full Obsidian type set (note, abstract, info, todo, tip,
success, question, warning, failure, danger, bug, example, quote) and
their aliases, plus custom titles and fold markers ([!note]- Title),
which pulldown-cmark does not recognise. Type names are case-insensitive
and unknown types fall back to note, as in Obsidian.Each type has a configurable symbol across the ascii, unicode and nerd
font presets.
- f1b6d9f Add multi-note tabs with cycling by @erikjuhani
Open several notes at once in a bufferline-style tab bar and cycle
through them. Selecting a note focuses its existing tab or opens a new
one, so each note keeps its own cursor, scroll and unsaved edits.Cycle with ctrl+n and ctrl+p, the bufferline-style L and H, or the
unimpaired ]b and [b, and close the active tab with ctrl+w. All bindings
are global so they work from any pane. Cycling moves the explorer
selection to the active note, expanding any collapsed folder in its path
so the note becomes visible.To free the global L for tab cycling, the debug log overlay's
level-cycle key moves from L to l.The bar renders one uniform-width tab per note, shrinking them from a
maximum toward a minimum as more open and only ever showing whole tabs.
Names are truncated with an ellipsis and tabs that share a name are
disambiguated by their parent directory. The active tab is a
reverse-video highlight so it contrasts on any theme.
- f28f6c0 Add configurable leader key for key bindings by @erikjuhani
Bindings can be written against a
<leader>prefix instead of a fixed
key, so a whole set of them can be moved to another prefix by changing
one line. The leader is set at the top level of the configuration file
and defaults to<space>.A binding string now parses into a
KeySpec, a sequence of elements that
are either a literal keystroke or the<leader>placeholder. Resolving
a spec against the leader yields the concreteKeythe runtime already
dispatches on, so the existing chord machinery is untouched.Keykeeps
its own deserializer and rejects<leader>, which makes a self
referentialleader = "<leader>"a config error.Resolution happens once the layers are known rather than at parse time.
The leader is read from the user config alone and applied to the bundled
config.toml and vim.toml as well, otherwise a<leader>binding shipped
with basalt would answer to a different key than the user's own.The leader may be a modified key or itself a sequence, and it may appear
more than once in a binding.
- 6692ba1 Add vim motions, operators and text objects to the note editor by @erikjuhani
Grow the experimental editor's Normal mode from a few cursor moves into a
full vim editing grammar.Motions run over the whole document through a pure motion engine
(motion.rs) and a jump_to_offset primitive that crosses blocks: 0 ^ $,
w W b B e E, { } %, gg G, and f F t T with ; , to repeat. A count
prefixes any motion (3w, 5j, 10G).Operators compose with motions via an operator-pending state machine:
d c y over any motion, dd cc yy, x D C s, and p/P through an unnamed
register. Text objects (ci", da(, ciw ...), r to replace a character,
and u / ctrl+r undo built on content snapshots round it out; visual-mode
d/c/y reuse the same path.Semantic keys stay rebindable in vim.toml. Only the inputs no static
binding can express -- count digits and the character after f/t/r or a
text object -- take a raw-key path, mirroring insert mode.
- 650413d Add themes with pane styling
Introduce a theme system that maps roles to colours, with per-pane border
and section styling. Add Basalt's own theme Causeway and a bundled set
(gruvbox, everforest, catppuccin and minimal), plus a theme picker that
saves the choice to the user config.
- 935edee Add a
--themeflag to run basalt with selected theme
The --theme flag overrides the configured theme.
Breaking
- 1863417 Relicense: GPL-3.0 for app, Apache-2.0 for libraries; add CLA by @erikjuhani
Move off MIT to a split model that protects against proprietary forks
while keeping the libraries reusable.
- basalt-tui: MIT -> GPL-3.0-or-later (copyleft and patent grant)
- basalt-core and basalt-widgets: MIT -> Apache-2.0 (permissive,
reusable, with a patent grant)Add a lightweight Contributor License Agreement so future GPL
contributions can still be relicensed, including under a commercial
license, without chasing past contributors for sign-off. Contributors
keep their copyright and agree by opening a pull request.Document the split in the README and CONTRIBUTING, and add a pull
request template that acknowledges the CLA.Already-published versions remain MIT for anyone who has them; the new
terms apply from the next release onward.
- fb5e51c Move four global bindings onto the leader key by @erikjuhani
The vault selector, debug log overlay, external editor and Obsidian
commands were on ctrl+g, g<, ctrl+alt+e and ctrl+alt+o. They are now
v, d, e and o, which frees the awkward
chords and lets all four follow a user's chosen leader. Quit, help and
the tab bindings are unchanged.The old keys stop working, so muscle memory for ctrl+g in particular
needs relearning. Rebinding them in the user config restores them.Note that is now a live prefix in every non editing pane, so a
bare space waits for the next keystroke. If that key completes no
sequence it is retried on its own, and insert mode and the input modal
bypass sequence handling entirely, so typing is unaffected.The debug log overlay carried the old key in its own title, so the hint
in the top right now reads Leader d.The vault-selector and debug-log tapes send the new keys and both gifs
are regenerated in each theme.
Fixed
- 59120fd Keep the cursor line from panning when wrapped text reaches the edge by @erikjuhani
While editing, typing a word that filled the line to the viewport width
panned the viewport right by one column, hiding the first column of every
line. The pan stuck even after the word wrapped to the next visual line.Wrapped text never exceeds the viewport width, so it needs no horizontal
pan. Reset the pan to zero for lines that fit, and keep panning only for
lines that truly overflow, such as code blocks and long unbroken words.
- 1aa72d0 Highlight prettified list markers in visual selection by @erikjuhani
Rendered list markers (and other leading synthetic glyphs like quote and
heading prefixes) carry no source range, so the selection highlight
skipped them and a selected line's marker was left blank. Highlight a
synthetic span when the content it precedes is selected, so the marker is
part of the selection.
- 8a44f14 Scroll an outline-jumped heading to the top of the viewport by @erikjuhani
Selecting a heading in the outline jumped the cursor to it but scrolled
the minimum amount needed to make it visible, so a heading below the
viewport landed on the last line with none of its content shown.It now scrolls the target line to the top of the viewport, clamped so the
last line never rises above the bottom, keeping as much content below the
heading visible as possible.
- 50198c0 Keep explorer cursor and selection stable across background rescans by @erikjuhani
The debounced vault watcher fired a rescan roughly 250ms after picking a
note, which rebuilt the tree and snapped the explorer cursor back to the
active note. Moving the cursor right after selecting caused it to jump
back once loading finished.Split the rebuild into an intentional-select path (used on create and
rename) and a new refresh_entries that captures the cursor and the picked
note by path before rebuilding and restores each independently, so a
background rescan snaps neither.