New unicode-graphemes addon.

Handle grapheme cluster lookup as well as wcwidth.
This is based on Unicode 15, and could replace the unicode11 addon.
This commit is contained in:
Per Bothner
2023-05-16 18:31:31 -07:00
parent 7a7f4f0add
commit 2f7fe1189c
28 changed files with 1055 additions and 49 deletions
+12 -2
View File
@@ -294,6 +294,11 @@ export interface IOscLinkService {
getLinkData(linkId: number): IOscLinkData | undefined;
}
/** Width and Grapheme_Cluster_Break properties of a character. */
export type UnicodeCharProperties = number;
export const UnicodeInitialProperties: UnicodeCharProperties = 0; // UNEEDED?
export type UnicodeCharWidth = 0 | 1 | 2;
export const IUnicodeService = createDecorator<IUnicodeService>('UnicodeService');
export interface IUnicodeService {
serviceBrand: undefined;
@@ -309,13 +314,18 @@ export interface IUnicodeService {
/**
* Unicode version dependent
*/
wcwidth(codepoint: number): number;
wcwidth(codepoint: number): UnicodeCharWidth;
getStringCellWidth(s: string): number;
/** Return character width, character type (for grapheme clustering).
* If preceding!=0, it is return code from previous character;
* in that case result specifies if characters should be joined. */
charProperties(codepoint: number, preceding: UnicodeCharProperties): UnicodeCharProperties;
}
export interface IUnicodeVersionProvider {
readonly version: string;
wcwidth(ucs: number): 0 | 1 | 2;
wcwidth(ucs: number): UnicodeCharWidth;
charProperties(codepoint: number, preceding: UnicodeCharProperties): UnicodeCharProperties;
}
export const IDecorationService = createDecorator<IDecorationService>('DecorationService');
@@ -12,6 +12,9 @@ class DummyProvider implements IUnicodeVersionProvider {
public wcwidth(n: number): 0 | 1 | 2 {
return 2;
}
charProperties(codepoint: number): number {
return UnicodeService.createPropertyValue(0, this.wcwidth(codepoint));
}
}
describe('unicode provider', () => {
+19 -2
View File
@@ -2,7 +2,7 @@
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IUnicodeService, IUnicodeVersionProvider } from 'common/services/Services';
import { IUnicodeService, IUnicodeVersionProvider, UnicodeCharProperties, UnicodeCharWidth } from 'common/services/Services';
import { EventEmitter, IEvent } from 'common/EventEmitter';
import { UnicodeV6 } from 'common/input/UnicodeV6';
@@ -16,6 +16,19 @@ export class UnicodeService implements IUnicodeService {
private readonly _onChange = new EventEmitter<string>();
public readonly onChange = this._onChange.event;
public static extractShouldJoin(value: UnicodeCharProperties): boolean {
return (value & 1) !== 0;
}
public static extractWidth(value: UnicodeCharProperties): UnicodeCharWidth {
return ((value >> 1) & 0x3) as UnicodeCharWidth;
}
public static extractCharKind(value: UnicodeCharProperties): number {
return value >> 3;
}
public static createPropertyValue(state: number, width: number, shouldJoin: boolean = false): UnicodeCharProperties {
return ((state & 0xffffff) << 3) | ((width & 3) << 1) | (shouldJoin?1:0);
}
constructor() {
const defaultProvider = new UnicodeV6();
this.register(defaultProvider);
@@ -51,7 +64,7 @@ export class UnicodeService implements IUnicodeService {
/**
* Unicode version dependent interface.
*/
public wcwidth(num: number): number {
public wcwidth(num: number): UnicodeCharWidth {
return this._activeProvider.wcwidth(num);
}
@@ -83,4 +96,8 @@ export class UnicodeService implements IUnicodeService {
}
return result;
}
charProperties(codepoint: number, preceding: UnicodeCharProperties): UnicodeCharProperties {
return this._activeProvider.charProperties(codepoint, preceding);
}
}