feat(lsp): show resolved color on hover - #39
Merged
Conversation
Register a textDocument/documentColor LSP provider that walks var() tokens in property values, recursively resolves them, and emits ColorInformation when the resolved value is a color. Definition sites (--*) are skipped to avoid duplicating VSCode's built-in CSS color provider. colorPresentation returns an empty array — color picker editing is not supported in this iteration. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
VSCode's ColorDetector only re-queries documentColor for files whose content changed. When a definition file is edited, usage files in other editors keep stale swatches because their text didn't change. When the client supports dynamic registration, register the color provider via client/registerCapability and re-register on changes that may affect cross-file color resolution. VSCode's colorProviderRegistry.onDidChange triggers ColorDetector to recompute on every open editor; back-to-back unregister+register coalesces into a single recompute (no flicker, no duplicates). Falls back to static ColorProviderCapability::Simple(true) when the client doesn't advertise dynamic_registration. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ange" This reverts commit 25cdf85.
This reverts commit 4bb2a14.
Replaces the abandoned textDocument/documentColor implementation with a hover-based preview. var(--name) usages now show the resolved value on hover, with a markdown color swatch when the value parses as a color. Multiple definitions across files are listed with their locations. Hover is re-queried by the client on every cursor move, so cross-file edits propagate without needing a workspace refresh request — the missing piece that broke documentColor in Helix and Zed. See docs/lsp-document-color-refresh.md for background. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… form Hover was running each definition through lightningcss's serializer, which rewrites colors into their shortest equivalent form (`hsl(0, 100%, 50%)` → `red`, `#00ff00` → `#0f0`). For users who write tokens in hsl or hwb, the hovered text no longer matched the source. Walk var() chains using the parsed token list but return each terminal definition's raw source text. Fallback resolution (when the var is undefined and the call has a fallback) still goes through the serializer since there is no source definition to copy from. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A bare `\n` between entries collapsed onto one line in markdown — the list-bullet rendering that previously separated them was removed when the `- ` prefix was dropped. Switch to ` \n` (trailing two spaces) so each definition renders on its own line. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…bility Zed's hover renderer ignores the trailing-two-space hard break that VSCode honors, collapsing multiple definitions onto one line. A blank line (paragraph break) is rendered consistently across VSCode, Zed, and Helix. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Helix renders \n\n as a true paragraph break with a blank line between entries, while VSCode and Zed collapse it to a single line gap. There is no markdown sequence that produces the same visual spacing in all three clients, so capture client_info.name from the initialize request and pick the separator per client: trailing two-space hard break for Helix, paragraph break for everyone else. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Reuse the hover formatting helpers to populate each completion item's documentation field. Single-def items show the resolved value with a swatch when applicable; multi-def items list every definition with its file:line location, matching what hover renders. The detail field still shows just the last value so the inline preview stays compact. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
VSCode renders the inline SVG data URI in hover popups but blocks it in the completion documentation panel, which appears to suppress the popup entirely. Plumb an include_swatch flag through the formatters and pass false from completion so the documentation contains text-only entries. Hover behavior is unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a faint "cvk" description to the right of each completion label, making our items visually distinguishable from those provided by other CSS language servers. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Move the inline value display to labelDetails.detail and gate it on single-definition variables. When multiple definitions exist, the inline value is ambiguous, so the value is shown only in the hover and the completion documentation panel. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The hover-color/components/app.css fixture was reformatted from single-line to multi-line in d44b24a, but lsp_hover.rs was still addressing the old layout, so every hover position request landed past end-of-line and the server returned null. Realign the line/col arguments and the inline layout comment. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace bespoke string-scanning (extract_enclosing_var_call, resolve_var_call) with a check against the Searcher's already-tracked variable usages: locate the property whose value byte range contains the cursor, then look up the Var token by name in its parsed token list. Drops the substring re-parse path entirely. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Move format_single, format_multi_def, resolve_to_raw_value, multi_def_separator and the swatch_markdown helper out of hover.rs into a new var_markdown module so completion no longer reaches across into the hover module for them. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Both hover content and completion documentation are forms of variable description, so name the module after that role. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Drop the line-scanning extract_variable_at_cursor + name-keyed find_var_by_name lookup in favour of walking the matched property's parsed Var tokens in source order, locating each ident inside value.raw and checking whether the cursor falls within its --name span. Restores byte_range_to_lsp_range now that the LSP range comes from absolute byte offsets. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Drop the separate relative-cursor calculation and the named name_start/name_end intermediates: thread search_from through scan, compute the var's absolute name range once, and pick the matching range with find against the absolute cursor. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Make multi_def_separator private inside description.rs so callers no longer need to pre-resolve the separator string. Both hover and completion now thread Option<&str> client_name through their helper chains; format_multi_def picks the appropriate separator internally. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
jo16oh
force-pushed
the
22-feat-show-resolved-color-in-vscode
branch
from
May 1, 2026 06:19
6e9dc22 to
efa3102
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.
#22