Open hediet opened 2 years ago
Related: https://github.com/microsoft/vscode/issues/157997#issuecomment-1213066409 in #157997
This is a counter example, where diffing both sides makes the experience worse:
When not removing the common prefix/suffix, both changes can easily be combined:
is there any way to have the checkbox experience back? i prefer checkbox over the current codesens
prompts.
Another example of where gits behavior is confusing that I just ran into:
GitHub/git (what is the conflict?):
VS Code Merge Editor (clearly on the left someone inserted two methods, on the right someone added one method):
This one is much worse:
GitHub (completely unusable diff):
VS Code:
Both are confusing, but VS Code got also lucky with a better diff, so it is much less confusing.
{
"languageId": "typescript",
"base": "/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Codicon } from 'vs/base/common/codicons';\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { EditorAction2, ServicesAccessor } from 'vs/editor/browser/editorExtensions';\nimport { findFocusedDiffEditor } from 'vs/editor/browser/widget/diffEditor.contribution';\nimport { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';\nimport { EditorContextKeys } from 'vs/editor/common/editorContextKeys';\nimport { localize } from 'vs/nls';\nimport { ILocalizedString } from 'vs/platform/action/common/action';\nimport { Action2, MenuId, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';\nimport { IConfigurationService } from 'vs/platform/configuration/common/configuration';\nimport { ContextKeyEqualsExpr, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';\n\nexport class ToggleCollapseUnchangedRegions extends Action2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.toggleCollapseUnchangedRegions',\n\t\t\ttitle: { value: localize('toggleCollapseUnchangedRegions', \"Toggle Collapse Unchanged Regions\"), original: 'Toggle Collapse Unchanged Regions' },\n\t\t\ticon: Codicon.map,\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\n\t\t\ttoggled: ContextKeyExpr.has('config.diffEditor.experimental.collapseUnchangedRegions'),\n\t\t\tmenu: {\n\t\t\t\tid: MenuId.EditorTitle,\n\t\t\t\torder: 22,\n\t\t\t\tgroup: 'navigation',\n\t\t\t\twhen: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\n\t\t\t},\n\t\t});\n\t}\n\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\n\t\tconst configurationService = accessor.get(IConfigurationService);\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.experimental.collapseUnchangedRegions');\n\t\tconfigurationService.updateValue('diffEditor.experimental.collapseUnchangedRegions', newValue);\n\t}\n}\n\nregisterAction2(ToggleCollapseUnchangedRegions);\n\nexport class ToggleShowMovedCodeBlocks extends Action2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.toggleShowMovedCodeBlocks',\n\t\t\ttitle: { value: localize('toggleShowMovedCodeBlocks', \"Toggle Show Moved Code Blocks\"), original: 'Toggle Show Moved Code Blocks' },\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\n\t\t});\n\t}\n\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\n\t\tconst configurationService = accessor.get(IConfigurationService);\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.experimental.showMoves');\n\t\tconfigurationService.updateValue('diffEditor.experimental.showMoves', newValue);\n\t}\n}\n\nregisterAction2(ToggleShowMovedCodeBlocks);\n\nexport class ToggleUseInlineViewWhenSpaceIsLimited extends Action2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.toggleUseInlineViewWhenSpaceIsLimited',\n\t\t\ttitle: { value: localize('toggleUseInlineViewWhenSpaceIsLimited', \"Toggle Use Inline View When Space Is Limited\"), original: 'Toggle Use Inline View When Space Is Limited' },\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\n\t\t});\n\t}\n\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\n\t\tconst configurationService = accessor.get(IConfigurationService);\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.useInlineViewWhenSpaceIsLimited');\n\t\tconfigurationService.updateValue('diffEditor.useInlineViewWhenSpaceIsLimited', newValue);\n\t}\n}\n\nregisterAction2(ToggleUseInlineViewWhenSpaceIsLimited);\n\nMenuRegistry.appendMenuItem(MenuId.EditorTitle, {\n\tcommand: {\n\t\tid: new ToggleUseInlineViewWhenSpaceIsLimited().desc.id,\n\t\ttitle: localize('useInlineViewWhenSpaceIsLimited', \"Use Inline View When Space Is Limited\"),\n\t\ttoggled: ContextKeyExpr.has('config.diffEditor.useInlineViewWhenSpaceIsLimited'),\n\t},\n\torder: 11,\n\tgroup: '1_diff',\n\twhen: ContextKeyExpr.and(\n\t\tEditorContextKeys.diffEditorRenderSideBySideInlineBreakpointReached,\n\t\tContextKeyEqualsExpr.create('diffEditorVersion', 2)\n\t)\n});\n\n/*\nTODO@hediet add this back once move detection is more polished.\nUsers can still enable this via settings.json (config.diffEditor.experimental.showMoves).\n\nMenuRegistry.appendMenuItem(MenuId.EditorTitle, {\n\tcommand: {\n\t\tid: new ToggleShowMovedCodeBlocks().desc.id,\n\t\ttitle: localize('showMoves', \"Show Moves\"),\n\t\ticon: Codicon.move,\n\t\ttoggled: ContextKeyEqualsExpr.create('config.diffEditor.experimental.showMoves', true),\n\t},\n\torder: 10,\n\tgroup: '1_diff',\n\twhen: ContextKeyEqualsExpr.create('diffEditorVersion', 2)\n});\n*/\n\nconst diffEditorCategory: ILocalizedString = {\n\tvalue: localize('diffEditor', 'Diff Editor'),\n\toriginal: 'Diff Editor',\n};\nexport class SwitchSide extends EditorAction2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.switchSide',\n\t\t\ttitle: { value: localize('switchSide', \"Switch Side\"), original: 'Switch Side' },\n\t\t\ticon: Codicon.arrowSwap,\n\t\t\tprecondition: ContextKeyExpr.and(ContextKeyEqualsExpr.create('diffEditorVersion', 2), ContextKeyExpr.has('isInDiffEditor')),\n\t\t\tf1: true,\n\t\t\tcategory: diffEditorCategory,\n\t\t});\n\t}\n\n\trunEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: unknown[]): void {\n\t\tconst diffEditor = findFocusedDiffEditor(accessor);\n\t\tif (diffEditor instanceof DiffEditorWidget2) {\n\t\t\tdiffEditor.switchSide();\n\t\t}\n\t}\n}\n\nregisterAction2(SwitchSide);\n",
"input1": "/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Codicon } from 'vs/base/common/codicons';\nimport { KeyCode } from 'vs/base/common/keyCodes';\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { EditorAction2, ServicesAccessor } from 'vs/editor/browser/editorExtensions';\nimport { findFocusedDiffEditor } from 'vs/editor/browser/widget/diffEditor.contribution';\nimport { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';\nimport { EditorContextKeys } from 'vs/editor/common/editorContextKeys';\nimport { localize } from 'vs/nls';\nimport { ILocalizedString } from 'vs/platform/action/common/action';\nimport { Action2, MenuId, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';\nimport { IConfigurationService } from 'vs/platform/configuration/common/configuration';\nimport { ContextKeyEqualsExpr, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';\n\nexport class ToggleCollapseUnchangedRegions extends Action2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.toggleCollapseUnchangedRegions',\n\t\t\ttitle: { value: localize('toggleCollapseUnchangedRegions', \"Toggle Collapse Unchanged Regions\"), original: 'Toggle Collapse Unchanged Regions' },\n\t\t\ticon: Codicon.map,\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\n\t\t\ttoggled: ContextKeyExpr.has('config.diffEditor.experimental.collapseUnchangedRegions'),\n\t\t\tmenu: {\n\t\t\t\tid: MenuId.EditorTitle,\n\t\t\t\torder: 22,\n\t\t\t\tgroup: 'navigation',\n\t\t\t\twhen: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\n\t\t\t},\n\t\t});\n\t}\n\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\n\t\tconst configurationService = accessor.get(IConfigurationService);\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.experimental.collapseUnchangedRegions');\n\t\tconfigurationService.updateValue('diffEditor.experimental.collapseUnchangedRegions', newValue);\n\t}\n}\n\nregisterAction2(ToggleCollapseUnchangedRegions);\n\nexport class ToggleShowMovedCodeBlocks extends Action2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.toggleShowMovedCodeBlocks',\n\t\t\ttitle: { value: localize('toggleShowMovedCodeBlocks', \"Toggle Show Moved Code Blocks\"), original: 'Toggle Show Moved Code Blocks' },\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\n\t\t});\n\t}\n\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\n\t\tconst configurationService = accessor.get(IConfigurationService);\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.experimental.showMoves');\n\t\tconfigurationService.updateValue('diffEditor.experimental.showMoves', newValue);\n\t}\n}\n\nregisterAction2(ToggleShowMovedCodeBlocks);\n\nexport class ToggleUseInlineViewWhenSpaceIsLimited extends Action2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.toggleUseInlineViewWhenSpaceIsLimited',\n\t\t\ttitle: { value: localize('toggleUseInlineViewWhenSpaceIsLimited', \"Toggle Use Inline View When Space Is Limited\"), original: 'Toggle Use Inline View When Space Is Limited' },\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\n\t\t});\n\t}\n\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\n\t\tconst configurationService = accessor.get(IConfigurationService);\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.useInlineViewWhenSpaceIsLimited');\n\t\tconfigurationService.updateValue('diffEditor.useInlineViewWhenSpaceIsLimited', newValue);\n\t}\n}\n\nregisterAction2(ToggleUseInlineViewWhenSpaceIsLimited);\n\nMenuRegistry.appendMenuItem(MenuId.EditorTitle, {\n\tcommand: {\n\t\tid: new ToggleUseInlineViewWhenSpaceIsLimited().desc.id,\n\t\ttitle: localize('useInlineViewWhenSpaceIsLimited', \"Use Inline View When Space Is Limited\"),\n\t\ttoggled: ContextKeyExpr.has('config.diffEditor.useInlineViewWhenSpaceIsLimited'),\n\t},\n\torder: 11,\n\tgroup: '1_diff',\n\twhen: ContextKeyExpr.and(\n\t\tEditorContextKeys.diffEditorRenderSideBySideInlineBreakpointReached,\n\t\tContextKeyEqualsExpr.create('diffEditorVersion', 2)\n\t)\n});\n\nMenuRegistry.appendMenuItem(MenuId.EditorTitle, {\n\tcommand: {\n\t\tid: new ToggleShowMovedCodeBlocks().desc.id,\n\t\ttitle: localize('showMoves', \"Show Moved Code Blocks\"),\n\t\ticon: Codicon.move,\n\t\ttoggled: ContextKeyEqualsExpr.create('config.diffEditor.experimental.showMoves', true),\n\t},\n\torder: 10,\n\tgroup: '1_diff',\n\twhen: ContextKeyEqualsExpr.create('diffEditorVersion', 2)\n});\n\nconst diffEditorCategory: ILocalizedString = {\n\tvalue: localize('diffEditor', 'Diff Editor'),\n\toriginal: 'Diff Editor',\n};\nexport class SwitchSide extends EditorAction2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.switchSide',\n\t\t\ttitle: { value: localize('switchSide', \"Switch Side\"), original: 'Switch Side' },\n\t\t\ticon: Codicon.arrowSwap,\n\t\t\tprecondition: ContextKeyExpr.and(ContextKeyEqualsExpr.create('diffEditorVersion', 2), ContextKeyExpr.has('isInDiffEditor')),\n\t\t\tf1: true,\n\t\t\tcategory: diffEditorCategory,\n\t\t});\n\t}\n\n\trunEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, arg?: { dryRun: boolean }): unknown {\n\t\tconst diffEditor = findFocusedDiffEditor(accessor);\n\t\tif (diffEditor instanceof DiffEditorWidget2) {\n\t\t\tif (arg && arg.dryRun) {\n\t\t\t\treturn { destinationSelection: diffEditor.mapToOtherSide().destinationSelection };\n\t\t\t} else {\n\t\t\t\tdiffEditor.switchSide();\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n}\n\nregisterAction2(SwitchSide);\n\nexport class ExitCompareMove extends EditorAction2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.exitCompareMove',\n\t\t\ttitle: { value: localize('exitCompareMove', \"Exit Compare Move\"), original: 'Exit Compare Move' },\n\t\t\ticon: Codicon.close,\n\t\t\tprecondition: EditorContextKeys.comparingMovedCode,\n\t\t\tf1: false,\n\t\t\tcategory: diffEditorCategory,\n\t\t\tkeybinding: {\n\t\t\t\tweight: 10000,\n\t\t\t\tprimary: KeyCode.Escape,\n\t\t\t}\n\t\t});\n\t}\n\n\trunEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: unknown[]): void {\n\t\tconst diffEditor = findFocusedDiffEditor(accessor);\n\t\tif (diffEditor instanceof DiffEditorWidget2) {\n\t\t\tdiffEditor.exitCompareMove();\n\t\t}\n\t}\n}\n\nregisterAction2(ExitCompareMove);\n",
"input2": "/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Codicon } from 'vs/base/common/codicons';\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\nimport { EditorAction2, ServicesAccessor } from 'vs/editor/browser/editorExtensions';\nimport { findFocusedDiffEditor } from 'vs/editor/browser/widget/diffEditor.contribution';\nimport { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';\nimport { EditorContextKeys } from 'vs/editor/common/editorContextKeys';\nimport { localize } from 'vs/nls';\nimport { ILocalizedString } from 'vs/platform/action/common/action';\nimport { Action2, MenuId, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';\nimport { IConfigurationService } from 'vs/platform/configuration/common/configuration';\nimport { ContextKeyEqualsExpr, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';\n\nexport class ToggleCollapseUnchangedRegions extends Action2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.toggleCollapseUnchangedRegions',\n\t\t\ttitle: { value: localize('toggleCollapseUnchangedRegions', \"Toggle Collapse Unchanged Regions\"), original: 'Toggle Collapse Unchanged Regions' },\n\t\t\ticon: Codicon.map,\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\n\t\t\ttoggled: ContextKeyExpr.has('config.diffEditor.experimental.collapseUnchangedRegions'),\n\t\t\tmenu: {\n\t\t\t\tid: MenuId.EditorTitle,\n\t\t\t\torder: 22,\n\t\t\t\tgroup: 'navigation',\n\t\t\t\twhen: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\n\t\t\t},\n\t\t});\n\t}\n\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\n\t\tconst configurationService = accessor.get(IConfigurationService);\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.experimental.collapseUnchangedRegions');\n\t\tconfigurationService.updateValue('diffEditor.experimental.collapseUnchangedRegions', newValue);\n\t}\n}\n\nregisterAction2(ToggleCollapseUnchangedRegions);\n\nexport class ToggleShowMovedCodeBlocks extends Action2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.toggleShowMovedCodeBlocks',\n\t\t\ttitle: { value: localize('toggleShowMovedCodeBlocks', \"Toggle Show Moved Code Blocks\"), original: 'Toggle Show Moved Code Blocks' },\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\n\t\t});\n\t}\n\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\n\t\tconst configurationService = accessor.get(IConfigurationService);\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.experimental.showMoves');\n\t\tconfigurationService.updateValue('diffEditor.experimental.showMoves', newValue);\n\t}\n}\n\nregisterAction2(ToggleShowMovedCodeBlocks);\n\nexport class ToggleUseInlineViewWhenSpaceIsLimited extends Action2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.toggleUseInlineViewWhenSpaceIsLimited',\n\t\t\ttitle: { value: localize('toggleUseInlineViewWhenSpaceIsLimited', \"Toggle Use Inline View When Space Is Limited\"), original: 'Toggle Use Inline View When Space Is Limited' },\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\n\t\t});\n\t}\n\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\n\t\tconst configurationService = accessor.get(IConfigurationService);\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.useInlineViewWhenSpaceIsLimited');\n\t\tconfigurationService.updateValue('diffEditor.useInlineViewWhenSpaceIsLimited', newValue);\n\t}\n}\n\nregisterAction2(ToggleUseInlineViewWhenSpaceIsLimited);\n\nMenuRegistry.appendMenuItem(MenuId.EditorTitle, {\n\tcommand: {\n\t\tid: new ToggleUseInlineViewWhenSpaceIsLimited().desc.id,\n\t\ttitle: localize('useInlineViewWhenSpaceIsLimited', \"Use Inline View When Space Is Limited\"),\n\t\ttoggled: ContextKeyExpr.has('config.diffEditor.useInlineViewWhenSpaceIsLimited'),\n\t},\n\torder: 11,\n\tgroup: '1_diff',\n\twhen: ContextKeyExpr.and(\n\t\tEditorContextKeys.diffEditorRenderSideBySideInlineBreakpointReached,\n\t\tContextKeyEqualsExpr.create('diffEditorVersion', 2)\n\t)\n});\n\n/*\nTODO@hediet add this back once move detection is more polished.\nUsers can still enable this via settings.json (config.diffEditor.experimental.showMoves).\n\nMenuRegistry.appendMenuItem(MenuId.EditorTitle, {\n\tcommand: {\n\t\tid: new ToggleShowMovedCodeBlocks().desc.id,\n\t\ttitle: localize('showMoves', \"Show Moves\"),\n\t\ticon: Codicon.move,\n\t\ttoggled: ContextKeyEqualsExpr.create('config.diffEditor.experimental.showMoves', true),\n\t},\n\torder: 10,\n\tgroup: '1_diff',\n\twhen: ContextKeyEqualsExpr.create('diffEditorVersion', 2)\n});\n*/\n\nconst diffEditorCategory: ILocalizedString = {\n\tvalue: localize('diffEditor', 'Diff Editor'),\n\toriginal: 'Diff Editor',\n};\n\nexport class SwitchSide extends EditorAction2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.switchSide',\n\t\t\ttitle: { value: localize('switchSide', \"Switch Side\"), original: 'Switch Side' },\n\t\t\ticon: Codicon.arrowSwap,\n\t\t\tprecondition: ContextKeyExpr.and(ContextKeyEqualsExpr.create('diffEditorVersion', 2), ContextKeyExpr.has('isInDiffEditor')),\n\t\t\tf1: true,\n\t\t\tcategory: diffEditorCategory,\n\t\t});\n\t}\n\n\trunEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: unknown[]): void {\n\t\tconst diffEditor = findFocusedDiffEditor(accessor);\n\t\tif (diffEditor instanceof DiffEditorWidget2) {\n\t\t\tdiffEditor.switchSide();\n\t\t}\n\t}\n}\n\nregisterAction2(SwitchSide);\n\nexport class CollapseAllUnchangedRegions extends EditorAction2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.collapseAllUnchangedRegions',\n\t\t\ttitle: { value: localize('collapseAllUnchangedRegions', \"Collapse All Unchanged Regions\"), original: 'Collapse All Unchanged Regions' },\n\t\t\ticon: Codicon.fold,\n\t\t\tprecondition: ContextKeyExpr.and(ContextKeyEqualsExpr.create('diffEditorVersion', 2), ContextKeyExpr.has('isInDiffEditor')),\n\t\t\tf1: true,\n\t\t\tcategory: diffEditorCategory,\n\t\t});\n\t}\n\n\trunEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: unknown[]): void {\n\t\tconst diffEditor = findFocusedDiffEditor(accessor);\n\t\tif (diffEditor instanceof DiffEditorWidget2) {\n\t\t\tdiffEditor.collapseAllUnchangedRegions();\n\t\t}\n\t}\n}\n\nregisterAction2(CollapseAllUnchangedRegions);\n\nexport class ShowAllUnchangedRegions extends EditorAction2 {\n\tconstructor() {\n\t\tsuper({\n\t\t\tid: 'diffEditor.showAllUnchangedRegions',\n\t\t\ttitle: { value: localize('showAllUnchangedRegions', \"Show All Unchanged Regions\"), original: 'Show All Unchanged Regions' },\n\t\t\ticon: Codicon.unfold,\n\t\t\tprecondition: ContextKeyExpr.and(ContextKeyEqualsExpr.create('diffEditorVersion', 2), ContextKeyExpr.has('isInDiffEditor')),\n\t\t\tf1: true,\n\t\t\tcategory: diffEditorCategory,\n\t\t});\n\t}\n\n\trunEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: unknown[]): void {\n\t\tconst diffEditor = findFocusedDiffEditor(accessor);\n\t\tif (diffEditor instanceof DiffEditorWidget2) {\n\t\t\tdiffEditor.showAllUnchangedRegions();\n\t\t}\n\t}\n}\n\nregisterAction2(ShowAllUnchangedRegions);\n",
"result": "/*---------------------------------------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License. See License.txt in the project root for license information.\r\n *--------------------------------------------------------------------------------------------*/\r\n\r\nimport { Codicon } from 'vs/base/common/codicons';\r\nimport { KeyCode } from 'vs/base/common/keyCodes';\r\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\r\nimport { EditorAction2, ServicesAccessor } from 'vs/editor/browser/editorExtensions';\r\nimport { findFocusedDiffEditor } from 'vs/editor/browser/widget/diffEditor.contribution';\r\nimport { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';\r\nimport { EditorContextKeys } from 'vs/editor/common/editorContextKeys';\r\nimport { localize } from 'vs/nls';\r\nimport { ILocalizedString } from 'vs/platform/action/common/action';\r\nimport { Action2, MenuId, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';\r\nimport { IConfigurationService } from 'vs/platform/configuration/common/configuration';\r\nimport { ContextKeyEqualsExpr, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';\r\n\r\nexport class ToggleCollapseUnchangedRegions extends Action2 {\r\n\tconstructor() {\r\n\t\tsuper({\r\n\t\t\tid: 'diffEditor.toggleCollapseUnchangedRegions',\r\n\t\t\ttitle: { value: localize('toggleCollapseUnchangedRegions', \"Toggle Collapse Unchanged Regions\"), original: 'Toggle Collapse Unchanged Regions' },\r\n\t\t\ticon: Codicon.map,\r\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\r\n\t\t\ttoggled: ContextKeyExpr.has('config.diffEditor.experimental.collapseUnchangedRegions'),\r\n\t\t\tmenu: {\r\n\t\t\t\tid: MenuId.EditorTitle,\r\n\t\t\t\torder: 22,\r\n\t\t\t\tgroup: 'navigation',\r\n\t\t\t\twhen: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\r\n\t\t\t},\r\n\t\t});\r\n\t}\r\n\r\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\r\n\t\tconst configurationService = accessor.get(IConfigurationService);\r\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.experimental.collapseUnchangedRegions');\r\n\t\tconfigurationService.updateValue('diffEditor.experimental.collapseUnchangedRegions', newValue);\r\n\t}\r\n}\r\n\r\nregisterAction2(ToggleCollapseUnchangedRegions);\r\n\r\nexport class ToggleShowMovedCodeBlocks extends Action2 {\r\n\tconstructor() {\r\n\t\tsuper({\r\n\t\t\tid: 'diffEditor.toggleShowMovedCodeBlocks',\r\n\t\t\ttitle: { value: localize('toggleShowMovedCodeBlocks', \"Toggle Show Moved Code Blocks\"), original: 'Toggle Show Moved Code Blocks' },\r\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\r\n\t\t});\r\n\t}\r\n\r\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\r\n\t\tconst configurationService = accessor.get(IConfigurationService);\r\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.experimental.showMoves');\r\n\t\tconfigurationService.updateValue('diffEditor.experimental.showMoves', newValue);\r\n\t}\r\n}\r\n\r\nregisterAction2(ToggleShowMovedCodeBlocks);\r\n\r\nexport class ToggleUseInlineViewWhenSpaceIsLimited extends Action2 {\r\n\tconstructor() {\r\n\t\tsuper({\r\n\t\t\tid: 'diffEditor.toggleUseInlineViewWhenSpaceIsLimited',\r\n\t\t\ttitle: { value: localize('toggleUseInlineViewWhenSpaceIsLimited', \"Toggle Use Inline View When Space Is Limited\"), original: 'Toggle Use Inline View When Space Is Limited' },\r\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\r\n\t\t});\r\n\t}\r\n\r\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\r\n\t\tconst configurationService = accessor.get(IConfigurationService);\r\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.useInlineViewWhenSpaceIsLimited');\r\n\t\tconfigurationService.updateValue('diffEditor.useInlineViewWhenSpaceIsLimited', newValue);\r\n\t}\r\n}\r\n\r\nregisterAction2(ToggleUseInlineViewWhenSpaceIsLimited);\r\n\r\nMenuRegistry.appendMenuItem(MenuId.EditorTitle, {\r\n\tcommand: {\r\n\t\tid: new ToggleUseInlineViewWhenSpaceIsLimited().desc.id,\r\n\t\ttitle: localize('useInlineViewWhenSpaceIsLimited', \"Use Inline View When Space Is Limited\"),\r\n\t\ttoggled: ContextKeyExpr.has('config.diffEditor.useInlineViewWhenSpaceIsLimited'),\r\n\t},\r\n\torder: 11,\r\n\tgroup: '1_diff',\r\n\twhen: ContextKeyExpr.and(\r\n\t\tEditorContextKeys.diffEditorRenderSideBySideInlineBreakpointReached,\r\n\t\tContextKeyEqualsExpr.create('diffEditorVersion', 2)\r\n\t)\r\n});\r\n\r\nMenuRegistry.appendMenuItem(MenuId.EditorTitle, {\r\n\tcommand: {\r\n\t\tid: new ToggleShowMovedCodeBlocks().desc.id,\r\n\t\ttitle: localize('showMoves', \"Show Moved Code Blocks\"),\r\n\t\ticon: Codicon.move,\r\n\t\ttoggled: ContextKeyEqualsExpr.create('config.diffEditor.experimental.showMoves', true),\r\n\t},\r\n\torder: 10,\r\n\tgroup: '1_diff',\r\n\twhen: ContextKeyEqualsExpr.create('diffEditorVersion', 2)\r\n});\r\n\r\nconst diffEditorCategory: ILocalizedString = {\r\n\tvalue: localize('diffEditor', 'Diff Editor'),\r\n\toriginal: 'Diff Editor',\r\n};\r\n\r\nexport class SwitchSide extends EditorAction2 {\r\n\tconstructor() {\r\n\t\tsuper({\r\n\t\t\tid: 'diffEditor.switchSide',\r\n\t\t\ttitle: { value: localize('switchSide', \"Switch Side\"), original: 'Switch Side' },\r\n\t\t\ticon: Codicon.arrowSwap,\r\n\t\t\tprecondition: ContextKeyExpr.and(ContextKeyEqualsExpr.create('diffEditorVersion', 2), ContextKeyExpr.has('isInDiffEditor')),\r\n\t\t\tf1: true,\r\n\t\t\tcategory: diffEditorCategory,\r\n\t\t});\r\n\t}\r\n\r\n\trunEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, arg?: { dryRun: boolean }): unknown {\r\n\t\tconst diffEditor = findFocusedDiffEditor(accessor);\r\n\t\tif (diffEditor instanceof DiffEditorWidget2) {\r\n\t\t\tif (arg && arg.dryRun) {\r\n\t\t\t\treturn { destinationSelection: diffEditor.mapToOtherSide().destinationSelection };\r\n\t\t\t} else {\r\n\t\t\t\tdiffEditor.switchSide();\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn undefined;\r\n\t}\r\n}\r\n\r\nregisterAction2(SwitchSide);\r\n\r\nexport class ExitCompareMove extends EditorAction2 {\r\n\tconstructor() {\r\n\t\tsuper({\r\n\t\t\tid: 'diffEditor.exitCompareMove',\r\n\t\t\ttitle: { value: localize('exitCompareMove', \"Exit Compare Move\"), original: 'Exit Compare Move' },\r\n\t\t\ticon: Codicon.close,\r\n\t\t\tprecondition: EditorContextKeys.comparingMovedCode,\r\n\t\t\tf1: false,\r\n\t\t\tcategory: diffEditorCategory,\r\n\t\t\tkeybinding: {\r\n\t\t\t\tweight: 10000,\r\n\t\t\t\tprimary: KeyCode.Escape,\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\trunEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: unknown[]): void {\r\n\t\tconst diffEditor = findFocusedDiffEditor(accessor);\r\n\t\tif (diffEditor instanceof DiffEditorWidget2) {\r\n\t\t\tdiffEditor.exitCompareMove();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nregisterAction2(SwitchSide);\r\n",
"initialResult": "/*---------------------------------------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License. See License.txt in the project root for license information.\r\n *--------------------------------------------------------------------------------------------*/\r\n\r\nimport { Codicon } from 'vs/base/common/codicons';\r\nimport { KeyCode } from 'vs/base/common/keyCodes';\r\nimport { ICodeEditor } from 'vs/editor/browser/editorBrowser';\r\nimport { EditorAction2, ServicesAccessor } from 'vs/editor/browser/editorExtensions';\r\nimport { findFocusedDiffEditor } from 'vs/editor/browser/widget/diffEditor.contribution';\r\nimport { DiffEditorWidget2 } from 'vs/editor/browser/widget/diffEditorWidget2/diffEditorWidget2';\r\nimport { EditorContextKeys } from 'vs/editor/common/editorContextKeys';\r\nimport { localize } from 'vs/nls';\r\nimport { ILocalizedString } from 'vs/platform/action/common/action';\r\nimport { Action2, MenuId, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';\r\nimport { IConfigurationService } from 'vs/platform/configuration/common/configuration';\r\nimport { ContextKeyEqualsExpr, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';\r\n\r\nexport class ToggleCollapseUnchangedRegions extends Action2 {\r\n\tconstructor() {\r\n\t\tsuper({\r\n\t\t\tid: 'diffEditor.toggleCollapseUnchangedRegions',\r\n\t\t\ttitle: { value: localize('toggleCollapseUnchangedRegions', \"Toggle Collapse Unchanged Regions\"), original: 'Toggle Collapse Unchanged Regions' },\r\n\t\t\ticon: Codicon.map,\r\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\r\n\t\t\ttoggled: ContextKeyExpr.has('config.diffEditor.experimental.collapseUnchangedRegions'),\r\n\t\t\tmenu: {\r\n\t\t\t\tid: MenuId.EditorTitle,\r\n\t\t\t\torder: 22,\r\n\t\t\t\tgroup: 'navigation',\r\n\t\t\t\twhen: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\r\n\t\t\t},\r\n\t\t});\r\n\t}\r\n\r\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\r\n\t\tconst configurationService = accessor.get(IConfigurationService);\r\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.experimental.collapseUnchangedRegions');\r\n\t\tconfigurationService.updateValue('diffEditor.experimental.collapseUnchangedRegions', newValue);\r\n\t}\r\n}\r\n\r\nregisterAction2(ToggleCollapseUnchangedRegions);\r\n\r\nexport class ToggleShowMovedCodeBlocks extends Action2 {\r\n\tconstructor() {\r\n\t\tsuper({\r\n\t\t\tid: 'diffEditor.toggleShowMovedCodeBlocks',\r\n\t\t\ttitle: { value: localize('toggleShowMovedCodeBlocks', \"Toggle Show Moved Code Blocks\"), original: 'Toggle Show Moved Code Blocks' },\r\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\r\n\t\t});\r\n\t}\r\n\r\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\r\n\t\tconst configurationService = accessor.get(IConfigurationService);\r\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.experimental.showMoves');\r\n\t\tconfigurationService.updateValue('diffEditor.experimental.showMoves', newValue);\r\n\t}\r\n}\r\n\r\nregisterAction2(ToggleShowMovedCodeBlocks);\r\n\r\nexport class ToggleUseInlineViewWhenSpaceIsLimited extends Action2 {\r\n\tconstructor() {\r\n\t\tsuper({\r\n\t\t\tid: 'diffEditor.toggleUseInlineViewWhenSpaceIsLimited',\r\n\t\t\ttitle: { value: localize('toggleUseInlineViewWhenSpaceIsLimited', \"Toggle Use Inline View When Space Is Limited\"), original: 'Toggle Use Inline View When Space Is Limited' },\r\n\t\t\tprecondition: ContextKeyEqualsExpr.create('diffEditorVersion', 2),\r\n\t\t});\r\n\t}\r\n\r\n\trun(accessor: ServicesAccessor, ...args: unknown[]): void {\r\n\t\tconst configurationService = accessor.get(IConfigurationService);\r\n\t\tconst newValue = !configurationService.getValue<boolean>('diffEditor.useInlineViewWhenSpaceIsLimited');\r\n\t\tconfigurationService.updateValue('diffEditor.useInlineViewWhenSpaceIsLimited', newValue);\r\n\t}\r\n}\r\n\r\nregisterAction2(ToggleUseInlineViewWhenSpaceIsLimited);\r\n\r\nMenuRegistry.appendMenuItem(MenuId.EditorTitle, {\r\n\tcommand: {\r\n\t\tid: new ToggleUseInlineViewWhenSpaceIsLimited().desc.id,\r\n\t\ttitle: localize('useInlineViewWhenSpaceIsLimited', \"Use Inline View When Space Is Limited\"),\r\n\t\ttoggled: ContextKeyExpr.has('config.diffEditor.useInlineViewWhenSpaceIsLimited'),\r\n\t},\r\n\torder: 11,\r\n\tgroup: '1_diff',\r\n\twhen: ContextKeyExpr.and(\r\n\t\tEditorContextKeys.diffEditorRenderSideBySideInlineBreakpointReached,\r\n\t\tContextKeyEqualsExpr.create('diffEditorVersion', 2)\r\n\t)\r\n});\r\n\r\nMenuRegistry.appendMenuItem(MenuId.EditorTitle, {\r\n\tcommand: {\r\n\t\tid: new ToggleShowMovedCodeBlocks().desc.id,\r\n\t\ttitle: localize('showMoves', \"Show Moved Code Blocks\"),\r\n\t\ticon: Codicon.move,\r\n\t\ttoggled: ContextKeyEqualsExpr.create('config.diffEditor.experimental.showMoves', true),\r\n\t},\r\n\torder: 10,\r\n\tgroup: '1_diff',\r\n\twhen: ContextKeyEqualsExpr.create('diffEditorVersion', 2)\r\n});\r\n\r\nconst diffEditorCategory: ILocalizedString = {\r\n\tvalue: localize('diffEditor', 'Diff Editor'),\r\n\toriginal: 'Diff Editor',\r\n};\r\n\r\nexport class SwitchSide extends EditorAction2 {\r\n\tconstructor() {\r\n\t\tsuper({\r\n\t\t\tid: 'diffEditor.switchSide',\r\n\t\t\ttitle: { value: localize('switchSide', \"Switch Side\"), original: 'Switch Side' },\r\n\t\t\ticon: Codicon.arrowSwap,\r\n\t\t\tprecondition: ContextKeyExpr.and(ContextKeyEqualsExpr.create('diffEditorVersion', 2), ContextKeyExpr.has('isInDiffEditor')),\r\n\t\t\tf1: true,\r\n\t\t\tcategory: diffEditorCategory,\r\n\t\t});\r\n\t}\r\n\r\n\trunEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, arg?: { dryRun: boolean }): unknown {\r\n\t\tconst diffEditor = findFocusedDiffEditor(accessor);\r\n\t\tif (diffEditor instanceof DiffEditorWidget2) {\r\n\t\t\tif (arg && arg.dryRun) {\r\n\t\t\t\treturn { destinationSelection: diffEditor.mapToOtherSide().destinationSelection };\r\n\t\t\t} else {\r\n\t\t\t\tdiffEditor.switchSide();\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn undefined;\r\n\t}\r\n}\r\n\r\nregisterAction2(SwitchSide);\r\n\r\n<<<<<<< HEAD\r\nexport class CollapseAllUnchangedRegions extends EditorAction2 {\r\n\tconstructor() {\r\n\t\tsuper({\r\n\t\t\tid: 'diffEditor.collapseAllUnchangedRegions',\r\n\t\t\ttitle: { value: localize('collapseAllUnchangedRegions', \"Collapse All Unchanged Regions\"), original: 'Collapse All Unchanged Regions' },\r\n\t\t\ticon: Codicon.fold,\r\n\t\t\tprecondition: ContextKeyExpr.and(ContextKeyEqualsExpr.create('diffEditorVersion', 2), ContextKeyExpr.has('isInDiffEditor')),\r\n\t\t\tf1: true,\r\n\t\t\tcategory: diffEditorCategory,\r\n=======\r\nexport class ExitCompareMove extends EditorAction2 {\r\n\tconstructor() {\r\n\t\tsuper({\r\n\t\t\tid: 'diffEditor.exitCompareMove',\r\n\t\t\ttitle: { value: localize('exitCompareMove', \"Exit Compare Move\"), original: 'Exit Compare Move' },\r\n\t\t\ticon: Codicon.close,\r\n\t\t\tprecondition: EditorContextKeys.comparingMovedCode,\r\n\t\t\tf1: false,\r\n\t\t\tcategory: diffEditorCategory,\r\n\t\t\tkeybinding: {\r\n\t\t\t\tweight: 10000,\r\n\t\t\t\tprimary: KeyCode.Escape,\r\n\t\t\t}\r\n>>>>>>> main\r\n\t\t});\r\n\t}\r\n\r\n\trunEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: unknown[]): void {\r\n\t\tconst diffEditor = findFocusedDiffEditor(accessor);\r\n\t\tif (diffEditor instanceof DiffEditorWidget2) {\r\n<<<<<<< HEAD\r\n\t\t\tdiffEditor.collapseAllUnchangedRegions();\r\n=======\r\n\t\t\tdiffEditor.exitCompareMove();\r\n>>>>>>> main\r\n\t\t}\r\n\t}\r\n}\r\n\r\n<<<<<<< HEAD\r\nregisterAction2(CollapseAllUnchangedRegions);\r\n\r\nexport class ShowAllUnchangedRegions extends EditorAction2 {\r\n\tconstructor() {\r\n\t\tsuper({\r\n\t\t\tid: 'diffEditor.showAllUnchangedRegions',\r\n\t\t\ttitle: { value: localize('showAllUnchangedRegions', \"Show All Unchanged Regions\"), original: 'Show All Unchanged Regions' },\r\n\t\t\ticon: Codicon.unfold,\r\n\t\t\tprecondition: ContextKeyExpr.and(ContextKeyEqualsExpr.create('diffEditorVersion', 2), ContextKeyExpr.has('isInDiffEditor')),\r\n\t\t\tf1: true,\r\n\t\t\tcategory: diffEditorCategory,\r\n\t\t});\r\n\t}\r\n\r\n\trunEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: unknown[]): void {\r\n\t\tconst diffEditor = findFocusedDiffEditor(accessor);\r\n\t\tif (diffEditor instanceof DiffEditorWidget2) {\r\n\t\t\tdiffEditor.showAllUnchangedRegions();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nregisterAction2(ShowAllUnchangedRegions);\r\n=======\r\nregisterAction2(ExitCompareMove);\r\n>>>>>>> main\r\n"
}
Currently, we just look at the diffs between input1 and base and input2 and base. However, if input1 and input2 caused the same edit relative to base, we should be smarter.
By default, git uses the conflict style
merge
, which diffs the changes against each other and accepts the longest common substring.Our implementation matches gits
diff3
conflict style, which does not move common lines out of conflicts.Related: #155965
create a new branch conflict new and commit a file merge_conflict_test.go, with Name: "n1"
back to master, also new file merge_conflict_test.go, without Name: "n1"
commit, then goto conflict, rebase master
with "git.mergeEditor": false on
3 way merge editor:
Originally posted by @Void-King in https://github.com/microsoft/vscode/issues/157469#issuecomment-1207839032