[diffs] CodeView: Ctrl+F#833
Draft
amadeus wants to merge 77 commits into
Draft
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
751afc2 to
c1e7c89
Compare
* Remove history coalesce
* Fix selction/crate not updated when do "redo" command
* Remove visualColumns.ts
* Move editor ts files
* Refactor textarea buffer
* Rename `EditSnippet` type to `TextareaSnapshot`
* Remove `Editor` component, introduce the `Editor` class for `File` component
* Update demo
* Update editor constants to set text and background color to transparent
* Rewrite rerender logic
* Format
* Remove dead code
* Fix caret postion on empty line
* Improve `renderSelectionRange` performance by using cached DOM elements
* Support range selection in textarea
* Improve rerender performance
* Use piece table data sturcture for the text document
* refactor
* Add public `setSelection` method for the `Editor` class
* Add `FileContentsWithLineOffsets` interface and update related components to support line offsets and line count. Refactor file handling to utilize computed line offsets for rendering and iteration.
* Add `updateRenderCacheAt` method to `FileRenderer` and `File` classes for improved rendering. Refactor theme handling in `Editor` to utilize a dedicated method for color map retrieval.
* Refactor file iteration logic by removing `iterateOverFile` utility and replacing it with direct loops in `VirtualizedFile` and `FileRenderer` components. Update line offset computation to exclude trailing newlines in multi-line files while maintaining correct line counts. Enhance tests to validate line counting behavior.
* Remove EOF field
* Remove text length fields from HistoryEntry and related test cases in EditHistory
* Rename class `EditHistory` to `EditStack`
* Refactor EditStack and PieceTable to use a unified text slice interface.
* Refactor PieceTable and TextDocument to improve line offset handling and remove unnecessary EOL trimming logic.
* Refactor `Editor` to utilize new dirty line resolution logic, enhancing performance and accuracy in line tracking.
* Fix multi-cursor textarea sync
* Refactor Editor rendering logic for improved performance and reduce direct DOM manipulation.
* Add grammer cache
* Enhance line position caching in Editor for improved performance and accuracy.
* Refactor indentation handling in Editor and remove unused utility function for improved clarity and performance.
* Fix testing types
* Improve performance of the `getCharacterX` method
* Improve caching mechanism for enhanced performance.
* Add maxEntries feature to EditStack for managing undo history size
* Refactor
* Enhance PieceTable and TextDocument to trim line endings in getLineText method, improving text handling consistency. Update related tests for accuracy.
* Refactor
* Add `BackgroundTokenzier` class
* Improve performance
* Fix hightlight bug
* Add `--diffs-bg-caret` css property
* Fix input
* Fix selection range rendering
* Fix prebuildStateStackCache funciton
* Update `TOKENIZE_MAX_LINE_LENGTH` to 10,000
* Add `DiffsEditor` interface
* Fix `lineAnnotations` argument on `triggerEdit` invoke
* Refactor editor edit method to accept onChange callback directly and update demo to log file changes
* Clean up
* typo
* Refactor BackgroundTokenizer to use message-based scheduling.
* Refactor editor focus handling by removing redundant event listeners and updating CSS selectors for caret visibility.
* Refactor
* Fix `toTextareaSelectionDirection` function
* Refactor
* Update `DiffsEditor` types
* Add line annotation handling
* Add documentation for `hasVisibleLineAnnotation` function.
* Get rid of enum
* Clean up
* Refactor
* Update editor CSS
* Support text wrap
* Clean up
* Fix line y/wrap cache
* Fix line cache
* Copies leading indentation onto the new line after Enter
* Focus textare after undo/redo
* Move multi-selection functions to editorSelection module
* Add support for handling leading indentation deletion in applyTextChangeToSelections
* Fix selection glitch bug
* Add extendSelection command
* Fix `focusTextare` function
* Fix `resolveTextareaChange` function
* Remove unnecessary target check in mouseup event listener in Editor class
* Fix textarea selction direction
* Fix selection bg color for safair
* Clean up
* Fix shift select
* Refactor
* Refactor
* Fix shift select delay
* Coalesce edit stack entries for simple typing or backspace operations.
* Add Support forward-delete coalescing for edit history
* docs: add docs for editStack module
* Refctor
* Fix 'documentStart' and 'documentEnd' commands
* Rewrite selection handle logic
* Fix shouldCoalesceEditStackEntry function
* Update demo
* Add `removeEditor` for File component
* Add react api
* Clean up
* Update demo app
* Refactor useFileInstance to remove redundant editor cleanup logic
* Fix `computeLineOffsets` function
* typo
* Update editor style
* Fix `getOrCreateLineOffSets` method
* Refactor line count and annotation handling in File component; remove hasVisibleLineAnnotation utility
* Fix lines deletion crocss virtul viewport
* Remove `normalizeSelectionsForDocument` function
* Fix `edit` function
* Add editor sub-module
* Use `contenteditable` model
* Fix line wrap
* Fix wrap line
* Fix selection on mobile
* Update editor style
* Fix resize handling
* Add editor overlay layer
* Cleanup
* Add `DiffsEditableComponent` types
* Fix `VirtualizedFile` component
* Update `DiffsEditableComponent` type
* Add editor demo
* Fix slection rendering
* Update editor demo app
* Fix VirualizedFile component
* Update editor demo app
* Fix some selection bugs
* Update demo app
* Refactor findNextNonOverlappingSubstring method into PieceTable and TextDocument
* Refactor
* feat: Implement line jump
* Fix selection rendering when scrolling
* Improve tokenzier performance
* feat: simple search pannel
* Update editor demo app
* Fix jump
* Update search UI
* Add lag radar
* Fix virtualizer
* Fix render range after typing
* Fix editor tokenzier cache
* Fix search input focus
* Update log rader position
* Improve piece table performance
* Refactor
* Add lag radar
* Fix line count for empty documents
* Fix offscreen lines flush
* Introduce gutter width tracking
* refactor
* Refactor
* fix import
* Add 'expandSelectionDocStart' and 'expandSelectionDocEnd' commands
* Fix buffer height
* Add matches text for the search pancel
* Disable preious/next icon when no matches
* Update style.css
* feat: Support `quiteEdit` action
* Update edtior demo app
* Refactor
* Update demo app
* Update demo app
* Fix girdRow when render quick edit UI
* Move testing files
* Clean up
* Add searchPanel.ts
* Fix expandCollapsedSelectionToWord to match when the cursor is immediately touching one of the word's boundaries
* clean up
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Fix typo
* Clean up searchPanel and quickEdit when swith file
* Rebase to beta-1.2
* Fix selection after clean up quick edit widget
* Fix virtual buffer
* Fix `updateWindowSelection` method of Editor class
* Fix render range when typing new line at the end of the file
* Fix buffer when adding large lines
* [editor] Support 'deleteHardLineForward' input
* Add `insertTranspose` input
* Move `change` handler to options
* Update css
* Merge beta-1.2 changes
* Fix emply line rendering
* Add search settings UI
* Merge branch 'main' into editor
* Support FileDiff component
* Update `DiffsEditableComponent` interface
* Fix `getSelectionAnchor` function
* Fix text measurement for emoji
* Increase delay for diff rendering in FileDiff component
* Update types
* Add unit testings for text measue functions
* Clean up dirty render cache
* Fix `lineAnnotations` re-rendering
* Disable gutter utility when editing
* Add global css
* Fix scrollToLine method
* Refactor selection handling in Editor class to initialize selections properly and streamline rendering logic
* Fix diffs components
* Allow to create selection from gutter interaction
* Fix focus
* Fix browser compatibility
* Support dual themes
* Fix selection bugs
* refactor
* Add `Metrics` class
* Clean up
* Fix wrap selection rendering on safari
* Add `QuickEditContext` types
* Fix caret scroll margin when search panel is on
* Refactor search panel widget
* Fix selection position
* Update react components
* Update search panel CSS
* Fix quick edit
* Add editor docs
* Fix react hooks for editor
* Update editor demo component
* Update Quick Edit docs
* Update `diffStyle` and `expandUnchanged` options when editing
* demo: remove editor route
* Update docs
* Update docs
* Update examples
* Reset selection when 'Esc' key pressed
* Fix selection focus
* Add 'enable edit' shortcut('e')
* Handle the arrow key events to scroll to the cursor position manually
* Merge of overlapping selections
* Handle cursor moving events
* Fix scroll margin top
* Add debug logging option to Editor class
* Fix selection bugs
* Fix selection renering for unified `FileDiff`
* Reset ignore selection change flag on mouse up event
* Clean up
* fix bun.lock
* Add editor theme style
* Refactor
* Fix react types
* Fix last line index calculation
* Update condition for marking DOM dirty in VirtualizedFile component
* Throw if someone is trying to edit with no editor instance
* Update `mergeFileDiffOptions` function
* `lineOffsets` -> `lines`
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…d for the `DiffsEditor` (#766) * feat(editor): add pause and resume functionality for background tokenization * pref(editor): Introduce `postponeBackgroundTokenizeToNextFrame` method for the `DiffsEditor` * fix * Add debug option for the tokenzier * Update types * Refactor * typo * Reduce requestAnimationFrame calls
* chore: empty commit for beta branch * Homepage FileDiff editor demo * Style kbd elements, add beta badge to docs content, redo table for keyboards, few edits * docs(editor): add MultiFileDiff React example Document editing with MultiFileDiff alongside File and FileDiff in the React integration tabs. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(editor): use parseDiffFromFile in FileDiff React example Align the editor FileDiff tab with the pre-parsed fileDiff prop API. Co-authored-by: Cursor <cursoragent@cursor.com> * Update editor react examples * docs(editor): document worker pool usage with useTokenTransformer Add a Worker Pool section with tabbed vanilla/React examples, and enable useTokenTransformer on the docs site worker pool so editing works off-thread. Co-authored-by: Cursor <cursoragent@cursor.com> * format * Remove toolbar, put reset into header metadata * add link * little copy editing * Update homepage example to include file and diff * redo reset --------- Co-authored-by: Amadeus Demarzi <amadeusdemarzi@gmail.com> Co-authored-by: Je Xia <i@jex.me> Co-authored-by: Cursor <cursoragent@cursor.com>
* Rounded selection boundaries * Search panel refactor/redesign * Introduce `postponeBackgroundTokenizeToNextFrame` method for the `DiffsEditor`
…`deleteWordBackward` (#789)
Removing BETA badge from Virtualization
* [diffs/editor] refactor editor API * Refactor * refactor * fix * Refactor * refactor * refactor * Add blur method to Editor class for improved focus management * Update docs * Refactor
* Includes editor code refactor * Find/Replace functionality
The editor renders its active-line highlight by calling the component setSelectedLines, which commits a line-selection range and fires the host onLineSelected callback. A caret or text selection in the editor is not a gutter line selection, so an editable File/FileDiff with a line-selection handler received a bogus notification on every selection update. Pass notify: false from the editor so the highlight renders without committing a line selection, and widen the component setSelectedLines type to accept the option. Add a regression test asserting onLineSelected stays silent for a multi-line editor selection.
Steps to reproduce: 1. Open edit mode with the selection action enabled. 2. Drag to select several characters inside a word. 3. Click the gutter lightning-bolt icon, then the wrap button. 4. Only the first (or last) character is wrapped, not the whole selection. The gutter icon is a cached DOM element reused across renders for the same line, but its click handler closed over the selection captured when the icon was first created. During a drag that is the first single-character selection (the first letter for a forward drag, the last for a backward drag), so the action ran against a stale range instead of the user's final selection. Read the current primary selection at click time so the action always operates on what the user has selected. Add a regression test covering the forward and backward drag cases.
Repro (diffs /playground, edit mode):
1. Select all text in the editor.
2. Press delete/backspace.
Before this fix the editor breaks: split mode collapses to a
single uneditable view and undo does nothing; unified mode keeps
the view but you can no longer type.
The editor's text document always keeps one (empty) line, but
splitFileContents('') returns [], so emptying the editable side
recomputed the diff with zero addition lines. The additions
column then rendered no line elements, leaving the attached
editor with nothing to host its caret.
Now an emptied document is represented as one empty editable
line: diff the unchanged deletions against a single empty line
and store the addition as [''] so it still joins back to the
editor's empty document. Covered by model- and DOM-level
regression tests in both split and unified modes.
When the editor is emptied, the recompute diffs the deletions against a single empty line to place one editable row. If the old side was itself a single blank line, that diff was a no-op (zero hunks), so iterateOverDiff emitted nothing and the row was still missing. Pick a sentinel that always differs from the deletion side so a hunk is produced; its text is discarded by the [''] override. Covered by the empty-document regression tests.
Turn on word wrap in an editable diff and type in a line until it grows long enough to wrap onto another row. Now click a line below it, or select text there: the caret and the selection highlight land a row too high, sitting on the wrapped line's extra row instead of the line you clicked. The editor caches each line's vertical position and only refreshed it when the number of lines changed. Wrapping a line adds a visual row without changing the line count, so the cached positions of the lines below it stayed stale, and the caret and selection drawn from them rendered a row too high. Refresh the cached positions after an edit whenever wrap is on, matching how the wrap offsets are already invalidated. This corrects only the vertical position of overlays on the lines below a wrap. Selecting a word on the wrapped line itself still mispaints the highlight horizontally; that is a separate bug.
Steps to reproduce: 1. Scroll a long file so the visible lines sit inside an unclosed block comment or template literal. 2. Delete the line directly above the viewport. 3. The visible lines lose their comment color and render as if they were plain code. The tokenizer read the loop's grammar state before the offscreen flush rebuilt the cached state stack up to the viewport's first line, so it captured INITIAL. The visible lines were then tokenized as if outside the construct — corrected by a later background pass, or never when the viewport reaches the end of the document and no background pass is scheduled. Seed the loop state after the offscreen flush instead. This reuses the state the flush already computed, so it adds no tokenization work and only changes the delete-reaches-viewport case; far-above edits with a gap stay seeded from INITIAL and are corrected by the background pass as before.
Paste inserted clipboard text verbatim, so a Windows clipboard (CRLF or CR) left mixed line endings in a file that otherwise uses one style, showing up as spurious diff noise. Rewrite clipboard line breaks to the document's detected EOL before inserting, matching what copy already does. Expose the line ending as TextDocument.eol with a normalizeEol() helper and move the generic endsWithLineBreak() predicate into editor utils, so this logic no longer sits among the selection helpers.
Repro: 1. Open the editor on a large file, or make many scattered edits so the document accumulates many internal fragments. 2. Keep typing; each keystroke gets progressively slower. Every edit (typing, deleting, applyEdits) rebuilt the editor's whole text structure from scratch, so a single edit cost time proportional to how fragmented the document had become; in a heavily edited file each keystroke paid for the entire document. That structure (a piece table) keeps text as a list of "pieces" indexed by a tree. The tree is now a treap: a binary search tree that also keeps each node's random priority in heap order, so it stays balanced without an explicit rebalancing pass. An edit now splits the tree at the edit, drops the removed part, and merges the new text in, touching one root-to-leaf path (O(log P)) instead of rebuilding all P pieces. Reads and editor behavior are unchanged.
Steps to reproduce: 1. Scroll a long file so the editor virtualizes (only a window of lines is rendered). 2. With a caret near the window bottom, insert lines there - press Enter on the last rendered line, or paste a few lines. 3. The just-typed line, and its caret, are missing from the window until the next scroll. #applyChange widened the render range only when the caret was exactly at the window's end, and never persisted the widened range, so a following edit read a stale renderRangeEndLine, treated the caret as past the window, and #rerender (clamped to the range) never built the new row; #isLineVisible/#renderCaret read the stale range and dropped the caret too. (Only edits that carry a caret reach this path - it is guarded on `selections` - so a bare programmatic applyEdits with no active selection is unaffected; the real triggers are typing and paste at the window bottom.) Widen the range to cover the caret line for inserts that reach the window's bottom edge and persist it to #renderRange so consecutive edits stay accurate and the caret draws. Bound that widening two ways so it can't defeat virtualization or render a gap. Cap it at twice the bounded window the virtualizer last synced (captured in __syncRenderView as #viewportWindowLines): a large insert at the caret - most often a big multi-line paste - can drop the caret far below the window, and widening to reach it would build a row per inserted line synchronously, risking a freeze. And skip widening when the edit starts below the window, since #rerender only builds rows from change.startLine - widening there would leave the intervening rows unbuilt while reporting them visible, mispositioning the new rows. Past either limit, keep the bounded window and only recompute the buffer, leaving the far region for the scroll that follows a focused edit (or the next user scroll) to render. Capturing the window at sync time also stops consecutive edits from ratcheting the cap up. Add editorVirtualizedEdit.test.ts: consecutive newlines and a small multi-line insert at the window bottom render; a 1000-line insert, a run of consecutive inserts, and an edit starting below the window all keep the rendered window bounded and contiguous.
Open a split diff with word wrap on and edit a line so it wraps onto several rows. Double-click a word on a wrapped row: the word is selected and the caret lands correctly, but the highlight is drawn at the row's left edge instead of over the word. Selecting whole lines across a multi-line range shows the same shift. In a split diff the editable panel sits to the right of the deletion panel. The caret math adds this horizontal panel offset, but the selection-highlight math did not, so every highlight was pulled left by the offset (its width stayed correct). Add the same content offset when computing the highlight's left edge, for both wrapped rows and selections that start at the beginning of a line.
In a split diff with word wrap on, edit a line so it wraps, then turn word wrap off. Select a whole line from its start: the highlight either vanishes or jumps far to the right of the text. #contentOffset caches the split panel's horizontal shift but is only set in a split + wrap diff and never cleared, so toggling wrap off leaves a stale value on the same editor. The selection start added that stale offset while the end (from #getCharX) did not, giving a negative width. Read the offset through a getter that returns it only while the live layout still applies, so caret, selection, and line-Y math all ignore a stale value.
* Phase 1: Setup the new slot architecture * Phase 2: Vanilla API shenanery * Phase 3: React implementation * Phase 4: Add CodeView support * Add demo-ability * Phase 5: Adding misc tests * Phase 6: Adding docs Both for the new API and also some forgotten docs for header prefix
[diffs/editor] Updated `editor.css` for marker popups to improve layout and responsiveness
Steps to reproduce: 1. Open a diff in edit mode and edit a line (e.g. rename a symbol). 2. Toggle any display option - word wrap, theme, diff style, line numbers. 3. The edit vanishes and the line shows its original text again; it only reappears on the next keystroke. When an editor is attached, its document is the source of truth for the content, but the host passes a static fileDiff. A display-option change forces a full re-render that rebuilds the diff rows from that fileDiff, so the in-progress edits are painted over with the original content - and inserted or deleted lines are lost. After a full re-render, when the editor's document survived it and the rendered rows no longer match it, re-render the diff from the document: rerenderFromDocument re-derives the diff and clears the render cache so the rebuild re-highlights from the edited contents. One pass restores text, syntax colors, and line count, with no per-row reconciliation. The diff is mutated in place so its cacheKey is kept and the editor's document and undo history survive. Gated to full re-renders (a scroll's partial render reuses the existing rows) and to components with a document-backed re-render (FileDiff; the plain File has no such path yet). Host-agnostic: this holds whether or not the host sets a cacheKey. Adds a regression test covering the toggle, further typing, an inserted line via both render APIs, and downstream block-comment highlighting - all with no cacheKey. Co-authored-by: Je Xia <i@jex.me>
* chore: empty commit for beta branch * Prevent transparent borders * Fix the editing example * fix cursor jumping in history demo * wip * updates * button fixes, history improvement * refactor(diffs): show the selection action in a floating popover Selecting text in an editable surface used to surface a lightning icon in the gutter; clicking it inserted the consumer's action element as a new inline row, which reflowed the document and took two interactions. Replace that with a floating popover that appears automatically once a ranged selection settles, anchored just below the selection's head and mounted in the overlay layer so it never reflows the content. The `renderSelectionAction` API is unchanged, and its handlers now read the live primary selection so keyboard-extending a selection keeps acting on the current range. Drop the now-unused gutter icon, its `quick` sprite, and the inline-row styling. * docs(docs): rebuild the selection action demo as "Add to chat" The edit page's selection demo wrapped the selection in t() or shouted it in caps from a toolbar. Rebuild it around the new popover: selecting code pops an indigo "Add to chat" action (plus a secondary copy) that sends the snippet to a mock chat panel beside the editor, complete with an inert composer mirroring the homepage agent UI. Snippets render with a read-only File. The page's shared worker pool is wired for the editable surface and doesn't highlight a dynamically mounted read-only File, so opt these out with disableWorkerPool and highlight on the main thread. The panel is height-matched to the editor so the list scrolls while the header and composer stay put. * docs(docs): describe the selection action popover Update the editor docs and copy to match the new behavior: the action appears in a floating popover anchored to the selection instead of a gutter icon you click, and it can hold any number of actions. Refresh the edit-page blurb, the Editor guide prose, and the option comment, and drop the selection action from the standalone EditorDemo so it stays focused on plain editing. * chore(demo): match the renamed selection action popover hook The selection action now renders as a popover, so target the new [data-selection-action-popover] selector and drop the inline margin that spaced the old inline action row. * test(diffs): cover selection action popover lifecycle Add cases for the popover's auto show/teardown: it disappears once the selection collapses, and it never renders (nor calls the consumer's callback) when enabledSelectionAction is left off. * feature updates * New replace and replaceall icons * better search shortcuts * Update keyboard shorcuts table * refactor search, fix some nits, redo icons in search, combine marker severity styles * remove labels * use claude to restore the delta between X's and my changes, then reapply to markers and popovers * improve focus, rearrange * localize the padding/margin for now --------- Co-authored-by: Amadeus Demarzi <amadeusdemarzi@gmail.com>
I need to more deeply review this... it's probably a fuck ton
c1e7c89 to
96d7c1c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A WIP vibe coded ctrl+f for CodeView.