Skip to content

Commit 34cd411

Browse files
committed
Fake code to call positronConsole.executeCode with uri, position returning position
1 parent 9ea8e83 commit 34cd411

File tree

5 files changed

+48
-57
lines changed

5 files changed

+48
-57
lines changed

apps/vscode/src/host/executors.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ import { documentFrontMatter } from "../markdown/document";
2222
import { isExecutableLanguageBlockOf } from "quarto-core";
2323
import { workspace } from "vscode";
2424
import { JupyterKernelspec } from "core";
25+
import { Position } from "vscode";
2526

2627
export interface CellExecutor {
2728
execute: (blocks: string[], editorUri?: Uri) => Promise<void>;
2829
executeSelection?: () => Promise<void>;
30+
executeSelectionAtPosition?: (uri: Uri, pos: Position) => Promise<Position>;
2931
}
3032

3133
export function executableLanguages() {

apps/vscode/src/host/hooks.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import { CellExecutor, cellExecutorForLanguage, executableLanguages, isKnitrDocu
2323
import { ExecuteQueue } from './execute-queue';
2424
import { MarkdownEngine } from '../markdown/engine';
2525
import { virtualDoc, adjustedPosition, unadjustedRange, withVirtualDocUri } from "../vdoc/vdoc";
26+
import { Position } from 'vscode';
27+
import { Uri } from 'vscode';
2628

2729
declare global {
2830
function acquirePositronApi(): hooks.PositronApi;
@@ -83,6 +85,12 @@ export function hooksExtensionHost(): ExtensionHost {
8385
},
8486
executeSelection: async (): Promise<void> => {
8587
await vscode.commands.executeCommand('workbench.action.positronConsole.executeCode', { languageId: language });
88+
},
89+
executeSelectionAtPosition: async (uri: Uri, position: Position): Promise<Position> => {
90+
return await vscode.commands.executeCommand(
91+
'workbench.action.positronConsole.executeCode',
92+
{ languageId: language, uri, position }
93+
);
8694
}
8795
};
8896

apps/vscode/src/providers/cell/commands.ts

Lines changed: 27 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import {
4646
codeWithoutOptionsFromBlock,
4747
executeInteractive,
4848
executeSelectionInteractive,
49+
executionSelectionAtPositionInteractive,
4950
} from "./executors";
5051
import { ExtensionHost } from "../../host";
5152
import { tryAcquirePositronApi } from "@posit-dev/positron";
@@ -265,15 +266,7 @@ class RunPreviousCellCommand extends RunCommand implements Command {
265266

266267
// More permissive type than `Position` so its easier to construct via a literal
267268
type LineAndCharPos = { line: number, character: number; };
268-
// More permissive type than `Range` so its easier to construct via a literal
269-
type LineAndCharRange = { start: LineAndCharPos, end: LineAndCharPos; };
270-
271-
function extractRangeFromCode(code: string, range: LineAndCharRange): string {
272-
const extractedRange = lines(code).slice(range.start.line, range.end.line + 1);
273-
extractedRange[0] = extractedRange[0].slice(range.start.character);
274-
extractedRange[extractedRange.length - 1] = extractedRange[extractedRange.length - 1].slice(0, range.end.character);
275-
return extractedRange.join('\n');
276-
}
269+
277270

278271
// Run the code at the cursor
279272
class RunCurrentCommand extends RunCommand implements Command {
@@ -355,14 +348,6 @@ class RunCurrentCommand extends RunCommand implements Command {
355348
const selection = context.selectedText;
356349
const activeBlock = context.blocks.find(block => block.active);
357350

358-
const exec = async (action: CodeViewSelectionAction, selection: string) => {
359-
const executor = await this.cellExecutorForLanguage(context.activeLanguage, editor.document, this.engine_);
360-
if (executor) {
361-
await executeInteractive(executor, [selection], editor.document);
362-
await editor.setBlockSelection(context, action);
363-
}
364-
};
365-
366351
// if in Positron
367352
if (isPositron) {
368353
if (activeBlock && selection.length <= 0) {
@@ -376,43 +361,23 @@ class RunCurrentCommand extends RunCommand implements Command {
376361
new Position(p.line + injectedLines, p.character);
377362
const positionOutOfVdoc = (p: LineAndCharPos) =>
378363
new Position(p.line - injectedLines, p.character);
379-
const rangeOutOfVdoc = (r: Range): LineAndCharRange => ({
380-
start: positionOutOfVdoc(r.start),
381-
end: positionOutOfVdoc(r.end)
382-
});
383-
const getStatementRange = async (pos: LineAndCharPos) => {
384-
const result = await withVirtualDocUri(vdoc, parentUri, "statementRange", async (uri) => {
385-
return await commands.executeCommand<StatementRange>(
386-
"vscode.executeStatementRangeProvider",
364+
365+
const executor = await this.cellExecutorForLanguage(context.activeLanguage, editor.document, this.engine_);
366+
if (executor) {
367+
const nextStatementPos = await withVirtualDocUri(
368+
vdoc,
369+
parentUri,
370+
"executeSelectionAtPositionInteractive",
371+
(uri) => executionSelectionAtPositionInteractive(
372+
executor,
387373
uri,
388-
positionIntoVdoc(pos)
389-
);
390-
});
391-
return rangeOutOfVdoc(result.range);
392-
};
393-
394-
const range = await getStatementRange(context.selection.start);
395-
const code = extractRangeFromCode(activeBlock.code, range);
396-
397-
// BEGIN ref: https://github.com/posit-dev/positron/blob/main/src/vs/workbench/contrib/positronConsole/browser/positronConsoleActions.ts#L428
398-
// strategy from Positron using `StatementRangeProvider` to find range of next statement
399-
// and move cursor based on that.
400-
if (range.end.line + 1 <= codeLines.length) {
401-
// get range of statement at line after current statement)
402-
const nextRange = await getStatementRange(new Position(range.end.line + 1, 1));
403-
404-
if (nextRange.start.line > range.end.line) {
405-
exec(nextRange.start, code);
406-
// the next statement range may start before & end after the current statement if e.g. inside a function:
407-
} else if (nextRange.end.line > range.end.line) {
408-
exec(nextRange.end, code);
409-
} else {
410-
exec("nextline", code);
374+
positionIntoVdoc(context.selection.start)
375+
)
376+
);
377+
if (nextStatementPos !== undefined) {
378+
await editor.setBlockSelection(context, positionOutOfVdoc(nextStatementPos));
411379
}
412-
} else {
413-
exec("nextline", code);
414380
}
415-
// END ref.
416381
}
417382
}
418383
// if not in Positron
@@ -427,11 +392,18 @@ class RunCurrentCommand extends RunCommand implements Command {
427392
}
428393
}
429394
} else {
430-
if (selection.length > 0) {
431-
exec("nextline", selection);
432-
} else if (activeBlock) { // if the selection is empty take the whole line as the selection
433-
exec("nextline", lines(activeBlock.code)[context.selection.start.line]);
395+
const executor = await this.cellExecutorForLanguage(context.activeLanguage, editor.document, this.engine_);
396+
if (executor) {
397+
if (selection.length > 0) {
398+
await executeInteractive(executor, [selection], editor.document);
399+
await editor.setBlockSelection(context, "nextline");
400+
} else if (activeBlock) { // if the selection is empty take the whole line as the selection
401+
await executeInteractive(executor, [lines(activeBlock.code)[context.selection.start.line]], editor.document);
402+
await editor.setBlockSelection(context, "nextline");
403+
}
404+
434405
}
406+
435407
}
436408
}
437409
}

apps/vscode/src/providers/cell/executors.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ import { cellOptionsForToken, kExecuteEval } from "./options";
3434

3535
import { CellExecutor, ExtensionHost } from "../../host";
3636
import { executableLanguages } from "../../host/executors";
37+
import { Position } from "vscode";
38+
import { Uri } from "vscode";
3739

3840

3941
export function hasExecutor(_host: ExtensionHost, language: string) {
@@ -90,6 +92,12 @@ export async function executeInteractive(
9092
return await executor.execute(blocks, !document.isUntitled ? document.uri : undefined);
9193
}
9294

95+
96+
export async function executionSelectionAtPositionInteractive(executor: CellExecutor, uri: Uri, position: Position) {
97+
if (executor?.executeSelectionAtPosition) {
98+
return await executor.executeSelectionAtPosition(uri, position);
99+
}
100+
}
93101
// attempt language aware execution of current selection (returns false
94102
// if the executor doesn't support this, in which case generic
95103
// executeInteractive will be called)

apps/vscode/src/vdoc/vdoc.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,10 @@ export type VirtualDocAction =
118118
"definition" |
119119
"format" |
120120
"statementRange" |
121-
"helpTopic";
121+
"helpTopic" |
122+
"executeSelectionAtPositionInteractive";
122123

123-
export type VirtualDocUri = { uri: Uri, cleanup?: () => Promise<void> };
124+
export type VirtualDocUri = { uri: Uri, cleanup?: () => Promise<void>; };
124125

125126
/**
126127
* Execute a callback on a virtual document's temporary URI

0 commit comments

Comments
 (0)