mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-23 13:20:30 -04:00
Vscode merge (#4582)
* Merge from vscode 37cb23d3dd4f9433d56d4ba5ea3203580719a0bd * fix issues with merges * bump node version in azpipe * replace license headers * remove duplicate launch task * fix build errors * fix build errors * fix tslint issues * working through package and linux build issues * more work * wip * fix packaged builds * working through linux build errors * wip * wip * wip * fix mac and linux file limits * iterate linux pipeline * disable editor typing * revert series to parallel * remove optimize vscode from linux * fix linting issues * revert testing change * add work round for new node * readd packaging for extensions * fix issue with angular not resolving decorator dependencies
This commit is contained in:
557
src/vs/workbench/contrib/search/browser/searchWidget.ts
Normal file
557
src/vs/workbench/contrib/search/browser/searchWidget.ts
Normal file
@@ -0,0 +1,557 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Button, IButtonOptions } from 'vs/base/browser/ui/button/button';
|
||||
import { FindInput, IFindInputOptions } from 'vs/base/browser/ui/findinput/findInput';
|
||||
import { HistoryInputBox, IMessage } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import { Widget } from 'vs/base/browser/ui/widget';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { CONTEXT_FIND_WIDGET_NOT_VISIBLE } from 'vs/editor/contrib/find/findModel';
|
||||
import * as nls from 'vs/nls';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ContextKeyExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { ISearchConfigurationProperties } from 'vs/workbench/services/search/common/search';
|
||||
import { attachFindInputBoxStyler, attachInputBoxStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { ContextScopedFindInput, ContextScopedHistoryInputBox } from 'vs/platform/browser/contextScopedHistoryWidget';
|
||||
import { appendKeyBindingLabel, isSearchViewFocused } from 'vs/workbench/contrib/search/browser/searchActions';
|
||||
import * as Constants from 'vs/workbench/contrib/search/common/constants';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
|
||||
|
||||
export interface ISearchWidgetOptions {
|
||||
value?: string;
|
||||
replaceValue?: string;
|
||||
isRegex?: boolean;
|
||||
isCaseSensitive?: boolean;
|
||||
isWholeWords?: boolean;
|
||||
searchHistory?: string[];
|
||||
replaceHistory?: string[];
|
||||
}
|
||||
|
||||
class ReplaceAllAction extends Action {
|
||||
|
||||
private static fgInstance: ReplaceAllAction | null = null;
|
||||
static readonly ID: string = 'search.action.replaceAll';
|
||||
|
||||
static get INSTANCE(): ReplaceAllAction {
|
||||
if (ReplaceAllAction.fgInstance === null) {
|
||||
ReplaceAllAction.fgInstance = new ReplaceAllAction();
|
||||
}
|
||||
return ReplaceAllAction.fgInstance;
|
||||
}
|
||||
|
||||
private _searchWidget: SearchWidget | null = null;
|
||||
|
||||
constructor() {
|
||||
super(ReplaceAllAction.ID, '', 'action-replace-all', false);
|
||||
}
|
||||
|
||||
set searchWidget(searchWidget: SearchWidget) {
|
||||
this._searchWidget = searchWidget;
|
||||
}
|
||||
|
||||
run(): Promise<any> {
|
||||
if (this._searchWidget) {
|
||||
return this._searchWidget.triggerReplaceAll();
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
|
||||
export class SearchWidget extends Widget {
|
||||
|
||||
private static readonly REPLACE_ALL_DISABLED_LABEL = nls.localize('search.action.replaceAll.disabled.label', "Replace All (Submit Search to Enable)");
|
||||
private static readonly REPLACE_ALL_ENABLED_LABEL = (keyBindingService2: IKeybindingService): string => {
|
||||
const kb = keyBindingService2.lookupKeybinding(ReplaceAllAction.ID);
|
||||
return appendKeyBindingLabel(nls.localize('search.action.replaceAll.enabled.label', "Replace All"), kb, keyBindingService2);
|
||||
}
|
||||
|
||||
domNode: HTMLElement;
|
||||
|
||||
searchInput: FindInput;
|
||||
searchInputFocusTracker: dom.IFocusTracker;
|
||||
private searchInputBoxFocused: IContextKey<boolean>;
|
||||
|
||||
private replaceContainer: HTMLElement;
|
||||
replaceInput: HistoryInputBox;
|
||||
private toggleReplaceButton: Button;
|
||||
private replaceAllAction: ReplaceAllAction;
|
||||
private replaceActive: IContextKey<boolean>;
|
||||
private replaceActionBar: ActionBar;
|
||||
replaceInputFocusTracker: dom.IFocusTracker;
|
||||
private replaceInputBoxFocused: IContextKey<boolean>;
|
||||
private _replaceHistoryDelayer: Delayer<void>;
|
||||
|
||||
private ignoreGlobalFindBufferOnNextFocus = false;
|
||||
private previousGlobalFindBufferValue: string;
|
||||
|
||||
private _onSearchSubmit = this._register(new Emitter<void>());
|
||||
readonly onSearchSubmit: Event<void> = this._onSearchSubmit.event;
|
||||
|
||||
private _onSearchCancel = this._register(new Emitter<void>());
|
||||
readonly onSearchCancel: Event<void> = this._onSearchCancel.event;
|
||||
|
||||
private _onReplaceToggled = this._register(new Emitter<void>());
|
||||
readonly onReplaceToggled: Event<void> = this._onReplaceToggled.event;
|
||||
|
||||
private _onReplaceStateChange = this._register(new Emitter<boolean>());
|
||||
readonly onReplaceStateChange: Event<boolean> = this._onReplaceStateChange.event;
|
||||
|
||||
private _onReplaceValueChanged = this._register(new Emitter<string | undefined>());
|
||||
readonly onReplaceValueChanged: Event<string> = this._onReplaceValueChanged.event;
|
||||
|
||||
private _onReplaceAll = this._register(new Emitter<void>());
|
||||
readonly onReplaceAll: Event<void> = this._onReplaceAll.event;
|
||||
|
||||
private _onBlur = this._register(new Emitter<void>());
|
||||
readonly onBlur: Event<void> = this._onBlur.event;
|
||||
|
||||
private _onDidHeightChange = this._register(new Emitter<void>());
|
||||
readonly onDidHeightChange: Event<void> = this._onDidHeightChange.event;
|
||||
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
options: ISearchWidgetOptions,
|
||||
@IContextViewService private readonly contextViewService: IContextViewService,
|
||||
@IThemeService private readonly themeService: IThemeService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IKeybindingService private readonly keyBindingService: IKeybindingService,
|
||||
@IClipboardService private readonly clipboardServce: IClipboardService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IAccessibilityService private readonly accessibilityService: IAccessibilityService
|
||||
) {
|
||||
super();
|
||||
this.replaceActive = Constants.ReplaceActiveKey.bindTo(this.contextKeyService);
|
||||
this.searchInputBoxFocused = Constants.SearchInputBoxFocusedKey.bindTo(this.contextKeyService);
|
||||
this.replaceInputBoxFocused = Constants.ReplaceInputBoxFocusedKey.bindTo(this.contextKeyService);
|
||||
this._replaceHistoryDelayer = new Delayer<void>(500);
|
||||
this.render(container, options);
|
||||
|
||||
this.configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('editor.accessibilitySupport')) {
|
||||
this.updateAccessibilitySupport();
|
||||
}
|
||||
});
|
||||
this.accessibilityService.onDidChangeAccessibilitySupport(() => this.updateAccessibilitySupport());
|
||||
this.updateAccessibilitySupport();
|
||||
}
|
||||
|
||||
focus(select: boolean = true, focusReplace: boolean = false, suppressGlobalSearchBuffer = false): void {
|
||||
this.ignoreGlobalFindBufferOnNextFocus = suppressGlobalSearchBuffer;
|
||||
|
||||
if (focusReplace && this.isReplaceShown()) {
|
||||
this.replaceInput.focus();
|
||||
if (select) {
|
||||
this.replaceInput.select();
|
||||
}
|
||||
} else {
|
||||
this.searchInput.focus();
|
||||
if (select) {
|
||||
this.searchInput.select();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setWidth(width: number) {
|
||||
this.searchInput.inputBox.layout();
|
||||
this.replaceInput.width = width - 28;
|
||||
this.replaceInput.layout();
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.searchInput.clear();
|
||||
this.replaceInput.value = '';
|
||||
this.setReplaceAllActionState(false);
|
||||
}
|
||||
|
||||
isReplaceShown(): boolean {
|
||||
return !dom.hasClass(this.replaceContainer, 'disabled');
|
||||
}
|
||||
|
||||
isReplaceActive(): boolean {
|
||||
return !!this.replaceActive.get();
|
||||
}
|
||||
|
||||
getReplaceValue(): string {
|
||||
return this.replaceInput.value;
|
||||
}
|
||||
|
||||
toggleReplace(show?: boolean): void {
|
||||
if (show === undefined || show !== this.isReplaceShown()) {
|
||||
this.onToggleReplaceButton();
|
||||
}
|
||||
}
|
||||
|
||||
getSearchHistory(): string[] {
|
||||
return this.searchInput.inputBox.getHistory();
|
||||
}
|
||||
|
||||
getReplaceHistory(): string[] {
|
||||
return this.replaceInput.getHistory();
|
||||
}
|
||||
|
||||
clearHistory(): void {
|
||||
this.searchInput.inputBox.clearHistory();
|
||||
}
|
||||
|
||||
showNextSearchTerm() {
|
||||
this.searchInput.inputBox.showNextValue();
|
||||
}
|
||||
|
||||
showPreviousSearchTerm() {
|
||||
this.searchInput.inputBox.showPreviousValue();
|
||||
}
|
||||
|
||||
showNextReplaceTerm() {
|
||||
this.replaceInput.showNextValue();
|
||||
}
|
||||
|
||||
showPreviousReplaceTerm() {
|
||||
this.replaceInput.showPreviousValue();
|
||||
}
|
||||
|
||||
searchInputHasFocus(): boolean {
|
||||
return !!this.searchInputBoxFocused.get();
|
||||
}
|
||||
|
||||
replaceInputHasFocus(): boolean {
|
||||
return this.replaceInput.hasFocus();
|
||||
}
|
||||
|
||||
focusReplaceAllAction(): void {
|
||||
this.replaceActionBar.focus(true);
|
||||
}
|
||||
|
||||
focusRegexAction(): void {
|
||||
this.searchInput.focusOnRegex();
|
||||
}
|
||||
|
||||
private render(container: HTMLElement, options: ISearchWidgetOptions): void {
|
||||
this.domNode = dom.append(container, dom.$('.search-widget'));
|
||||
this.domNode.style.position = 'relative';
|
||||
|
||||
this.renderToggleReplaceButton(this.domNode);
|
||||
|
||||
this.renderSearchInput(this.domNode, options);
|
||||
this.renderReplaceInput(this.domNode, options);
|
||||
}
|
||||
|
||||
private isScreenReaderOptimized() {
|
||||
const detected = this.accessibilityService.getAccessibilitySupport() === AccessibilitySupport.Enabled;
|
||||
const config = this.configurationService.getValue<IEditorOptions>('editor').accessibilitySupport;
|
||||
return config === 'on' || (config === 'auto' && detected);
|
||||
}
|
||||
|
||||
private updateAccessibilitySupport(): void {
|
||||
this.searchInput.setFocusInputOnOptionClick(!this.isScreenReaderOptimized());
|
||||
}
|
||||
|
||||
private renderToggleReplaceButton(parent: HTMLElement): void {
|
||||
const opts: IButtonOptions = {
|
||||
buttonBackground: undefined,
|
||||
buttonBorder: undefined,
|
||||
buttonForeground: undefined,
|
||||
buttonHoverBackground: undefined
|
||||
};
|
||||
this.toggleReplaceButton = this._register(new Button(parent, opts));
|
||||
this.toggleReplaceButton.element.setAttribute('aria-expanded', 'false');
|
||||
this.toggleReplaceButton.element.classList.add('collapse');
|
||||
this.toggleReplaceButton.icon = 'toggle-replace-button';
|
||||
// TODO@joh need to dispose this listener eventually
|
||||
this.toggleReplaceButton.onDidClick(() => this.onToggleReplaceButton());
|
||||
this.toggleReplaceButton.element.title = nls.localize('search.replace.toggle.button.title', "Toggle Replace");
|
||||
}
|
||||
|
||||
private renderSearchInput(parent: HTMLElement, options: ISearchWidgetOptions): void {
|
||||
const inputOptions: IFindInputOptions = {
|
||||
label: nls.localize('label.Search', 'Search: Type Search Term and press Enter to search or Escape to cancel'),
|
||||
validation: (value: string) => this.validateSearchInput(value),
|
||||
placeholder: nls.localize('search.placeHolder', "Search"),
|
||||
appendCaseSensitiveLabel: appendKeyBindingLabel('', this.keyBindingService.lookupKeybinding(Constants.ToggleCaseSensitiveCommandId), this.keyBindingService),
|
||||
appendWholeWordsLabel: appendKeyBindingLabel('', this.keyBindingService.lookupKeybinding(Constants.ToggleWholeWordCommandId), this.keyBindingService),
|
||||
appendRegexLabel: appendKeyBindingLabel('', this.keyBindingService.lookupKeybinding(Constants.ToggleRegexCommandId), this.keyBindingService),
|
||||
history: options.searchHistory,
|
||||
flexibleHeight: true
|
||||
};
|
||||
|
||||
const searchInputContainer = dom.append(parent, dom.$('.search-container.input-box'));
|
||||
this.searchInput = this._register(new ContextScopedFindInput(searchInputContainer, this.contextViewService, inputOptions, this.contextKeyService, true));
|
||||
this._register(attachFindInputBoxStyler(this.searchInput, this.themeService));
|
||||
this.searchInput.onKeyDown((keyboardEvent: IKeyboardEvent) => this.onSearchInputKeyDown(keyboardEvent));
|
||||
this.searchInput.setValue(options.value || '');
|
||||
this.searchInput.setRegex(!!options.isRegex);
|
||||
this.searchInput.setCaseSensitive(!!options.isCaseSensitive);
|
||||
this.searchInput.setWholeWords(!!options.isWholeWords);
|
||||
this._register(this.onSearchSubmit(() => {
|
||||
this.searchInput.inputBox.addToHistory();
|
||||
}));
|
||||
this._register(this.searchInput.onCaseSensitiveKeyDown((keyboardEvent: IKeyboardEvent) => this.onCaseSensitiveKeyDown(keyboardEvent)));
|
||||
this._register(this.searchInput.onRegexKeyDown((keyboardEvent: IKeyboardEvent) => this.onRegexKeyDown(keyboardEvent)));
|
||||
this._register(this.searchInput.inputBox.onDidChange(() => this.onSearchInputChanged()));
|
||||
this._register(this.searchInput.inputBox.onDidHeightChange(() => this._onDidHeightChange.fire()));
|
||||
|
||||
this._register(this.onReplaceValueChanged(() => {
|
||||
this._replaceHistoryDelayer.trigger(() => this.replaceInput.addToHistory());
|
||||
}));
|
||||
|
||||
this.searchInputFocusTracker = this._register(dom.trackFocus(this.searchInput.inputBox.inputElement));
|
||||
this._register(this.searchInputFocusTracker.onDidFocus(() => {
|
||||
this.searchInputBoxFocused.set(true);
|
||||
|
||||
const useGlobalFindBuffer = this.searchConfiguration.globalFindClipboard;
|
||||
if (!this.ignoreGlobalFindBufferOnNextFocus && useGlobalFindBuffer) {
|
||||
const globalBufferText = this.clipboardServce.readFindText();
|
||||
if (this.previousGlobalFindBufferValue !== globalBufferText) {
|
||||
this.searchInput.inputBox.addToHistory();
|
||||
this.searchInput.setValue(globalBufferText);
|
||||
this.searchInput.select();
|
||||
}
|
||||
|
||||
this.previousGlobalFindBufferValue = globalBufferText;
|
||||
}
|
||||
|
||||
this.ignoreGlobalFindBufferOnNextFocus = false;
|
||||
}));
|
||||
this._register(this.searchInputFocusTracker.onDidBlur(() => this.searchInputBoxFocused.set(false)));
|
||||
}
|
||||
|
||||
private renderReplaceInput(parent: HTMLElement, options: ISearchWidgetOptions): void {
|
||||
this.replaceContainer = dom.append(parent, dom.$('.replace-container.disabled'));
|
||||
const replaceBox = dom.append(this.replaceContainer, dom.$('.input-box'));
|
||||
this.replaceInput = this._register(new ContextScopedHistoryInputBox(replaceBox, this.contextViewService, {
|
||||
ariaLabel: nls.localize('label.Replace', 'Replace: Type replace term and press Enter to preview or Escape to cancel'),
|
||||
placeholder: nls.localize('search.replace.placeHolder', "Replace"),
|
||||
history: options.replaceHistory || [],
|
||||
flexibleHeight: true
|
||||
}, this.contextKeyService));
|
||||
this._register(attachInputBoxStyler(this.replaceInput, this.themeService));
|
||||
this.onkeydown(this.replaceInput.inputElement, (keyboardEvent) => this.onReplaceInputKeyDown(keyboardEvent));
|
||||
this.replaceInput.value = options.replaceValue || '';
|
||||
this._register(this.replaceInput.onDidChange(() => this._onReplaceValueChanged.fire(undefined)));
|
||||
this._register(this.replaceInput.onDidHeightChange(() => this._onDidHeightChange.fire()));
|
||||
|
||||
this.replaceAllAction = ReplaceAllAction.INSTANCE;
|
||||
this.replaceAllAction.searchWidget = this;
|
||||
this.replaceAllAction.label = SearchWidget.REPLACE_ALL_DISABLED_LABEL;
|
||||
this.replaceActionBar = this._register(new ActionBar(this.replaceContainer));
|
||||
this.replaceActionBar.push([this.replaceAllAction], { icon: true, label: false });
|
||||
this.onkeydown(this.replaceActionBar.domNode, (keyboardEvent) => this.onReplaceActionbarKeyDown(keyboardEvent));
|
||||
|
||||
this.replaceInputFocusTracker = this._register(dom.trackFocus(this.replaceInput.inputElement));
|
||||
this._register(this.replaceInputFocusTracker.onDidFocus(() => this.replaceInputBoxFocused.set(true)));
|
||||
this._register(this.replaceInputFocusTracker.onDidBlur(() => this.replaceInputBoxFocused.set(false)));
|
||||
}
|
||||
|
||||
triggerReplaceAll(): Promise<any> {
|
||||
this._onReplaceAll.fire();
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
private onToggleReplaceButton(): void {
|
||||
dom.toggleClass(this.replaceContainer, 'disabled');
|
||||
dom.toggleClass(this.toggleReplaceButton.element, 'collapse');
|
||||
dom.toggleClass(this.toggleReplaceButton.element, 'expand');
|
||||
this.toggleReplaceButton.element.setAttribute('aria-expanded', this.isReplaceShown() ? 'true' : 'false');
|
||||
this.updateReplaceActiveState();
|
||||
this._onReplaceToggled.fire();
|
||||
}
|
||||
|
||||
setReplaceAllActionState(enabled: boolean): void {
|
||||
if (this.replaceAllAction.enabled !== enabled) {
|
||||
this.replaceAllAction.enabled = enabled;
|
||||
this.replaceAllAction.label = enabled ? SearchWidget.REPLACE_ALL_ENABLED_LABEL(this.keyBindingService) : SearchWidget.REPLACE_ALL_DISABLED_LABEL;
|
||||
this.updateReplaceActiveState();
|
||||
}
|
||||
}
|
||||
|
||||
private updateReplaceActiveState(): void {
|
||||
const currentState = this.isReplaceActive();
|
||||
const newState = this.isReplaceShown() && this.replaceAllAction.enabled;
|
||||
if (currentState !== newState) {
|
||||
this.replaceActive.set(newState);
|
||||
this._onReplaceStateChange.fire(newState);
|
||||
this.replaceInput.layout();
|
||||
}
|
||||
}
|
||||
|
||||
private validateSearchInput(value: string): IMessage | null {
|
||||
if (value.length === 0) {
|
||||
return null;
|
||||
}
|
||||
if (!this.searchInput.getRegex()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// tslint:disable-next-line: no-unused-expression
|
||||
new RegExp(value);
|
||||
} catch (e) {
|
||||
return { content: e.message };
|
||||
}
|
||||
|
||||
if (strings.regExpContainsBackreference(value)) {
|
||||
if (!this.searchConfiguration.usePCRE2) {
|
||||
return { content: nls.localize('regexp.backreferenceValidationFailure', "Backreferences are not supported") };
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private onSearchInputChanged(): void {
|
||||
this.searchInput.clearMessage();
|
||||
this.setReplaceAllActionState(false);
|
||||
}
|
||||
|
||||
private onSearchInputKeyDown(keyboardEvent: IKeyboardEvent) {
|
||||
if (keyboardEvent.equals(KeyCode.Enter)) {
|
||||
this.submitSearch();
|
||||
keyboardEvent.preventDefault();
|
||||
}
|
||||
|
||||
else if (keyboardEvent.equals(KeyCode.Escape)) {
|
||||
this._onSearchCancel.fire();
|
||||
keyboardEvent.preventDefault();
|
||||
}
|
||||
|
||||
else if (keyboardEvent.equals(KeyCode.Tab)) {
|
||||
if (this.isReplaceShown()) {
|
||||
this.replaceInput.focus();
|
||||
} else {
|
||||
this.searchInput.focusOnCaseSensitive();
|
||||
}
|
||||
keyboardEvent.preventDefault();
|
||||
}
|
||||
|
||||
else if (keyboardEvent.equals(KeyCode.UpArrow)) {
|
||||
const ta = this.searchInput.domNode.querySelector('textarea');
|
||||
const isMultiline = !!this.searchInput.getValue().match(/\n/);
|
||||
if (ta && isMultiline && ta.selectionStart > 0) {
|
||||
keyboardEvent.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
else if (keyboardEvent.equals(KeyCode.DownArrow)) {
|
||||
const ta = this.searchInput.domNode.querySelector('textarea');
|
||||
const isMultiline = !!this.searchInput.getValue().match(/\n/);
|
||||
if (ta && isMultiline && ta.selectionEnd < ta.value.length) {
|
||||
keyboardEvent.stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private onCaseSensitiveKeyDown(keyboardEvent: IKeyboardEvent) {
|
||||
if (keyboardEvent.equals(KeyMod.Shift | KeyCode.Tab)) {
|
||||
if (this.isReplaceShown()) {
|
||||
this.replaceInput.focus();
|
||||
keyboardEvent.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private onRegexKeyDown(keyboardEvent: IKeyboardEvent) {
|
||||
if (keyboardEvent.equals(KeyCode.Tab)) {
|
||||
if (this.isReplaceActive()) {
|
||||
this.focusReplaceAllAction();
|
||||
} else {
|
||||
this._onBlur.fire();
|
||||
}
|
||||
keyboardEvent.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private onReplaceInputKeyDown(keyboardEvent: IKeyboardEvent) {
|
||||
if (keyboardEvent.equals(KeyCode.Enter)) {
|
||||
this.submitSearch();
|
||||
keyboardEvent.preventDefault();
|
||||
}
|
||||
|
||||
else if (keyboardEvent.equals(KeyCode.Tab)) {
|
||||
this.searchInput.focusOnCaseSensitive();
|
||||
keyboardEvent.preventDefault();
|
||||
}
|
||||
|
||||
else if (keyboardEvent.equals(KeyMod.Shift | KeyCode.Tab)) {
|
||||
this.searchInput.focus();
|
||||
keyboardEvent.preventDefault();
|
||||
}
|
||||
|
||||
else if (keyboardEvent.equals(KeyCode.UpArrow)) {
|
||||
const ta = this.searchInput.domNode.querySelector('textarea');
|
||||
if (ta && ta.selectionStart > 0) {
|
||||
keyboardEvent.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
else if (keyboardEvent.equals(KeyCode.DownArrow)) {
|
||||
const ta = this.searchInput.domNode.querySelector('textarea');
|
||||
if (ta && ta.selectionEnd < ta.value.length) {
|
||||
keyboardEvent.stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private onReplaceActionbarKeyDown(keyboardEvent: IKeyboardEvent) {
|
||||
if (keyboardEvent.equals(KeyMod.Shift | KeyCode.Tab)) {
|
||||
this.focusRegexAction();
|
||||
keyboardEvent.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private submitSearch(): void {
|
||||
this.searchInput.validate();
|
||||
if (!this.searchInput.inputBox.isInputValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const value = this.searchInput.getValue();
|
||||
const useGlobalFindBuffer = this.searchConfiguration.globalFindClipboard;
|
||||
if (value) {
|
||||
if (useGlobalFindBuffer) {
|
||||
this.clipboardServce.writeFindText(value);
|
||||
}
|
||||
|
||||
this._onSearchSubmit.fire();
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.setReplaceAllActionState(false);
|
||||
this.replaceAllAction.searchWidget = null;
|
||||
this.replaceActionBar = null;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private get searchConfiguration(): ISearchConfigurationProperties {
|
||||
return this.configurationService.getValue<ISearchConfigurationProperties>('search');
|
||||
}
|
||||
}
|
||||
|
||||
export function registerContributions() {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: ReplaceAllAction.ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: ContextKeyExpr.and(Constants.SearchViewVisibleKey, Constants.ReplaceActiveKey, CONTEXT_FIND_WIDGET_NOT_VISIBLE),
|
||||
primary: KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.Enter,
|
||||
handler: accessor => {
|
||||
if (isSearchViewFocused(accessor.get(IViewletService), accessor.get(IPanelService))) {
|
||||
ReplaceAllAction.INSTANCE.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user