Skip to content

Commit

Permalink
Move custom editor provider out of proposed to main api
Browse files Browse the repository at this point in the history
For #77131
  • Loading branch information
mjbvz committed Jun 1, 2020
1 parent 2656a0c commit eb09996
Show file tree
Hide file tree
Showing 4 changed files with 294 additions and 312 deletions.
2 changes: 1 addition & 1 deletion extensions/image-preview/src/extension.ts
Expand Up @@ -23,7 +23,7 @@ export function activate(context: vscode.ExtensionContext) {

const previewManager = new PreviewManager(extensionRoot, sizeStatusBarEntry, binarySizeStatusBarEntry, zoomStatusBarEntry);

context.subscriptions.push(vscode.window.registerCustomEditorProvider2(PreviewManager.viewType, previewManager, {
context.subscriptions.push(vscode.window.registerCustomEditorProvider(PreviewManager.viewType, previewManager, {
supportsMultipleEditorsPerDocument: true,
}));

Expand Down
294 changes: 292 additions & 2 deletions src/vs/vscode.d.ts
Expand Up @@ -6909,6 +6909,278 @@ declare module 'vscode' {
resolveCustomTextEditor(document: TextDocument, webviewPanel: WebviewPanel, token: CancellationToken): Thenable<void> | void;
}

/**
* Represents a custom document used by a [`CustomEditorProvider`](#CustomEditorProvider).
*
* Custom documents are only used within a given `CustomEditorProvider`. The lifecycle of a `CustomDocument` is
* managed by VS Code. When no more references remain to a `CustomDocument`, it is disposed of.
*/
interface CustomDocument {
/**
* The associated uri for this document.
*/
readonly uri: Uri;

/**
* Dispose of the custom document.
*
* This is invoked by VS Code when there are no more references to a given `CustomDocument` (for example when
* all editors associated with the document have been closed.)
*/
dispose(): void;
}

/**
* Event triggered by extensions to signal to VS Code that an edit has occurred on an [`CustomDocument`](#CustomDocument).
*
* @see [`CustomDocumentProvider.onDidChangeCustomDocument`](#CustomDocumentProvider.onDidChangeCustomDocument).
*/
interface CustomDocumentEditEvent<T extends CustomDocument = CustomDocument> {

/**
* The document that the edit is for.
*/
readonly document: T;

/**
* Undo the edit operation.
*
* This is invoked by VS Code when the user undoes this edit. To implement `undo`, your
* extension should restore the document and editor to the state they were in just before this
* edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`.
*/
undo(): Thenable<void> | void;

/**
* Redo the edit operation.
*
* This is invoked by VS Code when the user redoes this edit. To implement `redo`, your
* extension should restore the document and editor to the state they were in just after this
* edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`.
*/
redo(): Thenable<void> | void;

/**
* Display name describing the edit.
*
* This is shown in the UI to users.
*/
readonly label?: string;
}

/**
* Event triggered by extensions to signal to VS Code that the content of a [`CustomDocument`](#CustomDocument)
* has changed.
*
* @see [`CustomDocumentProvider.onDidChangeCustomDocument`](#CustomDocumentProvider.onDidChangeCustomDocument).
*/
interface CustomDocumentContentChangeEvent<T extends CustomDocument = CustomDocument> {
/**
* The document that the change is for.
*/
readonly document: T;
}

/**
* A backup for an [`CustomDocument`](#CustomDocument).
*/
interface CustomDocumentBackup {
/**
* Unique identifier for the backup.
*
* This id is passed back to your extension in `openCustomDocument` when opening a custom editor from a backup.
*/
readonly id: string;

/**
* Delete the current backup.
*
* This is called by VS Code when it is clear the current backup is no longer needed, such as when a new backup
* is made or when the file is saved.
*/
delete(): void;
}

/**
* Additional information used to implement [`CustomEditableDocument.backup`](#CustomEditableDocument.backup).
*/
interface CustomDocumentBackupContext {
/**
* Suggested file location to write the new backup.
*
* Note that your extension is free to ignore this and use its own strategy for backup.
*
* For editors for workspace resource, this destination will be in the workspace storage. The path may not
*/
readonly destination: Uri;
}

/**
* Additional information about the opening custom document.
*/
interface CustomDocumentOpenContext {
/**
* The id of the backup to restore the document from or `undefined` if there is no backup.
*
* If this is provided, your extension should restore the editor from the backup instead of reading the file
* the user's workspace.
*/
readonly backupId?: string;
}

/**
* Provider for readonly custom editors that use a custom document model.
*
* Custom editors use [`CustomDocument`](#CustomDocument) as their document model instead of a [`TextDocument`](#TextDocument).
*
* You should use this type of custom editor when dealing with binary files or more complex scenarios. For simple
* text based documents, use [`CustomTextEditorProvider`](#CustomTextEditorProvider) instead.
*
* @param T Type of the custom document returned by this provider.
*/
export interface CustomReadonlyEditorProvider<T extends CustomDocument = CustomDocument> {

/**
* Create a new document for a given resource.
*
* `openCustomDocument` is called when the first editor for a given resource is opened, and the resolve document
* is passed to `resolveCustomEditor`. The resolved `CustomDocument` is re-used for subsequent editor opens.
* If all editors for a given resource are closed, the `CustomDocument` is disposed of. Opening an editor at
* this point will trigger another call to `openCustomDocument`.
*
* @param uri Uri of the document to open.
* @param openContext Additional information about the opening custom document.
* @param token A cancellation token that indicates the result is no longer needed.
*
* @return The custom document.
*/
openCustomDocument(uri: Uri, openContext: CustomDocumentOpenContext, token: CancellationToken): Thenable<T> | T;

/**
* Resolve a custom editor for a given resource.
*
* This is called whenever the user opens a new editor for this `CustomEditorProvider`.
*
* To resolve a custom editor, the provider must fill in its initial html content and hook up all
* the event listeners it is interested it. The provider can also hold onto the `WebviewPanel` to use later,
* for example in a command. See [`WebviewPanel`](#WebviewPanel) for additional details.
*
* @param document Document for the resource being resolved.
* @param webviewPanel Webview to resolve.
* @param token A cancellation token that indicates the result is no longer needed.
*
* @return Optional thenable indicating that the custom editor has been resolved.
*/
resolveCustomEditor(document: T, webviewPanel: WebviewPanel, token: CancellationToken): Thenable<void> | void;
}

/**
* Provider for editiable custom editors that use a custom document model.
*
* Custom editors use [`CustomDocument`](#CustomDocument) as their document model instead of a [`TextDocument`](#TextDocument).
* This gives extensions full control over actions such as edit, save, and backup.
*
* You should use this type of custom editor when dealing with binary files or more complex scenarios. For simple
* text based documents, use [`CustomTextEditorProvider`](#CustomTextEditorProvider) instead.
*
* @param T Type of the custom document returned by this provider.
*/
export interface CustomEditorProvider<T extends CustomDocument = CustomDocument> extends CustomReadonlyEditorProvider<T> {
/**
* Signal that an edit has occurred inside a custom editor.
*
* This event must be fired by your extension whenever an edit happens in a custom editor. An edit can be
* anything from changing some text, to cropping an image, to reordering a list. Your extension is free to
* define what an edit is and what data is stored on each edit.
*
* Firing `onDidChange` causes VS Code to mark the editors as being dirty. This is cleared when the user either
* saves or reverts the file.
*
* Editors that support undo/redo must fire a `CustomDocumentEditEvent` whenever an edit happens. This allows
* users to undo and redo the edit using VS Code's standard VS Code keyboard shortcuts. VS Code will also mark
* the editor as no longer being dirty if the user undoes all edits to the last saved state.
*
* Editors that support editing but cannot use VS Code's standard undo/redo mechanism must fire a `CustomDocumentContentChangeEvent`.
* The only way for a user to clear the dirty state of an editor that does not support undo/redo is to either
* `save` or `revert` the file.
*
* An editor should only ever fire `CustomDocumentEditEvent` events, or only ever fire `CustomDocumentContentChangeEvent` events.
*/
readonly onDidChangeCustomDocument: Event<CustomDocumentEditEvent<T>> | Event<CustomDocumentContentChangeEvent<T>>;

/**
* Save a custom document.
*
* This method is invoked by VS Code when the user saves a custom editor. This can happen when the user
* triggers save while the custom editor is active, by commands such as `save all`, or by auto save if enabled.
*
* To implement `save`, the implementer must persist the custom editor. This usually means writing the
* file data for the custom document to disk. After `save` completes, any associated editor instances will
* no longer be marked as dirty.
*
* @param document Document to save.
* @param cancellation Token that signals the save is no longer required (for example, if another save was triggered).
*
* @return Thenable signaling that saving has completed.
*/
saveCustomDocument(document: T, cancellation: CancellationToken): Thenable<void>;

/**
* Save a custom document to a different location.
*
* This method is invoked by VS Code when the user triggers 'save as' on a custom editor. The implementer must
* persist the custom editor to `destination`.
*
* When the user accepts save as, the current editor is be replaced by an non-dirty editor for the newly saved file.
*
* @param document Document to save.
* @param destination Location to save to.
* @param cancellation Token that signals the save is no longer required.
*
* @return Thenable signaling that saving has completed.
*/
saveCustomDocumentAs(document: T, destination: Uri, cancellation: CancellationToken): Thenable<void>;

/**
* Revert a custom document to its last saved state.
*
* This method is invoked by VS Code when the user triggers `File: Revert File` in a custom editor. (Note that
* this is only used using VS Code's `File: Revert File` command and not on a `git revert` of the file).
*
* To implement `revert`, the implementer must make sure all editor instances (webviews) for `document`
* are displaying the document in the same state is saved in. This usually means reloading the file from the
* workspace.
*
* @param document Document to revert.
* @param cancellation Token that signals the revert is no longer required.
*
* @return Thenable signaling that the change has completed.
*/
revertCustomDocument(document: T, cancellation: CancellationToken): Thenable<void>;

/**
* Back up a dirty custom document.
*
* Backups are used for hot exit and to prevent data loss. Your `backup` method should persist the resource in
* its current state, i.e. with the edits applied. Most commonly this means saving the resource to disk in
* the `ExtensionContext.storagePath`. When VS Code reloads and your custom editor is opened for a resource,
* your extension should first check to see if any backups exist for the resource. If there is a backup, your
* extension should load the file contents from there instead of from the resource in the workspace.
*
* `backup` is triggered whenever an edit it made. Calls to `backup` are debounced so that if multiple edits are
* made in quick succession, `backup` is only triggered after the last one. `backup` is not invoked when
* `auto save` is enabled (since auto save already persists resource ).
*
* @param document Document to backup.
* @param context Information that can be used to backup the document.
* @param cancellation Token that signals the current backup since a new backup is coming in. It is up to your
* extension to decided how to respond to cancellation. If for example your extension is backing up a large file
* in an operation that takes time to complete, your extension may decide to finish the ongoing backup rather
* than cancelling it to ensure that VS Code has some valid backup.
*/
backupCustomDocument(document: T, context: CustomDocumentBackupContext, cancellation: CancellationToken): Thenable<CustomDocumentBackup>;
}

/**
* The clipboard provides read and write access to the system's clipboard.
*/
Expand Down Expand Up @@ -7750,7 +8022,8 @@ declare module 'vscode' {
* Register a provider for custom editors for the `viewType` contributed by the `customEditors` extension point.
*
* When a custom editor is opened, VS Code fires an `onCustomEditor:viewType` activation event. Your extension
* must register a [`CustomTextEditorProvider`](#CustomTextEditorProvider) for `viewType` as part of activation.
* must register a [`CustomTextEditorProvider`](#CustomTextEditorProvider), [`CustomReadonlyEditorProvider`](#CustomReadonlyEditorProvider),
* [`CustomEditorProvider`](#CustomEditorProvider)for `viewType` as part of activation.
*
* @param viewType Unique identifier for the custom editor provider. This should match the `viewType` from the
* `customEditors` contribution point.
Expand All @@ -7759,7 +8032,24 @@ declare module 'vscode' {
*
* @return Disposable that unregisters the provider.
*/
export function registerCustomEditorProvider(viewType: string, provider: CustomTextEditorProvider, options?: { readonly webviewOptions?: WebviewPanelOptions; }): Disposable;
export function registerCustomEditorProvider(viewType: string, provider: CustomTextEditorProvider | CustomReadonlyEditorProvider | CustomEditorProvider, options?: {
readonly webviewOptions?: WebviewPanelOptions;

/**
* Only applies to `CustomReadonlyEditorProvider | CustomEditorProvider`.
*
* Indicates that the provider allows multiple editor instances to be open at the same time for
* the same resource.
*
* If not set, VS Code only allows one editor instance to be open at a time for each resource. If the
* user tries to open a second editor instance for the resource, the first one is instead moved to where
* the second one was to be opened.
*
* When set, users can split and create copies of the custom editor. The custom editor must make sure it
* can properly synchronize the states of all editor instances for a resource so that they are consistent.
*/
readonly supportsMultipleEditorsPerDocument?: boolean;
}): Disposable;

/**
* The currently active color theme as configured in the settings. The active
Expand Down

0 comments on commit eb09996

Please sign in to comment.