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

Custom webview editor API #77131

Closed
mjbvz opened this issue Jul 10, 2019 · 136 comments
Closed

Custom webview editor API #77131

mjbvz opened this issue Jul 10, 2019 · 136 comments
Assignees
Labels
api api-finalization custom-editors Custom editor API (webview based editors) plan-item VS Code - planned item for upcoming
Milestone

Comments

@mjbvz
Copy link
Collaborator

mjbvz commented Jul 10, 2019

Updated: April 24, 2020

The Custom Text Editor API has shipped with VS Code 1.44! Checkout the documentation and example extension to get started creating your custom text editors.

If you encounter any issues using CustomTextEditorProvider, please open a new issue.

This issue now tracks custom editors for binary files, which we aim to finalize for VS Code 1.46


Overview

The custom editor API aims to allow extensions to create fully customizable read/write editors that are used in place of VS Code's standard text editor for specific resources. These editors will be based on webviews. We will support editors for both binary and text resources

A XAML custom editor, for example, could show a WYSIWYG style editor for your .xaml files. Our end goal is to give extensions the most flexibility possible while keeping VS Code fast, lean, and consistent.

Non-goals

Many features that are potentially related to custom editors are out of scope of this current proposal, including:

  • Specifying how resources are persisted and how resources are synchronized with webviews
  • Specifying what an edit is
  • Customization of VS Code's text editor using html / css
  • Embedding of VS Code's text editor in webviews
  • UI related to custom editors (beyond switching view types)

These all would fall under separate feature requests. Many also be a better fit for an external helper library instead of VS Code core

Tracking progress

This issue thread captures the evolution of the webview editor proposal. That means that many comments may now be out of date. Some of these have been minimized, others have not.

For the most up to date info, see:

@mjbvz mjbvz added api plan-item VS Code - planned item for upcoming labels Jul 10, 2019
@mjbvz mjbvz added this to the July 2019 milestone Jul 10, 2019
@mjbvz

This comment has been minimized.

@mjbvz

This comment has been minimized.

@jrieken

This comment has been minimized.

@TomMarius

This comment has been minimized.

@sijakret
Copy link
Contributor

Is it possible i read in the docs for extension developers (about a year ago) that functionality like this was deliberately not supported for performance and stability reasons?

Not that i'm not hyped as well.. ;)

@jrieken jrieken modified the milestones: July 2019, August 2019 Jul 29, 2019
mjbvz added a commit that referenced this issue Aug 16, 2019
For #77131

Adds a prototype of custom editors contributed by extensions
mjbvz added a commit that referenced this issue Aug 16, 2019
For #77131

Adds a prototype of custom editors contributed by extensions. This change does the following:

- Introduces a new contribution point for the declarative parts of a custom editor
- Adds API for registering a webview editor provider. This lets VS Code decided when to create a webview editor
- Adds an `openWith` command that lets you select which editor to use to open a resource from the file explorer
- Adds a setting that lets you say that you always want to use a custom editor for a given file extension
- Hooks up auto opening of a custom editor when opening a file from quick open or explorer
- Adds a new extension that contributes a custom image preview for png and jpg files

Still needs a lot of UX work and testing. We are also going to explore a more generic "open handler" based approach for supporting custom editors

Revert
@mjbvz

This comment has been minimized.

@Tyriar

This comment has been minimized.

@mjbvz

This comment has been minimized.

@jrieken
Copy link
Member

jrieken commented Aug 21, 2019

Does anyone has any specific use cases for the "open handler" proposal that could not be addressed by the previous custom editor proposed API

I think a use-case would be files that open as text but need some prior processing. E.g clicking a foo.class-file shouldn't open a web view editor but, after a decompile-step, should open a foo.generated.java-file. However, we can treat that as a different problem and think about it as a default text content provider so certain file-types.

Let's continue with the existing proposal.

I think undo and redo should definitely be considered from the beginning in order to make more useful non-read only editors.

@Tyriar Can you explain why? We have added save-logic because editors render the dirty state (in their titles) but undo/redo isn't part of the editor UX. I agree that undo/redo is important but to me it's just commands that an extension should register.

@bpasero
Copy link
Member

bpasero commented Aug 21, 2019

Does anyone has any specific use cases for the "open handler" proposal that could not be addressed by the previous custom editor proposed API or by existing VS Code apis?

So are we saying that https://marketplace.visualstudio.com/items?itemName=slevesque.vscode-hexdump needs to rewrite the extension so that the standalone editor is embedded into a webview? So they would have to ship the standalone editor as part of their extension? This scenario is quite popular (see #2582, has even more upvotes than #12176).

Maybe I misunderstood and we are still thinking of supporting text editors to open but with the previous API.

@jrieken
Copy link
Member

jrieken commented Aug 21, 2019

Maybe I misunderstood and we are still thinking of supporting text editors to open but with the previous API.

Yeah, I think that's still a valid scenario, e.g. the webview editor should have an option to let the workbench know that it wants to show to the side of a text editor. For hexdump but also for markdown

@bpasero
Copy link
Member

bpasero commented Aug 21, 2019

To be clear, here is what I expect:

  • I open the explorer
  • I click on a file that is binary
  • hexdump extension opens with a text editor with custom content

I agree that I would not put the burden of finding out if the editor is already opened onto the extension but on us.

@Tyriar
Copy link
Member

Tyriar commented Aug 21, 2019

Can you explain why? We have added save-logic because editors render the dirty state (in their titles) but undo/redo isn't part of the editor UX. I agree that undo/redo is important but to me it's just commands that an extension should register.

@bpasero I don't mind so much on how this is done, but if the user has a custom keybindings for the regular undo/redo commands it should work in the custom editor too.

mjbvz added a commit that referenced this issue Aug 22, 2019
For #77131

Adds a prototype of custom editors contributed by extensions. This change does the following:

- Introduces a new contribution point for the declarative parts of a custom editor
- Adds API for registering a webview editor provider. This lets VS Code decided when to create a webview editor
- Adds an `openWith` command that lets you select which editor to use to open a resource from the file explorer
- Adds a setting that lets you say that you always want to use a custom editor for a given file extension
- Hooks up auto opening of a custom editor when opening a file from quick open or explorer
- Adds a new extension that contributes a custom image preview for png and jpg files

Still needs a lot of UX work and testing. We are also going to explore a more generic "open handler" based approach for supporting custom editors

Revert
mjbvz added a commit that referenced this issue Aug 24, 2019
For #77131

Adds a prototype of custom editors contributed by extensions. This change does the following:

- Introduces a new contribution point for the declarative parts of a custom editor
- Adds API for registering a webview editor provider. This lets VS Code decided when to create a webview editor
- Adds an `openWith` command that lets you select which editor to use to open a resource from the file explorer
- Adds a setting that lets you say that you always want to use a custom editor for a given file extension
- Hooks up auto opening of a custom editor when opening a file from quick open or explorer
- Adds a new extension that contributes a custom image preview for png and jpg files

Still needs a lot of UX work and testing. We are also going to explore a more generic "open handler" based approach for supporting custom editors

Revert
@KevinWuWon
Copy link

Does anyone has any specific use cases for the "open handler" proposal that could not be addressed by the previous custom editor proposed API or by existing VS Code apis?

The original resolveWebviewEditor proposal is, at a broad level, probably enough for our needs. One thing it's missing compared to createWebviewEditor is starting a new document with no backing file. Is there a path to supporting this in the resolveWebviewEditor API?

Add a generic way to listen for commands:

YES! There are so many commands that we want to hook into. In addition to Save/Undo/Redo: Save As, Find/Replace; the LSP commands like Go To Definition/Find References, and the DAP commands like Debug Start/Continue/Step Into/Step Over/Stop.

mjbvz added a commit that referenced this issue Apr 24, 2020
Fixes #95854
Fixes #95849
For #77131

- Move all editing functionality back onto the provider. This better matches the notebook API.

- Rename `CustomEditorProvider` to `CustomReadonlyEditorProvider`.  `CustomEditorProvider` is now how editable custom editors are implemented

- Give extension a full suggested backup path instead of just a folder
@mjbvz mjbvz modified the milestones: April 2020, May 2020 Apr 24, 2020
@mjbvz
Copy link
Collaborator Author

mjbvz commented Apr 24, 2020

April 24, 2020

We've decided to keep the binary custom editor API proposed one more iteration. This lets us better align the custom editor API with the notebook API proposal, while also giving more time for you to provide feedback on it.

The currently version of the API checked into vscode.proposal.d.ts is what we plan to ship with VS Code 1.45. Here's an overview of recent changes:

Moved edit, save, revert, backup from documents back to the provider

In order to align with the notebook API proposal, we've moved the edit, save, revert, and backup function out of EditableCustomDocument and back onto the custom editor provider:

export interface CustomEditorProvider<T extends CustomDocument = CustomDocument> extends CustomReadonlyEditorProvider<T> {

	readonly onDidChangeCustomDocument: Event<CustomDocumentEditEvent> | Event<CustomDocumentContentChangeEvent>;

	saveCustomDocument(document: CustomDocument, cancellation: CancellationToken): Thenable<void>;

	saveCustomDocumentAs(document: CustomDocument, destination: Uri, cancellation: CancellationToken): Thenable<void>;

	revertCustomDocument(document: CustomDocument, cancellation: CancellationToken): Thenable<void>;

	backupCustomDocument(document: CustomDocument, context: CustomDocumentBackupContext, cancellation: CancellationToken): Thenable<CustomDocumentBackup>;
}

We've gone back and forth a few times about where these methods should live, but ultimately it is important to align with the notebook api here. Extension authors can also easily have the provider call into methods on their custom document.

CustomReadonlyEditorProvider

The CustomReadonlyEditorProvider interface is now the base for a custom editors provider. It has the same two methods the previous proposal did:

export interface CustomReadonlyEditorProvider<T extends CustomDocument = CustomDocument> {

	openCustomDocument(uri: Uri, openContext: CustomDocumentOpenContext, token: CancellationToken): Thenable<T> | T;

	resolveCustomEditor(document: T, webviewPanel: WebviewPanel, token: CancellationToken): Thenable<void> | void;
}

If your binary custom editors are editable, you would instead implement CustomEditorProvider which defines all the required editing hooks.

CustomDocumentBackupContext.destination

The CustomDocumentBackupContext.destination now suggests a specific file name to use for a backup. You extension does not have to write to this file, it is simply a suggestion.


Again, the current API in master is what plan to ship in VS Code 1.45. Provided no major issues are discovered next month, this is api is also what we plan to finalize.

If you have an extension in mind that would use binary custom editors, please give the new API a try and let us know if it works for you. We're specifically interested in understanding if you could implement all the required functions and if you ran into any confusion while doing so.

@caponetto
Copy link

caponetto commented Apr 28, 2020

Hi @mjbvz @jrieken,

I've been catching up with the daily updates, thanks for them btw.
While working on our stuff, I've been noticing some issues on VSCode.
Probably they're known issues but I'm sharing here in case they've been missed somehow.
I'm able to reproduce them on both our code and this code.

Linux and Windows

  • [File -> Auto Save] Auto save enabled: "Save" is not triggered if you quickly (less than 1s) close the editor after making a change.

Linux-only

  • [File -> Auto Save] The "check" symbol is not shown when you enable "auto save" within the custom editor; however, the operation works.
  • [File -> Revert File] Sometimes the menu button is kept disabled when you start VSCode, even after changes.
  • [File -> Save All] Same behavior ^
  • [File -> Save] Same behavior ^; Ctrl+S works.
  • [File -> Save As] Same behavior ^; Ctrl+Shift+S works.
    note: the menu buttons become enabled when I open a text editor

Windows-only

  • [File -> Revert File] Can't use; always disabled.

Please let me know if you need any further information.

@bpasero
Copy link
Member

bpasero commented Apr 28, 2020

@mjbvz one thing to note is that auto-save for text editors is not editor bound, so it will continue after an editor closes. Maybe for custom editors this is different and you need to wire this in properly.

@caponetto
Copy link

Regarding the backup feature.
I played a little bit more with the sample code but the restore part doesn't seem to be working.
I can see that the backup file is being created/deleted when appropriated,
but the backupId received on the openCustomDocument method is always undefined.

I understood that if I close the VSCode with unsaved changes,
then these changes will be restored once I open VSCode again.
Here's a gif where I do these steps.
Peek 2020-04-29 08-00

Am I missing something here?
Thanks in advance.

@mjbvz
Copy link
Collaborator Author

mjbvz commented Apr 29, 2020

@caponetto See #96484

@hediet
Copy link
Member

hediet commented May 12, 2020

If you are interested, I wrote some thoughts down I had when I implemented the drawio editor for png files.

@rdeline
Copy link
Contributor

rdeline commented May 14, 2020

I'd like my custom text editor to have a different UI when a document is open normally versus in the source control diff view. (There are features that are unneeded in a diff.) However, given the arguments to CustomTextEditorProvider.resolveCustomTextEditor, I don't see what logic I can write to tell that I'm in a diff view. In fact, for my use case, I'd prefer that Code use a regular text editor for diffs rather than creating my custom text editor. Maybe there's a way to specify that?

@mjbvz
Copy link
Collaborator Author

mjbvz commented May 14, 2020

@rdeline See #97683

@zaydek
Copy link

zaydek commented May 21, 2020

Hi all. I’m looking for some advice to address several of my concerns implementing a custom text editor.

I’m working on a WYSIWYG markdown editor -- you can play with the technical prototype here: https://editor-v2-arch.netlify.app. I’ve been working on making the extension-version for VSCode, but I’m honestly pretty confused. I’ve followed the abc (textarea) and catScratch demos for reference.

What I’m most confused about is undo and cursor selection.

So when my editor is an extension, the undo stack actually appears to live outside of my editor, right? The reason this confuses me is because I already implemented all of the undo functionality myself, but now I need to let VSCode handle that for me? Am I simply not allowed to intercept undo/redo events myself and handle them? Is there a way I can change the relationship so my editor is in charge of handling undo/redo? Having this work the other way around is seriously confusing me.

I understand that I can emit edits on every event, and message-pass those edits to VSCode, but when a user hits undo, from what I can tell, the way my editor is made aware of this is by VSCode message-passing me the entire document as a string (naive implementation) or VSCode passing individual edits I can respond to. If I respond to individual edits, this seems fine (I would need to rearchitect some things to make this work) but this leads me to my second point: cursor selection.

When a user presses undo, they expect the cursor to revert to where it was. So assuming my editor responds to edits (as mentioned in the previous paragraph), does this mean I need to compute the cursor? Right now, my undo history stack tracks the cursor positions, so there’s no need for me to compute anything during an undo, redo event. But this seems like something else I would need to architect in order to get even the most basic editor behaviors working.

All things considered, making my editor VSCode-ready is proving to be way more difficult than I would have imagined. I hope I’ve got some things wrong here and there’s a much simpler way for me to port my editor.

@jrieken
Copy link
Member

jrieken commented May 26, 2020

@codex-zaydek You are on the wrong issue, this is about custom binary editors, please create a new one.

@rchiodo
Copy link
Contributor

rchiodo commented May 29, 2020

@mjbvz I was wondering how I would create an untitled editor with the new API? I believe we used to do this with a uri of "untitled:Untitled-1.ipynb", but this gives an error now:

image

Adding a '/' to the front of the file name seems to allow the creation of the file, but it's not treated as untitled (it's just treated as a real file then and closing doesn't ask to save as)

@rchiodo
Copy link
Contributor

rchiodo commented May 29, 2020

Ah it seems there's already a discussion of this here:
#93441

@mjbvz
Copy link
Collaborator Author

mjbvz commented May 29, 2020

@rchiodo yes #93441 tracks a better solution. Until then, you should be able to create untitled files by using an untitled uri that points to a specific file path:

untitled:/absolute/path/to/file/in/workspace.png

@mjbvz
Copy link
Collaborator Author

mjbvz commented Jun 2, 2020

The binary custom editor API has been merged into vscode.d.ts.

If you were testing this proposed API previously, please make sure to update your code to call registerCustomEditorProvider instead of registerCustomEditorProvider2. Other than that, there should be no changes to the API

@DemonOne
Copy link

DemonOne commented Jun 3, 2020

Is there a way to change the title of a custom editor?
Right now my extension uses a webview witha custom title when editing a certain file, but I need the save/close features of the custom editor API.

@mjbvz
Copy link
Collaborator Author

mjbvz commented Jun 9, 2020

@DemonOne No, custom editors currently always use the 'resource' as their title (they try to match what we do for normal text editors)

@mjbvz
Copy link
Collaborator Author

mjbvz commented Jun 9, 2020

The binary custom editor API will ship with VS Code 1.46 🎉 Thanks to everyone who helped test this API and provided feedback along the way

Follow up resources:

Going forward, please open any bugs/feature-requests/questions as new issues.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api api-finalization custom-editors Custom editor API (webview based editors) plan-item VS Code - planned item for upcoming
Projects
None yet
Development

No branches or pull requests