Skip to content

Commit

Permalink
Merge branch 'main' into try-unique-temp-file-for-vdoc
Browse files Browse the repository at this point in the history
  • Loading branch information
juliasilge authored Oct 29, 2024
2 parents 74a30bc + 7d1582d commit e0c9a64
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 97 deletions.
1 change: 1 addition & 0 deletions apps/vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## 1.117.0 (unreleased)

- Fix issue with temp files for LSP request virtual documents (<https://github.com/quarto-dev/quarto/pull/585>)
- Improved statement execution for Python `.qmd` files in Positron (<https://github.com/quarto-dev/quarto/pull/589>)

## 1.116.0 (Release on 2024-10-08)

Expand Down
91 changes: 49 additions & 42 deletions apps/vscode/src/host/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ import { ExtensionHost, HostWebviewPanel, HostStatementRangeProvider } from '.';
import { CellExecutor, cellExecutorForLanguage, executableLanguages, isKnitrDocument, pythonWithReticulate } from './executors';
import { ExecuteQueue } from './execute-queue';
import { MarkdownEngine } from '../markdown/engine';
import { virtualDoc, virtualDocUri, adjustedPosition } from "../vdoc/vdoc";
import { virtualDoc, virtualDocUri, adjustedPosition, unadjustedRange } from "../vdoc/vdoc";
import { EmbeddedLanguage } from '../vdoc/languages';

declare global {
function acquirePositronApi() : hooks.PositronApi;
function acquirePositronApi(): hooks.PositronApi;
}

let api : hooks.PositronApi | null | undefined;
let api: hooks.PositronApi | null | undefined;

export function hooksApi() : hooks.PositronApi | null {
export function hooksApi(): hooks.PositronApi | null {
if (api === undefined) {
try {
api = acquirePositronApi();
Expand All @@ -43,20 +44,20 @@ export function hasHooks() {
return !!hooksApi();
}

export function hooksExtensionHost() : ExtensionHost {
export function hooksExtensionHost(): ExtensionHost {
return {
// supported executable languages (we delegate to the default for langugaes
// w/o runtimes so we support all languages)
executableLanguages,

cellExecutorForLanguage: async (language: string, document: vscode.TextDocument, engine: MarkdownEngine, silent?: boolean)
cellExecutorForLanguage: async (language: string, document: vscode.TextDocument, engine: MarkdownEngine, silent?: boolean)
: Promise<CellExecutor | undefined> => {
switch(language) {
switch (language) {
// use hooks for known runtimes
case "python":
case "r":
return {
execute: async (blocks: string[], _editorUri?: vscode.Uri) : Promise<void> => {
execute: async (blocks: string[], _editorUri?: vscode.Uri): Promise<void> => {
const runtime = hooksApi()?.runtime;

if (runtime === undefined) {
Expand All @@ -68,7 +69,7 @@ export function hooksExtensionHost() : ExtensionHost {
language = "r";
blocks = blocks.map(pythonWithReticulate);
}

// Our callback executes each block sequentially
const callback = async () => {
for (const block of blocks) {
Expand All @@ -78,9 +79,9 @@ export function hooksExtensionHost() : ExtensionHost {

await ExecuteQueue.instance.add(language, callback);
},
executeSelection: async () : Promise<void> => {
await vscode.commands.executeCommand('workbench.action.positronConsole.executeCode', {languageId: language});
}
executeSelection: async (): Promise<void> => {
await vscode.commands.executeCommand('workbench.action.positronConsole.executeCode', { languageId: language });
}
};

// delegate for other languages
Expand All @@ -92,16 +93,16 @@ export function hooksExtensionHost() : ExtensionHost {
registerStatementRangeProvider: (engine: MarkdownEngine): vscode.Disposable => {
const hooks = hooksApi();
if (hooks) {
return hooks.languages.registerStatementRangeProvider('quarto',
return hooks.languages.registerStatementRangeProvider('quarto',
new EmbeddedStatementRangeProvider(engine));
}
return new vscode.Disposable(() => {});
return new vscode.Disposable(() => { });
},

createPreviewPanel: (
viewType: string,
viewType: string,
title: string,
preserveFocus?: boolean,
preserveFocus?: boolean,
options?: vscode.WebviewPanelOptions & vscode.WebviewOptions
): HostWebviewPanel => {

Expand All @@ -117,7 +118,7 @@ export function hooksExtensionHost() : ExtensionHost {
portMapping: options?.portMapping
}
)!;

// adapt to host interface
return new HookWebviewPanel(panel);
}
Expand All @@ -126,7 +127,7 @@ export function hooksExtensionHost() : ExtensionHost {


class HookWebviewPanel implements HostWebviewPanel {
constructor(private readonly panel_: hooks.PreviewPanel) {}
constructor(private readonly panel_: hooks.PreviewPanel) { }

get webview() { return this.panel_.webview; };
get visible() { return this.panel_.visible; };
Expand All @@ -139,43 +140,49 @@ class HookWebviewPanel implements HostWebviewPanel {
}

class EmbeddedStatementRangeProvider implements HostStatementRangeProvider {
private readonly _engine: MarkdownEngine;
private readonly _engine: MarkdownEngine;

constructor(
readonly engine: MarkdownEngine,
) {
this._engine = engine;
}
constructor(
readonly engine: MarkdownEngine,
) {
this._engine = engine;
}

async provideStatementRange(
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken): Promise<hooks.StatementRange | undefined> {
const vdoc = await virtualDoc(document, position, this._engine);
if (vdoc) {
const vdocUri = await virtualDocUri(vdoc, document.uri, "statementRange");
try {
return getStatementRange(vdocUri.uri, adjustedPosition(vdoc.language, position));
} catch (error) {
return undefined;
} finally {
if (vdocUri.cleanup) {
await vdocUri.cleanup();
}
}
} else {
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken): Promise<hooks.StatementRange | undefined> {
const vdoc = await virtualDoc(document, position, this._engine);
if (vdoc) {
const vdocUri = await virtualDocUri(vdoc, document.uri, "statementRange");
try {
return getStatementRange(
vdocUri.uri,
adjustedPosition(vdoc.language, position),
vdoc.language
);
} catch (error) {
return undefined;
} finally {
if (vdocUri.cleanup) {
await vdocUri.cleanup();
}
}
};
} else {
return undefined;
}
};
}

async function getStatementRange(
uri: vscode.Uri,
position: vscode.Position,
language: EmbeddedLanguage
) {
return await vscode.commands.executeCommand<hooks.StatementRange>(
const result = await vscode.commands.executeCommand<hooks.StatementRange>(
"vscode.executeStatementRangeProvider",
uri,
position
);
return { range: unadjustedRange(language, result.range), code: result.code };
}
Loading

0 comments on commit e0c9a64

Please sign in to comment.