diff --git a/src/vs/base/browser/ui/findinput/findInput.css b/src/vs/base/browser/ui/findinput/findInput.css index c659f260e14e2ce22bfe313500eea8af5894a2cc..4bb6b8cec63feae7f18531b7a402fbabb365f1ae 100644 --- a/src/vs/base/browser/ui/findinput/findInput.css +++ b/src/vs/base/browser/ui/findinput/findInput.css @@ -11,7 +11,6 @@ .monaco-findInput .monaco-inputbox { font-size: 13px; width: 100%; - height: 25px; } .monaco-findInput > .controls { diff --git a/src/vs/base/browser/ui/findinput/findInput.ts b/src/vs/base/browser/ui/findinput/findInput.ts index 0ba7da016be15a19242404d0a7908a990eb7c5d1..50116b7f9d39bde45ba11e96f88d981c275aa817 100644 --- a/src/vs/base/browser/ui/findinput/findInput.ts +++ b/src/vs/base/browser/ui/findinput/findInput.ts @@ -23,6 +23,7 @@ export interface IFindInputOptions extends IFindInputStyles { readonly width?: number; readonly validation?: IInputValidator; readonly label: string; + readonly flexibleHeight?: boolean; readonly appendCaseSensitiveLabel?: string; readonly appendWholeWordsLabel?: string; @@ -118,7 +119,7 @@ export class FindInput extends Widget { this.domNode = null; this.inputBox = null; - this.buildDomNode(options.appendCaseSensitiveLabel || '', options.appendWholeWordsLabel || '', options.appendRegexLabel || '', options.history); + this.buildDomNode(options.appendCaseSensitiveLabel || '', options.appendWholeWordsLabel || '', options.appendRegexLabel || '', options.history, options.flexibleHeight); if (Boolean(parent)) { parent.appendChild(this.domNode); @@ -287,7 +288,7 @@ export class FindInput extends Widget { this.inputBox.width = w; } - private buildDomNode(appendCaseSensitiveLabel: string, appendWholeWordsLabel: string, appendRegexLabel: string, history: string[]): void { + private buildDomNode(appendCaseSensitiveLabel: string, appendWholeWordsLabel: string, appendRegexLabel: string, history: string[], flexibleHeight: boolean): void { this.domNode = document.createElement('div'); this.domNode.style.width = this.width + 'px'; dom.addClass(this.domNode, 'monaco-findInput'); @@ -310,7 +311,8 @@ export class FindInput extends Widget { inputValidationErrorBackground: this.inputValidationErrorBackground, inputValidationErrorForeground: this.inputValidationErrorForeground, inputValidationErrorBorder: this.inputValidationErrorBorder, - history + history, + flexibleHeight })); this.regex = this._register(new RegexCheckbox({ diff --git a/src/vs/base/browser/ui/inputbox/inputBox.ts b/src/vs/base/browser/ui/inputbox/inputBox.ts index 947e36a2c778dd1faad6822f78a9e24a70404080..7b9a9cdb3d7c29728f226d8af04653c3d529171a 100644 --- a/src/vs/base/browser/ui/inputbox/inputBox.ts +++ b/src/vs/base/browser/ui/inputbox/inputBox.ts @@ -291,6 +291,9 @@ export class InputBox extends Widget { public set width(width: number) { this.input.style.width = width + 'px'; + if (this.mirror) { + this.mirror.style.width = width + 'px'; + } } public showMessage(message: IMessage, force?: boolean): void { diff --git a/src/vs/workbench/parts/search/browser/media/searchview.css b/src/vs/workbench/parts/search/browser/media/searchview.css index f7c854b53cdd5a52ed2779279d297fb151bf5f22..6e8ab36c5e6314a23b588516fb6d5abd9f73a4bb 100644 --- a/src/vs/workbench/parts/search/browser/media/searchview.css +++ b/src/vs/workbench/parts/search/browser/media/searchview.css @@ -29,9 +29,21 @@ margin-left: 17px; } -.search-view .search-widget .input-box, -.search-view .search-widget .input-box .monaco-inputbox { - height: 25px; +.search-view .search-widget .monaco-inputbox > .wrapper { + height: 100%; +} + +.search-view .search-widget .monaco-inputbox > .wrapper > .mirror { + max-height: 134px; +} + +.search-view .monaco-inputbox > .wrapper > textarea.input { + overflow: initial; + height: 26px; /* set initial height before measure */ +} + +.search-view .monaco-inputbox > .wrapper > textarea.input::-webkit-scrollbar { + display: none; } .search-view .search-widget .monaco-findInput { @@ -39,6 +51,10 @@ vertical-align: middle; } +.search-view .search-widget .monaco-findInput > .controls { + top: 4px; /* Adjust controls, search view input box is slighty taller than find widget due to measurement */ +} + .search-view .search-widget .replace-container { margin-top: 6px; position: relative; diff --git a/src/vs/workbench/parts/search/browser/searchWidget.ts b/src/vs/workbench/parts/search/browser/searchWidget.ts index 806ce9f553e4688bd929c4abae26940b2101b953..689933f925f6c2f080bfaf6ffff3efc6cb65eeae 100644 --- a/src/vs/workbench/parts/search/browser/searchWidget.ts +++ b/src/vs/workbench/parts/search/browser/searchWidget.ts @@ -281,7 +281,8 @@ export class SearchWidget extends Widget { 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 + history: options.searchHistory, + flexibleHeight: true }; let searchInputContainer = dom.append(parent, dom.$('.search-container.input-box')); @@ -329,7 +330,8 @@ export class SearchWidget extends Widget { 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 || [] + history: options.replaceHistory || [], + flexibleHeight: true }, this.contextKeyService)); this._register(attachInputBoxStyler(this.replaceInput, this.themeService)); this.onkeydown(this.replaceInput.inputElement, (keyboardEvent) => this.onReplaceInputKeyDown(keyboardEvent)); @@ -376,6 +378,7 @@ export class SearchWidget extends Widget { if (currentState !== newState) { this.replaceActive.set(newState); this._onReplaceStateChange.fire(newState); + this.replaceInput.layout(); } } @@ -429,6 +432,20 @@ export class SearchWidget extends Widget { } 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 onCaseSensitiveKeyDown(keyboardEvent: IKeyboardEvent) { @@ -466,6 +483,20 @@ export class SearchWidget extends Widget { 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) { diff --git a/src/vs/workbench/parts/search/common/queryBuilder.ts b/src/vs/workbench/parts/search/common/queryBuilder.ts index c19373824e47c386271e620c971504beafe8a70e..b1e24134c2bd389079b085fb906732cba473280f 100644 --- a/src/vs/workbench/parts/search/common/queryBuilder.ts +++ b/src/vs/workbench/parts/search/common/queryBuilder.ts @@ -67,10 +67,8 @@ export class QueryBuilder { ) { } text(contentPattern: IPatternInfo, folderResources?: uri[], options: ITextQueryBuilderOptions = {}): ITextQuery { - contentPattern.isCaseSensitive = this.isCaseSensitive(contentPattern); - contentPattern.isMultiline = this.isMultiline(contentPattern); + contentPattern = this.getContentPattern(contentPattern); const searchConfig = this.configurationService.getValue(); - contentPattern.wordSeparators = searchConfig.editor.wordSeparators; const fallbackToPCRE = folderResources && folderResources.some(folder => { const folderConfig = this.configurationService.getValue({ resource: folder }); @@ -91,6 +89,28 @@ export class QueryBuilder { }; } + /** + * Adjusts input pattern for config + */ + private getContentPattern(inputPattern: IPatternInfo): IPatternInfo { + const searchConfig = this.configurationService.getValue(); + + const newPattern = { + ...inputPattern, + wordSeparators: searchConfig.editor.wordSeparators + }; + + if (this.isCaseSensitive(inputPattern)) { + newPattern.isCaseSensitive = true; + } + + if (this.isMultiline(inputPattern)) { + newPattern.isMultiline = true; + } + + return newPattern; + } + file(folderResources: uri[] | undefined, options: IFileQueryBuilderOptions = {}): IFileQuery { const commonQuery = this.commonQuery(folderResources, options); return { @@ -165,6 +185,10 @@ export class QueryBuilder { return true; } + if (contentPattern.pattern.indexOf('\n') >= 0) { + return true; + } + return false; } diff --git a/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts b/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts index 2b15d42a8902857c6166cae13ee739da54525433..8f3aa59557cd3cb175976ee5fe668d92f4ce50d3 100644 --- a/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts +++ b/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts @@ -7,7 +7,7 @@ import * as cp from 'child_process'; import { EventEmitter } from 'events'; import * as path from 'path'; import { NodeStringDecoder, StringDecoder } from 'string_decoder'; -import { createRegExp, startsWith, startsWithUTF8BOM, stripUTF8BOM } from 'vs/base/common/strings'; +import { createRegExp, startsWith, startsWithUTF8BOM, stripUTF8BOM, escapeRegExpCharacters } from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; import { IExtendedExtensionSearchOptions, SearchError, SearchErrorCode, serializeSearchError } from 'vs/platform/search/common/search'; import * as vscode from 'vscode'; @@ -343,6 +343,11 @@ function getRgArgs(query: vscode.TextSearchQuery, options: vscode.TextSearchOpti pattern = '\\-\\-'; } + if (query.isMultiline && !query.isRegExp) { + query.pattern = escapeRegExpCharacters(query.pattern); + query.isRegExp = true; + } + if ((options).usePCRE2) { args.push('--pcre2');