Vscode: Share "Reopen with" command and Editor Associations with notebooks, settings and keybindings UIs

Created on 3 Apr 2020  路  26Comments  路  Source: microsoft/vscode

Notebooks, settings UI and the keybindings UI are very similar to custom editors. We should make the command more generic so the method to view the backing file in the text editor is shared and behaves the same across each of these editors.

feature-request polish workbench-actions

Most helpful comment

@mjbvz thanks for the good work!

@roblourens @JacksonKearl @sandy081 if you want to adopt this set of APIs and commands in your component, feel free to create new issues to track them, it's no blocker for this iteration. We just need to make sure we are not introducing similar commands in the future.

All 26 comments

Internally we are all using EditorService.overrideOpenEditor(handler: IOpenEditorOverrideHandler): IDisposable; so it makes better sense that we implement the Reopen ... inside the service.

I'm thinking about prototyping a "PowerShell Notebooks" experience where the backing file is a regular .ps1.

I want to be able to toggle between rendering the .ps1 in the regular text editor & rendering the .ps1 as a Notebook.

Having a mechanism to do this would be fantastic.

Kapture 2020-04-08 at 17 55 03

Above is the prototype for shared "Reopen with..." command. Previously every "custom" editor registers a simple editor override handler

export interface IOpenEditorOverrideHandler {
  (editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup): IOpenEditorOverride | undefined;
}
interface IEditorService
  overrideOpenEditor(handler: IOpenEditorOverrideHandler): IDisposable;
}

Now the IOpenEditorOverrideHandler is enriched as

export interface IOpenEditorOverrideHandler {
  open: (editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup) => IOpenEditorOverride | undefined;
  canOpen: (editor: IEditorInput, options: IEditorOptions | undefined, group: IEditorGroup | undefined) => {  id?: string; label: string; description?: string; detail?: string; }[];
}

The shared "File: Reopen with..." action will show all custom editors (which can be multiple CustomEditors, multiple Notebook Editors, two types of Settings Editors and one Search Editor) which can handle the resource for users to choose from.

We also need to think about how to configure the default editor for a resource. @mjbvz added settings for CustomEditor but considering that the same file extension can be supported by different contributors.

@mjbvz @sandy081 @roblourens @JacksonKearl thoughts?

As the first step, I can add this action and adopt it in Notebook and then later on you can adopt it gradually in your "custom" editor.

The QuickPick now aligns with Custom Editor per feedback from today's sit-down

image

Pushed my first attempt to master https://github.com/microsoft/vscode/commit/dc1746e790f693660dc1eccce8c096b8ab1ae408 . To adopt the change in your editorOverride:

1. Implement IOpenEditorOverrideHandler.getEditorOverrides

 this.editorService.overrideOpenEditor({
  getEditorOverrides: (editor: IEditorInput, options: IEditorOptions | undefined, group: IEditorGroup | undefined) => {
  ...
  return [
    {
      label,
      id,
      active,
      detail
    }
  ];
  }
}

Note that the editorInput passed in can be any kind of IEditorInput, while previously it's FileEditorInput most of the time.

The return type is IOpenEditorOverrideEntry[]. If you are returning multiple entries, make sure the id property is unique thus you know which one users pick

Handle Reopening

The editor input reopen override handler now has one more optional parameter id. If it's undefined, it means users attempt to open the file through File Explorer, etc. If it's not empty, users pick the IOpenEditorOverrideEntry explicitly.

Thanks @rebornix. The approach looks good like a good start. I'll look into adopting it for custom editors.

I think it's also worth considering adopting more concepts from custom editors for notebooks and settings. For example, the workbench.editorAssociations setting lets users configure which custom editor is used for a given resource. This is very similar to what the "workbench.settings.editor" setting also does.

@mjbvz workbench.editorAssociations sounds a good config for mapping between file associations with "custom" editors. We use viewType as well for the notebook, in order to align with Custom Editor. So I think we can move it out to workbench/files from custom editor?

image

Settings and Keybinding can also register themselves with viewType like settings.ui, settings.json, keybinding.ui, keybindings.json and then users can use workbench.editorAssociations and deprecate settings like workbench.settings.useSplitJSON.

@rebornix I hooked custom editors up to use the shared api.

The only missing feature from the shared command compared the custom editor one is that custom editors show a gear icon:

Screen Shot 2020-04-15 at 12 50 26 PM

Clicking this gear sets workbench.editorAssociations for the file. I feel this improves the discoverability of workbench.editorAssociations

I see two options:

  • Add the gear as a shared feature. Clicking on it would set workbench.editorAssociations for both notebooks and custom editors

  • Let custom editors contribute a button to the reopen with quick pick.

@rebornix Would notebooks also benefit from making workbench.editorAssociations more easily configurable?

Add the gear as a shared feature. Clicking on it would set workbench.editorAssociations for both notebooks and custom editors

@mjbvz yes, notebook will have similar problems and having the gear as a shared feature makes best sense. Will you do the migration? I can do that as well.

@mjbvz adopted the gear icon in the quick pick, which will set editor association. It's safe to deprecate the "View: Reopen with..." command from Custom Editor now.

@rebornix Thanks! I'll move over any other custom editor functionality that makes sense to share

@rebornix is this an editor command I can take advantage of in an extension?

This one is an internal one for now but I've heard that @mjbvz is making a generic public command to open a resource with a specific "custom editor"

70a890efb6601c04e5235b06e537bdf47d85281d make the vscode.openWith command support other editor types besides custom editors

@mjbvz thanks for the good work!

@roblourens @JacksonKearl @sandy081 if you want to adopt this set of APIs and commands in your component, feel free to create new issues to track them, it's no blocker for this iteration. We just need to make sure we are not introducing similar commands in the future.

Moving to May for settings and keybindings UI adoption

I'm not sure about using this for settings, since we don't consider the different scopes to be in different settings GUI resources/editors. It doesn't fit my mental model. Makes sense for keybindings though.

@roblourens why not swap between whatever file it is based on the settings editor tab is opened? Sure it's a little different but it would be nice to have the same command/keybinding for switching to the text versions of keybindings, notebooks, custom editors and settings.

You can already have the same keybinding and you won't have to pick from two options in a quick pick. I can look into it though.

In Search editors, there鈥檚 currently no way to view the raw text^ and no feature requests for such a thing either. So probably not going to implement it just for this, but if demand arises I鈥檒l be sure to use this.

^ Exception is via diff view

You can already have the same keybinding and you won't have to pick from two options in a quick pick.

The command should just switch instead of showing a quick pick if there are only 2 options imo, or have an alternate toggle command which does this.

For context, here's what I'm doing in the PowerShell extension to emulate what the Settings UI/Json does today (flip between a fancy mode and raw mode).

https://github.com/TylerLeonhardt/vscode-powershell/blob/903c483a70fb3c4301186ba5eaad5c799bc78ed8/src/features/PowerShellNotebooks.ts#L31-L37

I looked into this for a bit and I don't think it supports what I need currently, but I might be wrong.

Basically when you open the settings UI editor, you are opening a vscode-settings: URI. If we want "reopen with > text editor" we need to open a different resource. I am expecting to be able to either override the entry that says "Text Editor/Built-in", or to intercept the open that happens after I pick "Text Editor" with my overrideOpenEditor handler. It doesn't seem like either of those things are possible.

Agree that supporting this in Keybindings makes good sense and settings is a bit weird. The Settings UI is a 1-N mapping between the UI and multiple settings.json.

Can somebody please explain to me what needs to be done here for Keyboard Shortcuts editor and any code references?

@sandy081 Keybindings contribution needs to register itself as an IOpenEditorOverrideHandler https://github.com/microsoft/vscode/blob/1ed5e6cf0ee95b9878d74813d4b97e67026e9fe1/src/vs/workbench/services/editor/common/editorService.ts#L246 and as a handler, it is responsible for

  1. getEditorOverrides, provides override candidates for a specific resource. For example, there are three different view types for keybindings.json: UI, Split JSON editor, simple JSON editor. The return result will be used in Editor: Reopen With.
  2. open(editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup, context: OpenEditorContext, handles the editor opening override This one is a bit tricky and we are looking into improving it, but now it works as

    • If users try to open keybindings.json directly, editor is a FileEditorInput. If options?.override is not set, we should open Keybindings Editor based on user settings (for example, by default it opens the UI editor)

    • if options?.override is set, open the right editor based on options?.override (it's the id of the override candidate)

Was this page helpful?
0 / 5 - 0 ratings