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

Add RuntimeCodeExecutionMode to runtime.executeCode() in the API #5450

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
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
25 changes: 16 additions & 9 deletions extensions/positron-zed/src/positronZedLanguageRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ const HelpLines = [
'env rm X - Removes X variables',
'env update X - Updates X variables',
'error X Y Z - Simulates an unsuccessful X line input with Y lines of error message and Z lines of traceback (where X >= 1 and Y >= 1 and Z >= 0)',
'exec X Y - Executes a code snippet Y in the language X',
'exec silent X Y - Executes a code snippet Y in the language X silently',
'exec X Y - Executes a code snippet Y in the language X interactively',
dhruvisompura marked this conversation as resolved.
Show resolved Hide resolved
'fancy - Simulates fancy HTML output',
'flicker - Simulates a flickering console prompt',
'help - Shows this help',
Expand Down Expand Up @@ -381,16 +382,17 @@ export class PositronZedRuntimeSession implements positron.LanguageRuntimeSessio
this.shutdown();
}
return;
// } else if (match = code.match(/^view( .+)?/)) {
// // Simulate a data viewer
// const title = (match.length > 1 && match[1]) ? match[1].trim() : 'Data';
// this.simulateDataView(id, code, `Zed: ${title}`);
// return;
} else if (match = code.match(/^exec silent ([a-zA-Z]+) (.+)/)) {
// Execute code silently in another language.
const languageId = match[1];
const codeToExecute = match[2];
this.simulateCodeExecution(id, code, languageId, codeToExecute, positron.RuntimeCodeExecutionMode.Silent);
return;
} else if (match = code.match(/^exec ([a-zA-Z]+) (.+)/)) {
// Execute code in another language.
const languageId = match[1];
const codeToExecute = match[2];
this.simulateCodeExecution(id, code, languageId, codeToExecute);
this.simulateCodeExecution(id, code, languageId, codeToExecute, positron.RuntimeCodeExecutionMode.Interactive);
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 default value that code is executed as is RuntimeCodeExecutionMode.Interactive if a RuntimeCodeExecutionMode isn't provided so this is change is a 50/50 on if we want to explicitly provide the value here or not.

return;
} else if (match = code.match(/^preview( .+)?/)) {
const command = (match.length > 1 && match[1]) ? match[1].trim() : 'default';
Expand Down Expand Up @@ -1592,20 +1594,25 @@ export class PositronZedRuntimeSession implements positron.LanguageRuntimeSessio
* @param code The Zed code the user entered.
* @param languageId The language identifier
* @param codeToExecute The code to execute.
* @param mode The execution mode to conform to.
*/
private async simulateCodeExecution(parentId: string,
code: string,
languageId: string,
codeToExecute: string) {
codeToExecute: string,
mode: positron.RuntimeCodeExecutionMode) {
// Enter busy state and output the code.
this.simulateBusyState(parentId);
this.simulateInputMessage(parentId, code);

// Let the user know what we're about to do
this.simulateOutputMessage(parentId, `Executing ${languageId} snippet: ${codeToExecute}`);

// Don't focus the console if code should being executed silently
const focus = mode !== positron.RuntimeCodeExecutionMode.Silent;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I figured it makes sense to update the focus value based off the RuntimeCodeExecutionMode. Since this is all used for dev testing it doesn't really matter but this felt more sane than always having focus set to true.


// Perform the execution
const success = await positron.runtime.executeCode(languageId, codeToExecute, true, true);
const success = await positron.runtime.executeCode(languageId, codeToExecute, focus, true, mode);
if (!success) {
this.simulateOutputMessage(parentId, `Failed; is there an active console for ${languageId}?`);
}
Expand Down
4 changes: 3 additions & 1 deletion src/positron-dts/positron.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1213,13 +1213,15 @@ declare module 'positron' {
* @param focus Whether to focus the runtime's console
* @param allowIncomplete Whether to bypass runtime code completeness checks. If true, the `code`
* will be executed by the runtime even if it is incomplete or invalid. Defaults to false
* @param mode Possible code execution modes for a language runtime
* @returns A Thenable that resolves with true if the code was sent to a
* runtime successfully, false otherwise.
*/
export function executeCode(languageId: string,
code: string,
focus: boolean,
allowIncomplete?: boolean): Thenable<boolean>;
allowIncomplete?: boolean,
mode?: RuntimeCodeExecutionMode): Thenable<boolean>;

/**
* Register a language runtime manager with Positron. Returns a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1252,8 +1252,8 @@ export class MainThreadLanguageRuntime
}
}

$executeCode(languageId: string, code: string, focus: boolean, allowIncomplete?: boolean): Promise<boolean> {
return this._positronConsoleService.executeCode(languageId, code, focus, allowIncomplete);
$executeCode(languageId: string, code: string, focus: boolean, allowIncomplete?: boolean, mode?: RuntimeCodeExecutionMode): Promise<boolean> {
return this._positronConsoleService.executeCode(languageId, code, focus, allowIncomplete, mode);
}

public dispose(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ export function createPositronApiFactoryAndRegisterActors(accessor: ServicesAcce

// --- Start Positron ---
const runtime: typeof positron.runtime = {
executeCode(languageId, code, focus, allowIncomplete): Thenable<boolean> {
return extHostLanguageRuntime.executeCode(languageId, code, focus, allowIncomplete);
executeCode(languageId, code, focus, allowIncomplete, mode): Thenable<boolean> {
return extHostLanguageRuntime.executeCode(languageId, code, focus, allowIncomplete, mode);
},
registerLanguageRuntimeManager(
manager: positron.LanguageRuntimeManager): vscode.Disposable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export interface MainThreadLanguageRuntimeShape extends IDisposable {
$startLanguageRuntime(runtimeId: string, sessionName: string, sessionMode: LanguageRuntimeSessionMode, notebookUri: URI | undefined): Promise<string>;
$completeLanguageRuntimeDiscovery(): void;
$unregisterLanguageRuntime(handle: number): void;
$executeCode(languageId: string, code: string, focus: boolean, allowIncomplete?: boolean): Promise<boolean>;
$executeCode(languageId: string, code: string, focus: boolean, allowIncomplete?: boolean, mode?: RuntimeCodeExecutionMode): Promise<boolean>;
$getPreferredRuntime(languageId: string): Promise<ILanguageRuntimeMetadata>;
$getForegroundSession(): Promise<string | undefined>;
$getNotebookSession(notebookUri: URI): Promise<string | undefined>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -715,8 +715,8 @@ export class ExtHostLanguageRuntime implements extHostProtocol.ExtHostLanguageRu
});
}

public executeCode(languageId: string, code: string, focus: boolean, allowIncomplete?: boolean): Promise<boolean> {
return this._proxy.$executeCode(languageId, code, focus, allowIncomplete);
public executeCode(languageId: string, code: string, focus: boolean, allowIncomplete?: boolean, mode?: RuntimeCodeExecutionMode): Promise<boolean> {
return this._proxy.$executeCode(languageId, code, focus, allowIncomplete, mode);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { ParameterHintsController } from 'vs/editor/contrib/parameterHints/brows
import { IInputHistoryEntry } from 'vs/workbench/contrib/executionHistory/common/executionHistoryService';
import { SelectionClipboardContributionID } from 'vs/workbench/contrib/codeEditor/browser/selectionClipboard';
import { usePositronConsoleContext } from 'vs/workbench/contrib/positronConsole/browser/positronConsoleContext';
import { RuntimeCodeFragmentStatus } from 'vs/workbench/services/languageRuntime/common/languageRuntimeService';
import { RuntimeCodeExecutionMode, RuntimeCodeFragmentStatus } from 'vs/workbench/services/languageRuntime/common/languageRuntimeService';
import { HistoryBrowserPopup } from 'vs/workbench/contrib/positronConsole/browser/components/historyBrowserPopup';
import { HistoryInfixMatchStrategy } from 'vs/workbench/contrib/positronConsole/common/historyInfixMatchStrategy';
import { HistoryPrefixMatchStrategy } from 'vs/workbench/contrib/positronConsole/common/historyPrefixMatchStrategy';
Expand Down Expand Up @@ -866,11 +866,12 @@ export const ConsoleInput = (props: ConsoleInputProps) => {
}));

// Add the onDidExecuteCode event handler.
disposableStore.add(props.positronConsoleInstance.onDidExecuteCode(code => {
// Trim the code. If it isn't empty, or a duplicate of the last history entry, add it to
// the history.
disposableStore.add(props.positronConsoleInstance.onDidExecuteCode(({ code, mode }) => {
// Trim the code
const trimmedCode = code.trim();
if (trimmedCode.length) {

// If the code isn't empty and run interactively, add it to the history.
if (trimmedCode.length && mode === RuntimeCodeExecutionMode.Interactive) {
// Creates an IInputHistoryEntry.
const createInputHistoryEntry = (): IInputHistoryEntry => ({
when: new Date().getTime(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ export const ConsoleInstance = (props: ConsoleInstanceProps) => {
}));

// Add the onDidExecuteCode event handler.
disposableStore.add(props.positronConsoleInstance.onDidExecuteCode(_code => {
disposableStore.add(props.positronConsoleInstance.onDidExecuteCode(() => {
scrollToBottom();
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { ITextModel } from 'vs/editor/common/model';
import { IEditor } from 'vs/editor/common/editorCommon';
import { ILogService } from 'vs/platform/log/common/log';
import { Position } from 'vs/editor/common/core/position';
import { IStatementRange, StatementRangeProvider } from 'vs/editor/common/languages';
import { CancellationToken } from 'vs/base/common/cancellation';
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { ILocalizedString } from 'vs/platform/action/common/action';
Expand All @@ -22,10 +21,12 @@ import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
import { IViewsService } from 'vs/workbench/services/views/common/viewsService';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IStatementRange, StatementRangeProvider } from 'vs/editor/common/languages';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { NOTEBOOK_EDITOR_FOCUSED } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
import { RuntimeCodeExecutionMode } from 'vs/workbench/services/languageRuntime/common/languageRuntimeService';
import { IExecutionHistoryService } from 'vs/workbench/contrib/executionHistory/common/executionHistoryService';
import { IPositronModalDialogsService } from 'vs/workbench/services/positronModalDialogs/common/positronModalDialogs';
import { IPositronConsoleService, POSITRON_CONSOLE_VIEW_ID } from 'vs/workbench/services/positronConsole/browser/interfaces/positronConsoleService';
Expand Down Expand Up @@ -268,14 +269,16 @@ export function registerPositronConsoleActions() {
* @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.
* @param advance Whether to advance the cursor to the next statement.
* - advance: Optionally, if the cursor should be advanced to the next statement. If `undefined`, fallbacks to `true`.
* - mode: Optionally, the code execution mode for a language runtime. If `undefined` fallbacks to `Interactive`.
*/
async run(
accessor: ServicesAccessor,
opts: {
allowIncomplete?: boolean;
languageId?: string;
advance?: boolean;
mode?: RuntimeCodeExecutionMode;
} = {}
) {
// Access services.
Expand Down Expand Up @@ -427,7 +430,7 @@ export function registerPositronConsoleActions() {

// Ask the Positron console service to execute the code. Do not focus the console as
// this will rip focus away from the editor.
if (!await positronConsoleService.executeCode(languageId, code, false, allowIncomplete)) {
if (!await positronConsoleService.executeCode(languageId, code, false, allowIncomplete, opts.mode)) {
const languageName = languageService.getLanguageName(languageId);
notificationService.notify({
severity: Severity.Info,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
import { Event } from 'vs/base/common/event';
import { IEditor } from 'vs/editor/common/editorCommon';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ActivityItemPrompt } from 'vs/workbench/services/positronConsole/browser/classes/activityItemPrompt';
import { RuntimeItem } from 'vs/workbench/services/positronConsole/browser/classes/runtimeItem';
import { ILanguageRuntimeSession } from 'vs/workbench/services/runtimeSession/common/runtimeSessionService';
import { ActivityItemPrompt } from 'vs/workbench/services/positronConsole/browser/classes/activityItemPrompt';
import { RuntimeCodeExecutionMode } from 'vs/workbench/services/languageRuntime/common/languageRuntimeService';

// Create the decorator for the Positron console service (used in dependency injection).
export const IPositronConsoleService = createDecorator<IPositronConsoleService>('positronConsoleService');
Expand Down Expand Up @@ -88,9 +89,10 @@ export interface IPositronConsoleService {
* @param focus A value which indicates whether to focus Positron console instance.
* @param allowIncomplete Whether to bypass runtime code completeness checks. If true, the `code`
* will be executed by the runtime even if it is incomplete or invalid. Defaults to false
* @param mode Possible code execution modes for a language runtime
* @returns A value which indicates whether the code could be executed.
*/
executeCode(languageId: string, code: string, focus: boolean, allowIncomplete?: boolean): Promise<boolean>;
executeCode(languageId: string, code: string, focus: boolean, allowIncomplete?: boolean, mode?: RuntimeCodeExecutionMode): Promise<boolean>;
}

/**
Expand All @@ -110,6 +112,17 @@ export enum SessionAttachMode {
Connected = 'connected',
}

/**
* An event that fires after code has been executed in a language runtime session
*/
export interface ILanguageRuntimeCodeExecutedEvent {
/* The code that was executed in the language runtime session */
code: string;

/* The mode used to execute the code in the language runtime session */
mode: RuntimeCodeExecutionMode;
}

/**
* IPositronConsoleInstance interface.
*/
Expand Down Expand Up @@ -212,7 +225,7 @@ export interface IPositronConsoleInstance {
/**
* The onDidExecuteCode event.
*/
readonly onDidExecuteCode: Event<string>;
readonly onDidExecuteCode: Event<ILanguageRuntimeCodeExecutedEvent>;

/**
* The onDidSelectPlot event.
Expand Down Expand Up @@ -296,14 +309,16 @@ export interface IPositronConsoleInstance {
* @param code The code to enqueue.
* @param allowIncomplete Whether to bypass runtime code completeness checks. If true, the `code`
* will be executed by the runtime even if it is incomplete or invalid. Defaults to false
* @param mode Possible code execution modes for a language runtime.
*/
enqueueCode(code: string, allowIncomplete?: boolean): Promise<void>;
enqueueCode(code: string, allowIncomplete?: boolean, mode?: RuntimeCodeExecutionMode): Promise<void>;

/**
* Executes code.
* @param code The code to execute.
* @param mode Possible code execution modes for a language runtime.
*/
executeCode(code: string): void;
executeCode(code: string, mode?: RuntimeCodeExecutionMode): void;

/**
* Replies to a prompt.
Expand Down
Loading