5 import { ITerminal } from './Interfaces';
6 import { translateBufferLineToString } from './utils/BufferLine';
8 interface ISearchResult {
14 export class SearchHelper {
15 constructor(private _terminal: ITerminal) {
16 // TODO: Search for multiple instances on 1 line
17 // TODO: Don't use the actual selection, instead use a "find selection" so multiple instances can be highlighted
18 // TODO: Highlight other instances in the viewport
19 // TODO: Support regex, case sensitivity, etc.
23 * Find the next instance of the term, then scroll to and select it. If it
24 * doesn't exist, do nothing.
25 * @param term The term to search for.
26 * @return Whether a result was found.
28 public findNext(term: string): boolean {
29 if (!term || term.length === 0) {
33 let result: ISearchResult;
35 let startRow = this._terminal.ydisp;
36 if (this._terminal.selectionManager.selectionEnd) {
37 // Start from the selection end if there is a selection
38 startRow = this._terminal.selectionManager.selectionEnd[1];
41 // Search from ydisp + 1 to end
42 for (let y = startRow + 1; y < this._terminal.ybase + this._terminal.rows; y++) {
43 result = this._findInLine(term, y);
49 // Search from the top to the current ydisp
51 for (let y = 0; y < startRow; y++) {
52 result = this._findInLine(term, y);
59 // Set selection and scroll if a result was found
60 return this._selectResult(result);
64 * Find the previous instance of the term, then scroll to and select it. If it
65 * doesn't exist, do nothing.
66 * @param term The term to search for.
67 * @return Whether a result was found.
69 public findPrevious(term: string): boolean {
70 if (!term || term.length === 0) {
74 let result: ISearchResult;
76 let startRow = this._terminal.ydisp;
77 if (this._terminal.selectionManager.selectionStart) {
78 // Start from the selection end if there is a selection
79 startRow = this._terminal.selectionManager.selectionStart[1];
82 // Search from ydisp + 1 to end
83 for (let y = startRow - 1; y >= 0; y--) {
84 result = this._findInLine(term, y);
90 // Search from the top to the current ydisp
92 for (let y = this._terminal.ybase + this._terminal.rows - 1; y > startRow; y--) {
93 result = this._findInLine(term, y);
100 // Set selection and scroll if a result was found
101 return this._selectResult(result);
104 private _findInLine(term: string, y: number): ISearchResult {
105 const bufferLine = this._terminal.lines.get(y);
106 const lowerStringLine = translateBufferLineToString(bufferLine, true).toLowerCase();
107 const lowerTerm = term.toLowerCase();
108 const searchIndex = lowerStringLine.indexOf(lowerTerm);
109 if (searchIndex >= 0) {
118 private _selectResult(result: ISearchResult): boolean {
122 this._terminal.selectionManager.setSelection(result.col, result.row, result.term.length);
123 this._terminal.scrollDisp(result.row - this._terminal.ydisp, false);