Skip to content

Add product and runCommand on notebook renderer API #103864

@connor4312

Description

@connor4312

Problem

Notebook renderers need to be able to communicate back to the content provider and/or kernel in several cases. For example, @DonJayamanne described a case where double-clicking on ipywidget graphs opens a separate window with more information. In a case where I have a .cpuprofile notebook, I would also want to be able to run a command to open a file or apply code lenses.

Currently we have the NotebookCommunication object that allows a pure renderer to communicate with the notebook content provider and kernel. This implies that renderers and content providers share a contract, but a goal of renderers is to have them be generic, standalone, swap-able bits of functionality. I should be able to write a flame chart renderer that takes .cpuprofile-formatted data without mandating that the content provider be one that I write.

Solution

Notebook renderer types are here: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/vscode-notebook-renderer/index.d.ts

This adds two new fields to the renderer API:

/**
 * Name of the product and its version displaying the renderer.
 */
product: { version: string; name: string };

/**
 * Runs a command in the context of the renderer. Returns a promise with
 * the command result.
 */
runCommand<T>(name: string, ...args: unknown[]): Promise<T>;
  • The product field is added so that renderers can discern appropriate functionality for the current environment. Until this point, the notebook renderer API was generic and independent of any particular editor. However, this change introduces a the ability to interact with the outside world, so product is added to make sure the renderer can interact correctly.
  • runCommand is self-explanitory

In VS Code, when the command is invoked it will run the registered command. It will prepend the notebook context to the arguments list, which is:

interface NotebookCommandContext {
  document: NotebookDocument;
}

Limitations

Having the document is required in many scenarios, so it needs to be somewhere in the context of the command:

  • appending the context to the arguments means that a command can't add more arguments without breaking backwards compatibility
  • prepending a context, or wrapping the arguments in a context+data object, means that you won't be able to invoke commands that aren't made to be called from a notebook renderer

One alternative would be to provide some "notebook document placeholder" symbol in the renderer (providing the entire NotebookDocument is not practical and would allow undesired mutations) that the renderer could pass up to be replaced with the NotebookDocument interface in the call.

One entirely different alternative would be to not use standard commands, but have a separate registerNotebookRendererCommand API that extensions could use.

cc @rebornix

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions