Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update 'workbench.action.positronConsole.executeCode' to be used in Quarto #3107

Merged
merged 7 commits into from
May 22, 2024
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*---------------------------------------------------------------------------------------------
* Copyright (C) 2024 Posit Software, PBC. All rights reserved.
*--------------------------------------------------------------------------------------------*/

import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import * as languages from 'vs/editor/common/languages';
import { onUnexpectedExternalError } from 'vs/base/common/errors';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { assertType } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
import { IPosition, Position } from 'vs/editor/common/core/position';
import { ITextModel } from 'vs/editor/common/model';
import { IModelService } from 'vs/editor/common/services/model';
import { CancellationToken } from 'vs/base/common/cancellation';


async function provideStatementRange(
registry: LanguageFeatureRegistry<languages.StatementRangeProvider>,
model: ITextModel,
position: Position,
token: CancellationToken
): Promise<languages.IStatementRange | undefined> {

const providers = registry.ordered(model);

for (const provider of providers) {
try {
const result = await provider.provideStatementRange(model, position, token);
if (result) {
return result;
}
} catch (err) {
onUnexpectedExternalError(err);
}
}
return undefined;
}

CommandsRegistry.registerCommand('_executeStatementRangeProvider', async (accessor, ...args: [URI, IPosition]) => {
juliasilge marked this conversation as resolved.
Show resolved Hide resolved
const [uri, position] = args;
assertType(URI.isUri(uri));
assertType(Position.isIPosition(position));

const model = accessor.get(IModelService).getModel(uri);
if (!model) {
return undefined;
}
const languageFeaturesService = accessor.get(ILanguageFeaturesService);
return await provideStatementRange(
languageFeaturesService.statementRangeProvider,
model,
Position.lift(position),
CancellationToken.None
);
});
1 change: 1 addition & 0 deletions src/vs/editor/editor.all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import 'vs/editor/contrib/diffEditorBreadcrumbs/browser/contribution';

// --- Start Positron ---
import 'vs/editor/contrib/positronEditorActions/browser/positronEditorActions';
import 'vs/editor/contrib/positronStatementRange/browser/provideStatementRange';
// --- End Positron ---

// Load up these strings even in VSCode, even if they are not used
Expand Down
15 changes: 4 additions & 11 deletions src/vs/workbench/api/common/extHostApiCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { StatementRange } from 'positron';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { VSBuffer } from 'vs/base/common/buffer';
import { Schemas, matchesSomeScheme } from 'vs/base/common/network';
Expand Down Expand Up @@ -489,18 +490,10 @@ const newCommands: ApiCommand[] = [
// -- statement range
new ApiCommand(
'vscode.executeStatementRangeProvider', '_executeStatementRangeProvider', 'Execute statement range provider.',
[ApiCommandArgument.Uri,
new ApiCommandArgument<types.Position, IPosition>('position',
'A position in a text document',
// validator: check for a valid position
v => types.Position.isPosition(v),
// converter: convert from vscode.Position to IPosition (API type)
v => {
return typeConverters.Position.from(v);
})],
new ApiCommandResult<IRange, types.Range>('A promise that resolves to a range.', result => {
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
new ApiCommandResult<languages.IStatementRange, StatementRange>('A promise that resolves to a statement range.', result => {
// converter: convert from IRange (API type) to vscode.Range
return typeConverters.Range.to(result);
return { range: typeConverters.Range.to(result.range), code: result.code };
})
),
// --- End Positron
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,11 @@ export function registerPositronConsoleActions() {
/**
* Runs action.
* @param accessor The services accessor.
* @param opts Options for code execution
* - allowIncomplete: Optionally, should incomplete statements be accepted? If `undefined`, treated as `false`.
* - languageId: Optionally, a language override for the code to execute. If `undefined`, the language of the active text editor is used. Useful for notebooks.
*/
async run(accessor: ServicesAccessor, opts: { allowIncomplete?: boolean } = {}) {
async run(accessor: ServicesAccessor, opts: { allowIncomplete?: boolean; languageId?: string } = {}) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Quarto extension knows what language we are using and can send it over in opts.

// Access services.
const editorService = accessor.get(IEditorService);
const languageFeaturesService = accessor.get(ILanguageFeaturesService);
Expand Down Expand Up @@ -499,7 +502,7 @@ export function registerPositronConsoleActions() {
}

// Now that we've gotten this far, ensure we have a target language.
const languageId = editorService.activeTextEditorLanguageId;
const languageId = opts.languageId ? opts.languageId : editorService.activeTextEditorLanguageId;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to update here to get the console to execute it in the correct runtime.

if (!languageId) {
notificationService.notify({
severity: Severity.Info,
Expand All @@ -513,7 +516,7 @@ export function registerPositronConsoleActions() {
// By default, we don't allow incomplete code to be executed, but the language runtime can override this.
// This means that if allowIncomplete is false or undefined, the incomplete code will not be sent to the backend for execution.
// The console will continue to wait for more input until the user completes the code, or cancels out of the operation.
const { allowIncomplete } = opts;
const allowIncomplete = opts.allowIncomplete;


// Ask the Positron console service to execute the code. Do not focus the console as
Expand Down
Loading