Repository navigation
fix(ui): stabilize tab switching, gutter layering, folder expansion, and lsp underlines - #23
Merged
Merged
Conversation
added 9 commits
October 12, 2026 15:53
…ge-detection Both features are merged and passing 113 tests. Updates CURRENT_STATE.md to mark completion as wired and external-change detection as done, adds MEMORY.md entries #19-#22 (language identifier matching, sourcekit string IDs, UTF-16 positions, URL resourceValues quirks), and updates PROJECT_PLAN.md quality gates, README roadmap, and PROCESS.md test counts.
Closes #2 (diagnostics part): sourcekit-lsp's publishDiagnostics notifications now drive underlines on the text view and a live error/warning count in the status bar. - DocumentDiagnostic + DocumentDiagnosticsSeverity in Core (Foundation-only, so Document stores diagnostics without importing CodeEditorLSP) - Document.setDiagnostics(_:): replaces the batch, @observable so the status bar re-renders - LSPTextViewCoordinator subscribes to client.onDiagnosticsChanged in openIfNeeded(), converts LSP Diagnostic → DocumentDiagnostic via offset(forLine:column:), and paints .underlineStyle + .underlineColor from Theme.semantic (red/green/yellow) - Clear + re-render on tab switch and destroy - StatusBarView shows "N errors, M warnings" when diagnostics are present - DocumentDiagnosticsTests: setDiagnostics round-trip + range-to-NSRange Gutter markers are a follow-up — the upstream GutterView has no marker API in 0.15.
Closes #3: ⌘-click navigates to a symbol's definition, and the popover shows server-provided documentation alongside the target. - LSPTextViewCoordinator conforms to JumpToDefinitionDelegate - queryLinks(forRange:): resolves the NSRange to an LSP Position, then fetches definition + hover concurrently via async let - link(from:hover:): same-file links carry an NSRange so the upstream model sets the selection; cross-file links carry a URL the AppState opens - CodeEditorView passes lspCoordinator as jumpToDefinitionDelegate to SourceEditor
A Settings sheet (⌘,) consolidates every persisted editor preference in one Form so they're discoverable without hunting menu submenus. - AppState gains isSettingsVisible (mirrors the isSidebar/isTerminal/isStatusBar pattern) - SettingsView: theme picker (Menu with checkmark), font size, tab width, and the four view toggles — all bound to EditorState setters - MainWindowView shows the sheet - CodeEditorApp adds the Settings… command in the .appSettings group - Theme, Chrome, and Semantic conform to Hashable (their only stored properties are already Hashable EditorColor values) so Theme can serve as a Picker/Selection value
…r/goto-def/settings - CURRENT_STATE.md: 113→115 tests; diagnostics + hover/def + settings marked working; status bar diagnostic-count mention; size table bumped for 5 new files (Diagnostic.swift, DocumentDiagnosticsTests, LSPTextViewCoordinator edits, SettingsView, StatusBarView edits) - PROJECT_PLAN.md: #2, #3, #4 marked done; test-count gate updated - MEMORY.md: #23 on Picker(selection:) resolving to init(sources:) on this toolchain; FAQ entries for settings picker + diagnostic colours Closes the 'before you call it done' checklist for issues #2, #3, #4.
…d lsp underlines - fix(sidebar): prevent cyclic tab/selection oscillation by guarding programmatic reveals with isSyncingSelection and checking activeDocumentURL - fix(sidebar): fix folder expansion requiring selection by decoupling disclosure chevron button from List selection state - fix(chrome): prevent gutter line number layering over TabBarView by adding zIndex(1) and clipped() - fix(lsp): switch diagnostic rendering from NSTextStorage attributes to CodeEditTextView EmphasisManager to prevent Tree-sitter wipes - fix(lsp): add publishDiagnostics to ClientCapabilities and enable cached diagnostic rendering on document attach - docs: document EmphasisManager, disclosure button, selection guard, and AppKit layering in MEMORY.md (#24-#27)
…d recent projects welcome hub - Fix diagnostic highlight accuracy by aligning offset calculations to UTF-16 code units (LSP spec) - Add diagnostic reason popover tooltip on cursor/mouse hover over error lines - Disable aggressive session restoration on launch to prevent startup tab switching and editor flickers - Add Welcome Hub in main window area featuring Recent Projects store with 1-click open, Middle-truncation, and Finder actions - Add gopls integration with staticcheck, analyses, and unimported completions - Add gofmt formatting on save and via Shift+Option+F shortcut - Add Product menu commands for Run (Cmd+R) and Test (Cmd+U) in integrated terminal drawer - Inject Go and local toolchain paths into GUI subprocess PATH environment
…d live diagnostics - Synchronously sync document edits in DocumentTextCoordinator to guarantee immediate tab dirty indicator - Extract TabItemView with @bindable document observation in TabBarView - Add .id(document.id) to CodeEditorView to avoid stale tab coordinators and bindings - Support trigger characters and range-based offset resolution for LSP code suggestions - Dispatch LSP onDiagnosticsChanged to MainActor for real-time continuous linting and underlining
Yan123-tech
force-pushed
the
fix/ui-stability-and-diagnostics
branch
from
October 12, 2026 12:53
f976e02 to
88a0c5f
Compare
Yan123-tech
pushed a commit
that referenced
this pull request
Oct 12, 2026
…r/goto-def/settings - CURRENT_STATE.md: 113→115 tests; diagnostics + hover/def + settings marked working; status bar diagnostic-count mention; size table bumped for 5 new files (Diagnostic.swift, DocumentDiagnosticsTests, LSPTextViewCoordinator edits, SettingsView, StatusBarView edits) - PROJECT_PLAN.md: #2, #3, #4 marked done; test-count gate updated - MEMORY.md: #23 on Picker(selection:) resolving to init(sources:) on this toolchain; FAQ entries for settings picker + diagnostic colours Closes the 'before you call it done' checklist for issues #2, #3, #4.
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.
Summary
This PR addresses critical UI stability and editor presentation issues discovered during self-testing:
NSTextStorageattributes.Detailed Changes
1. Fix Tab Fluctuation & Editor Flickering
FileExplorerView's.task(id: activeDocumentURL)calledrevealActiveDocument(), mutatingselection. This triggered.onChange(of: selection)which calledonOpenFile(item.url), re-activating the document asynchronously and creating a cyclical feedback loop that repeatedly reloaded the editor.isSyncingSelectioninFileExplorerViewto guard.onChange(of: selection).activate(_:)inFileExplorerViewfrom re-opening items whenitem.url == activeDocumentURL.guard activeDocument !== document else { return }inDocumentManager.activate(_:).2. Fix LSP Diagnostic Underlining in Code Editor Area
NSTextStorage.CodeEditTextViewCoreText layout does not render standard TextKit underline attributes, andCodeEditSourceEditor's Tree-sitterHighlighterwipes raw storage attributes on every pass.LSPTextViewCoordinatortoCodeEditTextView's nativeEmphasisManager(textView.emphasisManager?.replaceEmphases(...)), drawing stableCAShapeLayerunderlines with semantic theme colors.publishDiagnosticsclient capability inLSPTypes.swiftand madeDiagnosticdecoding fault-tolerant against arbitrary server fields.3. Fix Line Number Gutter Layering on Scroll
GutterViewinCodeEditSourceEditoris anNSScrollViewfloating subview. When scrolling, AppKit subviews rendered over sibling SwiftUI views becauseeditorArealacked clipping andTabBarViewhad default z-index..zIndex(1)and.clipped()toTabBarView..clipped()toeditorAreaandCodeEditorViewinMainWindowView.swiftto ensure all overscroll and floating views remain masked to editor bounds.4. Fix Folder Expansion Requiring Selection
selection = item; fileSystemManager.toggleExpansion(of: item). For unselected folders, settingselectiontriggered.onChange(of: selection) -> activate() -> toggleExpansion()a second time, immediately reversing the toggle.selection = itemfrom the chevron disclosure control inFileExplorerView..rightArrowto expand,.leftArrowto collapse).Documentation
docs/MEMORY.md(entries #24, #25, #26, #27).Verification
swift test: All 115 unit & integration tests in 32 suites passed../Scripts/build-app.sh: Release.appbuilt and ad-hoc signed cleanly (106MB).