diff --git a/src/vs/platform/extensions/common/extensionsApiProposals.ts b/src/vs/platform/extensions/common/extensionsApiProposals.ts index a3f677336d139..af8f389f127dc 100644 --- a/src/vs/platform/extensions/common/extensionsApiProposals.ts +++ b/src/vs/platform/extensions/common/extensionsApiProposals.ts @@ -166,6 +166,9 @@ const _allApiProposals = { editSessionIdentityProvider: { proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.editSessionIdentityProvider.d.ts', }, + editorEncoding: { + proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.editorEncoding.d.ts', + }, editorHoverVerbosityLevel: { proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.editorHoverVerbosityLevel.d.ts', }, diff --git a/src/vs/workbench/api/browser/mainThreadEditors.ts b/src/vs/workbench/api/browser/mainThreadEditors.ts index 84bc6f34f1eaf..ba90b21b5ad08 100644 --- a/src/vs/workbench/api/browser/mainThreadEditors.ts +++ b/src/vs/workbench/api/browser/mainThreadEditors.ts @@ -29,6 +29,8 @@ import { IEditorControl } from 'vs/workbench/common/editor'; import { getCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { DirtyDiffContribution } from 'vs/workbench/contrib/scm/browser/dirtydiffDecorator'; +import { toEditorWithEncodingSupport } from 'vs/workbench/browser/parts/editor/editorStatus'; +import { EncodingMode } from 'vs/workbench/services/textfile/common/textfiles'; export interface IMainThreadEditorLocator { getEditor(id: string): MainThreadTextEditor | undefined; @@ -274,6 +276,52 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape { return Promise.resolve([]); } + + $tryGetEncoding(id: string): Promise { + const editor = this._editorLocator.getEditor(id); + + if (!editor) { + return Promise.reject(new Error('No such TextEditor')); + } + + const editorPanes = this._editorService.visibleEditorPanes; + for (const editorPane of editorPanes) { + if (editor.matches(editorPane)) { + const encodingSupport = toEditorWithEncodingSupport(editorPane.input); + if (!encodingSupport) { + return Promise.reject(new Error('No file active at this time')); + } + + const encoding = encodingSupport.getEncoding(); + + return Promise.resolve(encoding); + } + } + + return Promise.reject(new Error('No text editor active at this time')); + } + + $trySetEncoding(id: string, encoding: string, mode: EncodingMode): Promise { + const editor = this._editorLocator.getEditor(id); + + if (!editor) { + return Promise.reject(new Error('No such TextEditor')); + } + + const editorPanes = this._editorService.visibleEditorPanes; + for (const editorPane of editorPanes) { + if (editor.matches(editorPane)) { + const encodingSupport = toEditorWithEncodingSupport(editorPane.input); + if (!encodingSupport) { + return Promise.reject(new Error('No file active at this time')); + } + + return encodingSupport.setEncoding(encoding, mode); + } + } + + return Promise.reject(new Error('No text editor active at this time')); + } } // --- commands diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index b6b4f5746bb65..54bc573b04b09 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1753,6 +1753,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I NewSymbolNameTriggerKind: extHostTypes.NewSymbolNameTriggerKind, InlineEdit: extHostTypes.InlineEdit, InlineEditTriggerKind: extHostTypes.InlineEditTriggerKind, + EncodingMode: extHostTypes.EncodingMode, }; }; } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 7bbab68a618c7..53246964785ed 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -83,6 +83,7 @@ import * as search from 'vs/workbench/services/search/common/search'; import { ISaveProfileResult } from 'vs/workbench/services/userDataProfile/common/userDataProfile'; import type { TerminalShellExecutionCommandLineConfidence } from 'vscode'; import { AuthInfo, Credentials } from 'vs/platform/request/common/request'; +import { EncodingMode } from 'vs/workbench/services/textfile/common/textfiles'; export interface IWorkspaceData extends IStaticWorkspaceData { folders: { uri: UriComponents; name: string; index: number }[]; @@ -282,6 +283,8 @@ export interface MainThreadTextEditorsShape extends IDisposable { $tryApplyEdits(id: string, modelVersionId: number, edits: ISingleEditOperation[], opts: IApplyEditsOptions): Promise; $tryInsertSnippet(id: string, modelVersionId: number, template: string, selections: readonly IRange[], opts: IUndoStopOptions): Promise; $getDiffInformation(id: string): Promise; + $tryGetEncoding(id: string): Promise; + $trySetEncoding(id: string, encoding: string, mode: EncodingMode): Promise; } export interface MainThreadTreeViewsShape extends IDisposable { diff --git a/src/vs/workbench/api/common/extHostTextEditor.ts b/src/vs/workbench/api/common/extHostTextEditor.ts index 44ed8f3804fa5..037f03b7d1757 100644 --- a/src/vs/workbench/api/common/extHostTextEditor.ts +++ b/src/vs/workbench/api/common/extHostTextEditor.ts @@ -11,11 +11,12 @@ import { IRange } from 'vs/editor/common/core/range'; import { ISingleEditOperation } from 'vs/editor/common/core/editOperation'; import { IResolvedTextEditorConfiguration, ITextEditorConfigurationUpdate, MainThreadTextEditorsShape } from 'vs/workbench/api/common/extHost.protocol'; import * as TypeConverters from 'vs/workbench/api/common/extHostTypeConverters'; -import { EndOfLine, Position, Range, Selection, SnippetString, TextEditorLineNumbersStyle, TextEditorRevealType } from 'vs/workbench/api/common/extHostTypes'; +import { EncodingMode, EndOfLine, Position, Range, Selection, SnippetString, TextEditorLineNumbersStyle, TextEditorRevealType } from 'vs/workbench/api/common/extHostTypes'; import type * as vscode from 'vscode'; import { ILogService } from 'vs/platform/log/common/log'; import { Lazy } from 'vs/base/common/lazy'; import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import * as TextFiles from 'vs/workbench/services/textfile/common/textfiles'; export class TextEditorDecorationType { @@ -566,6 +567,13 @@ export class ExtHostTextEditor { }, hide() { _proxy.$tryHideEditor(id); + }, + getEncoding(): Promise { + return _proxy.$tryGetEncoding(id); + }, + setEncoding(encoding: string, mode: EncodingMode): Promise { + const _mode: TextFiles.EncodingMode = mode === EncodingMode.Encode ? TextFiles.EncodingMode.Encode : TextFiles.EncodingMode.Decode; + return _proxy.$trySetEncoding(id, encoding, _mode); } }); } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 92b968e001ee3..24c003e70e791 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -4638,3 +4638,11 @@ export enum InlineEditTriggerKind { } //#endregion + +//#region +export enum EncodingMode { + Encode = 0, + Decode = 1 +} + +//#endregion diff --git a/src/vs/workbench/api/test/browser/extHostTextEditor.test.ts b/src/vs/workbench/api/test/browser/extHostTextEditor.test.ts index 98bc776615106..589edec00ed06 100644 --- a/src/vs/workbench/api/test/browser/extHostTextEditor.test.ts +++ b/src/vs/workbench/api/test/browser/extHostTextEditor.test.ts @@ -89,7 +89,9 @@ suite('ExtHostTextEditorOptions', () => { $trySetSelections: undefined!, $tryApplyEdits: undefined!, $tryInsertSnippet: undefined!, - $getDiffInformation: undefined! + $getDiffInformation: undefined!, + $tryGetEncoding: undefined!, + $trySetEncoding: undefined! }; opts = new ExtHostTextEditorOptions(mockProxy, '1', { tabSize: 4, diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 845160784b16a..74422bc916de6 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -80,7 +80,7 @@ class SideBySideEditorLanguageSupport implements ILanguageSupport { } } -function toEditorWithEncodingSupport(input: EditorInput): IEncodingSupport | null { +export function toEditorWithEncodingSupport(input: EditorInput): IEncodingSupport | null { // Untitled Text Editor if (input instanceof UntitledTextEditorInput) { diff --git a/src/vscode-dts/vscode.proposed.editorEncoding.d.ts b/src/vscode-dts/vscode.proposed.editorEncoding.d.ts new file mode 100644 index 0000000000000..cb7835ef02fb3 --- /dev/null +++ b/src/vscode-dts/vscode.proposed.editorEncoding.d.ts @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode' { + // https://github.com/microsoft/vscode/issues/824 + + export enum EncodingMode { + + /** + * Instructs the encoding support to encode the object with the provided encoding + */ + Encode = 0, + + /** + * Instructs the encoding support to decode the object with the provided encoding + */ + Decode = 1 + } + + export interface TextEditor { + /** + * Get the text editor encoding. + */ + getEncoding(): Thenable; + + /** + * Set the text editor encoding. + * @param encoding + * @param mode + */ + setEncoding(encoding: string, mode: EncodingMode): Thenable; + } +}