Skip to content

Commit

Permalink
Invalidate Visible Range, Responsive Language Update (#238)
Browse files Browse the repository at this point in the history
### Description

- Updates the visible set of indices when text storage happens, fixing
the linked issue.
- When setting a new language on the highlighter, adds a small "reset"
that clears all current highlights. This makes the language update feel
snappier, as the user receives immediate feedback. Before the ts parser
could take a few seconds to begin highlighting, so there would be a
delay making it seem like the language update was not happening.
- Adds a missing `throw` to the tree-sitter client that made edits
always run synchronously (didn't feel big enough for a whole PR, found
while debugging).
- Only updates the font if the font is new, making text layouts occur
much less frequently (also doesn't feel big enough for a separate PR)

### Related Issues

* #235 

### Checklist

- [x] I read and understood the [contributing
guide](https://github.com/CodeEditApp/CodeEdit/blob/main/CONTRIBUTING.md)
as well as the [code of
conduct](https://github.com/CodeEditApp/CodeEdit/blob/main/CODE_OF_CONDUCT.md)
- [x] The issues this PR addresses are related to each other
- [x] My changes generate no new warnings
- [x] My code builds and runs on my machine
- [x] My changes are all related to the related issue above
- [x] I documented my code

### Screenshots



https://github.com/CodeEditApp/CodeEditSourceEditor/assets/35942988/e719178e-bc9a-4830-9ca5-8d113dcb9d8b
  • Loading branch information
thecoolwinter authored Feb 29, 2024
1 parent 63dcea1 commit a5581a2
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 8 deletions.
10 changes: 9 additions & 1 deletion Sources/CodeEditSourceEditor/CodeEditSourceEditor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,16 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
return
}

controller.font = font
if controller.font != font {
controller.font = font
}

controller.wrapLines = wrapLines
controller.useThemeBackground = useThemeBackground
controller.lineHeightMultiple = lineHeight
controller.editorOverscroll = editorOverscroll
controller.contentInsets = contentInsets

if controller.isEditable != isEditable {
controller.isEditable = isEditable
}
Expand All @@ -173,15 +177,19 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
if controller.language.id != language.id {
controller.language = language
}

if controller.theme != theme {
controller.theme = theme
}

if controller.indentOption != indentOption {
controller.indentOption = indentOption
}

if controller.tabWidth != tabWidth {
controller.tabWidth = tabWidth
}

if controller.letterSpacing != letterSpacing {
controller.letterSpacing = letterSpacing
}
Expand Down
17 changes: 11 additions & 6 deletions Sources/CodeEditSourceEditor/Highlighting/Highlighter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ class Highlighter: NSObject {
return IndexSet(integersIn: textView?.visibleTextRange ?? NSRange())
}()

// MARK: - Tasks

private var runningTasks: [UUID: Task<Void, Never>] = [:]

// MARK: - UI

/// The text view to highlight
Expand Down Expand Up @@ -114,6 +110,15 @@ class Highlighter: NSObject {
/// - Parameter language: The language to update to.
public func setLanguage(language: CodeLanguage) {
guard let textView = self.textView else { return }
// Remove all current highlights. Makes the language setting feel snappier and tells the user we're doing
// something immediately.
textView.textStorage.setAttributes(
attributeProvider.attributesFor(nil),
range: NSRange(location: 0, length: textView.textStorage.length)
)
textView.layoutManager.invalidateLayoutForRect(textView.visibleRect)
validSet.removeAll()
pendingSet.removeAll()
highlightProvider?.setUp(textView: textView, codeLanguage: language)
invalidate()
}
Expand Down Expand Up @@ -304,11 +309,11 @@ extension Highlighter {
visibleSet.insert(range: editedRange)
}

updateVisibleSet(textView: textView)

highlightProvider?.applyEdit(textView: textView, range: range, delta: delta) { [weak self] invalidIndexSet in
let indexSet = invalidIndexSet
.union(IndexSet(integersIn: editedRange))
// Only invalidate indices that are visible.
.intersection(self?.visibleSet ?? IndexSet())

for range in indexSet.rangeView {
self?.invalidate(range: NSRange(range))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ public final class TreeSitterClient: HighlightProviding {
let longDocument = textView.documentRange.length > Constants.maxSyncContentLength

if longEdit || longDocument {

throw Error.syncUnavailable
}
try performSync(operation)
} catch {
Expand Down

0 comments on commit a5581a2

Please sign in to comment.