Mostly emoji selection

Selection is not aware of characters that have a size greater than 1.

When the emoji is at the start of the selection it still doesn't work.

Fixes #1015
This commit is contained in:
Daniel Imms
2017-09-30 06:13:58 -04:00
parent 313d1e6fec
commit feb2b958a4
2 changed files with 72 additions and 13 deletions
+30 -8
View File
@@ -208,9 +208,19 @@ export class Buffer implements IBuffer {
public translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol: number = 0, endCol: number = null): string {
// Get full line
let lineString = '';
let widthAdjustedStartCol = startCol;
let widthAdjustedEndCol = endCol;
const line = this.lines.get(lineIndex);
if (!line) {
return '';
}
// Initialize column and index values. Column values represent the actual
// cell column, indexes represent the index in the string. Indexes are
// needed here because some chars are 0 characters long (eg. after wide
// chars) and some chars are longer than 1 characters long (eg. emojis).
let startIndex = startCol;
endCol = endCol || line.length;
let endIndex = endCol;
for (let i = 0; i < line.length; i++) {
const char = line[i];
lineString += char[CHAR_DATA_CHAR_INDEX];
@@ -218,29 +228,41 @@ export class Buffer implements IBuffer {
// column indexes
if (char[CHAR_DATA_WIDTH_INDEX] === 0) {
if (startCol >= i) {
widthAdjustedStartCol--;
startIndex -= char[CHAR_DATA_CHAR_INDEX].length;
}
if (endCol >= i) {
widthAdjustedEndCol--;
endIndex -= char[CHAR_DATA_CHAR_INDEX].length;
}
} else {
// Adjust the columns to take glyphs that are represented by multiple
// code points into account.
if (char[CHAR_DATA_CHAR_INDEX].length > 1) {
if (startCol >= i) {
startIndex += char[CHAR_DATA_CHAR_INDEX].length - 1;
}
if (endCol >= i) {
endIndex += char[CHAR_DATA_CHAR_INDEX].length - 1;
}
}
}
// TODO: startCol needs to be emoji-aware, currently each emoji code point is
// consuming addition space in the selection text
}
// Calculate the final end col by trimming whitespace on the right of the
// line if needed.
let finalEndCol = widthAdjustedEndCol || line.length;
if (trimRight) {
const rightWhitespaceIndex = lineString.search(/\s+$/);
if (rightWhitespaceIndex !== -1) {
finalEndCol = Math.min(finalEndCol, rightWhitespaceIndex);
endIndex = Math.min(endIndex, rightWhitespaceIndex);
}
// Return the empty string if only trimmed whitespace is selected
if (finalEndCol <= widthAdjustedStartCol) {
if (endIndex <= startIndex) {
return '';
}
}
return lineString.substring(widthAdjustedStartCol, finalEndCol);
return lineString.substring(startIndex, endIndex);
}
/**