Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ public/dist
/.luarc.json
.vscode-test
*.vsix
*.timestamp-*.mjs
29 changes: 27 additions & 2 deletions apps/lsp/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ export class ConfigurationManager extends Disposable {

private _settings: Settings;
private _logger: ILogger;
private _activeColorThemeKind: "light" | "dark" = "dark";
private _themeExplicitlySet = false;

constructor(
private readonly connection_: Connection,
Expand Down Expand Up @@ -177,6 +179,18 @@ export class ConfigurationManager extends Disposable {
}
}
};

// Fallback: try to detect theme from name if we haven't received an explicit notification yet
// This is a best-effort approach for compatibility, but won't work with autoDetectColorScheme
// Only apply fallback if theme hasn't been explicitly set via notification
if (!this._themeExplicitlySet) {
if (settings.workbench.colorTheme.includes("Light")) {
this._activeColorThemeKind = "light";
} else if (settings.workbench.colorTheme.includes("Dark")) {
this._activeColorThemeKind = "dark";
}
}

this._onDidChangeConfiguration.fire(this._settings);
}

Expand All @@ -202,6 +216,18 @@ export class ConfigurationManager extends Disposable {
public getSettings(): Settings {
return this._settings;
}

public setActiveColorThemeKind(kind: "light" | "dark") {
if (this._activeColorThemeKind !== kind) {
this._activeColorThemeKind = kind;
this._themeExplicitlySet = true;
this._onDidChangeConfiguration.fire(this._settings);
}
}

public getActiveColorThemeKind(): "light" | "dark" {
return this._activeColorThemeKind;
}
}

export function lsConfiguration(configManager: ConfigurationManager): LsConfiguration {
Expand All @@ -226,8 +252,7 @@ export function lsConfiguration(configManager: ConfigurationManager): LsConfigur
}
},
get colorTheme(): "light" | "dark" {
const settings = configManager.getSettings();
return settings.workbench.colorTheme.includes("Light") ? "light" : "dark";
return configManager.getActiveColorThemeKind();
},
get mathjaxScale(): number {
return configManager.getSettings().quarto.mathjax.scale;
Expand Down
11 changes: 11 additions & 0 deletions apps/lsp/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,17 @@ connection.onInitialized(async () => {
logger.setConfigurationManager(configManager);
}

// listen for color theme changes from the client
connection.onNotification("quarto/didChangeActiveColorTheme", (params: { kind: string; }) => {
logger.logNotification('didChangeActiveColorTheme');
// Validate the theme kind before using it
if (params.kind === "light" || params.kind === "dark") {
configManager.setActiveColorThemeKind(params.kind);
} else {
logger.logError(`Invalid theme kind received: ${params.kind}`);
}
});

// initialize connection to quarto
const workspaceFolders = await connection.workspace.getWorkspaceFolders();
const workspaceDir = workspaceFolders?.length
Expand Down
25 changes: 24 additions & 1 deletion apps/vscode/src/lsp/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ import {
Definition,
LogOutputChannel,
Uri,
Diagnostic
Diagnostic,
window,
ColorThemeKind
} from "vscode";
import {
LanguageClient,
Expand Down Expand Up @@ -151,12 +153,33 @@ export async function activateLsp(
clientOptions
);

// Helper to send current theme to LSP server
const sendThemeNotification = () => {
if (client) {
// Map VS Code theme kinds to light/dark. HighContrast themes are treated as dark
// since they typically have light text on dark backgrounds
const kind = (window.activeColorTheme.kind === ColorThemeKind.Light || window.activeColorTheme.kind === ColorThemeKind.HighContrastLight) ? "light" : "dark";
client.sendNotification("quarto/didChangeActiveColorTheme", { kind });
}
};

// Listen for theme changes and notify the server
context.subscriptions.push(
window.onDidChangeActiveColorTheme(() => {
sendThemeNotification();
})
);

// return once the server is running
return new Promise<LanguageClient>((resolve, reject) => {

const handler = client.onDidChangeState(e => {
if (e.newState === State.Running) {
handler.dispose();
// Send initial theme on startup, slightly delayed to ensure server is ready
setTimeout(() => {
sendThemeNotification();
}, 100);
resolve(client);
} else if (e.newState === State.Stopped) {
reject(new Error("Failed to start Quarto LSP Server"));
Expand Down