Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

### Added

- **Split view for Markdown and HTML documents** ([#461](https://github.com/raiseCatError/notMyShell/issues/461)). **F2** (or `s` in the read-only views) in the document workspace shows the editor beside NMSh's own preview of the *same* buffer: the text on the left, the rendered document on the right, updated as you type, without saving. The preview follows the caret to its block (`l` in the preview pane turns that off), **Ctrl+O** moves between the panes, `x` swaps the sides and `<` `>` change their widths (30–70%). Only the text pane is editable; keys typed while the preview has the focus never reach the text. The preview pane has its own find (`/`) and heading prompt (`#`). Below 100 columns only the focused pane is shown at full width, and widening the terminal brings the split back. Esc leaves for the read-only source view with your unsaved text kept; F2 again returns to editing. The browser-quality preview is not used in the split; the pane is NMSh's renderer. Mouse input in the split is not handled yet.
- **Heading navigation** ([#462](https://github.com/raiseCatError/notMyShell/issues/462), first slice). In a Markdown or HTML document, **`#`** in the viewer or workspace opens a heading prompt: type to narrow, Up/Down choose, Enter jumps (source or rendered view, any width) and **Backspace** goes back to where you were. In the editor, F1 then `h` (or *Go to heading…* in the snippet palette) lists the headings with their depth; `j` / *Back* returns to the caret position you left, even after edits. `/view README.md#install` opens the file at that heading. Anchors follow GitHub's rules (lower-case, punctuation dropped, `-1`, `-2` for repeats; raw HTML headings listed without an anchor); Jekyll/Kramdown ids are different and are not implemented (see the [architecture note](docs/architecture/document-source-map.md)). Underneath, every parsed Markdown block now knows its source lines and every rendered row its block's line, the shared map the coming split view and hybrid editing build on.
- **`/playground`: an unsaved Markdown or HTML document** ([#468](https://github.com/raiseCatError/notMyShell/issues/468), second slice). `/playground md`, `/playground html`, or `/playground` to choose, opens an editable scratch document in the document workspace at once — type, switch between source, edit and preview with the usual keys, and use the snippets. Nothing is saved for you: **Ctrl+S asks for a file name** (Save As creates a new file with the same checked save as `/edit` and never replaces an existing one), and closing with unsaved text asks Save As, Discard or Keep editing. If NMSh or the terminal dies, the text is kept as a private draft and `/playground recover` brings it back. The preview is NMSh's own renderer: no browser process, no folder served, scripts and network stay off. Split view arrives with [#461](https://github.com/raiseCatError/notMyShell/issues/461).
- **Snippets in `/edit`** ([#468](https://github.com/raiseCatError/notMyShell/issues/468), first slice). In a Markdown or HTML file, **F1** (Markdown: F1 then `/`) opens a searchable palette of built-in templates — headings, tables, task lists, fenced code, block quotes, footnotes, Mermaid and math blocks as source text (NMSh does not render them), an HTML page skeleton, semantic sections, lists, tables, links and images — together with the editing actions that already exist. Type to filter, Enter inserts. A snippet is plain text inserted as one undoable edit; its placeholders are selected one by one with **Tab / Shift+Tab** for as long as you are inside it, **Esc** or moving away ends that without touching the text, and Tab is an ordinary tab everywhere else. Block templates start on their own line, wrap a selection where it makes sense, and follow the line's indentation. Nothing is executed, fetched or installed.
Expand Down
9 changes: 9 additions & 0 deletions docs/design/document-workspace.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ Limits: code fences are recognised by a line scan (indented code blocks and fenc

**Verified by** `tests/markdownEdit.test.ts` (each helper: empty and multi-line selections, nested and mixed lists, quotes, fences, Unicode, very long lines, one undo step, restored drafts) and `tests/markdownEditorKeys.test.ts` (keys, menu at 30–120 columns, non-Markdown files unchanged, CRLF saved as CRLF). Physical Ghostty/Zed: NOT RUN.

## Split view

`DocumentMode` gains `'split'` (#461). The session keeps the one `EditorState` and one `ViewerState`; the split adds a `SplitState` (focus, swapped, ratio, linked, a buffer version counter fed by `TextBuffer.observe`, the last caret line). The preview pane is the existing native renderer (`renderViewer` with `rendered` true), re-synced from the buffer only when the version changed. Keys: **F2** (the new `splitToggle` key) or `s` from the read-only views enters; **Ctrl+O** switches the focused pane (elsewhere it still opens the preview); a key goes to exactly one pane. The source pane is the editor unchanged (snippets, helpers, recovery, review and Save As all work in it; a dialog or prompt takes the whole panel). The preview pane takes the viewer's navigation, find and heading keys plus `x` swap, `<`/`>` width (30–70%), `l` link/unlink, `e` focus the text, `s` back to editing, Esc to the source view.

- **Linked scrolling:** when the caret moves to another line the preview shows the first row of that line's block (`rowForLine`, the source map). Scrolling the preview by hand is respected until the caret moves again; `l` turns following off.
- **Layout:** at 100 columns and up the panes share the width minus a one-column divider (preview 30–70%, never under 40 columns); below 100 only the focused pane is drawn full width and Ctrl+O switches — nothing is crushed. Resizing re-lays out from the same state.
- **Not provided:** the Chromium preview in the split (it owns a page and a served folder per file; the native renderer is what the split shows), pointer input and independent pane focus by mouse, a vertical (stacked) orientation, synchronised scrolling from preview back to the caret, and a per-heading synchronisation beyond block granularity.
- **Verified by** `tests/documentSplit.test.ts` (layout, both panes of one buffer, edits and undo reaching the preview, linked scrolling, focus and key ownership, swap and resize bounds, narrow collapse and restore, Esc/F2 transitions, dirty and save from the split, preview find and heading prompts, NO_COLOR, hostile and 40,000-line documents, and the real app).

## Playground

`/playground [md|html|recover]` ([#468](https://github.com/raiseCatError/notMyShell/issues/468), slice 2) opens a **scratch document**: an `EditableFile` with `scratch: {id}`, `path` `Untitled.md` / `Untitled.html` (a display name that gives the format), `realPath` `scratch:<16 hex>` and no disk identity. The `scratch:` identity is what the recovery drafts of #469 are keyed by; it is never a path, and nothing reads or writes it as one.
Expand Down
2 changes: 2 additions & 0 deletions docs/development/v024-ledger.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ The paused issues #460–#469 are the milestone (the maintainer superseded the e

6. **#462 slice 1: source-position map and heading navigation** — branch `feature/v024-outline` (stacked on the Playground slice). Done: spans on every block, `MarkdownRow.line`, `DocumentIndex`, `SourceAnchor`, GitHub slugs, viewer `#` prompt + Backspace, editor *Go to heading…*/*Back*, `/view file#heading`, architecture note `docs/architecture/document-source-map.md`. **#462 remaining:** `<details>/<summary>` disclosure, Mermaid, math (distinct later slices), a persistent outline rail (not started: the prompt/palette fit the existing layout without taking width), following `#fragment` links inside a rendered document (no link focus exists yet). **Next in order:** #461 (Source/Preview/Split, using `rowForLine`/`lineForRow`), then #460, then #466. **#463** still lacks footnote renumbering.

7. **#461: split view** — branch `feature/v024-split` (stacked on #462 slice 1). Done: `split` mode with editor + native preview of one buffer, linked scrolling, focus/ownership, swap/ratio, narrow collapse, F2. **#461 remaining:** pointer input and hit testing, vertical orientation, the Chromium preview inside the split, preview→caret sync; physical QA. **Next:** #460 (hybrid Markdown editing) builds on `blockAt`/`rowForLine`; #466 diagnostics uses the heading index and block spans; #462's details/Mermaid/math slices; #463 footnote renumbering.

## Environment notes

Scratch and test runs: `t7run`; focused tests via `/Volumes/T7Tmp/ai-dev/runtests.mjs` (see the testing-gotchas memory). `npm ci` was needed in a fresh worktree (the main checkout's `node_modules` is stale).
6 changes: 6 additions & 0 deletions docs/testing/v024-editor-physical-qa.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ Automated tests cover the logic headlessly. Everything below is **NOT RUN** unti
- [ ] Mermaid and math entries say they are source text; nothing in the preview claims to render them.
- [ ] The palette rows and footer fit 30, 50, 80 and 120 columns; NO_COLOR and Safe Glyphs stay legible.

## Split view (#461)
- [ ] F2 is delivered by the terminal and by Zed's terminal (otherwise use `s` from the read-only view). The split shows the text and the rendered document side by side; typing updates the preview; the preview follows the caret; `l` unlinks.
- [ ] Ctrl+O switches panes; letters typed in the preview pane never change the text; `x`, `<`, `>` behave; below 100 columns one pane at a time; widen the window and the split returns.
- [ ] Esc keeps unsaved text; Ctrl+S saves (or asks for a name in a Playground); resize while typing does not corrupt the screen.
- [ ] 30, 50, 80, 100 and 120+ columns; NO_COLOR; Safe Glyphs (divider is `|`).

## Heading navigation (#462)
- [ ] In a long Markdown file `#` opens the heading prompt (is `#` delivered by your terminal and Zed?); type, Up/Down, Enter jumps in both the source and the rendered view; Backspace returns.
- [ ] `/view README.md#some-heading` opens at the heading. In `/edit`, F1 then `h` lists headings with indentation; `j` returns after editing above the starting point.
Expand Down
4 changes: 3 additions & 1 deletion src/terminal/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export type Key =
| {kind: 'left' | 'right' | 'up' | 'down' | 'lineHome' | 'lineEnd' | 'backspace' | 'delete' | 'enter' | 'newline' | 'complete' | 'escape' | 'selectAll'}
| {kind: 'selectLeft' | 'selectRight' | 'selectUp' | 'selectDown' | 'selectLineHome' | 'selectLineEnd'}
| {kind: 'bufferHome' | 'bufferEnd' | 'selectBufferHome' | 'selectBufferEnd'}
| {kind: 'historySearch' | 'historyDelete' | 'find' | 'previousFailure' | 'nextFailure'} | {kind: 'suggestNext' | 'suggestPrevious' | 'palette'} | {kind: 'pageUp' | 'pageDown' | 'latest' | 'interrupt' | 'suspend' | 'eof' | 'wheelUp' | 'wheelDown' | 'mouseMove' | 'mouseClick' | 'mouseDrag' | 'mouseRelease' | 'focusPrevious' | 'focusNext' | 'toggleDetails'
| {kind: 'historySearch' | 'historyDelete' | 'find' | 'previousFailure' | 'nextFailure'} | {kind: 'suggestNext' | 'suggestPrevious' | 'palette'} | {kind: 'pageUp' | 'pageDown' | 'latest' | 'interrupt' | 'suspend' | 'eof' | 'wheelUp' | 'wheelDown' | 'mouseMove' | 'mouseClick' | 'mouseDrag' | 'mouseRelease' | 'focusPrevious' | 'focusNext' | 'toggleDetails' | 'splitToggle'
/** Ctrl+Q: add the composer's command to the queue; Ctrl+S: send it to the running program's input. */
| 'queueCommand' | 'sendToProgram'
/** Ctrl+T: open the Arcade. NMSh's own key: it is never written to a program, so it is safe while a command runs. */
Expand Down Expand Up @@ -104,6 +104,8 @@ const SEQUENCES: Array<[string, Key['kind']]> = [
// Command palette: Ctrl+Shift+P and Cmd+Shift+P need CSI-u reporting (plain Ctrl+Shift+P is Ctrl+P); F1 is the legacy fallback.
['\u001B[112;6u', 'palette'], ['\u001B[80;6u', 'palette'], ['\u001B[112;10u', 'palette'], ['\u001B[80;10u', 'palette'],
['\u001BOP', 'palette'], ['\u001B[11~', 'palette'],
// F2 opens or closes the document workspace's split view.
['\u001BOQ', 'splitToggle'], ['\u001B[12~', 'splitToggle'], ['\u001B[Q', 'splitToggle'],
// Kitty keyboard protocol functional-key form (`CSI 1 P`, the 1 omitted when unmodified); NMSh enables that protocol where supported.
['\u001B[P', 'palette'],
['\u001B[110;5u', 'suggestNext'], // Kitty Ctrl+N
Expand Down
Loading
Loading