提交 2924e2b1 编写于 作者: B Benjamin Pasero

Enable to search on the full path when parts of the query contain path separators

上级 0a7c9f72
...@@ -8,6 +8,7 @@ import {Registry} from 'vs/platform/platform'; ...@@ -8,6 +8,7 @@ import {Registry} from 'vs/platform/platform';
import filters = require('vs/base/common/filters'); import filters = require('vs/base/common/filters');
import strings = require('vs/base/common/strings'); import strings = require('vs/base/common/strings');
import types = require('vs/base/common/types'); import types = require('vs/base/common/types');
import paths = require('vs/base/common/paths');
import URI from 'vs/base/common/uri'; import URI from 'vs/base/common/uri';
import {EventType} from 'vs/base/common/events'; import {EventType} from 'vs/base/common/events';
import comparers = require('vs/base/common/comparers'); import comparers = require('vs/base/common/comparers');
...@@ -31,7 +32,8 @@ export class EditorHistoryEntry extends EditorQuickOpenEntry { ...@@ -31,7 +32,8 @@ export class EditorHistoryEntry extends EditorQuickOpenEntry {
editorService: IWorkbenchEditorService, editorService: IWorkbenchEditorService,
private contextService: IWorkspaceContextService, private contextService: IWorkspaceContextService,
input: EditorInput, input: EditorInput,
highlights: IHighlight[], labelHighlights: IHighlight[],
descriptionHighlights: IHighlight[],
model: EditorHistoryModel model: EditorHistoryModel
) { ) {
super(editorService); super(editorService);
...@@ -49,11 +51,11 @@ export class EditorHistoryEntry extends EditorQuickOpenEntry { ...@@ -49,11 +51,11 @@ export class EditorHistoryEntry extends EditorQuickOpenEntry {
} }
} }
this.setHighlights(highlights); this.setHighlights(labelHighlights, descriptionHighlights);
} }
public clone(highlights: IHighlight[]): EditorHistoryEntry { public clone(labelHighlights: IHighlight[], descriptionHighlights?: IHighlight[]): EditorHistoryEntry {
return new EditorHistoryEntry(this.editorService, this.contextService, this.input, highlights, this.model); return new EditorHistoryEntry(this.editorService, this.contextService, this.input, labelHighlights, descriptionHighlights, this.model);
} }
public getLabel(): string { public getLabel(): string {
...@@ -130,7 +132,7 @@ export class EditorHistoryModel extends QuickOpenModel { ...@@ -130,7 +132,7 @@ export class EditorHistoryModel extends QuickOpenModel {
// Remove any existing entry and add to the beginning // Remove any existing entry and add to the beginning
this.remove(entry); this.remove(entry);
this.entries.unshift(new EditorHistoryEntry(this.editorService, this.contextService, entry, null, this)); this.entries.unshift(new EditorHistoryEntry(this.editorService, this.contextService, entry, null, null, this));
// Respect max entries setting // Respect max entries setting
if (this.entries.length > MAX_ENTRIES) { if (this.entries.length > MAX_ENTRIES) {
...@@ -207,14 +209,35 @@ export class EditorHistoryModel extends QuickOpenModel { ...@@ -207,14 +209,35 @@ export class EditorHistoryModel extends QuickOpenModel {
let results: QuickOpenEntry[] = []; let results: QuickOpenEntry[] = [];
for (let i = 0; i < this.entries.length; i++) { for (let i = 0; i < this.entries.length; i++) {
let entry = this.entries[i]; let entry = <EditorHistoryEntry>this.entries[i];
if (!entry.getResource()) { if (!entry.getResource()) {
continue; //For now, only support to match on inputs that provide resource information continue; //For now, only support to match on inputs that provide resource information
} }
let highlights = filters.matchesFuzzy(searchValue, (<EditorHistoryEntry>entry).getInput().getName()); let label = entry.getInput().getName();
if (highlights) { let description = entry.getInput().getDescription();
results.push((<EditorHistoryEntry>entry).clone(highlights));
let labelHighlights: IHighlight[] = [];
let descriptionHighlights: IHighlight[] = [];
// Search inside filename
if (searchValue.indexOf(paths.nativeSep) < 0) {
labelHighlights = filters.matchesFuzzy(searchValue, label);
}
// Search in full path
else {
descriptionHighlights = filters.matchesFuzzy(strings.trim(searchValue, paths.nativeSep), description);
// If we have no highlights, assume that the match is split among name and parent folder
if (!descriptionHighlights || !descriptionHighlights.length) {
labelHighlights = filters.matchesFuzzy(paths.basename(searchValue), label);
descriptionHighlights = filters.matchesFuzzy(strings.trim(paths.dirname(searchValue), paths.nativeSep), description);
}
}
if ((labelHighlights && labelHighlights.length) || (descriptionHighlights && descriptionHighlights.length)) {
results.push(entry.clone(labelHighlights, descriptionHighlights));
} }
} }
...@@ -222,7 +245,20 @@ export class EditorHistoryModel extends QuickOpenModel { ...@@ -222,7 +245,20 @@ export class EditorHistoryModel extends QuickOpenModel {
if (searchValue) { if (searchValue) {
let normalizedSearchValue = strings.stripWildcards(searchValue.toLowerCase()); let normalizedSearchValue = strings.stripWildcards(searchValue.toLowerCase());
return results.sort((elementA:EditorHistoryEntry, elementB:EditorHistoryEntry) => { return results.sort((elementA: EditorHistoryEntry, elementB: EditorHistoryEntry) => {
// Give matches with label highlights higher priority over
// those with only description highlights
const labelHighlightsA = elementA.getHighlights()[0] || [];
const labelHighlightsB = elementB.getHighlights()[0] || [];
if (labelHighlightsA.length && !labelHighlightsB.length) {
return -1;
} else if (!labelHighlightsA.length && labelHighlightsB.length) {
return 1;
}
// Sort by name/path
let nameA = elementA.getInput().getName(); let nameA = elementA.getInput().getName();
let nameB = elementB.getInput().getName(); let nameB = elementB.getInput().getName();
......
...@@ -10,6 +10,7 @@ import nls = require('vs/nls'); ...@@ -10,6 +10,7 @@ import nls = require('vs/nls');
import {ThrottledDelayer} from 'vs/base/common/async'; import {ThrottledDelayer} from 'vs/base/common/async';
import types = require('vs/base/common/types'); import types = require('vs/base/common/types');
import strings = require('vs/base/common/strings'); import strings = require('vs/base/common/strings');
import paths = require('vs/base/common/paths');
import filters = require('vs/base/common/filters'); import filters = require('vs/base/common/filters');
import {IRange} from 'vs/editor/common/editorCommon'; import {IRange} from 'vs/editor/common/editorCommon';
import {compareAnything} from 'vs/base/common/comparers'; import {compareAnything} from 'vs/base/common/comparers';
...@@ -210,6 +211,9 @@ export class OpenAnythingHandler extends QuickOpenHandler { ...@@ -210,6 +211,9 @@ export class OpenAnythingHandler extends QuickOpenHandler {
} }
public getResultsFromCache(searchValue: string, range: IRange = null): QuickOpenEntry[] { public getResultsFromCache(searchValue: string, range: IRange = null): QuickOpenEntry[] {
if (searchValue.indexOf(paths.nativeSep) >= 0) {
return null; // TODO@Ben implement caching for path search
}
// Find cache entries by prefix of search value // Find cache entries by prefix of search value
let cachedEntries: QuickOpenEntry[]; let cachedEntries: QuickOpenEntry[];
...@@ -257,6 +261,19 @@ export class OpenAnythingHandler extends QuickOpenHandler { ...@@ -257,6 +261,19 @@ export class OpenAnythingHandler extends QuickOpenHandler {
} }
private compareResults(elementA:QuickOpenEntry, elementB:QuickOpenEntry, searchValue: string): number { private compareResults(elementA:QuickOpenEntry, elementB:QuickOpenEntry, searchValue: string): number {
// Give matches with label highlights higher priority over
// those with only description highlights
const labelHighlightsA = elementA.getHighlights()[0] || [];
const labelHighlightsB = elementB.getHighlights()[0] || [];
if (labelHighlightsA.length && !labelHighlightsB.length) {
return -1;
} else if (!labelHighlightsA.length && labelHighlightsB.length) {
return 1;
}
// Sort by name/path
let nameA = elementA.getLabel(); let nameA = elementA.getLabel();
let nameB = elementB.getLabel(); let nameB = elementB.getLabel();
......
...@@ -34,7 +34,12 @@ export class FileEntry extends EditorQuickOpenEntry { ...@@ -34,7 +34,12 @@ export class FileEntry extends EditorQuickOpenEntry {
private resource: URI; private resource: URI;
private range: IRange; private range: IRange;
constructor(name: string, resource: URI, highlights: IHighlight[], constructor(
name: string,
description: string,
resource: URI,
labelHighlights: IHighlight[],
descriptionHighlights: IHighlight[],
@IWorkbenchEditorService editorService: IWorkbenchEditorService, @IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IInstantiationService private instantiationService: IInstantiationService, @IInstantiationService private instantiationService: IInstantiationService,
@IWorkspaceContextService contextService: IWorkspaceContextService @IWorkspaceContextService contextService: IWorkspaceContextService
...@@ -43,8 +48,8 @@ export class FileEntry extends EditorQuickOpenEntry { ...@@ -43,8 +48,8 @@ export class FileEntry extends EditorQuickOpenEntry {
this.resource = resource; this.resource = resource;
this.name = name; this.name = name;
this.description = labels.getPathLabel(paths.dirname(this.resource.fsPath), contextService); this.description = description;
this.setHighlights(highlights); this.setHighlights(labelHighlights, descriptionHighlights);
} }
public getLabel(): string { public getLabel(): string {
...@@ -149,9 +154,28 @@ export class OpenFileHandler extends QuickOpenHandler { ...@@ -149,9 +154,28 @@ export class OpenFileHandler extends QuickOpenHandler {
let results: QuickOpenEntry[] = []; let results: QuickOpenEntry[] = [];
for (let i = 0; i < matches.length; i++) { for (let i = 0; i < matches.length; i++) {
let fileMatch = matches[i]; let fileMatch = matches[i];
let highlights = filters.matchesFuzzy(searchValue, fileMatch.name()); let description = labels.getPathLabel(paths.dirname(fileMatch.resource().fsPath), this.contextService);
let labelHighlights: IHighlight[] = [];
let descriptionHighlights: IHighlight[] = [];
// Search inside filename
if (searchValue.indexOf(paths.nativeSep) < 0) {
labelHighlights = filters.matchesFuzzy(searchValue, fileMatch.name());
}
// Search in full path
else {
descriptionHighlights = filters.matchesFuzzy(strings.trim(searchValue, paths.nativeSep), description);
// If we have no highlights, assume that the match is split among name and parent folder
if (!descriptionHighlights || !descriptionHighlights.length) {
labelHighlights = filters.matchesFuzzy(paths.basename(searchValue), fileMatch.name());
descriptionHighlights = filters.matchesFuzzy(strings.trim(paths.dirname(searchValue), paths.nativeSep), description);
}
}
results.push(this.instantiationService.createInstance(FileEntry, fileMatch.name(), fileMatch.resource(), highlights)); results.push(this.instantiationService.createInstance(FileEntry, fileMatch.name(), description, fileMatch.resource(), labelHighlights, descriptionHighlights));
} }
return results; return results;
......
...@@ -31,6 +31,7 @@ export class FileWalker { ...@@ -31,6 +31,7 @@ export class FileWalker {
private isLimitHit: boolean; private isLimitHit: boolean;
private resultCount: number; private resultCount: number;
private isCanceled: boolean; private isCanceled: boolean;
private searchInPath: boolean;
private walkedPaths: { [path: string]: boolean; }; private walkedPaths: { [path: string]: boolean; };
...@@ -41,6 +42,7 @@ export class FileWalker { ...@@ -41,6 +42,7 @@ export class FileWalker {
this.includePattern = config.includePattern; this.includePattern = config.includePattern;
this.maxResults = config.maxResults || null; this.maxResults = config.maxResults || null;
this.walkedPaths = Object.create(null); this.walkedPaths = Object.create(null);
this.searchInPath = this.filePattern && this.filePattern.indexOf(paths.sep) >= 0;
} }
private resetState(): void { private resetState(): void {
...@@ -81,7 +83,7 @@ export class FileWalker { ...@@ -81,7 +83,7 @@ export class FileWalker {
} }
// Check for match on file pattern and include pattern // Check for match on file pattern and include pattern
if (this.isFilePatternMatch(paths.basename(absolutePath)) && (!this.includePattern || glob.match(this.includePattern, absolutePath))) { if (this.isFilePatternMatch(paths.basename(absolutePath), absolutePath) && (!this.includePattern || glob.match(this.includePattern, absolutePath))) {
this.resultCount++; this.resultCount++;
if (this.maxResults && this.resultCount > this.maxResults) { if (this.maxResults && this.resultCount > this.maxResults) {
...@@ -156,7 +158,7 @@ export class FileWalker { ...@@ -156,7 +158,7 @@ export class FileWalker {
if ((<any>error).code === FileWalker.ENOTDIR && !this.isCanceled && !this.isLimitHit) { if ((<any>error).code === FileWalker.ENOTDIR && !this.isCanceled && !this.isLimitHit) {
// Check for match on file pattern and include pattern // Check for match on file pattern and include pattern
if (this.isFilePatternMatch(file) && (!this.includePattern || glob.match(this.includePattern, relativeFilePath, children))) { if (this.isFilePatternMatch(file, relativeFilePath) && (!this.includePattern || glob.match(this.includePattern, relativeFilePath, children))) {
this.resultCount++; this.resultCount++;
if (this.maxResults && this.resultCount > this.maxResults) { if (this.maxResults && this.resultCount > this.maxResults) {
...@@ -183,11 +185,11 @@ export class FileWalker { ...@@ -183,11 +185,11 @@ export class FileWalker {
}); });
} }
private isFilePatternMatch(path: string): boolean { private isFilePatternMatch(name: string, path: string): boolean {
// Check for search pattern // Check for search pattern
if (this.filePattern) { if (this.filePattern) {
const res = filters.matchesFuzzy(this.filePattern, path); const res = filters.matchesFuzzy(this.filePattern, this.searchInPath ? path : name);
return !!res && res.length > 0; return !!res && res.length > 0;
} }
......
...@@ -47,6 +47,24 @@ suite('Search', () => { ...@@ -47,6 +47,24 @@ suite('Search', () => {
}); });
}); });
test('Files: examples/com*', function(done: () => void) {
let engine = new FileSearchEngine({
rootPaths: [require.toUrl('./fixtures')],
filePattern: 'examples' + path.sep + 'com*'
});
let count = 0;
engine.search((result) => {
if (result) {
count++;
}
}, () => { }, (error) => {
assert.ok(!error);
assert.equal(count, 1);
done();
});
});
test('Files: *.js (Files as roots)', function(done: () => void) { test('Files: *.js (Files as roots)', function(done: () => void) {
let engine = new FileSearchEngine({ let engine = new FileSearchEngine({
rootPaths: [require.toUrl('./fixtures/examples/company.js'), require.toUrl('./fixtures/examples/small.js')], rootPaths: [require.toUrl('./fixtures/examples/company.js'), require.toUrl('./fixtures/examples/small.js')],
......
...@@ -43,7 +43,7 @@ suite('Workbench QuickOpen', () => { ...@@ -43,7 +43,7 @@ suite('Workbench QuickOpen', () => {
let model = new EditorHistoryModel(editorService, null, contextService); let model = new EditorHistoryModel(editorService, null, contextService);
let input1 = inst.createInstance(StringEditorInput, "name1", 'description', "value1", "text/plain", false); let input1 = inst.createInstance(StringEditorInput, "name1", 'description', "value1", "text/plain", false);
let entry1 = new EditorHistoryEntry(editorService, contextService, input1, null, model); let entry1 = new EditorHistoryEntry(editorService, contextService, input1, null, null, model);
assert.equal(input1.getName(), entry1.getLabel()); assert.equal(input1.getName(), entry1.getLabel());
assert.equal(input1.getDescription(), entry1.getDescription()); assert.equal(input1.getDescription(), entry1.getDescription());
...@@ -63,7 +63,7 @@ suite('Workbench QuickOpen', () => { ...@@ -63,7 +63,7 @@ suite('Workbench QuickOpen', () => {
let input2 = inst.createInstance(StringEditorInput, "name2", 'description', "value2", "text/plain", false); let input2 = inst.createInstance(StringEditorInput, "name2", 'description', "value2", "text/plain", false);
(<any>input2).getResource = () => "path"; (<any>input2).getResource = () => "path";
let entry2 = new EditorHistoryEntry(editorService, contextService, input2, null, model); let entry2 = new EditorHistoryEntry(editorService, contextService, input2, null, null, model);
assert.equal(entry2.getResource(), "path"); assert.equal(entry2.getResource(), "path");
assert(!entry1.matches(entry2.getInput())); assert(!entry1.matches(entry2.getInput()));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册