]> git.proxmox.com Git - mirror_xterm.js.git/blob - src/addons/search/SearchHelper.ts
Fix browserify build and search addon (#804)
[mirror_xterm.js.git] / src / addons / search / SearchHelper.ts
1 /**
2 * @license MIT
3 */
4
5 // import { ITerminal } from '../../Interfaces';
6 // import { translateBufferLineToString } from '../../utils/BufferLine';
7
8 interface ISearchResult {
9 term: string;
10 col: number;
11 row: number;
12 }
13
14 /**
15 * A class that knows how to search the terminal and how to display the results.
16 */
17 export class SearchHelper {
18 constructor(private _terminal: any, private _translateBufferLineToString: any) {
19 // TODO: Search for multiple instances on 1 line
20 // TODO: Don't use the actual selection, instead use a "find selection" so multiple instances can be highlighted
21 // TODO: Highlight other instances in the viewport
22 // TODO: Support regex, case sensitivity, etc.
23 }
24
25 /**
26 * Find the next instance of the term, then scroll to and select it. If it
27 * doesn't exist, do nothing.
28 * @param term Tne search term.
29 * @return Whether a result was found.
30 */
31 public findNext(term: string): boolean {
32 if (!term || term.length === 0) {
33 return false;
34 }
35
36 let result: ISearchResult;
37
38 let startRow = this._terminal.buffer.ydisp;
39 if (this._terminal.selectionManager.selectionEnd) {
40 // Start from the selection end if there is a selection
41 startRow = this._terminal.selectionManager.selectionEnd[1];
42 }
43
44 // Search from ydisp + 1 to end
45 for (let y = startRow + 1; y < this._terminal.buffer.ybase + this._terminal.rows; y++) {
46 result = this._findInLine(term, y);
47 if (result) {
48 break;
49 }
50 }
51
52 // Search from the top to the current ydisp
53 if (!result) {
54 for (let y = 0; y < startRow; y++) {
55 result = this._findInLine(term, y);
56 if (result) {
57 break;
58 }
59 }
60 }
61
62 // Set selection and scroll if a result was found
63 return this._selectResult(result);
64 }
65
66 /**
67 * Find the previous instance of the term, then scroll to and select it. If it
68 * doesn't exist, do nothing.
69 * @param term Tne search term.
70 * @return Whether a result was found.
71 */
72 public findPrevious(term: string): boolean {
73 if (!term || term.length === 0) {
74 return false;
75 }
76
77 let result: ISearchResult;
78
79 let startRow = this._terminal.buffer.ydisp;
80 if (this._terminal.selectionManager.selectionStart) {
81 // Start from the selection end if there is a selection
82 startRow = this._terminal.selectionManager.selectionStart[1];
83 }
84
85 // Search from ydisp + 1 to end
86 for (let y = startRow - 1; y >= 0; y--) {
87 result = this._findInLine(term, y);
88 if (result) {
89 break;
90 }
91 }
92
93 // Search from the top to the current ydisp
94 if (!result) {
95 for (let y = this._terminal.buffer.ybase + this._terminal.rows - 1; y > startRow; y--) {
96 result = this._findInLine(term, y);
97 if (result) {
98 break;
99 }
100 }
101 }
102
103 // Set selection and scroll if a result was found
104 return this._selectResult(result);
105 }
106
107 /**
108 * Searches a line for a search term.
109 * @param term Tne search term.
110 * @param y The line to search.
111 * @return The search result if it was found.
112 */
113 private _findInLine(term: string, y: number): ISearchResult {
114 const bufferLine = this._terminal.buffer.lines.get(y);
115 const lowerStringLine = this._translateBufferLineToString(bufferLine, true).toLowerCase();
116 const lowerTerm = term.toLowerCase();
117 const searchIndex = lowerStringLine.indexOf(lowerTerm);
118 if (searchIndex >= 0) {
119 return {
120 term,
121 col: searchIndex,
122 row: y
123 };
124 }
125 }
126
127 /**
128 * Selects and scrolls to a result.
129 * @param result The result to select.
130 * @return Whethera result was selected.
131 */
132 private _selectResult(result: ISearchResult): boolean {
133 if (!result) {
134 return false;
135 }
136 this._terminal.selectionManager.setSelection(result.col, result.row, result.term.length);
137 this._terminal.scrollDisp(result.row - this._terminal.buffer.ydisp, false);
138 return true;
139 }
140 }