mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge pull request #1664 from alexr00/alexr00/searchWord
Added search support for 'match whole word'
This commit is contained in:
+2
-2
@@ -102,7 +102,7 @@ function createTerminal(): void {
|
||||
e.preventDefault();
|
||||
const searchOptions = {
|
||||
regex: (document.getElementById('regex') as HTMLInputElement).checked,
|
||||
wholeWord: false,
|
||||
wholeWord: (document.getElementById('whole-word') as HTMLInputElement).checked,
|
||||
caseSensitive: (document.getElementById('case-sensitive') as HTMLInputElement).checked
|
||||
};
|
||||
term.findNext(actionElements.findNext.value, searchOptions);
|
||||
@@ -113,7 +113,7 @@ function createTerminal(): void {
|
||||
e.preventDefault();
|
||||
const searchOptions = {
|
||||
regex: (document.getElementById('regex') as HTMLInputElement).checked,
|
||||
wholeWord: false,
|
||||
wholeWord: (document.getElementById('whole-word') as HTMLInputElement).checked,
|
||||
caseSensitive: (document.getElementById('case-sensitive') as HTMLInputElement).checked
|
||||
};
|
||||
term.findPrevious(actionElements.findPrevious.value, searchOptions);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<label>Find previous <input id="find-previous"/></label>
|
||||
<label>Use regex<input type="checkbox" id="regex"/></label>
|
||||
<label>Case sensitive<input type="checkbox" id="case-sensitive"/></label>
|
||||
<label>Whole word<input type="checkbox" id="whole-word"/></label>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
import { ISearchHelper, ISearchAddonTerminal, ISearchOptions, ISearchResult } from './Interfaces';
|
||||
const nonWordCharacters = ' ~!@#$%^&*()_+`-=[]{}|\;:"\',./<>?';
|
||||
|
||||
/**
|
||||
* A class that knows how to search the terminal and how to display the results.
|
||||
@@ -99,6 +100,17 @@ export class SearchHelper implements ISearchHelper {
|
||||
return this._selectResult(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* A found substring is a whole word if it doesn't have an alphanumeric character directly adjacent to it.
|
||||
* @param searchIndex starting indext of the potential whole word substring
|
||||
* @param line entire string in which the potential whole word was found
|
||||
* @param term the substring that starts at searchIndex
|
||||
*/
|
||||
private _isWholeWord(searchIndex: number, line: string, term: string): boolean {
|
||||
return (((searchIndex === 0) || (nonWordCharacters.indexOf(line[searchIndex - 1]) !== -1)) &&
|
||||
(((searchIndex + term.length) === line.length) || (nonWordCharacters.indexOf(line[searchIndex + term.length]) !== -1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -136,6 +148,10 @@ export class SearchHelper implements ISearchHelper {
|
||||
y += Math.floor(searchIndex / this._terminal.cols);
|
||||
searchIndex = searchIndex % this._terminal.cols;
|
||||
}
|
||||
if (searchOptions.wholeWord && !this._isWholeWord(searchIndex, searchStringLine, term)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const line = this._terminal._core.buffer.lines.get(y);
|
||||
|
||||
for (let i = 0; i < searchIndex; i++) {
|
||||
|
||||
@@ -70,12 +70,12 @@ describe('search addon', () => {
|
||||
goodbye
|
||||
*/
|
||||
|
||||
const hello0 = (term.searchHelper as any)._findInLine('Hello', 0);
|
||||
const hello1 = (term.searchHelper as any)._findInLine('Hello', 1);
|
||||
const hello2 = (term.searchHelper as any)._findInLine('Hello', 2);
|
||||
const hello3 = (term.searchHelper as any)._findInLine('Hello', 3);
|
||||
const llo = (term.searchHelper as any)._findInLine('llo', 1);
|
||||
const goodbye = (term.searchHelper as any)._findInLine('goodbye', 2);
|
||||
const hello0 = term.searchHelper.findInLine('Hello', 0);
|
||||
const hello1 = term.searchHelper.findInLine('Hello', 1);
|
||||
const hello2 = term.searchHelper.findInLine('Hello', 2);
|
||||
const hello3 = term.searchHelper.findInLine('Hello', 3);
|
||||
const llo = term.searchHelper.findInLine('llo', 1);
|
||||
const goodbye = term.searchHelper.findInLine('goodbye', 2);
|
||||
expect(hello0).eql({col: 8, row: 0, term: 'Hello'});
|
||||
expect(hello1).eql(undefined);
|
||||
expect(hello2).eql({col: 2, row: 3, term: 'Hello'});
|
||||
@@ -130,9 +130,9 @@ describe('search addon', () => {
|
||||
wholeWord: false,
|
||||
caseSensitive: true
|
||||
};
|
||||
const hello0 = (term.searchHelper as any)._findInLine('Hello', 0, searchOptions);
|
||||
const hello1 = (term.searchHelper as any)._findInLine('Hello', 1, searchOptions);
|
||||
const hello2 = (term.searchHelper as any)._findInLine('Hello', 2, searchOptions);
|
||||
const hello0 = term.searchHelper.findInLine('Hello', 0, searchOptions);
|
||||
const hello1 = term.searchHelper.findInLine('Hello', 1, searchOptions);
|
||||
const hello2 = term.searchHelper.findInLine('Hello', 2, searchOptions);
|
||||
expect(hello0).eql({col: 0, row: 0, term: 'Hello'});
|
||||
expect(hello1).eql(undefined);
|
||||
expect(hello2).eql({col: 8, row: 2, term: 'Hello'});
|
||||
@@ -153,14 +153,96 @@ describe('search addon', () => {
|
||||
wholeWord: false,
|
||||
caseSensitive: true
|
||||
};
|
||||
const hello0 = (term.searchHelper as any)._findInLine('Hello', 0, searchOptions);
|
||||
const hello1 = (term.searchHelper as any)._findInLine('Hello$', 0, searchOptions);
|
||||
const hello2 = (term.searchHelper as any)._findInLine('Hello', 1, searchOptions);
|
||||
const hello3 = (term.searchHelper as any)._findInLine('Hello$', 1, searchOptions);
|
||||
const hello0 = term.searchHelper.findInLine('Hello', 0, searchOptions);
|
||||
const hello1 = term.searchHelper.findInLine('Hello$', 0, searchOptions);
|
||||
const hello2 = term.searchHelper.findInLine('Hello', 1, searchOptions);
|
||||
const hello3 = term.searchHelper.findInLine('Hello$', 1, searchOptions);
|
||||
expect(hello0).eql(undefined);
|
||||
expect(hello1).eql(undefined);
|
||||
expect(hello2).eql({col: 0, row: 1, term: 'Hello'});
|
||||
expect(hello3).eql({col: 5, row: 1, term: 'Hello'});
|
||||
});
|
||||
it('should respect whole-word search option', function(): void {
|
||||
search.apply(<any>MockTerminal);
|
||||
const term = new MockTerminal({cols: 20, rows: 5});
|
||||
term.core.write('Hello World\r\nWorld Hello\r\nWorldHelloWorld\r\nHelloWorld\r\nWorldHello');
|
||||
term.pushWriteData();
|
||||
const searchOptions = {
|
||||
regex: false,
|
||||
wholeWord: true,
|
||||
caseSensitive: false
|
||||
};
|
||||
const hello0 = term.searchHelper.findInLine('Hello', 0, searchOptions);
|
||||
const hello1 = term.searchHelper.findInLine('Hello', 1, searchOptions);
|
||||
const hello2 = term.searchHelper.findInLine('Hello', 2, searchOptions);
|
||||
const hello3 = term.searchHelper.findInLine('Hello', 3, searchOptions);
|
||||
const hello4 = term.searchHelper.findInLine('Hello', 4, searchOptions);
|
||||
expect(hello0).eql({col: 0, row: 0, term: 'Hello'});
|
||||
expect(hello1).eql({col: 6, row: 1, term: 'Hello'});
|
||||
expect(hello2).eql(undefined);
|
||||
expect(hello3).eql(undefined);
|
||||
expect(hello4).eql(undefined);
|
||||
});
|
||||
it('should respect whole-word + case sensitive search options', function(): void {
|
||||
search.apply(<any>MockTerminal);
|
||||
const term = new MockTerminal({cols: 20, rows: 5});
|
||||
term.core.write('Hello World\r\nHelloWorld');
|
||||
term.pushWriteData();
|
||||
const searchOptions = {
|
||||
regex: false,
|
||||
wholeWord: true,
|
||||
caseSensitive: true
|
||||
};
|
||||
const hello0 = term.searchHelper.findInLine('Hello', 0, searchOptions);
|
||||
const hello1 = term.searchHelper.findInLine('hello', 0, searchOptions);
|
||||
const hello2 = term.searchHelper.findInLine('Hello', 1, searchOptions);
|
||||
const hello3 = term.searchHelper.findInLine('hello', 1, searchOptions);
|
||||
expect(hello0).eql({col: 0, row: 0, term: 'Hello'});
|
||||
expect(hello1).eql(undefined);
|
||||
expect(hello2).eql(undefined);
|
||||
expect(hello3).eql(undefined);
|
||||
});
|
||||
it('should respect whole-word + regex search options', function(): void {
|
||||
search.apply(<any>MockTerminal);
|
||||
const term = new MockTerminal({cols: 20, rows: 5});
|
||||
term.core.write('Hello World Hello\r\nHelloWorldHello');
|
||||
term.pushWriteData();
|
||||
const searchOptions = {
|
||||
regex: true,
|
||||
wholeWord: true,
|
||||
caseSensitive: false
|
||||
};
|
||||
const hello0 = term.searchHelper.findInLine('Hello', 0, searchOptions);
|
||||
const hello1 = term.searchHelper.findInLine('Hello$', 0, searchOptions);
|
||||
const hello2 = term.searchHelper.findInLine('Hello', 1, searchOptions);
|
||||
const hello3 = term.searchHelper.findInLine('Hello$', 1, searchOptions);
|
||||
expect(hello0).eql({col: 0, row: 0, term: 'hello'});
|
||||
expect(hello1).eql({col: 12, row: 0, term: 'hello'});
|
||||
expect(hello2).eql(undefined);
|
||||
expect(hello3).eql(undefined);
|
||||
});
|
||||
it('should respect all search options', function(): void {
|
||||
search.apply(<any>MockTerminal);
|
||||
const term = new MockTerminal({cols: 20, rows: 5});
|
||||
term.core.write('Hello World Hello\r\nHelloWorldHello');
|
||||
term.pushWriteData();
|
||||
const searchOptions = {
|
||||
regex: true,
|
||||
wholeWord: true,
|
||||
caseSensitive: true
|
||||
};
|
||||
const hello0 = term.searchHelper.findInLine('Hello', 0, searchOptions);
|
||||
const hello1 = term.searchHelper.findInLine('Hello$', 0, searchOptions);
|
||||
const hello2 = term.searchHelper.findInLine('hello', 0, searchOptions);
|
||||
const hello3 = term.searchHelper.findInLine('hello$', 0, searchOptions);
|
||||
const hello4 = term.searchHelper.findInLine('hello', 1, searchOptions);
|
||||
const hello5 = term.searchHelper.findInLine('hello$', 1, searchOptions);
|
||||
expect(hello0).eql({col: 0, row: 0, term: 'Hello'});
|
||||
expect(hello1).eql({col: 12, row: 0, term: 'Hello'});
|
||||
expect(hello2).eql(undefined);
|
||||
expect(hello3).eql(undefined);
|
||||
expect(hello4).eql(undefined);
|
||||
expect(hello5).eql(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user