From 4084b74ee8f16ce143085327afcecc369d5ef96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= Date: Fri, 9 Feb 2024 10:26:46 +0100 Subject: [PATCH 1/4] lib: update to VSCode 1.86.1 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 405a09fa..f25f9d81 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,8 @@ }, "config": { "vscode": { - "version": "1.86.0", - "ref": "1.86.0" + "version": "1.86.1", + "ref": "1.86.1" } }, "devDependencies": { From 1e37072935efd9fee46b2a4ba33c885539ac74c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= Date: Fri, 9 Feb 2024 10:27:39 +0100 Subject: [PATCH 2/4] fix: include file save commands in editor service override --- .eslintrc | 3 +- rollup/rollup.config.ts | 2 +- scripts/vscode.patch | 475 +++++++++++++++++++++++++++++++++ src/service-override/editor.ts | 1 + 4 files changed, 479 insertions(+), 2 deletions(-) diff --git a/.eslintrc b/.eslintrc index c5e79667..2cd8caf4 100644 --- a/.eslintrc +++ b/.eslintrc @@ -34,7 +34,8 @@ "services": "always", "api": "always", "all": "always", - "main": "always" + "main": "always", + "save": "always" } ], "@typescript-eslint/no-unused-vars": [ diff --git a/rollup/rollup.config.ts b/rollup/rollup.config.ts index 06cd502a..036de733 100644 --- a/rollup/rollup.config.ts +++ b/rollup/rollup.config.ts @@ -513,7 +513,7 @@ export default (args: Record): rollup.RollupOptions[] => { path.endsWith('.all.js') || path.endsWith('xtensionPoint.js') || path.includes('vs/workbench/api/browser/') || - path.endsWith('/fileCommands.js') || + path.includes('fileCommands') || path.endsWith('/listCommands.js') || path.endsWith('/quickAccessActions.js') || path.endsWith('/gotoLineQuickAccess.js') || diff --git a/scripts/vscode.patch b/scripts/vscode.patch index 8f814bac..c0852650 100644 --- a/scripts/vscode.patch +++ b/scripts/vscode.patch @@ -3401,6 +3401,481 @@ index bb3f66c7175..6c9601873bc 100644 } get repository(): string | undefined { +diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.save.ts b/src/vs/workbench/contrib/files/browser/fileCommands.save.ts +new file mode 100644 +index 00000000000..e7540d3d049 +--- /dev/null ++++ b/src/vs/workbench/contrib/files/browser/fileCommands.save.ts +@@ -0,0 +1,198 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import { toAction } from 'vs/base/common/actions'; ++import { coalesce } from 'vs/base/common/arrays'; ++import { toErrorMessage } from 'vs/base/common/errorMessage'; ++import { isCancellationError } from 'vs/base/common/errors'; ++import { hash } from 'vs/base/common/hash'; ++import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; ++import { isEqual } from 'vs/base/common/resources'; ++import { URI } from 'vs/base/common/uri'; ++import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; ++import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; ++import * as nls from 'vs/nls'; ++import { CommandsRegistry } from 'vs/platform/commands/common/commands'; ++import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; ++import { KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; ++import { IListService } from 'vs/platform/list/browser/listService'; ++import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; ++import { getMultiSelectedEditorContexts } from 'vs/workbench/browser/parts/editor/editorCommands'; ++import { EditorInputCapabilities, EditorResourceAccessor, EditorsOrder, IEditorCommandsContext, IEditorIdentifier, SaveReason, SideBySideEditor } from 'vs/workbench/common/editor'; ++import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; ++import { getOpenEditorsViewMultiSelection } from 'vs/workbench/contrib/files/browser/files'; ++import { GroupsOrder, IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; ++import { IEditorService, ISaveEditorsOptions } from 'vs/workbench/services/editor/common/editorService'; ++import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; ++import { SAVE_ALL_COMMAND_ID, SAVE_ALL_IN_GROUP_COMMAND_ID, SAVE_FILES_COMMAND_ID, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID } from './fileConstants'; ++ ++async function saveSelectedEditors(accessor: ServicesAccessor, options?: ISaveEditorsOptions): Promise { ++ const listService = accessor.get(IListService); ++ const editorGroupService = accessor.get(IEditorGroupsService); ++ const codeEditorService = accessor.get(ICodeEditorService); ++ const textFileService = accessor.get(ITextFileService); ++ ++ // Retrieve selected or active editor ++ let editors = getOpenEditorsViewMultiSelection(listService, editorGroupService); ++ if (!editors) { ++ const activeGroup = editorGroupService.activeGroup; ++ if (activeGroup.activeEditor) { ++ editors = []; ++ ++ // Special treatment for side by side editors: if the active editor ++ // has 2 sides, we consider both, to support saving both sides. ++ // We only allow this when saving, not for "Save As" and not if any ++ // editor is untitled which would bring up a "Save As" dialog too. ++ // In addition, we require the secondary side to be modified to not ++ // trigger a touch operation unexpectedly. ++ // ++ // See also https://github.com/microsoft/vscode/issues/4180 ++ // See also https://github.com/microsoft/vscode/issues/106330 ++ // See also https://github.com/microsoft/vscode/issues/190210 ++ if ( ++ activeGroup.activeEditor instanceof SideBySideEditorInput && ++ !options?.saveAs && !(activeGroup.activeEditor.primary.hasCapability(EditorInputCapabilities.Untitled) || activeGroup.activeEditor.secondary.hasCapability(EditorInputCapabilities.Untitled)) && ++ activeGroup.activeEditor.secondary.isModified() ++ ) { ++ editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.primary }); ++ editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.secondary }); ++ } else { ++ editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor }); ++ } ++ } ++ } ++ ++ if (!editors || editors.length === 0) { ++ return; // nothing to save ++ } ++ ++ // Save editors ++ await doSaveEditors(accessor, editors, options); ++ ++ // Special treatment for embedded editors: if we detect that focus is ++ // inside an embedded code editor, we save that model as well if we ++ // find it in our text file models. Currently, only textual editors ++ // support embedded editors. ++ const focusedCodeEditor = codeEditorService.getFocusedCodeEditor(); ++ if (focusedCodeEditor instanceof EmbeddedCodeEditorWidget && !focusedCodeEditor.isSimpleWidget) { ++ const resource = focusedCodeEditor.getModel()?.uri; ++ ++ // Check that the resource of the model was not saved already ++ if (resource && !editors.some(({ editor }) => isEqual(EditorResourceAccessor.getCanonicalUri(editor, { supportSideBySide: SideBySideEditor.PRIMARY }), resource))) { ++ const model = textFileService.files.get(resource); ++ if (!model?.isReadonly()) { ++ await textFileService.save(resource, options); ++ } ++ } ++ } ++} ++ ++function saveDirtyEditorsOfGroups(accessor: ServicesAccessor, groups: readonly IEditorGroup[], options?: ISaveEditorsOptions): Promise { ++ const dirtyEditors: IEditorIdentifier[] = []; ++ for (const group of groups) { ++ for (const editor of group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)) { ++ if (editor.isDirty()) { ++ dirtyEditors.push({ groupId: group.id, editor }); ++ } ++ } ++ } ++ ++ return doSaveEditors(accessor, dirtyEditors, options); ++} ++ ++async function doSaveEditors(accessor: ServicesAccessor, editors: IEditorIdentifier[], options?: ISaveEditorsOptions): Promise { ++ const editorService = accessor.get(IEditorService); ++ const notificationService = accessor.get(INotificationService); ++ const instantiationService = accessor.get(IInstantiationService); ++ ++ try { ++ await editorService.save(editors, options); ++ } catch (error) { ++ if (!isCancellationError(error)) { ++ notificationService.notify({ ++ id: editors.map(({ editor }) => hash(editor.resource?.toString())).join(), // ensure unique notification ID per set of editor ++ severity: Severity.Error, ++ message: nls.localize({ key: 'genericSaveError', comment: ['{0} is the resource that failed to save and {1} the error message'] }, "Failed to save '{0}': {1}", editors.map(({ editor }) => editor.getName()).join(', '), toErrorMessage(error, false)), ++ actions: { ++ primary: [ ++ toAction({ id: 'workbench.action.files.saveEditors', label: nls.localize('retry', "Retry"), run: () => instantiationService.invokeFunction(accessor => doSaveEditors(accessor, editors, options)) }), ++ toAction({ id: 'workbench.action.files.revertEditors', label: nls.localize('discard', "Discard"), run: () => editorService.revert(editors) }) ++ ] ++ } ++ }); ++ } ++ } ++} ++ ++KeybindingsRegistry.registerCommandAndKeybindingRule({ ++ when: undefined, ++ weight: KeybindingWeight.WorkbenchContrib, ++ primary: KeyMod.CtrlCmd | KeyCode.KeyS, ++ id: SAVE_FILE_COMMAND_ID, ++ handler: accessor => { ++ return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true /* force save even when non-dirty */ }); ++ } ++}); ++ ++KeybindingsRegistry.registerCommandAndKeybindingRule({ ++ when: undefined, ++ weight: KeybindingWeight.WorkbenchContrib, ++ primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyS), ++ win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyS) }, ++ id: SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, ++ handler: accessor => { ++ return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true /* force save even when non-dirty */, skipSaveParticipants: true }); ++ } ++}); ++ ++KeybindingsRegistry.registerCommandAndKeybindingRule({ ++ id: SAVE_FILE_AS_COMMAND_ID, ++ weight: KeybindingWeight.WorkbenchContrib, ++ when: undefined, ++ primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyS, ++ handler: accessor => { ++ return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, saveAs: true }); ++ } ++}); ++ ++KeybindingsRegistry.registerCommandAndKeybindingRule({ ++ when: undefined, ++ weight: KeybindingWeight.WorkbenchContrib, ++ primary: undefined, ++ mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KeyS }, ++ win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyS) }, ++ id: SAVE_ALL_COMMAND_ID, ++ handler: accessor => { ++ return saveDirtyEditorsOfGroups(accessor, accessor.get(IEditorGroupsService).getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE), { reason: SaveReason.EXPLICIT }); ++ } ++}); ++ ++CommandsRegistry.registerCommand({ ++ id: SAVE_ALL_IN_GROUP_COMMAND_ID, ++ handler: (accessor, _: URI | object, editorContext: IEditorCommandsContext) => { ++ const editorGroupService = accessor.get(IEditorGroupsService); ++ ++ const contexts = getMultiSelectedEditorContexts(editorContext, accessor.get(IListService), accessor.get(IEditorGroupsService)); ++ ++ let groups: readonly IEditorGroup[] | undefined = undefined; ++ if (!contexts.length) { ++ groups = editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); ++ } else { ++ groups = coalesce(contexts.map(context => editorGroupService.getGroup(context.groupId))); ++ } ++ ++ return saveDirtyEditorsOfGroups(accessor, groups, { reason: SaveReason.EXPLICIT }); ++ } ++}); ++ ++CommandsRegistry.registerCommand({ ++ id: SAVE_FILES_COMMAND_ID, ++ handler: async accessor => { ++ const editorService = accessor.get(IEditorService); ++ ++ const res = await editorService.saveAll({ includeUntitled: false, reason: SaveReason.EXPLICIT }); ++ return res.success; ++ } ++}); +diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts +index 6fa04545a0e..7fe3e6ecee1 100644 +--- a/src/vs/workbench/contrib/files/browser/fileCommands.ts ++++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts +@@ -3,56 +3,48 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import * as nls from 'vs/nls'; ++import { toErrorMessage } from 'vs/base/common/errorMessage'; ++import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; ++import { IDisposable, dispose } from 'vs/base/common/lifecycle'; ++import { Schemas } from 'vs/base/common/network'; ++import { isWeb, isWindows } from 'vs/base/common/platform'; ++import { basename, joinPath } from 'vs/base/common/resources'; + import { URI } from 'vs/base/common/uri'; +-import { EditorResourceAccessor, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier, SaveReason, EditorsOrder, EditorInputCapabilities } from 'vs/workbench/common/editor'; +-import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; +-import { IWindowOpenable, IOpenWindowOptions, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/window/common/window'; +-import { IHostService } from 'vs/workbench/services/host/browser/host'; +-import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +-import { IWorkspaceContextService, UNTITLED_WORKSPACE_NAME } from 'vs/platform/workspace/common/workspace'; +-import { ExplorerFocusCondition, TextFileContentProvider, VIEWLET_ID, ExplorerCompressedFocusContext, ExplorerCompressedFirstFocusContext, ExplorerCompressedLastFocusContext, FilesExplorerFocusCondition, ExplorerFolderContext, VIEW_ID } from 'vs/workbench/contrib/files/common/files'; +-import { ExplorerViewPaneContainer } from 'vs/workbench/contrib/files/browser/explorerViewlet'; ++import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; ++import { ITextModelService } from 'vs/editor/common/services/resolverService'; ++import * as nls from 'vs/nls'; + import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +-import { toErrorMessage } from 'vs/base/common/errorMessage'; +-import { IListService } from 'vs/platform/list/browser/listService'; + import { CommandsRegistry, ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands'; +-import { IContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; ++import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; ++import { ContextKeyExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; ++import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; ++import { EditorOpenSource, EditorResolution } from 'vs/platform/editor/common/editor'; ++import { IEnvironmentService } from 'vs/platform/environment/common/environment'; + import { IFileService } from 'vs/platform/files/common/files'; +-import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +-import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; +-import { isWeb, isWindows } from 'vs/base/common/platform'; +-import { ITextModelService } from 'vs/editor/common/services/resolverService'; +-import { getResourceForCommand, getMultiSelectedResources, getOpenEditorsViewMultiSelection, IExplorerService } from 'vs/workbench/contrib/files/browser/files'; +-import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; +-import { getMultiSelectedEditorContexts } from 'vs/workbench/browser/parts/editor/editorCommands'; +-import { Schemas } from 'vs/base/common/network'; +-import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; +-import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; +-import { IEditorService, SIDE_GROUP, ISaveEditorsOptions } from 'vs/workbench/services/editor/common/editorService'; +-import { IEditorGroupsService, GroupsOrder, IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; ++import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; ++import { KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; + import { ILabelService } from 'vs/platform/label/common/label'; +-import { basename, joinPath, isEqual } from 'vs/base/common/resources'; +-import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +-import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +-import { coalesce } from 'vs/base/common/arrays'; +-import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; +-import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; +-import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; ++import { IListService } from 'vs/platform/list/browser/listService'; ++import { INotificationService } from 'vs/platform/notification/common/notification'; + import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; +-import { isCancellationError } from 'vs/base/common/errors'; +-import { toAction } from 'vs/base/common/actions'; +-import { EditorOpenSource, EditorResolution } from 'vs/platform/editor/common/editor'; +-import { hash } from 'vs/base/common/hash'; +-import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +-import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; +-import { ViewContainerLocation } from 'vs/workbench/common/views'; +-import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; +-import { OPEN_TO_SIDE_COMMAND_ID, COMPARE_WITH_SAVED_COMMAND_ID, SELECT_FOR_COMPARE_COMMAND_ID, ResourceSelectedForCompareContext, COMPARE_SELECTED_COMMAND_ID, COMPARE_RESOURCE_COMMAND_ID, COPY_PATH_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, OPEN_WITH_EXPLORER_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, SAVE_FILE_AS_COMMAND_ID, SAVE_ALL_COMMAND_ID, SAVE_ALL_IN_GROUP_COMMAND_ID, SAVE_FILES_COMMAND_ID, REVERT_FILE_COMMAND_ID, REMOVE_ROOT_FOLDER_COMMAND_ID, PREVIOUS_COMPRESSED_FOLDER, NEXT_COMPRESSED_FOLDER, FIRST_COMPRESSED_FOLDER, LAST_COMPRESSED_FOLDER, NEW_UNTITLED_FILE_COMMAND_ID, NEW_UNTITLED_FILE_LABEL, NEW_FILE_COMMAND_ID } from './fileConstants'; +-import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; ++import { IOpenEmptyWindowOptions, IOpenWindowOptions, IWindowOpenable, isWorkspaceToOpen } from 'vs/platform/window/common/window'; ++import { IWorkspaceContextService, UNTITLED_WORKSPACE_NAME } from 'vs/platform/workspace/common/workspace'; + import { RemoveRootFolderAction } from 'vs/workbench/browser/actions/workspaceActions'; +-import { OpenEditorsView } from 'vs/workbench/contrib/files/browser/views/openEditorsView'; ++import { EditorInputCapabilities, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; ++import { ViewContainerLocation } from 'vs/workbench/common/views'; ++import { ExplorerViewPaneContainer } from 'vs/workbench/contrib/files/browser/explorerViewlet'; ++import { IExplorerService, getMultiSelectedResources, getOpenEditorsViewMultiSelection, getResourceForCommand } from 'vs/workbench/contrib/files/browser/files'; + import { ExplorerView } from 'vs/workbench/contrib/files/browser/views/explorerView'; ++import { OpenEditorsView } from 'vs/workbench/contrib/files/browser/views/openEditorsView'; ++import { ExplorerCompressedFirstFocusContext, ExplorerCompressedFocusContext, ExplorerCompressedLastFocusContext, ExplorerFocusCondition, ExplorerFolderContext, FilesExplorerFocusCondition, TextFileContentProvider, VIEWLET_ID, VIEW_ID } from 'vs/workbench/contrib/files/common/files'; ++import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; ++import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; ++import { IHostService } from 'vs/workbench/services/host/browser/host'; ++import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; ++import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; ++import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; ++import { COMPARE_RESOURCE_COMMAND_ID, COMPARE_SELECTED_COMMAND_ID, COMPARE_WITH_SAVED_COMMAND_ID, COPY_PATH_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID, FIRST_COMPRESSED_FOLDER, LAST_COMPRESSED_FOLDER, NEW_FILE_COMMAND_ID, NEW_UNTITLED_FILE_COMMAND_ID, NEW_UNTITLED_FILE_LABEL, NEXT_COMPRESSED_FOLDER, OPEN_TO_SIDE_COMMAND_ID, OPEN_WITH_EXPLORER_COMMAND_ID, PREVIOUS_COMPRESSED_FOLDER, REMOVE_ROOT_FOLDER_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, REVERT_FILE_COMMAND_ID, ResourceSelectedForCompareContext, SELECT_FOR_COMPARE_COMMAND_ID } from './fileConstants'; ++import './fileCommands.save'; + + export const openWindowCommand = (accessor: ServicesAccessor, toOpen: IWindowOpenable[], options?: IOpenWindowOptions) => { + if (Array.isArray(toOpen)) { +@@ -366,175 +358,6 @@ CommandsRegistry.registerCommand({ + + // Save / Save As / Save All / Revert + +-async function saveSelectedEditors(accessor: ServicesAccessor, options?: ISaveEditorsOptions): Promise { +- const listService = accessor.get(IListService); +- const editorGroupService = accessor.get(IEditorGroupsService); +- const codeEditorService = accessor.get(ICodeEditorService); +- const textFileService = accessor.get(ITextFileService); +- +- // Retrieve selected or active editor +- let editors = getOpenEditorsViewMultiSelection(listService, editorGroupService); +- if (!editors) { +- const activeGroup = editorGroupService.activeGroup; +- if (activeGroup.activeEditor) { +- editors = []; +- +- // Special treatment for side by side editors: if the active editor +- // has 2 sides, we consider both, to support saving both sides. +- // We only allow this when saving, not for "Save As" and not if any +- // editor is untitled which would bring up a "Save As" dialog too. +- // In addition, we require the secondary side to be modified to not +- // trigger a touch operation unexpectedly. +- // +- // See also https://github.com/microsoft/vscode/issues/4180 +- // See also https://github.com/microsoft/vscode/issues/106330 +- // See also https://github.com/microsoft/vscode/issues/190210 +- if ( +- activeGroup.activeEditor instanceof SideBySideEditorInput && +- !options?.saveAs && !(activeGroup.activeEditor.primary.hasCapability(EditorInputCapabilities.Untitled) || activeGroup.activeEditor.secondary.hasCapability(EditorInputCapabilities.Untitled)) && +- activeGroup.activeEditor.secondary.isModified() +- ) { +- editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.primary }); +- editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.secondary }); +- } else { +- editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor }); +- } +- } +- } +- +- if (!editors || editors.length === 0) { +- return; // nothing to save +- } +- +- // Save editors +- await doSaveEditors(accessor, editors, options); +- +- // Special treatment for embedded editors: if we detect that focus is +- // inside an embedded code editor, we save that model as well if we +- // find it in our text file models. Currently, only textual editors +- // support embedded editors. +- const focusedCodeEditor = codeEditorService.getFocusedCodeEditor(); +- if (focusedCodeEditor instanceof EmbeddedCodeEditorWidget && !focusedCodeEditor.isSimpleWidget) { +- const resource = focusedCodeEditor.getModel()?.uri; +- +- // Check that the resource of the model was not saved already +- if (resource && !editors.some(({ editor }) => isEqual(EditorResourceAccessor.getCanonicalUri(editor, { supportSideBySide: SideBySideEditor.PRIMARY }), resource))) { +- const model = textFileService.files.get(resource); +- if (!model?.isReadonly()) { +- await textFileService.save(resource, options); +- } +- } +- } +-} +- +-function saveDirtyEditorsOfGroups(accessor: ServicesAccessor, groups: readonly IEditorGroup[], options?: ISaveEditorsOptions): Promise { +- const dirtyEditors: IEditorIdentifier[] = []; +- for (const group of groups) { +- for (const editor of group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)) { +- if (editor.isDirty()) { +- dirtyEditors.push({ groupId: group.id, editor }); +- } +- } +- } +- +- return doSaveEditors(accessor, dirtyEditors, options); +-} +- +-async function doSaveEditors(accessor: ServicesAccessor, editors: IEditorIdentifier[], options?: ISaveEditorsOptions): Promise { +- const editorService = accessor.get(IEditorService); +- const notificationService = accessor.get(INotificationService); +- const instantiationService = accessor.get(IInstantiationService); +- +- try { +- await editorService.save(editors, options); +- } catch (error) { +- if (!isCancellationError(error)) { +- notificationService.notify({ +- id: editors.map(({ editor }) => hash(editor.resource?.toString())).join(), // ensure unique notification ID per set of editor +- severity: Severity.Error, +- message: nls.localize({ key: 'genericSaveError', comment: ['{0} is the resource that failed to save and {1} the error message'] }, "Failed to save '{0}': {1}", editors.map(({ editor }) => editor.getName()).join(', '), toErrorMessage(error, false)), +- actions: { +- primary: [ +- toAction({ id: 'workbench.action.files.saveEditors', label: nls.localize('retry', "Retry"), run: () => instantiationService.invokeFunction(accessor => doSaveEditors(accessor, editors, options)) }), +- toAction({ id: 'workbench.action.files.revertEditors', label: nls.localize('discard', "Discard"), run: () => editorService.revert(editors) }) +- ] +- } +- }); +- } +- } +-} +- +-KeybindingsRegistry.registerCommandAndKeybindingRule({ +- when: undefined, +- weight: KeybindingWeight.WorkbenchContrib, +- primary: KeyMod.CtrlCmd | KeyCode.KeyS, +- id: SAVE_FILE_COMMAND_ID, +- handler: accessor => { +- return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true /* force save even when non-dirty */ }); +- } +-}); +- +-KeybindingsRegistry.registerCommandAndKeybindingRule({ +- when: undefined, +- weight: KeybindingWeight.WorkbenchContrib, +- primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyS), +- win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyS) }, +- id: SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, +- handler: accessor => { +- return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true /* force save even when non-dirty */, skipSaveParticipants: true }); +- } +-}); +- +-KeybindingsRegistry.registerCommandAndKeybindingRule({ +- id: SAVE_FILE_AS_COMMAND_ID, +- weight: KeybindingWeight.WorkbenchContrib, +- when: undefined, +- primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyS, +- handler: accessor => { +- return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, saveAs: true }); +- } +-}); +- +-KeybindingsRegistry.registerCommandAndKeybindingRule({ +- when: undefined, +- weight: KeybindingWeight.WorkbenchContrib, +- primary: undefined, +- mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KeyS }, +- win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyS) }, +- id: SAVE_ALL_COMMAND_ID, +- handler: accessor => { +- return saveDirtyEditorsOfGroups(accessor, accessor.get(IEditorGroupsService).getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE), { reason: SaveReason.EXPLICIT }); +- } +-}); +- +-CommandsRegistry.registerCommand({ +- id: SAVE_ALL_IN_GROUP_COMMAND_ID, +- handler: (accessor, _: URI | object, editorContext: IEditorCommandsContext) => { +- const editorGroupService = accessor.get(IEditorGroupsService); +- +- const contexts = getMultiSelectedEditorContexts(editorContext, accessor.get(IListService), accessor.get(IEditorGroupsService)); +- +- let groups: readonly IEditorGroup[] | undefined = undefined; +- if (!contexts.length) { +- groups = editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); +- } else { +- groups = coalesce(contexts.map(context => editorGroupService.getGroup(context.groupId))); +- } +- +- return saveDirtyEditorsOfGroups(accessor, groups, { reason: SaveReason.EXPLICIT }); +- } +-}); +- +-CommandsRegistry.registerCommand({ +- id: SAVE_FILES_COMMAND_ID, +- handler: async accessor => { +- const editorService = accessor.get(IEditorService); +- +- const res = await editorService.saveAll({ includeUntitled: false, reason: SaveReason.EXPLICIT }); +- return res.success; +- } +-}); +- + CommandsRegistry.registerCommand({ + id: REVERT_FILE_COMMAND_ID, + handler: async accessor => { diff --git a/src/vs/workbench/contrib/files/browser/files.configuration.contribution.ts b/src/vs/workbench/contrib/files/browser/files.configuration.contribution.ts new file mode 100644 index 00000000000..39509160248 diff --git a/src/service-override/editor.ts b/src/service-override/editor.ts index 2f49de63..b21481cf 100644 --- a/src/service-override/editor.ts +++ b/src/service-override/editor.ts @@ -17,6 +17,7 @@ import { MonacoDelegateEditorGroupsService, MonacoEditorService, OpenEditor } fr import { unsupported } from '../tools' import 'vs/workbench/browser/parts/editor/editor.autosave.contribution' import 'vs/workbench/contrib/files/browser/files.fileEditorFactory.contribution' +import 'vs/workbench/contrib/files/browser/fileCommands.save' class EmptyEditorGroup implements IEditorGroup, IEditorGroupView { windowId = mainWindow.vscodeWindowId From 7573f6ebd4817ef34d2a65356aa633fca3ca4af9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= Date: Fri, 9 Feb 2024 11:00:23 +0100 Subject: [PATCH 3/4] fix: only apply VSCode global style to VSCode elements to be able to keep it --- rollup/rollup.config.ts | 4 - scripts/vscode.patch | 194 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+), 4 deletions(-) diff --git a/rollup/rollup.config.ts b/rollup/rollup.config.ts index 036de733..72713729 100644 --- a/rollup/rollup.config.ts +++ b/rollup/rollup.config.ts @@ -499,10 +499,6 @@ export default (args: Record): rollup.RollupOptions[] => { preset: 'smallest', moduleSideEffects (id) { const path = new URL(id, 'file:/').pathname - if (path.endsWith('vs/workbench/browser/media/style.css')) { - // Remove global vscode css rules - return false - } return path.startsWith(SRC_DIR) || path.includes('vs/editor') || path.includes('codiconStyles') || diff --git a/scripts/vscode.patch b/scripts/vscode.patch index c0852650..e98d2571 100644 --- a/scripts/vscode.patch +++ b/scripts/vscode.patch @@ -2720,6 +2720,200 @@ index ccdbaf9d6bd..77e894faf5c 100644 readonly filesToOpenOrCreate?: IPathToOpen[]; readonly filesToDiff?: IPathToOpen[]; readonly filesToMerge?: IPathToOpen[]; +diff --git a/src/vs/workbench/browser/media/style.css b/src/vs/workbench/browser/media/style.css +index 262745f0ed2..487faffe72e 100644 +--- a/src/vs/workbench/browser/media/style.css ++++ b/src/vs/workbench/browser/media/style.css +@@ -34,22 +34,7 @@ + + /* Global Styles */ + +-body { +- height: 100%; +- width: 100%; +- margin: 0; +- padding: 0; +- overflow: hidden; +- font-size: 11px; +- user-select: none; +- -webkit-user-select: none; +-} +- +-body.web { +- position: fixed; /* prevent bounce effect */ +-} +- +-.monaco-workbench { ++.monaco-workbench .monaco-editor, .monaco-workbench .part { + font-size: 13px; + line-height: 1.4em; + position: relative; +@@ -58,81 +43,70 @@ body.web { + color: var(--vscode-foreground); + } + +-.monaco-workbench.web { ++.monaco-workbench.web .monaco-editor, .monaco-workbench.web .part { + touch-action: none; /* Disable browser handling of all panning and zooming gestures. Removes 300ms touch delay. */ + } + +-.monaco-workbench.border:not(.fullscreen) { +- box-sizing: border-box; +- border: 1px solid var(--window-border-color); +-} +- +-.monaco-workbench.border.mac { +- border-radius: 5px; +-} +- +-.monaco-workbench.border.mac.macos-bigsur-or-newer { +- border-radius: 10px; /* macOS Big Sur increased rounded corners size */ +-} +- +-.monaco-workbench img { ++.monaco-workbench .monaco-editor img, .monaco-workbench .part img { + border: 0; + } + +-.monaco-workbench label { ++.monaco-workbench .monaco-editor label, .monaco-workbench .part label { + cursor: pointer; + } + +-.monaco-workbench a { ++.monaco-workbench .monaco-editor a, .monaco-workbench .part a { + text-decoration: none; + } + +-.monaco-workbench a:active { ++.monaco-workbench .monaco-editor a:active, .monaco-workbench .part a:active { + color: inherit; + background-color: inherit; + } + +-.monaco-workbench a.plain { ++.monaco-workbench .monaco-editor a.plain, .monaco-workbench .part a.plain { + color: inherit; + text-decoration: none; + } + +-.monaco-workbench a.plain:hover, +-.monaco-workbench a.plain.hover { ++.monaco-workbench .monaco-editor a.plain:hover, ++.monaco-workbench .monaco-editor a.plain.hover, ++.monaco-workbench .part a.plain:hover, ++.monaco-workbench .part a.plain.hover { + color: inherit; + text-decoration: none; + } + +-.monaco-workbench input { ++.monaco-workbench .monaco-editor input, .monaco-workbench .part input { + color: inherit; + font-family: inherit; + font-size: 100%; + } + +-.monaco-workbench input::placeholder { color: var(--vscode-input-placeholderForeground); } +-.monaco-workbench input::-webkit-input-placeholder { color: var(--vscode-input-placeholderForeground); } +-.monaco-workbench input::-moz-placeholder { color: var(--vscode-input-placeholderForeground); } ++.monaco-workbench .monaco-editor input::placeholder, .monaco-workbench .part input::placeholder { color: var(--vscode-input-placeholderForeground); } ++.monaco-workbench .monaco-editor input::-webkit-input-placeholder , .monaco-workbench .part input::-webkit-input-placeholder { color: var(--vscode-input-placeholderForeground); } ++.monaco-workbench .monaco-editor input::-moz-placeholder, .monaco-workbench .part input::-moz-placeholder { color: var(--vscode-input-placeholderForeground); } + +-.monaco-workbench textarea::placeholder { color: var(--vscode-input-placeholderForeground); } +-.monaco-workbench textarea::-webkit-input-placeholder { color: var(--vscode-input-placeholderForeground); } +-.monaco-workbench textarea::-moz-placeholder { color: var(--vscode-input-placeholderForeground); } ++.monaco-workbench .monaco-editor textarea::placeholder, .monaco-workbench .part textarea::placeholder { color: var(--vscode-input-placeholderForeground); } ++.monaco-workbench .monaco-editor textarea::-webkit-input-placeholder, .monaco-workbench .part textarea::-webkit-input-placeholder { color: var(--vscode-input-placeholderForeground); } ++.monaco-workbench .monaco-editor textarea::-moz-placeholder, .monaco-workbench .part textarea::-moz-placeholder { color: var(--vscode-input-placeholderForeground); } + +-.monaco-workbench .pointer { ++.monaco-workbench .monaco-editor .pointer, .monaco-workbench .part .pointer { + cursor: pointer; + } + +-.monaco-workbench.mac.monaco-font-aliasing-antialiased { ++.monaco-workbench.mac.monaco-font-aliasing-antialiased .monaco-editor, .monaco-workbench.mac.monaco-font-aliasing-antialiased .part { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + +-.monaco-workbench.mac.monaco-font-aliasing-none { ++.monaco-workbench.mac.monaco-font-aliasing-none .monaco-editor, .monaco-workbench.mac.monaco-font-aliasing-none .part { + -webkit-font-smoothing: none; + -moz-osx-font-smoothing: unset; + } + + @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { +- .monaco-workbench.mac.monaco-font-aliasing-auto { ++ .monaco-workbench.mac.monaco-font-aliasing-auto .monaco-editor, .monaco-workbench.mac.monaco-font-aliasing-auto .part { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } +@@ -167,7 +141,7 @@ body.web { + + /* Custom Dropdown (select) Arrows */ + +-.monaco-workbench select { ++.monaco-workbench .monaco-editor select, .monaco-workbench .part select { + font-family: inherit; + appearance: none; + -webkit-appearance: none; +@@ -197,16 +171,16 @@ body.web { + + /* Keyboard Focus Indication Styles */ + +-.monaco-workbench [tabindex="0"]:focus, +-.monaco-workbench [tabindex="-1"]:focus, +-.monaco-workbench .synthetic-focus, +-.monaco-workbench select:focus, +-.monaco-workbench input[type="button"]:focus, +-.monaco-workbench input[type="text"]:focus, +-.monaco-workbench button:focus, +-.monaco-workbench textarea:focus, +-.monaco-workbench input[type="search"]:focus, +-.monaco-workbench input[type="checkbox"]:focus { ++.monaco-workbench .monaco-editor [tabindex="0"]:focus, .monaco-workbench .mpart [tabindex="0"]:focus,, ++.monaco-workbench .monaco-editor [tabindex="-1"]:focus, .monaco-workbench .part [tabindex="-1"]:focus, ++.monaco-workbench .monaco-editor .synthetic-focus, .monaco-workbench .part .synthetic-focus, ++.monaco-workbench .monaco-editor select:focus, .monaco-workbench .part select:focus, ++.monaco-workbench .monaco-editor input[type="button"]:focus,.monaco-workbench .part input[type="button"]:focus, ++.monaco-workbench .monaco-editor input[type="text"]:focus, .monaco-workbench .part input[type="text"]:focus, ++.monaco-workbench .monaco-editor button:focus, .monaco-workbench .part button:focus, ++.monaco-workbench .monaco-editor textarea:focus, .monaco-workbench .part textarea:focus, ++.monaco-workbench .monaco-editor input[type="search"]:focus, .monaco-workbench .part input[type="search"]:focus, ++.monaco-workbench .monaco-editor input[type="checkbox"]:focus, .monaco-workbench .part input[type="checkbox"]:focus { + outline-width: 1px; + outline-style: solid; + outline-offset: -1px; +@@ -219,19 +193,19 @@ body.web { + background: transparent; /* Search input focus fix when in high contrast */ + } + +-.monaco-workbench input[type="checkbox"]:focus { ++.monaco-workbench .monaco-editor input[type="checkbox"]:focus, .monaco-workbench .part input[type="checkbox"]:focus { + outline-offset: 2px; + } + +-.monaco-workbench [tabindex="0"]:active, +-.monaco-workbench [tabindex="-1"]:active, +-.monaco-workbench select:active, +-.monaco-workbench input[type="button"]:active, +-.monaco-workbench input[type="checkbox"]:active { ++.monaco-workbench .monaco-editor [tabindex="0"]:active, .monaco-workbench part [tabindex="0"]:active, ++.monaco-workbench .monaco-editor [tabindex="-1"]:active, .monaco-workbench .part [tabindex="-1"]:active, ++.monaco-workbench .monaco-editor select:active, .monaco-workbench .part select:active, ++.monaco-workbench .monaco-editor input[type="button"]:active, .monaco-workbench .part input[type="button"]:active, ++.monaco-workbench .monaco-editor input[type="checkbox"]:active, .monaco-workbench .part input[type="checkbox"]:active { + outline: 0 !important; /* fixes some flashing outlines from showing up when clicking */ + } + +-.monaco-workbench.mac select:focus { ++.monaco-workbench.mac .monaco-editor select:focus, .monaco-workbench.mac .part select:focus { + border-color: transparent; /* outline is a square, but border has a radius, so we avoid this glitch when focused (https://github.com/microsoft/vscode/issues/26045) */ + } + diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index a2007e18299..7446cfcfc5f 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts From 682e285846b7875029103d629089ebbe63322546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= Date: Fri, 9 Feb 2024 11:00:38 +0100 Subject: [PATCH 4/4] cleanup: remove console.warn --- scripts/vscode.patch | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/scripts/vscode.patch b/scripts/vscode.patch index e98d2571..a93eaa1a 100644 --- a/scripts/vscode.patch +++ b/scripts/vscode.patch @@ -5752,6 +5752,35 @@ index 1ba671448d2..bec87c04f1e 100644 await vscodeOniguruma.loadWASM({ data: wasm, print: (str: string) => { +diff --git a/src/vs/workbench/services/textMate/common/TMScopeRegistry.ts b/src/vs/workbench/services/textMate/common/TMScopeRegistry.ts +index a1a0779371e..18ca6d1b496 100644 +--- a/src/vs/workbench/services/textMate/common/TMScopeRegistry.ts ++++ b/src/vs/workbench/services/textMate/common/TMScopeRegistry.ts +@@ -3,7 +3,6 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import * as resources from 'vs/base/common/resources'; + import { URI } from 'vs/base/common/uri'; + import { LanguageId, StandardTokenType } from 'vs/editor/common/encodedTokenAttributes'; + +@@ -40,16 +39,6 @@ export class TMScopeRegistry { + } + + public register(def: IValidGrammarDefinition): void { +- if (this._scopeNameToLanguageRegistration[def.scopeName]) { +- const existingRegistration = this._scopeNameToLanguageRegistration[def.scopeName]; +- if (!resources.isEqual(existingRegistration.location, def.location)) { +- console.warn( +- `Overwriting grammar scope name to file mapping for scope ${def.scopeName}.\n` + +- `Old grammar file: ${existingRegistration.location.toString()}.\n` + +- `New grammar file: ${def.location.toString()}` +- ); +- } +- } + this._scopeNameToLanguageRegistration[def.scopeName] = def; + } + diff --git a/src/vs/workbench/services/textfile/common/encoding.ts b/src/vs/workbench/services/textfile/common/encoding.ts index ad67fb4f422..fadf86cece5 100644 --- a/src/vs/workbench/services/textfile/common/encoding.ts