Repository navigation
Releases: matiaskorhonen/doop-editor
Releases · matiaskorhonen/doop-editor
Release list
v0.13.5
Immutable
release. Only release title and notes can be modified.
Changes
Fixes for crashes and stuck selections found by new randomized stress tests.
- Fixed an
NSInvalidArgumentExceptionwhen undoing a multi-part edit.replaceCharactersscrolled to the
selection from inside undo's batched edit, while the line storage was still stale. - Fixed an
NSRangeExceptionfrom bracket-pair emphasis when the search limit, taken from the visible rect,
lagged a cursor that had just moved or text that had just shrunk. - Fixed delete-by-word and extend-by-word on text with emoji or combining marks. The range was measured in
Characters rather than UTF-16 units and fell short of the word. - Fixed indenting and dedenting with several cursors. Only the selection being processed was updated, so the
others could end up past the end of the text. - Fixed crashes when several cursors moved or deleted by word or line onto the same text. Overlapping
selections are now merged, so shared text is no longer replaced once per selection. - Fixed a selection's length going negative when extending it past its pivot, and a stale pivot left behind by
an edit anchoring the next extension to text that wasn't selected. - Fixed the editor having no selection after undoing or redoing a grouped edit.
- Added opt-in randomized stress tests (
DOOP_STRESS=1 swift test --filter StressTests).
v0.13.4
Immutable
release. Only release title and notes can be modified.
Changes
- Fixed an
NSRangeExceptionraised from a layout pass. A scroll in the middle of an edit (undo and
paste select and scroll to the result) could start a pass after the text storage had changed and
before the line storage had caught up, and typesetting a line from its stale range read past the end
of the text.layoutLinesnow waits, and marks layout dirty, while the two lengths differ. An
exception raised there had left the layout lock held, which skipped every later layout pass in 0.13.1
and hung the main thread before that. - Removed the Objective-C exception catch added in 0.13.3. Catching an exception that has unwound
through Swift frames skips their cleanup, and the app crashed inswift_beginAccessshortly after one.
v0.13.3
Immutable
release. Only release title and notes can be modified.
Changes
- A layout pass that raises an Objective-C exception no longer leaves the editor's layout lock held and
itsCATransactionopen. After one, every later layout pass was skipped (0.13.1) or hung the main
thread (0.13.0), and views in other windows could stop being laid out.layoutLinesnow catches the
exception, releases the lock, commits the transaction and logs the exception's name, reason and call
stack as a fault in theTextLayoutManagercategory, so what raised it can be found.
v0.13.2
Immutable
release. Only release title and notes can be modified.
Changes
- Fixed a crash while typing. An edit that took the asynchronous tree-sitter path reported its result
from a background thread, and the result mutated the highlight provider's index sets, which are
main-actor state, while the main thread was using them. The completion is now delivered on the main
thread, as the synchronous and query paths already did. The race was older than 0.13.0, but 0.13.0's
slow-edit fallback sent many more edits down the asynchronous path and made it easy to hit.
v0.13.1
Immutable
release. Only release title and notes can be modified.
Changes
- A layout pass no longer hangs the main thread when
layoutLockis already held. A UI stress test
deadlocked the editor with the main thread blocked on a lock it owned and no layout pass beneath
it, so an earlier pass had leaked the lock.layoutLinesnow tries the lock: if it is held, it
logs a fault in theTextLayoutManagercategory and skips that pass instead of waiting forever.
This is a safety net; what leaks the lock is not yet known, and the fault log is how to find out.
v0.13.0
Immutable
release. Only release title and notes can be modified.
Changes
- A slow synchronous tree-sitter edit no longer keeps the editor on the main thread. An edit that
takes longer thanTreeSitterClient.Constants.maxSyncEditDuration(30ms) sends later edits to
the asynchronous path, and an edit that comes back under it brings synchronous editing back. Every
edit re-runs the language's query over the whole tree to look for injections, so its cost grows
with the document (about 1.1µs per character in a release build), and the length checks alone
couldn't keep that off the main thread. Multiple cursors multiply it, since each one reparses. - Documents over
TreeSitterClient.Constants.maxHighlightableContentLength(250,000 characters,
about 280ms per edit) are no longer highlighted. The client stops parsing and returns no
highlights, and starts again over the whole document when it shrinks back under the limit or a
new language is set. Text that was already highlighted when the document crossed the limit keeps
its colours.
v0.12.1
Immutable
release. Only release title and notes can be modified.
Fixes
- An asynchronous highlight query no longer styles text that has since been deleted. Tree-sitter
answers off the main thread for a long query or a long document, and the completion came back
carrying the range the query was issued for, which went toNSTextStorage.setAttributes
unchecked. If the document shrank in between — Doop replaces the whole document on every script
run — the range ran past the end andNSMutableRLEArrayraisedNSRangeException, crashing the
host app. The range is now clamped to the document as it stands when the result arrives.
v0.12.0
Immutable
release. Only release title and notes can be modified.
Fixes
- A line is now as tall as the font it is set in. Line fragments took their height and baseline
from the fonts CoreText actually drew with, and a text font has no emoji glyph, so CoreText
substituted Apple Color Emoji — about 40% taller at the same point size. Typing an emoji grew its
line by ~5.7pt at Menlo 12 and moved every baseline below it. The editor's font is now carried
down to the typesetter and text fragments are sized from it; width, line breaking and hit testing
still come from the realCTLine. - Find-and-replace carried its offsets in the wrong direction. Every match after a replacement
moves by the difference between the replacement's length and the match's, andreplaceMatch
subtracted that difference instead of adding it: replacing "a" with "alpha" in "a one a" put the
second replacement inside the first — "alalphaha one a". Replace-all's text was unaffected, since
it works back to front, but its final cursor landed short by the accumulated difference. CEUndoManager.disable()now actually suppresses recording. Onlyundo()andredo()checked
the flag;registerMutationdid not, so the editssetMarkedTextandunmarkTextwrap in it
went onto the undo stack anyway. Composing a character rewrites the marked range on every
keystroke, so each intermediate state became its own undo entry — undoing after composing
Japanese or Chinese walked back through composition states the user never typed as such.
Changes
- Removed 352 lines with no callers here or in Doop:
TextView+EditorMenus.swift(unwired CodeEdit
IDE menu stubs),TreeSitterClient+Temporary,NSRange+NSTextRange.swift, and a handful of
single members. Two were public and leave the binary package's swiftinterface with the source:
NSTextRange'sinit/nsRangepair andTextLayoutManager.visibleLines().
Tests
CEUndoManager's grouping heuristic, driven throughTextView, including the explicit grouping
Doop's find-and-replace leans on.- Replacing from the find panel, against a real
TextViewController: each sign of the length
change, adjacent matches, and replace-all as one undo group. DeleteWhitespaceFilterandTabReplacementFilter, which run on every backspace and tab in an
indented document and had no coverage.
CI
- Cache SwiftPM's working copies, not just its mirrors, and prune the grammar submodules' example
corpora before the cache is written — 6.0GB of the checkouts' 6.9GB that no target compiles.
v0.11.1
Immutable
release. Only release title and notes can be modified.
Fixes
- Pasting over a column of multi-cursor selections left the cursors in the wrong places, and the
next keystroke could crash the host app. Replacing each selection with a string of the same
length reported the insertion as a net growth, so every cursor after the first accumulated a
spurious shift — pastingIpsumover threeIpsumselections put the last cursor ten characters
past the end of the document, where the following edit hit an unconditionalfatalErrorin
TextStory. A replacement shorter than what it replaced drifted the same way without going out of
bounds, misplacing cursors silently.
v0.11.0
Immutable
release. Only release title and notes can be modified.
copy:now writes the selection as plain text. It wrote anNSAttributedStringbefore, which
carries RTF as well as a string, so code pasted into a rich text app arrived in the editor's
theme colors — a dark theme's text landing unreadable on a white page.- The styled copy is still there as
copyWithHighlighting(_:), for a host app to put behind its
own menu item. It paints the editor's background onto the copied text, which its foreground
colors were chosen against. - Both go through the new
copySelection(to:withHighlighting:), which takes the pasteboard to
write to.