Fixed issues around searching lines twice and considering a wrapped line both it's own line and part of the previous line.

This commit is contained in:
Alex Ross
2018-09-10 10:25:23 -07:00
parent 1460a34796
commit 54ed988fd1
3 changed files with 50 additions and 30 deletions
-22
View File
@@ -265,28 +265,6 @@ export class Buffer implements IBuffer {
return lineString.substring(startIndex, endIndex);
}
/**
* Translates a buffer line to a string, including subsequent lines if they are wraps.
* Wide characters will count as two columns in the resulting string. This
* function is useful for getting the actual text underneath the raw selection
* position.
* @param line The line being translated.
* @param trimRight Whether to trim whitespace to the right.
*/
public translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean): string {
let lineString = '';
let lineWrapsToNext: boolean;
do {
lineString += this.translateBufferLineToString(lineIndex, true);
lineIndex++;
const nextLine = this.lines.get(lineIndex);
lineWrapsToNext = nextLine ? this.lines.get(lineIndex).isWrapped : false;
} while (lineWrapsToNext);
return lineString;
}
public getWrappedRangeForLine(y: number): { first: number, last: number } {
let first = y;
let last = y;
+39 -6
View File
@@ -100,15 +100,20 @@ export class SearchHelper implements ISearchHelper {
}
/**
* Searches a line for a search term.
* @param term The search term.
* Searches a line for a search term. Takes the provided terminal line and searches the text line, which may contain
* subsequent terminal lines if the text is wrapped. If the provided line number is part of a wrapped text line that
* started on an earlier line then it is skipped since it will be properly searched when the terminal line that the
* text starts on is searched.
* @param term Tne search term.
* @param y The line to search.
* @param searchOptions Search options.
* @return The search result if it was found.
*/
protected _findInLine(term: string, y: number, searchOptions: ISearchOptions = {}): ISearchResult {
const lowerStringLine = this._terminal._core.buffer.translateBufferLineToStringWithWrap(y, true).toLowerCase();
const lowerTerm = term.toLowerCase();
if (this._terminal._core.buffer.lines.get(y).isWrapped) {
return;
}
const lowerStringLine = this.translateBufferLineToStringWithWrap(y, true).toLowerCase(); const lowerTerm = term.toLowerCase();
let searchIndex = -1;
if (searchOptions.regex) {
const searchRegex = RegExp(lowerTerm, 'g');
@@ -121,8 +126,14 @@ export class SearchHelper implements ISearchHelper {
searchIndex = lowerStringLine.indexOf(lowerTerm);
}
const line = this._terminal._core.buffer.lines.get(y);
if ((searchIndex >= 0) && (searchIndex < line.length)) {
if (searchIndex >= 0) {
// Adjust the row number and search index if needed since a "line" of text can span multiple rows
if (searchIndex >= this._terminal.cols) {
y += Math.floor(searchIndex / this._terminal.cols);
searchIndex = searchIndex % this._terminal.cols;
}
const line = this._terminal._core.buffer.lines.get(y);
for (let i = 0; i < searchIndex; i++) {
const charData = line.get(i);
// Adjust the searchIndex to normalize emoji into single chars
@@ -145,6 +156,28 @@ export class SearchHelper implements ISearchHelper {
}
}
/**
* Translates a buffer line to a string, including subsequent lines if they are wraps.
* Wide characters will count as two columns in the resulting string. This
* function is useful for getting the actual text underneath the raw selection
* position.
* @param line The line being translated.
* @param trimRight Whether to trim whitespace to the right.
*/
public translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean): string {
let lineString = '';
let lineWrapsToNext: boolean;
do {
lineString += this._terminal._core.buffer.translateBufferLineToString(lineIndex, true);
lineIndex++;
const nextLine = this._terminal._core.buffer.lines.get(lineIndex);
lineWrapsToNext = nextLine ? this._terminal._core.buffer.lines.get(lineIndex).isWrapped : false;
} while (lineWrapsToNext);
return lineString;
}
/**
* Selects and scrolls to a result.
* @param result The result to select.
+11 -2
View File
@@ -13,10 +13,19 @@ class MockTerminalPlain {}
class MockTerminal {
private _core: any;
<<<<<<< HEAD
public searchHelper: TestSearchHelper;
constructor(options: any) {
this._core = new (require('../../../lib/Terminal').Terminal)(options);
this.searchHelper = new TestSearchHelper(this as any);
=======
public searchHelper: ISearchHelper;
public cols: number;
constructor(options: any) {
this._core = new (require('../../../lib/Terminal').Terminal)(options);
this.searchHelper = new SearchHelper(this as any);
this.cols = options.cols;
>>>>>>> Fixed issues around searching lines twice and considering a wrapped line both it's own line and part of the previous line.
}
get core(): any {
return this._core;
@@ -66,8 +75,8 @@ describe('search addon', function(): void {
const hello3 = (term.searchHelper as any)._findInLine('Hello', 3);
expect(hello0).eql({col: 8, row: 0, term: 'Hello'});
expect(hello1).eql(undefined);
expect(hello2).eql(undefined);
expect(hello3).eql({col: 2, row: 3, term: 'Hello'});
expect(hello2).eql({col: 2, row: 3, term: 'Hello'});
expect(hello3).eql(undefined);
});
it('should respect search regex', function(): void {
search.apply(<any>MockTerminal);