diff --git a/src/vs/base/browser/ui/findinput/findInput.ts b/src/vs/base/browser/ui/findinput/findInput.ts index 180e23447a46d..aff73ea473e9e 100644 --- a/src/vs/base/browser/ui/findinput/findInput.ts +++ b/src/vs/base/browser/ui/findinput/findInput.ts @@ -12,6 +12,7 @@ import keyboard = require('vs/base/browser/keyboardEvent'); import InputBox = require('vs/base/browser/ui/inputbox/inputBox'); import Checkbox = require('vs/base/browser/ui/checkbox/checkbox'); import ContextView = require('vs/base/browser/ui/contextview/contextview'); +import EditorBrowser = require('vs/editor/browser/editorBrowser'); var $ = Builder.$; @@ -32,6 +33,7 @@ export class FindInput { private placeholder:string; private validation:InputBox.IInputValidator; private label:string; + private editor:EditorBrowser.ICodeEditor; private listenersToRemove:{():void;}[]; private regex:Checkbox.Checkbox; @@ -42,8 +44,9 @@ export class FindInput { private inputNode:HTMLInputElement; private inputBox:InputBox.InputBox; - constructor(parent:HTMLElement, contextViewProvider: ContextView.IContextViewProvider, options?:IOptions) { + constructor(parent:HTMLElement, contextViewProvider: ContextView.IContextViewProvider, codeEditor:EditorBrowser.ICodeEditor, options?:IOptions) { this.contextViewProvider = contextViewProvider; + this.editor = codeEditor; this.onOptionChange = null; this.width = options.width || 100; this.placeholder = options.placeholder || ''; diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index ff27c0893bac7..36b5eec8528ac 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -83,6 +83,7 @@ export interface IView extends Lifecycle.IDisposable { getCodeEditorHelper(): ICodeEditorHelper; getCenteredRangeInViewport(): EditorCommon.IEditorRange; + getEditablerangeInViewport() : EditorCommon.IEditorRange; change(callback:(changeAccessor:IViewZoneChangeAccessor) => any): boolean; getWhitespaces(): EditorCommon.IEditorWhitespace[]; diff --git a/src/vs/editor/browser/view/viewImpl.ts b/src/vs/editor/browser/view/viewImpl.ts index a90f06c2e9ddb..34468e306d368 100644 --- a/src/vs/editor/browser/view/viewImpl.ts +++ b/src/vs/editor/browser/view/viewImpl.ts @@ -597,6 +597,11 @@ export class View extends ViewEventHandler implements EditorBrowser.IView, Lifec return viewModel.convertViewRangeToModelRange(currentCenteredViewRange); } + public getEditablerangeInViewport() : EditorCommon.IEditorRange { + var viewLineNumber = this.layoutProvider.getCenteredViewLineNumberInViewport(); + return new Range(this.viewLines._rendLineNumberStart, 1, this.viewLines._rendLineNumberStart + this.viewLines._lines.length, this.context.model.getLineMaxColumn(viewLineNumber)); + } + // public getLineInfoProvider():view.ILineInfoProvider { // return this.viewLines; // } @@ -957,4 +962,4 @@ class ViewContext implements EditorBrowser.IViewContext { this.addEventHandler = addEventHandler; this.removeEventHandler = removeEventHandler; } -} \ No newline at end of file +} diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index b204985b86c34..1059bf245b3ad 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -15,7 +15,7 @@ import Event from 'vs/base/common/event'; import {IDisposable} from 'vs/base/common/lifecycle'; import {TPromise} from 'vs/base/common/winjs.base'; import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; - +import EditorBrowser = require('vs/editor/browser/editorBrowser'); export type KeyCode = KeyCode; export type KeyMod = KeyMod; @@ -1452,6 +1452,18 @@ export interface ITokenizedModel extends ITextModel { * @param position The position at which to look for a bracket. */ matchBracket(position:IPosition, inaccurateResultAcceptable?:boolean): IMatchBracketResult; + + /** + * No mode supports allowed on this model because it is simply too large. + * (even tokenization would cause too much memory pressure) + */ + isTooLargeForHavingAMode(): boolean; + + /** + * Only basic mode supports allowed on this model because it is simply too large. + * (tokenization is allowed and other basic supports) + */ + isTooLargeForHavingARichMode(): boolean; } /** @@ -2965,7 +2977,7 @@ export interface ICommonCodeEditor extends IEditor { * Type the getModel() of IEditor. */ getModel(): IModel; - + getView(): EditorBrowser.IView; /** * Returns the current editor's configuration */ diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index e519fa173b1c6..613f766259328 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -15,7 +15,7 @@ import Event, {Emitter} from 'vs/base/common/event'; var __space = ' '.charCodeAt(0); var __tab = '\t'.charCodeAt(0); -var LIMIT_FIND_COUNT = 999; +var LIMIT_FIND_COUNT = Number.MAX_VALUE; var DEFAULT_PLATFORM_EOL = (Platform.isLinux || Platform.isMacintosh) ? '\n' : '\r\n'; export interface IIndentationFactors { @@ -991,4 +991,4 @@ export class TextModel extends OrderGuaranteeEventEmitter implements EditorCommo } while(m); return counter; } -} \ No newline at end of file +} diff --git a/src/vs/editor/contrib/find/browser/findModel.ts b/src/vs/editor/contrib/find/browser/findModel.ts index da7a3dcc83c3a..b4d925f87eb75 100644 --- a/src/vs/editor/contrib/find/browser/findModel.ts +++ b/src/vs/editor/contrib/find/browser/findModel.ts @@ -187,7 +187,7 @@ export class FindModelBoundToEditorModel extends Events.EventEmitter implements if (this.searchOnlyEditableRange) { searchRange = this.editor.getModel().getEditableRange(); } else { - searchRange = this.editor.getModel().getFullModelRange(); + searchRange = this.editor.getView().getEditablerangeInViewport(); } if (this.hasFindScope()) { @@ -214,7 +214,7 @@ export class FindModelBoundToEditorModel extends Events.EventEmitter implements this.findScopeDecorationId = decorations[0]; } - this.addMatchesDecorations(changeAccessor, this.editor.getModel().findMatches(this.searchString, this._getSearchRange(), this.isRegex, this.matchCase, this.wholeWord)); + this.addMatchesDecorations(changeAccessor, this._findMatches()); }); this.highlightedDecorationId = null; @@ -326,7 +326,6 @@ export class FindModelBoundToEditorModel extends Events.EventEmitter implements } } - private setSelectionToDecoration(decorationId:string): void { this.editor.changeDecorations((changeAccessor: EditorCommon.IModelDecorationsChangeAccessor) => { if (this.highlightedDecorationId !== null) { @@ -346,8 +345,10 @@ export class FindModelBoundToEditorModel extends Events.EventEmitter implements if (!this.isRegex) { return this.replaceString; } - var regexp = Strings.createRegExp(this.searchString, this.isRegex, this.matchCase, this.wholeWord); - return matchedString.replace(regexp, this.replaceString); + let regexp = Strings.createRegExp(this.searchString, this.isRegex, this.matchCase, this.wholeWord); + // Parse the replace string to support that \t or \n mean the right thing + let parsedReplaceString = parseReplaceString(this.replaceString); + return matchedString.replace(regexp, parsedReplaceString); } public replace(): void { @@ -379,6 +380,10 @@ export class FindModelBoundToEditorModel extends Events.EventEmitter implements } } + private _findMatches(limitResultCount?:number): EditorCommon.IEditorRange[] { + return this.editor.getModel().findMatches(this.searchString, this._getSearchRange(), this.isRegex, this.matchCase, this.wholeWord, limitResultCount); + } + public replaceAll(): void { if (this.decorations.length === 0) { return; @@ -387,7 +392,7 @@ export class FindModelBoundToEditorModel extends Events.EventEmitter implements let model = this.editor.getModel(); // Get all the ranges (even more than the highlighted ones) - let ranges = this.editor.getModel().findMatches(this.searchString, this._getSearchRange(), this.isRegex, this.matchCase, this.wholeWord, Number.MAX_VALUE); + let ranges = this._findMatches(Number.MAX_VALUE); // Remove all decorations this.editor.changeDecorations((changeAccessor:EditorCommon.IModelDecorationsChangeAccessor) => { @@ -474,3 +479,64 @@ export class FindModelBoundToEditorModel extends Events.EventEmitter implements } +const BACKSLASH_CHAR_CODE = '\\'.charCodeAt(0); +const n_CHAR_CODE = 'n'.charCodeAt(0); +const t_CHAR_CODE = 't'.charCodeAt(0); + +/** + * \n => LF + * \t => TAB + * \\ => \ + * everything else stays untouched + */ +export function parseReplaceString(input:string): string { + if (!input || input.length === 0) { + return input; + } + + let substrFrom = 0, result = ''; + for (let i = 0, len = input.length; i < len; i++) { + let chCode = input.charCodeAt(i); + + if (chCode === BACKSLASH_CHAR_CODE) { + + // move to next char + i++; + + if (i >= len) { + // string ends with a \ + break; + } + + let nextChCode = input.charCodeAt(i); + let replaceWithCharacter: string = null; + + switch (nextChCode) { + case BACKSLASH_CHAR_CODE: + // \\ => \ + replaceWithCharacter = '\\'; + break; + case n_CHAR_CODE: + // \n => LF + replaceWithCharacter = '\n'; + break; + case t_CHAR_CODE: + // \t => TAB + replaceWithCharacter = '\t'; + break; + } + + if (replaceWithCharacter) { + result += input.substring(substrFrom, i - 1) + replaceWithCharacter; + substrFrom = i + 1; + } + } + } + + if (substrFrom === 0) { + // no replacement occured + return input; + } + + return result + input.substring(substrFrom); +} diff --git a/src/vs/editor/contrib/find/browser/findWidget.ts b/src/vs/editor/contrib/find/browser/findWidget.ts index e19a017b02e8c..8bae30e774508 100644 --- a/src/vs/editor/contrib/find/browser/findWidget.ts +++ b/src/vs/editor/contrib/find/browser/findWidget.ts @@ -16,7 +16,7 @@ import InputBox = require('vs/base/browser/ui/inputbox/inputBox'); import Findinput = require('vs/base/browser/ui/findinput/findInput'); import EditorBrowser = require('vs/editor/browser/editorBrowser'); import EditorCommon = require('vs/editor/common/editorCommon'); -import FindModel = require('./findModel'); +import FindModel = require('vs/editor/contrib/find/common/findModel'); import Lifecycle = require('vs/base/common/lifecycle'); import {CommonKeybindings} from 'vs/base/common/keyCodes'; @@ -302,7 +302,7 @@ export class FindWidget extends EventEmitter.EventEmitter implements EditorBrows private _buildFindPart(): HTMLElement { // Find input - this._findInput = new Findinput.FindInput(null, this._contextViewProvider, { + this._findInput = new Findinput.FindInput(null, this._contextViewProvider, this._codeEditor, { width: FindWidget.FIND_INPUT_AREA_WIDTH, label: nls.localize('label.find', "Find"), placeholder: nls.localize('placeholder.find', "Find"), diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index 27d68d45479fe..e0d570d4b80dd 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -733,7 +733,7 @@ export class SearchViewlet extends Viewlet { } } }; - this.findInput = new FindInput(div.getHTMLElement(), this.contextViewService, options) + this.findInput = new FindInput(div.getHTMLElement(), this.contextViewService, null, options) .on(dom.EventType.KEY_UP, onKeyUp) .on(dom.EventType.KEY_DOWN, (e: KeyboardEvent) => { let keyboardEvent = new StandardKeyboardEvent(e); @@ -929,7 +929,7 @@ export class SearchViewlet extends Viewlet { this.viewModel.toggleHighlights(visible); } - // Open focussed element from results in case the editor area is otherwise empty + // Open focused element from results in case the editor area is otherwise empty if (visible && !this.editorService.getActiveEditorInput()) { let focus = this.tree.getFocus(); if (focus) { @@ -1457,4 +1457,4 @@ export class SearchViewlet extends Viewlet { } lifecycle.cAll(this.callOnModelChange); } -} \ No newline at end of file +}