terminal option unicodeVersion

This commit is contained in:
Jörg Breitbart
2019-11-15 13:33:28 +01:00
parent 9c9aa68c23
commit c7ad4aa460
8 changed files with 31 additions and 21 deletions
+2 -1
View File
@@ -256,7 +256,8 @@ function initOptions(term: TerminalType): void {
fontWeightBold: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
logLevel: ['debug', 'info', 'warn', 'error', 'off'],
rendererType: ['dom', 'canvas'],
wordSeparator: null
wordSeparator: null,
unicodeVersion: ['6', '10']
};
const options = Object.keys((<any>term)._core.options);
const booleanOptions = [];
+9 -3
View File
@@ -7,7 +7,7 @@
import { IInputHandler, IInputHandlingTerminal } from './Types';
import { C0, C1 } from 'common/data/EscapeSequences';
import { CHARSETS, DEFAULT_CHARSET } from 'common/data/Charsets';
import { wcwidth, wcwidth10 } from 'common/CharWidth';
import { wcwidthV6, wcwidthV10 } from 'common/CharWidth';
import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser';
import { Disposable } from 'common/Lifecycle';
import { concat } from 'common/TypedArrayUtils';
@@ -127,6 +127,7 @@ export class InputHandler extends Disposable implements IInputHandler {
private _stringDecoder: StringToUtf32 = new StringToUtf32();
private _utf8Decoder: Utf8ToUtf32 = new Utf8ToUtf32();
private _workCell: CellData = new CellData();
private _wcwidth: (codepoint: number) => number;
private _onCursorMove = new EventEmitter<void>();
public get onCursorMove(): IEvent<void> { return this._onCursorMove.event; }
@@ -146,6 +147,12 @@ export class InputHandler extends Disposable implements IInputHandler {
private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser())
{
super();
this._wcwidth = this._optionsService.options.unicodeVersion === '10' ? wcwidthV10 : wcwidthV6;
this._optionsService.onOptionChange(option => {
if (option === 'unicodeVersion') {
this._wcwidth = this._optionsService.options.unicodeVersion === '10' ? wcwidthV10 : wcwidthV6;
}
});
this.register(this._parser);
@@ -393,8 +400,7 @@ export class InputHandler extends Disposable implements IInputHandler {
// calculate print space
// expensive call, therefore we save width in line buffer
chWidth = wcwidth(code);
chWidth = wcwidth10(code);
chWidth = this._wcwidth(code);
// get charset replacement character
// charset is only defined for ASCII, therefore we only
+2 -2
View File
@@ -7,7 +7,7 @@ import { assert, expect } from 'chai';
import { MockViewport, MockCompositionHelper, MockRenderer, TestTerminal } from './TestUtils.test';
import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
import { CellData } from 'common/buffer/CellData';
import { wcwidth } from 'common/CharWidth';
import { wcwidthV6 } from 'common/CharWidth';
import { IBufferService } from 'common/services/Services';
import { Linkifier } from 'browser/Linkifier';
import { MockLogService } from 'common/TestUtils.test';
@@ -762,7 +762,7 @@ describe('Terminal', () => {
for (let i = 0xDC00; i <= 0xDCFF; ++i) {
term.buffer.x = term.cols - 1;
term.wraparoundMode = false;
const width = wcwidth((0xD800 - 0xD800) * 0x400 + i - 0xDC00 + 0x10000);
const width = wcwidthV6((0xD800 - 0xD800) * 0x400 + i - 0xDC00 + 0x10000);
if (width !== 1) {
continue;
}
+2 -2
View File
@@ -5,7 +5,7 @@
import { ILinkifierEvent, ILinkMatcher, LinkMatcherHandler, ILinkMatcherOptions, ILinkifier, IMouseZoneManager, IMouseZone, IRegisteredLinkMatcher } from 'browser/Types';
import { IBufferStringIteratorResult } from 'common/buffer/Types';
import { getStringCellWidth } from 'common/CharWidth';
import { getStringCellWidthV6 } from 'common/CharWidth';
import { EventEmitter, IEvent } from 'common/EventEmitter';
import { ILogService, IBufferService } from 'common/services/Services';
@@ -278,7 +278,7 @@ export class Linkifier implements ILinkifier {
return;
}
const width = getStringCellWidth(uri);
const width = getStringCellWidthV6(uri); // FIXME: apply options.unicodeVersion
const x1 = x % this._bufferService.cols;
const y1 = y + Math.floor(x / this._bufferService.cols);
let x2 = (x1 + width) % this._bufferService.cols;
+2 -2
View File
@@ -4,7 +4,7 @@
*/
import { assert } from 'chai';
import { wcwidth } from 'common/CharWidth';
import { wcwidthV6 } from 'common/CharWidth';
it('wcwidth should match all values from the old implementation', function(): void {
// old implementation
@@ -177,6 +177,6 @@ it('wcwidth should match all values from the old implementation', function(): vo
// test full BMP range old vs new implmenetation
for (let i = 0; i < 65536; ++i) {
assert.equal(wcwidth(i), wcwidthOld(i), `mismatch for i: ${i}`);
assert.equal(wcwidthV6(i), wcwidthOld(i), `mismatch for i: ${i}`);
}
});
+10 -10
View File
@@ -5,7 +5,7 @@
import { fill } from 'common/TypedArrayUtils';
export const wcwidth = (function(opts: {nul: number, control: number}): (ucs: number) => number {
export const wcwidthV6 = (function(opts: {nul: number, control: number}): (ucs: number) => number {
// extracted from https://www.cl.cam.ac.uk/%7Emgk25/ucs/wcwidth.c
// combining characters
const COMBINING_BMP = [
@@ -141,7 +141,7 @@ export const wcwidth = (function(opts: {nul: number, control: number}): (ucs: nu
/**
* Get the terminal cell width for a string.
*/
export function getStringCellWidth(s: string): number {
export function getStringCellWidthV6(s: string): number {
let result = 0;
const length = s.length;
for (let i = 0; i < length; ++i) {
@@ -154,7 +154,7 @@ export function getStringCellWidth(s: string): number {
// and therefore always should contain the second part
// for any other string we still have to handle it somehow:
// simply treat the lonely surrogate first as a single char (UCS-2 behavior)
return result + wcwidth(code);
return result + wcwidthV6(code);
}
const second = s.charCodeAt(i);
// convert surrogate pair to high codepoint only for valid second part (UTF-16)
@@ -162,10 +162,10 @@ export function getStringCellWidth(s: string): number {
if (0xDC00 <= second && second <= 0xDFFF) {
code = (code - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
} else {
result += wcwidth(second);
result += wcwidthV6(second);
}
}
result += wcwidth(code);
result += wcwidthV6(code);
}
return result;
}
@@ -377,7 +377,7 @@ for (let r = 0; r < WIDE_BMP.length; ++r) {
fill(TABLE, 2, WIDE_BMP[r][0], WIDE_BMP[r][1] + 1);
}
export function wcwidth10(num: number): number {
export function wcwidthV10(num: number): number {
if (num < 32) {
return 0;
}
@@ -390,7 +390,7 @@ export function wcwidth10(num: number): number {
return wcwidthHigh(num);
};
export function getStringCellWidth10(s: string): number {
export function getStringCellWidthV10(s: string): number {
let result = 0;
const length = s.length;
for (let i = 0; i < length; ++i) {
@@ -403,7 +403,7 @@ export function getStringCellWidth10(s: string): number {
// and therefore always should contain the second part
// for any other string we still have to handle it somehow:
// simply treat the lonely surrogate first as a single char (UCS-2 behavior)
return result + wcwidth10(code);
return result + wcwidthV10(code);
}
const second = s.charCodeAt(i);
// convert surrogate pair to high codepoint only for valid second part (UTF-16)
@@ -411,10 +411,10 @@ export function getStringCellWidth10(s: string): number {
if (0xDC00 <= second && second <= 0xDFFF) {
code = (code - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
} else {
result += wcwidth10(second);
result += wcwidthV10(second);
}
}
result += wcwidth10(code);
result += wcwidthV10(code);
}
return result;
}
+2 -1
View File
@@ -50,7 +50,8 @@ export const DEFAULT_OPTIONS: ITerminalOptions = Object.freeze({
screenKeys: false,
cancelEvents: false,
useFlowControl: false,
wordSeparator: ' ()[]{}\',:;"'
wordSeparator: ' ()[]{}\',:;"',
unicodeVersion: '6'
});
/**
+2
View File
@@ -212,6 +212,7 @@ export interface IPartialTerminalOptions {
scrollSensitivity?: number;
tabStopWidth?: number;
theme?: ITheme;
unicodeVersion?: '6' | '10';
windowsMode?: boolean;
wordSeparator?: string;
}
@@ -244,6 +245,7 @@ export interface ITerminalOptions {
scrollSensitivity: number;
tabStopWidth: number;
theme: ITheme;
unicodeVersion: '6' | '10';
windowsMode: boolean;
wordSeparator: string;