findState.ts 8.1 KB
Newer Older
A
Alex Dima 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

M
Matt Bierner 已提交
6
import { Event, Emitter } from 'vs/base/common/event';
J
Johannes Rieken 已提交
7 8
import { IDisposable } from 'vs/base/common/lifecycle';
import { Range } from 'vs/editor/common/core/range';
A
Alex Dima 已提交
9 10 11

export interface FindReplaceStateChangedEvent {
	moveCursor: boolean;
12
	updateHistory: boolean;
A
Alex Dima 已提交
13 14 15 16 17 18 19 20 21

	searchString: boolean;
	replaceString: boolean;
	isRevealed: boolean;
	isReplaceRevealed: boolean;
	isRegex: boolean;
	wholeWord: boolean;
	matchCase: boolean;
	searchScope: boolean;
22
	matchesPosition: boolean;
A
Alex Dima 已提交
23
	matchesCount: boolean;
24
	currentMatch: boolean;
A
Alex Dima 已提交
25 26
}

A
Alex Dima 已提交
27 28 29 30 31 32
export const enum FindOptionOverride {
	NotSet = 0,
	True = 1,
	False = 2
}

A
Alex Dima 已提交
33 34 35 36 37 38
export interface INewFindReplaceState {
	searchString?: string;
	replaceString?: string;
	isRevealed?: boolean;
	isReplaceRevealed?: boolean;
	isRegex?: boolean;
A
Alex Dima 已提交
39
	isRegexOverride?: FindOptionOverride;
A
Alex Dima 已提交
40
	wholeWord?: boolean;
A
Alex Dima 已提交
41
	wholeWordOverride?: FindOptionOverride;
A
Alex Dima 已提交
42
	matchCase?: boolean;
A
Alex Dima 已提交
43
	matchCaseOverride?: FindOptionOverride;
44
	searchScope?: Range;
A
Alex Dima 已提交
45 46
}

A
Alex Dima 已提交
47 48 49 50 51 52 53 54 55 56
function effectiveOptionValue(override: FindOptionOverride, value: boolean): boolean {
	if (override === FindOptionOverride.True) {
		return true;
	}
	if (override === FindOptionOverride.False) {
		return false;
	}
	return value;
}

A
Alex Dima 已提交
57 58 59 60 61 62
export class FindReplaceState implements IDisposable {
	private _searchString: string;
	private _replaceString: string;
	private _isRevealed: boolean;
	private _isReplaceRevealed: boolean;
	private _isRegex: boolean;
A
Alex Dima 已提交
63
	private _isRegexOverride: FindOptionOverride;
A
Alex Dima 已提交
64
	private _wholeWord: boolean;
A
Alex Dima 已提交
65
	private _wholeWordOverride: FindOptionOverride;
A
Alex Dima 已提交
66
	private _matchCase: boolean;
A
Alex Dima 已提交
67
	private _matchCaseOverride: FindOptionOverride;
A
Alex Dima 已提交
68
	private _searchScope: Range | null;
69
	private _matchesPosition: number;
A
Alex Dima 已提交
70
	private _matchesCount: number;
A
Alex Dima 已提交
71
	private _currentMatch: Range | null;
M
Matt Bierner 已提交
72
	private readonly _onFindReplaceStateChange: Emitter<FindReplaceStateChangedEvent>;
A
Alex Dima 已提交
73 74 75 76 77

	public get searchString(): string { return this._searchString; }
	public get replaceString(): string { return this._replaceString; }
	public get isRevealed(): boolean { return this._isRevealed; }
	public get isReplaceRevealed(): boolean { return this._isReplaceRevealed; }
A
Alex Dima 已提交
78 79 80
	public get isRegex(): boolean { return effectiveOptionValue(this._isRegexOverride, this._isRegex); }
	public get wholeWord(): boolean { return effectiveOptionValue(this._wholeWordOverride, this._wholeWord); }
	public get matchCase(): boolean { return effectiveOptionValue(this._matchCaseOverride, this._matchCase); }
81 82 83 84 85

	public get actualIsRegex(): boolean { return this._isRegex; }
	public get actualWholeWord(): boolean { return this._wholeWord; }
	public get actualMatchCase(): boolean { return this._matchCase; }

A
Alex Dima 已提交
86
	public get searchScope(): Range | null { return this._searchScope; }
87
	public get matchesPosition(): number { return this._matchesPosition; }
A
Alex Dima 已提交
88
	public get matchesCount(): number { return this._matchesCount; }
A
Alex Dima 已提交
89
	public get currentMatch(): Range | null { return this._currentMatch; }
R
rebornix 已提交
90
	public get onFindReplaceStateChange(): Event<FindReplaceStateChangedEvent> { return this._onFindReplaceStateChange.event; }
A
Alex Dima 已提交
91 92 93 94 95 96 97

	constructor() {
		this._searchString = '';
		this._replaceString = '';
		this._isRevealed = false;
		this._isReplaceRevealed = false;
		this._isRegex = false;
A
Alex Dima 已提交
98
		this._isRegexOverride = FindOptionOverride.NotSet;
A
Alex Dima 已提交
99
		this._wholeWord = false;
A
Alex Dima 已提交
100
		this._wholeWordOverride = FindOptionOverride.NotSet;
A
Alex Dima 已提交
101
		this._matchCase = false;
A
Alex Dima 已提交
102
		this._matchCaseOverride = FindOptionOverride.NotSet;
A
Alex Dima 已提交
103
		this._searchScope = null;
104
		this._matchesPosition = 0;
A
Alex Dima 已提交
105
		this._matchesCount = 0;
106
		this._currentMatch = null;
R
rebornix 已提交
107
		this._onFindReplaceStateChange = new Emitter<FindReplaceStateChangedEvent>();
A
Alex Dima 已提交
108 109 110 111 112
	}

	public dispose(): void {
	}

J
Johannes Rieken 已提交
113 114
	public changeMatchInfo(matchesPosition: number, matchesCount: number, currentMatch: Range): void {
		let changeEvent: FindReplaceStateChangedEvent = {
A
Alex Dima 已提交
115
			moveCursor: false,
116
			updateHistory: false,
A
Alex Dima 已提交
117 118 119 120 121 122 123 124 125
			searchString: false,
			replaceString: false,
			isRevealed: false,
			isReplaceRevealed: false,
			isRegex: false,
			wholeWord: false,
			matchCase: false,
			searchScope: false,
			matchesPosition: false,
126 127
			matchesCount: false,
			currentMatch: false
A
Alex Dima 已提交
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
		};
		let somethingChanged = false;

		if (matchesCount === 0) {
			matchesPosition = 0;
		}
		if (matchesPosition > matchesCount) {
			matchesPosition = matchesCount;
		}

		if (this._matchesPosition !== matchesPosition) {
			this._matchesPosition = matchesPosition;
			changeEvent.matchesPosition = true;
			somethingChanged = true;
		}
		if (this._matchesCount !== matchesCount) {
			this._matchesCount = matchesCount;
			changeEvent.matchesCount = true;
			somethingChanged = true;
		}

149 150 151 152 153 154 155 156
		if (typeof currentMatch !== 'undefined') {
			if (!Range.equalsRange(this._currentMatch, currentMatch)) {
				this._currentMatch = currentMatch;
				changeEvent.currentMatch = true;
				somethingChanged = true;
			}
		}

A
Alex Dima 已提交
157
		if (somethingChanged) {
R
rebornix 已提交
158
			this._onFindReplaceStateChange.fire(changeEvent);
A
Alex Dima 已提交
159 160 161
		}
	}

J
Johannes Rieken 已提交
162 163
	public change(newState: INewFindReplaceState, moveCursor: boolean, updateHistory: boolean = true): void {
		let changeEvent: FindReplaceStateChangedEvent = {
A
Alex Dima 已提交
164
			moveCursor: moveCursor,
165
			updateHistory: updateHistory,
A
Alex Dima 已提交
166 167 168 169 170 171 172 173
			searchString: false,
			replaceString: false,
			isRevealed: false,
			isReplaceRevealed: false,
			isRegex: false,
			wholeWord: false,
			matchCase: false,
			searchScope: false,
174
			matchesPosition: false,
175 176
			matchesCount: false,
			currentMatch: false
A
Alex Dima 已提交
177 178 179
		};
		let somethingChanged = false;

A
Alex Dima 已提交
180 181 182 183
		const oldEffectiveIsRegex = this.isRegex;
		const oldEffectiveWholeWords = this.wholeWord;
		const oldEffectiveMatchCase = this.matchCase;

A
Alex Dima 已提交
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
		if (typeof newState.searchString !== 'undefined') {
			if (this._searchString !== newState.searchString) {
				this._searchString = newState.searchString;
				changeEvent.searchString = true;
				somethingChanged = true;
			}
		}
		if (typeof newState.replaceString !== 'undefined') {
			if (this._replaceString !== newState.replaceString) {
				this._replaceString = newState.replaceString;
				changeEvent.replaceString = true;
				somethingChanged = true;
			}
		}
		if (typeof newState.isRevealed !== 'undefined') {
			if (this._isRevealed !== newState.isRevealed) {
				this._isRevealed = newState.isRevealed;
				changeEvent.isRevealed = true;
				somethingChanged = true;
			}
		}
		if (typeof newState.isReplaceRevealed !== 'undefined') {
			if (this._isReplaceRevealed !== newState.isReplaceRevealed) {
				this._isReplaceRevealed = newState.isReplaceRevealed;
				changeEvent.isReplaceRevealed = true;
				somethingChanged = true;
			}
		}
		if (typeof newState.isRegex !== 'undefined') {
A
Alex Dima 已提交
213
			this._isRegex = newState.isRegex;
A
Alex Dima 已提交
214 215
		}
		if (typeof newState.wholeWord !== 'undefined') {
A
Alex Dima 已提交
216
			this._wholeWord = newState.wholeWord;
A
Alex Dima 已提交
217 218
		}
		if (typeof newState.matchCase !== 'undefined') {
A
Alex Dima 已提交
219
			this._matchCase = newState.matchCase;
A
Alex Dima 已提交
220 221 222 223 224 225 226 227
		}
		if (typeof newState.searchScope !== 'undefined') {
			if (!Range.equalsRange(this._searchScope, newState.searchScope)) {
				this._searchScope = newState.searchScope;
				changeEvent.searchScope = true;
				somethingChanged = true;
			}
		}
228

A
Alex Dima 已提交
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
		// Overrides get set when they explicitly come in and get reset anytime something else changes
		this._isRegexOverride = (typeof newState.isRegexOverride !== 'undefined' ? newState.isRegexOverride : FindOptionOverride.NotSet);
		this._wholeWordOverride = (typeof newState.wholeWordOverride !== 'undefined' ? newState.wholeWordOverride : FindOptionOverride.NotSet);
		this._matchCaseOverride = (typeof newState.matchCaseOverride !== 'undefined' ? newState.matchCaseOverride : FindOptionOverride.NotSet);

		if (oldEffectiveIsRegex !== this.isRegex) {
			somethingChanged = true;
			changeEvent.isRegex = true;
		}
		if (oldEffectiveWholeWords !== this.wholeWord) {
			somethingChanged = true;
			changeEvent.wholeWord = true;
		}
		if (oldEffectiveMatchCase !== this.matchCase) {
			somethingChanged = true;
			changeEvent.matchCase = true;
		}

A
Alex Dima 已提交
247
		if (somethingChanged) {
R
rebornix 已提交
248
			this._onFindReplaceStateChange.fire(changeEvent);
A
Alex Dima 已提交
249 250 251
		}
	}
}