Reason for entry point to move
Surprisingly, I never found an actual explanation of why this sentence works (or does not work).
In this case, the reason for insertion point: .editedCharacters ( NSTextStorageEditedCharacters in ObjC) affects the position of the insertion point from NSLayoutManager.processEditing(from:editedMask:...) .
If only .editedAttributes / NSTextStorageEditedAttributes , the insertion point will not be affected. This is what you want to achieve when you highlight: change only attributes.
Why backlighting affects the insertion point
The problem with highlighting is that NSTextStorage collects all edited calls during one processing run and combines ranges starting from a user-editable change (for example, insert at input), then forming a union of this and all ranges reported by addAttributes(_:range:) . This results in a single call to NSLayoutManager.processEditing(from:editedMask:...) - with editedMask as [.editedCharacters, .editedAttributes] .
So, you want to send .editedAttributes for the selected ranges, but in the end you will form a union with .editedCharacters . This union moves the waaaaaaaaay entry point beyond where it should go.
Reordering in processEditing to call super first works because the layout manager will be notified of the finished editing. But this approach will still break for some edge cases, which leads to invalid layouts or scroll offsets when you enter very large paragraphs.
This is true for connecting to NSTextStorageDelegate , by the way.
Interact in callbacks after the layout has really finished calling backlight instead of processEditing
The only solution that will work reliably based on the reasons inherent in the Cocoa infrastructure is to perform the selection from textDidChange(_:) exclusively, that is, after the completion of the layout processing. Subscribing to NSTextDidChangeNotification works just as well.
Downside: you need to initiate the allocation of passes for programmatic changes on the main line, since they will not call the textDidChange(_:) callback.
If you want to know more about the source of the problem, I will provide more of my research, various approaches, and solution details in a much longer blog for reference. This post is still a self-sufficient solution in itself: http://christiantietze.de/posts/2017/11/syntax-highlight-nstextstorage-insertion-point-change/