Skip to content

Commit adee8fa

Browse files
committed
editors - shorten diff labels (#110694)
1 parent 54cdd9c commit adee8fa

File tree

12 files changed

+218
-139
lines changed

12 files changed

+218
-139
lines changed

extensions/git/src/fileSystemProvider.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,6 @@ export class GitFileSystemProvider implements FileSystemProvider {
4848
model.onDidChangeRepository(this.onDidChangeRepository, this),
4949
model.onDidChangeOriginalResource(this.onDidChangeOriginalResource, this),
5050
workspace.registerFileSystemProvider('git', this, { isReadonly: true, isCaseSensitive: true }),
51-
workspace.registerResourceLabelFormatter({
52-
scheme: 'git',
53-
formatting: {
54-
label: '${path} (git)',
55-
separator: '/'
56-
}
57-
})
5851
);
5952

6053
setInterval(() => this.cleanup(), FIVE_MINUTES);

src/vs/base/browser/ui/iconLabel/iconlabel.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
opacity: 0.75;
8888
font-size: 90%;
8989
font-weight: 600;
90-
margin: 0 16px 0 5px;
90+
margin: auto 16px 0 5px; /* https://github.com/microsoft/vscode/issues/113223 */
9191
text-align: center;
9292
}
9393

src/vs/workbench/browser/parts/editor/editorQuickAccess.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro
155155

156156
return isDirty ? localize('entryAriaLabelDirty', "{0}, dirty", nameAndDescription) : nameAndDescription;
157157
})(),
158-
description: editor.getDescription(),
158+
description,
159159
iconClasses: getIconClasses(this.modelService, this.modeService, resource).concat(editor.getLabelExtraClasses()),
160160
italic: !this.editorGroupService.getGroup(groupId)?.isPinned(editor),
161161
buttons: (() => {

src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,13 @@ export class NoTabsTitleControl extends TitleControl {
7878
this._register(addDisposableListener(titleContainer, TouchEventType.Tap, (e: GestureEvent) => this.onTitleTap(e)));
7979

8080
// Context Menu
81-
[EventType.CONTEXT_MENU, TouchEventType.Contextmenu].forEach(event => {
81+
for (const event of [EventType.CONTEXT_MENU, TouchEventType.Contextmenu]) {
8282
this._register(addDisposableListener(titleContainer, event, e => {
8383
if (this.group.activeEditor) {
8484
this.onContextMenu(this.group.activeEditor, e, titleContainer);
8585
}
8686
}));
87-
});
87+
}
8888
}
8989

9090
private onTitleLabelClick(e: MouseEvent): void {

src/vs/workbench/browser/parts/editor/tabsTitleControl.ts

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import 'vs/css!./media/tabstitlecontrol';
77
import { isMacintosh, isWindows } from 'vs/base/common/platform';
88
import { shorten } from 'vs/base/common/labels';
9-
import { EditorResourceAccessor, GroupIdentifier, Verbosity, IEditorPartOptions, SideBySideEditor, DEFAULT_EDITOR_ASSOCIATION } from 'vs/workbench/common/editor';
9+
import { EditorResourceAccessor, GroupIdentifier, Verbosity, IEditorPartOptions, SideBySideEditor, DEFAULT_EDITOR_ASSOCIATION, EditorInputCapabilities } from 'vs/workbench/common/editor';
1010
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
1111
import { computeEditorAriaLabel } from 'vs/workbench/browser/editor';
1212
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
@@ -40,7 +40,7 @@ import { CloseOneEditorAction, UnpinEditorAction } from 'vs/workbench/browser/pa
4040
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
4141
import { BreadcrumbsControl } from 'vs/workbench/browser/parts/editor/breadcrumbsControl';
4242
import { IFileService } from 'vs/platform/files/common/files';
43-
import { withNullAsUndefined, assertAllDefined, assertIsDefined } from 'vs/base/common/types';
43+
import { assertAllDefined, assertIsDefined } from 'vs/base/common/types';
4444
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
4545
import { basenameOrAuthority } from 'vs/base/common/resources';
4646
import { RunOnceScheduler } from 'vs/base/common/async';
@@ -56,11 +56,12 @@ import { UNLOCK_GROUP_COMMAND_ID } from 'vs/workbench/browser/parts/editor/edito
5656
interface IEditorInputLabel {
5757
name?: string;
5858
description?: string;
59+
forceDescription?: boolean;
5960
title?: string;
6061
ariaLabel?: string;
6162
}
6263

63-
type AugmentedLabel = IEditorInputLabel & { editor: EditorInput };
64+
type IEditorInputLabelAndEditor = IEditorInputLabel & { editor: EditorInput };
6465

6566
export class TabsTitleControl extends TitleControl {
6667

@@ -218,7 +219,7 @@ export class TabsTitleControl extends TitleControl {
218219
}));
219220

220221
// New file when double clicking on tabs container (but not tabs)
221-
[TouchEventType.Tap, EventType.DBLCLICK].forEach(eventType => {
222+
for (const eventType of [TouchEventType.Tap, EventType.DBLCLICK]) {
222223
this._register(addDisposableListener(tabsContainer, eventType, (e: MouseEvent | GestureEvent) => {
223224
if (eventType === EventType.DBLCLICK) {
224225
if (e.target !== tabsContainer) {
@@ -245,7 +246,7 @@ export class TabsTitleControl extends TitleControl {
245246
}
246247
}, this.group.id);
247248
}));
248-
});
249+
}
249250

250251
// Prevent auto-scrolling (https://github.com/microsoft/vscode/issues/16690)
251252
this._register(addDisposableListener(tabsContainer, EventType.MOUSE_DOWN, e => {
@@ -784,7 +785,7 @@ export class TabsTitleControl extends TitleControl {
784785
}));
785786

786787
// Double click: either pin or toggle maximized
787-
[TouchEventType.Tap, EventType.DBLCLICK].forEach(eventType => {
788+
for (const eventType of [TouchEventType.Tap, EventType.DBLCLICK]) {
788789
disposables.add(addDisposableListener(tab, eventType, (e: MouseEvent | GestureEvent) => {
789790
if (eventType === EventType.DBLCLICK) {
790791
EventHelper.stop(e);
@@ -799,7 +800,7 @@ export class TabsTitleControl extends TitleControl {
799800
this.group.pinEditor(editor);
800801
}
801802
}));
802-
});
803+
}
803804

804805
// Context menu
805806
disposables.add(addDisposableListener(tab, EventType.CONTEXT_MENU, e => {
@@ -953,11 +954,12 @@ export class TabsTitleControl extends TitleControl {
953954
const { verbosity, shortenDuplicates } = this.getLabelConfigFlags(labelFormat);
954955

955956
// Build labels and descriptions for each editor
956-
const labels = this.group.editors.map((editor, index) => ({
957+
const labels: IEditorInputLabelAndEditor[] = this.group.editors.map((editor, index) => ({
957958
editor,
958959
name: editor.getName(),
959960
description: editor.getDescription(verbosity),
960-
title: withNullAsUndefined(editor.getTitle(Verbosity.LONG)),
961+
forceDescription: editor.hasCapability(EditorInputCapabilities.ForceDescription),
962+
title: editor.getTitle(Verbosity.LONG),
961963
ariaLabel: computeEditorAriaLabel(editor, index, this.group, this.editorGroupService.count)
962964
}));
963965

@@ -969,63 +971,68 @@ export class TabsTitleControl extends TitleControl {
969971
this.tabLabels = labels;
970972
}
971973

972-
private shortenTabLabels(labels: AugmentedLabel[]): void {
974+
private shortenTabLabels(labels: IEditorInputLabelAndEditor[]): void {
973975

974976
// Gather duplicate titles, while filtering out invalid descriptions
975-
const mapTitleToDuplicates = new Map<string, AugmentedLabel[]>();
977+
const mapNameToDuplicates = new Map<string, IEditorInputLabelAndEditor[]>();
976978
for (const label of labels) {
977979
if (typeof label.description === 'string') {
978-
getOrSet(mapTitleToDuplicates, label.name, []).push(label);
980+
getOrSet(mapNameToDuplicates, label.name, []).push(label);
979981
} else {
980982
label.description = '';
981983
}
982984
}
983985

984-
// Identify duplicate titles and shorten descriptions
985-
mapTitleToDuplicates.forEach(duplicateTitles => {
986+
// Identify duplicate names and shorten descriptions
987+
for (const [, duplicateLabels] of mapNameToDuplicates) {
986988

987989
// Remove description if the title isn't duplicated
988-
if (duplicateTitles.length === 1) {
989-
duplicateTitles[0].description = '';
990+
// and we have no indication to enforce description
991+
if (duplicateLabels.length === 1 && !duplicateLabels[0].forceDescription) {
992+
duplicateLabels[0].description = '';
990993

991-
return;
994+
continue;
992995
}
993996

994997
// Identify duplicate descriptions
995-
const mapDescriptionToDuplicates = new Map<string, AugmentedLabel[]>();
996-
for (const label of duplicateTitles) {
997-
getOrSet(mapDescriptionToDuplicates, label.description, []).push(label);
998+
const mapDescriptionToDuplicates = new Map<string, IEditorInputLabelAndEditor[]>();
999+
for (const duplicateLabel of duplicateLabels) {
1000+
getOrSet(mapDescriptionToDuplicates, duplicateLabel.description, []).push(duplicateLabel);
9981001
}
9991002

10001003
// For editors with duplicate descriptions, check whether any long descriptions differ
10011004
let useLongDescriptions = false;
1002-
mapDescriptionToDuplicates.forEach((duplicateDescriptions, name) => {
1003-
if (!useLongDescriptions && duplicateDescriptions.length > 1) {
1004-
const [first, ...rest] = duplicateDescriptions.map(({ editor }) => editor.getDescription(Verbosity.LONG));
1005+
for (const [, duplicateLabels] of mapDescriptionToDuplicates) {
1006+
if (!useLongDescriptions && duplicateLabels.length > 1) {
1007+
const [first, ...rest] = duplicateLabels.map(({ editor }) => editor.getDescription(Verbosity.LONG));
10051008
useLongDescriptions = rest.some(description => description !== first);
10061009
}
1007-
});
1010+
}
10081011

10091012
// If so, replace all descriptions with long descriptions
10101013
if (useLongDescriptions) {
10111014
mapDescriptionToDuplicates.clear();
1012-
duplicateTitles.forEach(label => {
1013-
label.description = label.editor.getDescription(Verbosity.LONG);
1014-
getOrSet(mapDescriptionToDuplicates, label.description, []).push(label);
1015-
});
1015+
for (const duplicateLabel of duplicateLabels) {
1016+
duplicateLabel.description = duplicateLabel.editor.getDescription(Verbosity.LONG);
1017+
getOrSet(mapDescriptionToDuplicates, duplicateLabel.description, []).push(duplicateLabel);
1018+
}
10161019
}
10171020

10181021
// Obtain final set of descriptions
10191022
const descriptions: string[] = [];
1020-
mapDescriptionToDuplicates.forEach((_, description) => descriptions.push(description));
1023+
for (const [description] of mapDescriptionToDuplicates) {
1024+
descriptions.push(description);
1025+
}
10211026

1022-
// Remove description if all descriptions are identical
1027+
// Remove description if all descriptions are identical unless forced
10231028
if (descriptions.length === 1) {
10241029
for (const label of mapDescriptionToDuplicates.get(descriptions[0]) || []) {
1025-
label.description = '';
1030+
if (!label.forceDescription) {
1031+
label.description = '';
1032+
}
10261033
}
10271034

1028-
return;
1035+
continue;
10291036
}
10301037

10311038
// Shorten descriptions
@@ -1035,7 +1042,7 @@ export class TabsTitleControl extends TitleControl {
10351042
label.description = shortenedDescriptions[index];
10361043
}
10371044
});
1038-
});
1045+
}
10391046
}
10401047

10411048
private getLabelConfigFlags(value: string | undefined) {
@@ -1096,21 +1103,21 @@ export class TabsTitleControl extends TitleControl {
10961103

10971104
// Settings
10981105
const tabActionsVisibility = isTabSticky && options.pinnedTabSizing === 'compact' ? 'off' /* treat sticky compact tabs as tabCloseButton: 'off' */ : options.tabCloseButton;
1099-
['off', 'left', 'right'].forEach(option => {
1106+
for (const option of ['off', 'left', 'right']) {
11001107
tabContainer.classList.toggle(`tab-actions-${option}`, tabActionsVisibility === option);
1101-
});
1108+
}
11021109

11031110
const tabSizing = isTabSticky && options.pinnedTabSizing === 'shrink' ? 'shrink' /* treat sticky shrink tabs as tabSizing: 'shrink' */ : options.tabSizing;
1104-
['fit', 'shrink'].forEach(option => {
1111+
for (const option of ['fit', 'shrink']) {
11051112
tabContainer.classList.toggle(`sizing-${option}`, tabSizing === option);
1106-
});
1113+
}
11071114

11081115
tabContainer.classList.toggle('has-icon', options.showIcons && options.hasIcons);
11091116

11101117
tabContainer.classList.toggle('sticky', isTabSticky);
1111-
['normal', 'compact', 'shrink'].forEach(option => {
1118+
for (const option of ['normal', 'compact', 'shrink']) {
11121119
tabContainer.classList.toggle(`sticky-${option}`, isTabSticky && options.pinnedTabSizing === option);
1113-
});
1120+
}
11141121

11151122
// Sticky compact/shrink tabs need a position to remain at their location
11161123
// when scrolling to stay in view (requirement for position: sticky)

src/vs/workbench/common/editor.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,15 @@ export const enum EditorInputCapabilities {
522522
* Signals that the editor can split into 2 in the same
523523
* editor group.
524524
*/
525-
CanSplitInGroup = 1 << 5
525+
CanSplitInGroup = 1 << 5,
526+
527+
/**
528+
* Signals that the editor wants it's description to be
529+
* visible when presented to the user. By default, a UI
530+
* component may decide to hide the description portion
531+
* for brevity.
532+
*/
533+
ForceDescription = 1 << 6
526534
}
527535

528536
export type IUntypedEditorInput = IResourceEditorInput | ITextResourceEditorInput | IUntitledTextResourceEditorInput | IResourceDiffEditorInput | IResourceSideBySideEditorInput;

0 commit comments

Comments
 (0)