openFileHandler.ts 6.0 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

B
Benjamin Pasero 已提交
7
import {TPromise} from 'vs/base/common/winjs.base';
E
Erich Gamma 已提交
8 9 10 11 12 13 14
import nls = require('vs/nls');
import {ThrottledDelayer} from 'vs/base/common/async';
import paths = require('vs/base/common/paths');
import labels = require('vs/base/common/labels');
import URI from 'vs/base/common/uri';
import {IRange} from 'vs/editor/common/editorCommon';
import {IAutoFocus} from 'vs/base/parts/quickopen/browser/quickOpen';
B
Benjamin Pasero 已提交
15
import {QuickOpenEntry, QuickOpenModel} from 'vs/base/parts/quickopen/browser/quickOpenModel';
E
Erich Gamma 已提交
16 17 18 19 20 21 22 23
import {QuickOpenHandler, EditorQuickOpenEntry} from 'vs/workbench/browser/quickopen';
import {QueryBuilder} from 'vs/workbench/parts/search/common/searchQuery';
import {ITextFileService} from 'vs/workbench/parts/files/common/files';
import {EditorInput} from 'vs/workbench/common/editor';
import {IWorkbenchEditorService, IFileInput} from 'vs/workbench/services/editor/common/editorService';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IMessageService} from 'vs/platform/message/common/message';
B
Benjamin Pasero 已提交
24
import {IQueryOptions, ISearchService} from 'vs/platform/search/common/search';
E
Erich Gamma 已提交
25 26 27 28 29 30 31 32
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';

export class FileEntry extends EditorQuickOpenEntry {
	private name: string;
	private description: string;
	private resource: URI;
	private range: IRange;

33 34 35 36
	constructor(
		name: string,
		description: string,
		resource: URI,
E
Erich Gamma 已提交
37 38 39 40 41 42 43 44
		@IWorkbenchEditorService editorService: IWorkbenchEditorService,
		@IInstantiationService private instantiationService: IInstantiationService,
		@IWorkspaceContextService contextService: IWorkspaceContextService
	) {
		super(editorService);

		this.resource = resource;
		this.name = name;
45
		this.description = description;
E
Erich Gamma 已提交
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
	}

	public getLabel(): string {
		return this.name;
	}

	public getDescription(): string {
		return this.description;
	}

	public getIcon(): string {
		return 'file';
	}

	public getResource(): URI {
		return this.resource;
	}

	public setRange(range: IRange): void {
		this.range = range;
	}

	public getInput(): IFileInput | EditorInput {
		let input: IFileInput = {
			resource: this.resource,
		};

		if (this.range) {
			input.options = {
				selection: this.range
			};
		}

		return input;
	}
}

export class OpenFileHandler extends QuickOpenHandler {

85
	private static SEARCH_DELAY = 500; // This delay accommodates for the user typing a word and then stops typing to start searching
E
Erich Gamma 已提交
86 87

	private queryBuilder: QueryBuilder;
J
Joao Moreno 已提交
88
	private delayer: ThrottledDelayer<QuickOpenEntry[]>;
E
Erich Gamma 已提交
89
	private isStandalone: boolean;
90
	private fuzzyMatchingEnabled: boolean;
E
Erich Gamma 已提交
91 92 93 94 95 96 97 98

	constructor(
		@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
		@IMessageService private messageService: IMessageService,
		@IInstantiationService private instantiationService: IInstantiationService,
		@IConfigurationService private configurationService: IConfigurationService,
		@IWorkspaceContextService private contextService: IWorkspaceContextService,
		@ITextFileService private textFileService: ITextFileService,
B
Benjamin Pasero 已提交
99
		@ISearchService private searchService: ISearchService
E
Erich Gamma 已提交
100 101 102 103
	) {
		super();

		this.queryBuilder = this.instantiationService.createInstance(QueryBuilder);
J
Joao Moreno 已提交
104
		this.delayer = new ThrottledDelayer<QuickOpenEntry[]>(OpenFileHandler.SEARCH_DELAY);
E
Erich Gamma 已提交
105 106 107 108
		this.isStandalone = true;
	}

	public setStandalone(standalone: boolean) {
J
Joao Moreno 已提交
109
		this.delayer = standalone ? new ThrottledDelayer<QuickOpenEntry[]>(OpenFileHandler.SEARCH_DELAY) : null;
E
Erich Gamma 已提交
110 111 112
		this.isStandalone = standalone;
	}

113 114 115 116
	public setFuzzyMatchingEnabled(enabled: boolean): void {
		this.fuzzyMatchingEnabled = enabled;
	}

E
Erich Gamma 已提交
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
	public getResults(searchValue: string): TPromise<QuickOpenModel> {
		searchValue = searchValue.trim();
		let promise: TPromise<QuickOpenEntry[]>;

		// Respond directly to empty search
		if (!searchValue) {
			promise = TPromise.as([]);
		} else if (this.delayer) {
			promise = this.delayer.trigger(() => this.doFindResults(searchValue)); // Run search with delay as needed
		} else {
			promise = this.doFindResults(searchValue);
		}

		return promise.then(e => new QuickOpenModel(e));
	}

	private doFindResults(searchValue: string): TPromise<QuickOpenEntry[]> {
		let rootResources = this.textFileService.getWorkingFilesModel().getOutOfWorkspaceContextEntries().map((e) => e.resource);
		if (this.contextService.getWorkspace()) {
			rootResources.push(this.contextService.getWorkspace().resource);
		}

139
		let query: IQueryOptions = { filePattern: searchValue, matchFuzzy: this.fuzzyMatchingEnabled, rootResources: rootResources };
E
Erich Gamma 已提交
140

141
		return this.queryBuilder.file(query).then((query) => this.searchService.search(query)).then((complete) => {
E
Erich Gamma 已提交
142 143

			// Highlight
144
			let results: QuickOpenEntry[] = [];
145 146 147 148 149
			for (let i = 0; i < complete.results.length; i++) {
				let fileMatch = complete.results[i];

				let label = paths.basename(fileMatch.resource.fsPath);
				let description = labels.getPathLabel(paths.dirname(fileMatch.resource.fsPath), this.contextService);
150

151
				let entry = this.instantiationService.createInstance(FileEntry, label, description, fileMatch.resource);
152 153

				// Apply highlights
154
				let {labelHighlights, descriptionHighlights} = QuickOpenEntry.highlight(entry, searchValue, this.fuzzyMatchingEnabled);
155
				entry.setHighlights(labelHighlights, descriptionHighlights);
156

157
				results.push(entry);
E
Erich Gamma 已提交
158 159
			}

160 161
			// Sort (standalone only)
			if (this.isStandalone) {
162
				results = results.sort((elementA, elementB) => QuickOpenEntry.compare(elementA, elementB, searchValue));
163 164
			}

E
Erich Gamma 已提交
165 166 167 168 169 170 171 172 173 174 175 176 177 178
			return results;
		});
	}

	public getGroupLabel(): string {
		return nls.localize('searchResults', "search results");
	}

	public getAutoFocus(searchValue: string): IAutoFocus {
		return {
			autoFocusFirstEntry: true
		};
	}
}