Skip to content

Commit cd7b12b

Browse files
committed
extract extension Query
1 parent 1f291a9 commit cd7b12b

3 files changed

Lines changed: 116 additions & 25 deletions

File tree

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import 'vs/css!./media/extensionActions';
7+
8+
export class Query {
9+
10+
constructor(public value: string, public sortBy: string, public sortOrder: string) {}
11+
12+
static parse(value: string): Query {
13+
let sortBy: string = undefined;
14+
let sortOrder: string = undefined;
15+
16+
value = value.replace(/@sort:(\w+)(-asc|-desc)?\b/g, (match, by: string, order: string) => {
17+
if (order) {
18+
sortOrder = order.substr(1);
19+
}
20+
21+
sortBy = by;
22+
23+
return '';
24+
});
25+
26+
return new Query(value.trim(), sortBy, sortOrder);
27+
}
28+
29+
toString(): string {
30+
let result = this.value;
31+
32+
if (this.sortBy) {
33+
result = `${ result }${ result ? ' ' : '' }@sort:${ this.sortBy }`;
34+
35+
if (this.sortOrder) {
36+
result = `${ result }-${ this.sortOrder }`;
37+
}
38+
}
39+
40+
return result;
41+
}
42+
43+
isValid(): boolean {
44+
return !!this.sortBy || !this.sortOrder;
45+
}
46+
47+
equals(other: Query): boolean {
48+
return this.value === other.value && this.sortBy === other.sortBy && this.sortOrder === other.sortOrder;
49+
}
50+
}

src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { IMessageService, LaterAction } from 'vs/platform/message/common/message
1717
import { ToggleViewletAction } from 'vs/workbench/browser/viewlet';
1818
import { IViewletService } from 'vs/workbench/services/viewlet/common/viewletService';
1919
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
20+
import { Query } from './extensionQuery';
2021

2122
export class InstallAction extends Action {
2223

@@ -410,6 +411,50 @@ export class ShowRecommendedExtensionsAction extends Action {
410411
});
411412
}
412413

414+
protected isEnabled(): boolean {
415+
return true;
416+
}
417+
}
418+
419+
export class ChangeSortAction extends Action {
420+
421+
private query: Query;
422+
private disposables: IDisposable[] = [];
423+
424+
constructor(
425+
id: string,
426+
label: string,
427+
onSearchChange: Event<string>,
428+
private sortBy: string,
429+
private sortOrder: string,
430+
@IViewletService private viewletService: IViewletService
431+
) {
432+
super(id, label, null, true);
433+
434+
if (this.sortBy === undefined && this.sortOrder === undefined) {
435+
throw new Error('bad arguments');
436+
}
437+
438+
this.query = Query.parse('');
439+
this.enabled = false;
440+
onSearchChange(this.onSearchChange, this, this.disposables);
441+
}
442+
443+
private onSearchChange(value: string): void {
444+
const query = Query.parse(value);
445+
this.query = new Query(query.value, this.sortBy || query.sortBy, this.sortOrder || query.sortOrder);
446+
this.enabled = this.query.isValid() && !this.query.equals(query);
447+
}
448+
449+
run(): TPromise<void> {
450+
return this.viewletService.openViewlet(VIEWLET_ID, true)
451+
.then(viewlet => viewlet as IExtensionsViewlet)
452+
.then(viewlet => {
453+
viewlet.search(this.query.toString());
454+
viewlet.focus();
455+
});
456+
}
457+
413458
protected isEnabled(): boolean {
414459
return true;
415460
}

src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
1616
import EventOf, { mapEvent, filterEvent } from 'vs/base/common/event';
1717
import { IAction } from 'vs/base/common/actions';
1818
import { domEvent } from 'vs/base/browser/event';
19+
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
1920
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
2021
import { KeyCode } from 'vs/base/common/keyCodes';
2122
import { Viewlet } from 'vs/workbench/browser/viewlet';
@@ -26,9 +27,10 @@ import { PagedList } from 'vs/base/browser/ui/list/listPaging';
2627
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
2728
import { Delegate, Renderer } from './extensionsList';
2829
import { IExtensionsWorkbenchService, IExtension, IExtensionsViewlet, VIEWLET_ID } from './extensions';
29-
import { ShowRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowInstalledExtensionsAction, ShowOutdatedExtensionsAction, ClearExtensionsInputAction } from './extensionsActions';
30+
import { ShowRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowInstalledExtensionsAction, ShowOutdatedExtensionsAction, ClearExtensionsInputAction, ChangeSortAction } from './extensionsActions';
3031
import { IExtensionManagementService, IExtensionGalleryService, IExtensionTipsService, SortBy, SortOrder, IQueryOptions } from 'vs/platform/extensionManagement/common/extensionManagement';
3132
import { ExtensionsInput } from './extensionsInput';
33+
import { Query } from './extensionQuery';
3234
import { IProgressService } from 'vs/platform/progress/common/progress';
3335
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
3436
import { IURLService } from 'vs/platform/url/common/url';
@@ -154,7 +156,12 @@ export class ExtensionsViewlet extends Viewlet implements IExtensionsViewlet {
154156
this.instantiationService.createInstance(ShowInstalledExtensionsAction, ShowInstalledExtensionsAction.ID, ShowInstalledExtensionsAction.LABEL),
155157
this.instantiationService.createInstance(ShowOutdatedExtensionsAction, ShowOutdatedExtensionsAction.ID, ShowOutdatedExtensionsAction.LABEL),
156158
this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, ShowRecommendedExtensionsAction.LABEL),
157-
this.instantiationService.createInstance(ShowPopularExtensionsAction, ShowPopularExtensionsAction.ID, ShowPopularExtensionsAction.LABEL)
159+
this.instantiationService.createInstance(ShowPopularExtensionsAction, ShowPopularExtensionsAction.ID, ShowPopularExtensionsAction.LABEL),
160+
new Separator(),
161+
this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.install.asc', localize('sort by installs', "Sort By: Install Count"), this.onSearchChange, 'installs', undefined),
162+
new Separator(),
163+
this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.asc', localize('ascending', "Sort Order: ↑"), this.onSearchChange, undefined, 'asc'),
164+
this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.desc', localize('descending', "Sort Order: ↓"), this.onSearchChange, undefined, 'desc'),
158165
];
159166
}
160167

@@ -196,10 +203,11 @@ export class ExtensionsViewlet extends Viewlet implements IExtensionsViewlet {
196203
return local.then(result => new PagedModel(result));
197204
}
198205

206+
const query = Query.parse(value);
199207
let options: IQueryOptions = {};
200208

201-
if (/@recommended/i.test(value)) {
202-
value = value.replace(/@recommended/g, '').trim();
209+
if (/@recommended/i.test(query.value)) {
210+
const value = query.value.replace(/@recommended/g, '').trim();
203211

204212
return this.extensionsWorkbenchService.queryLocal().then(local => {
205213
const names = this.tipsService.getRecommendations()
@@ -215,29 +223,17 @@ export class ExtensionsViewlet extends Viewlet implements IExtensionsViewlet {
215223
});
216224
}
217225

218-
value = value.replace(/@sort:(\w+)(-asc|-desc)?\b/g, (match, by, order) => {
219-
let sortOrder = SortOrder.Default;
220-
221-
switch (order) {
222-
case '-asc': sortOrder = SortOrder.Ascending; break;
223-
case '-desc': sortOrder = SortOrder.Descending; break;
224-
}
225-
226-
let sortBy = SortBy.NoneOrRelevance;
227-
228-
switch(by) {
229-
case 'installs': sortBy = SortBy.InstallCount; break;
230-
default: return match;
231-
}
232-
233-
options = assign(options, { sortBy, sortOrder });
234-
return '';
235-
});
226+
switch(query.sortBy) {
227+
case 'installs': options = assign(options, { sortBy: SortBy.InstallCount }); break;
228+
}
236229

237-
value = value.trim();
230+
switch (query.sortOrder) {
231+
case 'asc': options = assign(options, { sortOrder: SortOrder.Ascending }); break;
232+
case 'desc': options = assign(options, { sortOrder: SortOrder.Descending }); break;
233+
}
238234

239-
if (value) {
240-
options = assign(options, { text: value });
235+
if (query.value) {
236+
options = assign(options, { text: query.value });
241237
}
242238

243239
return this.extensionsWorkbenchService.queryGallery(options)

0 commit comments

Comments
 (0)