mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
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:
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user