From e9c0aeb8b00db16dad3b11426d78a64ff18b5dc2 Mon Sep 17 00:00:00 2001 From: Peter Elmers Date: Fri, 12 Jul 2019 09:41:27 -0700 Subject: [PATCH] Add optional sortByLabel to QuickPick to control whether to re-sort items when query changes Summary: Address issue #73904 by adding an optional `sortByLabel` to the QuickPick class which determines whether the picker re-sorts the result list when the user types in the input field. If true, the picker applies a sort to order results by the index of the first appearance of the input in the label. For backwards compatibility, this field is true by default. https://github.com/microsoft/vscode/issues/73904 Test Plan: attached video shows behavior both before and after {F167292605} note: there aren't any existing tests on what happens when the query input changes in the QuickPick Reviewers: dalongi, ericblue, hchau Reviewed By: ericblue Differential Revision: https://phabricator.intern.facebook.com/D16203434 Signature: 16203434:1562878837:5413e3852f2bd04c8e81b9fe5c4a08127dfe3b65 --- src/vs/platform/quickinput/common/quickInput.ts | 7 +++++++ src/vs/vscode.d.ts | 10 ++++++++++ src/vs/workbench/api/common/extHost.protocol.ts | 2 ++ src/vs/workbench/api/common/extHostQuickOpen.ts | 11 +++++++++++ .../browser/parts/quickinput/quickInput.ts | 14 ++++++++++++++ .../browser/parts/quickinput/quickInputList.ts | 3 ++- 6 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/vs/platform/quickinput/common/quickInput.ts b/src/vs/platform/quickinput/common/quickInput.ts index 3b23b66bbad..abebe127138 100644 --- a/src/vs/platform/quickinput/common/quickInput.ts +++ b/src/vs/platform/quickinput/common/quickInput.ts @@ -57,6 +57,11 @@ export interface IPickOptions { */ matchOnLabel?: boolean; + /** + * an optional flag to sort the final results by index of first query match in label. Defaults to true. + */ + sortByLabel?: boolean; + /** * an option flag to control whether focus is always automatically brought to a list item. Defaults to true. */ @@ -188,6 +193,8 @@ export interface IQuickPick extends IQuickInput { matchOnLabel: boolean; + sortByLabel: boolean; + autoFocusOnList: boolean; quickNavigate: IQuickNavigateConfiguration | undefined; diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 4eed2e45d76..6d4ebd6e1ae 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -1616,6 +1616,11 @@ declare module 'vscode' { */ matchOnDetail?: boolean; + /** + * An optional flag to sort the final results by index of first query match in label, defaults to true. + */ + sortByLabel?: boolean; + /** * An optional string to show as place holder in the input box to guide the user what to pick on. */ @@ -7853,6 +7858,11 @@ declare module 'vscode' { */ matchOnDetail: boolean; + /** + * An optional flag to sort the final results by index of first query match in label. Defaults to true. + */ + sortByLabel: boolean; + /** * Active items. This can be read and updated by the extension. */ diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 87349faf1cb..0f8c286ca81 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -475,6 +475,8 @@ export interface TransferQuickPick extends BaseTransferQuickInput { matchOnDescription?: boolean; + sortByLabel?: boolean; + matchOnDetail?: boolean; } diff --git a/src/vs/workbench/api/common/extHostQuickOpen.ts b/src/vs/workbench/api/common/extHostQuickOpen.ts index 65f94310001..30dcc1e8edb 100644 --- a/src/vs/workbench/api/common/extHostQuickOpen.ts +++ b/src/vs/workbench/api/common/extHostQuickOpen.ts @@ -54,6 +54,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape { placeHolder: options && options.placeHolder, matchOnDescription: options && options.matchOnDescription, matchOnDetail: options && options.matchOnDetail, + sortByLabel: options && options.sortByLabel, ignoreFocusLost: options && options.ignoreFocusOut, canPickMany: options && options.canPickMany }, token); @@ -485,6 +486,7 @@ class ExtHostQuickPick extends ExtHostQuickInput implem private _canSelectMany = false; private _matchOnDescription = true; private _matchOnDetail = true; + private _sortByLabel = true; private _activeItems: T[] = []; private readonly _onDidChangeActiveEmitter = new Emitter(); private _selectedItems: T[] = []; @@ -550,6 +552,15 @@ class ExtHostQuickPick extends ExtHostQuickInput implem this.update({ matchOnDetail }); } + get sortByLabel() { + return this._sortByLabel; + } + + set sortByLabel(sortByLabel: boolean) { + this._sortByLabel = sortByLabel; + this.update({ sortByLabel }); + } + get activeItems() { return this._activeItems; } diff --git a/src/vs/workbench/browser/parts/quickinput/quickInput.ts b/src/vs/workbench/browser/parts/quickinput/quickInput.ts index 892e5521e12..745a857b918 100644 --- a/src/vs/workbench/browser/parts/quickinput/quickInput.ts +++ b/src/vs/workbench/browser/parts/quickinput/quickInput.ts @@ -343,6 +343,7 @@ class QuickPick extends QuickInput implements IQuickPi private _matchOnDescription = false; private _matchOnDetail = false; private _matchOnLabel = true; + private _sortByLabel = true; private _autoFocusOnList = true; private _activeItems: T[] = []; private activeItemsUpdated = false; @@ -434,6 +435,16 @@ class QuickPick extends QuickInput implements IQuickPi this.update(); } + get sortByLabel() { + return this._sortByLabel; + } + + set sortByLabel(sortByLabel: boolean) { + this._sortByLabel = sortByLabel; + this.update(); + } + + get autoFocusOnList() { return this._autoFocusOnList; } @@ -762,6 +773,7 @@ class QuickPick extends QuickInput implements IQuickPi this.ui.list.matchOnDescription = this.matchOnDescription; this.ui.list.matchOnDetail = this.matchOnDetail; this.ui.list.matchOnLabel = this.matchOnLabel; + this.ui.list.sortByLabel = this.sortByLabel; this.ui.setComboboxAccessibility(true); this.ui.inputBox.setAttribute('aria-label', QuickPick.INPUT_BOX_ARIA_LABEL); } @@ -1259,6 +1271,7 @@ export class QuickInputService extends Component implements IQuickInputService { input.matchOnDescription = !!options.matchOnDescription; input.matchOnDetail = !!options.matchOnDetail; input.matchOnLabel = (options.matchOnLabel === undefined) || options.matchOnLabel; // default to true + input.sortByLabel = (options.sortByLabel === undefined) || options.sortByLabel; // default to true input.autoFocusOnList = (options.autoFocusOnList === undefined) || options.autoFocusOnList; // default to true input.quickNavigate = options.quickNavigate; input.contextKey = options.contextKey; @@ -1378,6 +1391,7 @@ export class QuickInputService extends Component implements IQuickInputService { ui.list.matchOnDescription = false; ui.list.matchOnDetail = false; ui.list.matchOnLabel = true; + ui.list.sortByLabel = true; ui.ignoreFocusOut = false; this.setComboboxAccessibility(false); ui.inputBox.removeAttribute('aria-label'); diff --git a/src/vs/workbench/browser/parts/quickinput/quickInputList.ts b/src/vs/workbench/browser/parts/quickinput/quickInputList.ts index 9129e303b84..2c66e409b0e 100644 --- a/src/vs/workbench/browser/parts/quickinput/quickInputList.ts +++ b/src/vs/workbench/browser/parts/quickinput/quickInputList.ts @@ -222,6 +222,7 @@ export class QuickInputList { matchOnDescription = false; matchOnDetail = false; matchOnLabel = true; + sortByLabel = true; private readonly _onChangedAllVisibleChecked = new Emitter(); onChangedAllVisibleChecked: Event = this._onChangedAllVisibleChecked.event; private readonly _onChangedCheckedCount = new Emitter(); @@ -516,7 +517,7 @@ export class QuickInputList { const shownElements = this.elements.filter(element => !element.hidden); // Sort by value - if (query) { + if (this.sortByLabel && query) { const normalizedSearchValue = query.toLowerCase(); shownElements.sort((a, b) => { return compareEntries(a, b, normalizedSearchValue);