Skip to content

Commit 693069d

Browse files
committed
Re-write of search addon (squashed)
1 parent ce095b3 commit 693069d

File tree

7 files changed

+1004
-527
lines changed

7 files changed

+1004
-527
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { Terminal } from '@xterm/xterm';
2+
export type LineCacheEntry = [
3+
/**
4+
* The string representation of a line (as opposed to the buffer cell representation).
5+
*/
6+
lineAsString: string,
7+
/**
8+
* The offsets where each line starts when the entry describes a wrapped line.
9+
*/
10+
lineOffsets: number[]
11+
];
12+
export function stringLengthToBufferSize(terminal: Terminal,row: number, offset: number): number {
13+
const line = terminal!.buffer.active.getLine(row);
14+
if (!line) {
15+
return 0;
16+
}
17+
for (let i = 0; i < offset; i++) {
18+
const cell = line.getCell(i);
19+
if (!cell) {
20+
break;
21+
}
22+
// Adjust the searchIndex to normalize emoji into single chars
23+
const char = cell.getChars();
24+
if (char.length > 1) {
25+
offset -= char.length - 1;
26+
}
27+
// Adjust the searchIndex for empty characters following wide unicode
28+
// chars (eg. CJK)
29+
const nextCell = line.getCell(i + 1);
30+
if (nextCell && nextCell.getWidth() === 0) {
31+
offset++;
32+
}
33+
}
34+
return offset;
35+
}
36+
37+
38+
export function bufferColsToStringOffset(terminal: Terminal,startRow: number, cols: number): number {
39+
let lineIndex = startRow;
40+
let offset = 0;
41+
let line = terminal.buffer.active.getLine(lineIndex);
42+
while (cols > 0 && line) {
43+
for (let i = 0; i < cols && i < terminal.cols; i++) {
44+
const cell = line.getCell(i);
45+
if (!cell) {
46+
break;
47+
}
48+
if (cell.getWidth()) {
49+
// Treat null characters as whitespace to align with the translateToString API
50+
offset += cell.getCode() === 0 ? 1 : cell.getChars().length;
51+
}
52+
}
53+
lineIndex++;
54+
line = terminal.buffer.active.getLine(lineIndex);
55+
if (line && !line.isWrapped) {
56+
break;
57+
}
58+
cols -= terminal.cols;
59+
}
60+
return offset;
61+
}
62+
63+
64+
/**
65+
* Translates a buffer line to a string, including subsequent lines if they are wraps.
66+
* Wide characters will count as two columns in the resulting string. This
67+
* function is useful for getting the actual text underneath the raw selection
68+
* position.
69+
* @param lineIndex The index of the line being translated.
70+
* @param trimRight Whether to trim whitespace to the right.
71+
*/
72+
export function translateBufferLineToStringWithWrap(terminal: Terminal,lineIndex: number, trimRight: boolean): LineCacheEntry {
73+
const strings = [];
74+
const lineOffsets = [0];
75+
let line = terminal.buffer.active.getLine(lineIndex);
76+
while (line) {
77+
const nextLine = terminal.buffer.active.getLine(lineIndex + 1);
78+
const lineWrapsToNext = nextLine ? nextLine.isWrapped : false;
79+
let string = line.translateToString(!lineWrapsToNext && trimRight);
80+
if (lineWrapsToNext && nextLine) {
81+
const lastCell = line.getCell(line.length - 1);
82+
const lastCellIsNull = lastCell && lastCell.getCode() === 0 && lastCell.getWidth() === 1;
83+
// a wide character wrapped to the next line
84+
if (lastCellIsNull && nextLine.getCell(0)?.getWidth() === 2) {
85+
string = string.slice(0, -1);
86+
}
87+
}
88+
strings.push(string);
89+
if (lineWrapsToNext) {
90+
lineOffsets.push(lineOffsets[lineOffsets.length - 1] + string.length);
91+
} else {
92+
break;
93+
}
94+
lineIndex++;
95+
line = nextLine;
96+
}
97+
return [strings.join(''), lineOffsets];
98+
}
99+

0 commit comments

Comments
 (0)