shiki (私記)
← Full changelog

shiki v0.8.8

Released 2026-07-29.

Share: X Bluesky Reddit Hacker News WhatsApp Telegram Email
shiki v0.8.8, running in a terminal

Added

  • In-memory scratchpad (leader+p) for temporary writing. Ctrl+S saves its contents as a real note through the existing new-note flow; closing it with Esc discards the buffer.
  • New [editor] config section (EDITOR tab in Settings, leader+s) — six independently toggleable behaviors for the native note editor's mouse/keyboard UX: mouse_selection, find_replace, os_clipboard, select_all_ctrl_a, line_numbers, multi_cursor.
  • editor.mouse_selection (on by default): click to position the cursor inside the note editor, click-and-drag to select, double-click to select a word, triple-click to select a line — the editor had no mouse support at all before this.
  • editor.line_numbers (off by default): a line-number gutter in the editor.
  • editor.find_replace (on by default): Ctrl+F opens a find/replace bar inside the editor — live search-as-you-type, Enter/Shift+Enter for next/previous match, Ctrl+Enter to replace the current match and advance, Ctrl+Alt+Enter to replace every occurrence.
  • editor.os_clipboard (off by default): Ctrl+C/X/V in the editor use the real OS clipboard (via arboard), falling back automatically to the existing OSC 52 mechanism when there's no display server to reach (e.g. headless SSH). Bracketed-paste is now enabled unconditionally so a terminal paste anywhere in the app lands as one atomic insert instead of a burst of keystrokes.
  • editor.select_all_ctrl_a (off by default): Ctrl+A selects the whole buffer instead of tui-textarea's default Emacs-style "move to start of line".
  • editor.multi_cursor (off by default): full multi-cursor editing. Alt+Click adds a cursor (dedups against existing ones); Ctrl+Alt+Up/Down adds one at the same column one row up/down from whichever cursor sits furthest in that direction (VS Code's own "Add Cursor Above/Below", a keyboard-only alternative added after Alt+Click alone felt uncomfortable in practice); Ctrl+D selects the word under the primary cursor and, on each further press, adds the next occurrence as its own independently-selecting cursor, wrapping around the buffer and reporting "no more occurrences" once every match already has a cursor. Every keystroke (typing, Backspace/Delete, Enter, navigation) replays across the primary and every secondary cursor via a new multicursor module built specifically because tui-textarea itself has no multi-cursor concept at all — see the Fixed section below for the real bugs this uncovered along the way. Ctrl+U/ Ctrl+R undo/redo a multi-cursor edit as one action (however many cursors it actually mutated), not one step per cursor. Esc collapses back to a single cursor first (VS Code's own convention); a second Esc then saves and exits as usual. Secondary cursors render as a solid accent-colored block, distinct from the primary's plain reverse-video.
  • A plain (non-dragged) mouse click on a PREVIEW row now jumps straight into Mode::Edit with the cursor on that clicked line — a mouse-only alternative to i/vim motions for anyone reading a note who wants to start editing it. Click-and-drag still selects text and copies it to the clipboard on release, same as before; only the plain-click case changed, gated behind the same existing mouse_drag_selection toggle. Contributed by @elsieej (#23).

Fixed

  • Mouse wheel scroll was never handled anywhere at all — reported live: scrolling over PREVIEW or the editor did nothing. Now scrolls the editor's cursor (Mode::Edit, which in turn scrolls the view — see the next entry) or reuses move_selection's existing delta logic (Mode::Normal/ Visual, covers NOTEBOOKS/NOTES/PREVIEW the same way j/k already do), gated behind the same "no modal is open" guard mouse clicks already use.
  • PageUp/PageDown did nothing at all inside the note editor (Mode::Edit) — reported live alongside the mouse-scroll gap. Root cause: forwarding them to tui-textarea reaches Scrolling::PageUp/PageDown, which scrolls its *internal* Viewport — but that viewport is only ever populated by tui-textarea's own Widget impl, and InlineEditor::render deliberately bypasses that entirely (word-wrap support, see the struct's own doc comment), so the viewport being scrolled is permanently zero-sized and the cursor never actually moves. Fixed by moving the cursor directly instead, which InlineEditor's own scroll-follow (driven purely by cursor position) then scrolls the view to match.
  • Added Ctrl+Home/Ctrl+End to jump to the very start/end of the note — plain Home/End already worked correctly (tui-textarea's own start/end-of-*current-line*, no viewport dependency involved), but there was no way to jump to the start/end of the whole document at all.
  • Multi-cursor's own replay algorithm initially processed cursors bottom-to-top on the assumption that this alone avoids invalidating other cursors' positions — caught by a failing unit test before it ever reached a person: an edit that changes row count (Enter, or backspace-merging two rows) *does* still invalidate an already-processed cursor's recorded result once a later (higher, "more top") edit shifts rows below it. Replaced with the standard top-to-bottom algorithm that tracks a running row/column delta instead, derived from lines().len()/cursor position before and after each per-cursor edit rather than reimplementing tui-textarea's own insert/delete arithmetic by hand.
  • A single tui_textarea::TextArea::input() call can silently push *two* separate undo-history entries, not always one — verified directly against the vendored crate: typing a character over an active selection is "delete the selection, then insert the character" (2 entries), while Backspace over that same selection is just "delete" (1 entry). Assuming a flat count per keystroke (as an earlier version of this work did) left Ctrl+U undoing only half of a multi-cursor edit that replaced a selection, e.g. after Ctrl+D-selecting three occurrences and typing a replacement. Fixed by measuring the real count directly — undo repeatedly until the pre-edit content reappears, then redo back to the post-edit state — instead of guessing per key.
  • Secondary cursors reused cursor_style() (tui-textarea's default Modifier::REVERSED, the same style the primary cursor uses) and had no fallback for sitting past the last character of a line — reported live: "solo hay 1 visualmente, no parpadean varios cursores." A terminal can only ever blink one real caret, so secondary cursors were never going to blink like the primary regardless of styling, but reusing the *exact same* subtle reverse-video look made them easy to miss entirely, and a cursor landing at end-of-line (the common case right after typing) had nothing to render at all. Fixed with a distinct solid accent-colored block style plus the missing end-of-line fallback.
  • arboard's clipboard handle is now kept alive for the process's lifetime instead of being constructed and dropped on every copy/paste — the previous per-call pattern hit arboard's own X11 "clipboard was dropped very quickly" guard, which eprintln!s a warning straight to the real terminal underneath ratatui's alternate screen, visibly corrupting the TUI on every Ctrl+C/Ctrl+V. Caught live by checking the real system clipboard (wl-copy/wl-paste) around a Ctrl+C, not just by reasoning about the code.
← v0.8.7 All releases v0.8.9 →