diff --git a/packages/core/src/renderer.ts b/packages/core/src/renderer.ts index 54ab0dacd..6fa18328c 100644 --- a/packages/core/src/renderer.ts +++ b/packages/core/src/renderer.ts @@ -784,7 +784,7 @@ export class CliRenderer extends EventEmitter implements RenderContext { public get widthMethod(): WidthMethod { const caps = this.capabilities - return caps?.unicode === "wcwidth" ? "wcwidth" : "unicode" + return caps?.unicode === 0 ? "wcwidth" : caps?.unicode === 2 ? "no_zwj" : "unicode" } private writeOut(chunk: any, encoding?: any, callback?: any): boolean { diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index f3a2b72c0..65cd32afd 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -54,7 +54,7 @@ export enum TargetChannel { Both = 3, } -export type WidthMethod = "wcwidth" | "unicode" +export type WidthMethod = "wcwidth" | "unicode" | "no_zwj" export interface RendererEvents { resize: (width: number, height: number) => void diff --git a/packages/core/src/zig.ts b/packages/core/src/zig.ts index e86c2cbcc..daeed726c 100644 --- a/packages/core/src/zig.ts +++ b/packages/core/src/zig.ts @@ -99,6 +99,7 @@ registerEnvVar({ const CURSOR_STYLE_TO_ID = { block: 0, line: 1, underline: 2, default: 3 } as const const CURSOR_ID_TO_STYLE = ["block", "line", "underline", "default"] as const const MOUSE_STYLE_TO_ID = { default: 0, pointer: 1, text: 2, crosshair: 3, move: 4, "not-allowed": 5 } as const +const WIDTH_METHOD_TO_CODE = { wcwidth: 0, unicode: 1, no_zwj: 2 } as const // Global singleton state for FFI tracing to prevent duplicate exit handlers let globalTraceSymbols: Record | null = null @@ -2422,7 +2423,7 @@ class FFIRenderLib implements RenderLib { console.error(new Error(`Invalid dimensions for OptimizedBuffer: ${width}x${height}`).stack) } - const widthMethodCode = widthMethod === "wcwidth" ? 0 : 1 + const widthMethodCode = WIDTH_METHOD_TO_CODE[widthMethod] const idToUse = id || "unnamed buffer" const idBytes = this.encoder.encode(idToUse) const bufferPtr = this.opentui.symbols.createOptimizedBuffer( @@ -2592,7 +2593,7 @@ class FFIRenderLib implements RenderLib { // TextBuffer methods public createTextBuffer(widthMethod: WidthMethod): TextBuffer { - const widthMethodCode = widthMethod === "wcwidth" ? 0 : 1 + const widthMethodCode = WIDTH_METHOD_TO_CODE[widthMethod] const bufferPtr = this.opentui.symbols.createTextBuffer(widthMethodCode) if (!bufferPtr) { throw new Error(`Failed to create TextBuffer`) @@ -3176,7 +3177,7 @@ class FFIRenderLib implements RenderLib { // EditBuffer implementations public createEditBuffer(widthMethod: WidthMethod): Pointer { - const widthMethodCode = widthMethod === "wcwidth" ? 0 : 1 + const widthMethodCode = WIDTH_METHOD_TO_CODE[widthMethod] const bufferPtr = this.opentui.symbols.createEditBuffer(widthMethodCode) if (!bufferPtr) { throw new Error("Failed to create EditBuffer") @@ -3641,7 +3642,7 @@ class FFIRenderLib implements RenderLib { widthMethod: WidthMethod, ): { ptr: Pointer; data: Array<{ width: number; char: number }> } | null { const textBytes = this.encoder.encode(text) - const widthMethodCode = widthMethod === "wcwidth" ? 0 : 1 + const widthMethodCode = WIDTH_METHOD_TO_CODE[widthMethod] const outPtrBuffer = new ArrayBuffer(8) // Pointer size const outLenBuffer = new ArrayBuffer(8) // usize diff --git a/packages/core/src/zig/lib.zig b/packages/core/src/zig/lib.zig index 8c69295b1..d0c48f101 100644 --- a/packages/core/src/zig/lib.zig +++ b/packages/core/src/zig/lib.zig @@ -276,7 +276,7 @@ export fn createOptimizedBuffer(width: u32, height: u32, respectAlpha: bool, wid const pool = gp.initGlobalPool(globalArena); const link_pool = link.initGlobalLinkPool(globalArena); - const wMethod: utf8.WidthMethod = if (widthMethod == 0) .wcwidth else .unicode; + const wMethod: utf8.WidthMethod = std.meta.intToEnum(utf8.WidthMethod, widthMethod) catch .unicode; const id = idPtr[0..idLen]; return buffer.OptimizedBuffer.init(globalAllocator, width, height, .{ @@ -343,7 +343,7 @@ export fn getTerminalCapabilities(rendererPtr: *renderer.CliRenderer, capsPtr: * .kitty_keyboard = caps.kitty_keyboard, .kitty_graphics = caps.kitty_graphics, .rgb = caps.rgb, - .unicode = if (caps.unicode == .wcwidth) 0 else 1, + .unicode = @intFromEnum(caps.unicode), .sgr_pixels = caps.sgr_pixels, .color_scheme_updates = caps.color_scheme_updates, .explicit_width = caps.explicit_width, @@ -798,7 +798,7 @@ export fn writeOut(rendererPtr: *renderer.CliRenderer, dataPtr: [*]const u8, dat export fn createTextBuffer(widthMethod: u8) ?*text_buffer.UnifiedTextBuffer { const pool = gp.initGlobalPool(globalArena); const link_pool = link.initGlobalLinkPool(globalArena); - const wMethod: utf8.WidthMethod = if (widthMethod == 0) .wcwidth else .unicode; + const wMethod: utf8.WidthMethod = std.meta.intToEnum(utf8.WidthMethod, widthMethod) catch .unicode; return text_buffer.UnifiedTextBuffer.init(globalAllocator, pool, link_pool, wMethod) catch { return null; @@ -1057,7 +1057,7 @@ export fn textBufferViewMeasureForDimensions(view: *text_buffer_view.UnifiedText export fn createEditBuffer(widthMethod: u8) ?*edit_buffer_mod.EditBuffer { const pool = gp.initGlobalPool(globalArena); const link_pool = link.initGlobalLinkPool(globalArena); - const wMethod: utf8.WidthMethod = if (widthMethod == 0) .wcwidth else .unicode; + const wMethod: utf8.WidthMethod = std.meta.intToEnum(utf8.WidthMethod, widthMethod) catch .unicode; return edit_buffer_mod.EditBuffer.init( globalAllocator, @@ -1702,7 +1702,7 @@ export fn encodeUnicode( ) bool { const text = textPtr[0..textLen]; const pool = gp.initGlobalPool(globalArena); - const wMethod: utf8.WidthMethod = if (widthMethod == 0) .wcwidth else .unicode; + const wMethod: utf8.WidthMethod = std.meta.intToEnum(utf8.WidthMethod, widthMethod) catch .unicode; // Check if ASCII only for optimization const is_ascii_only = utf8.isAsciiOnly(text);