From 2c0f9bfc28cf9e0e7e7a8040eae73d759b304cb4 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 24 Jul 2024 18:44:14 -0700 Subject: [PATCH] terminal: cell returns empty for Kitty placeholder So we don't render the replacement char --- src/terminal/Terminal.zig | 6 +++++- src/terminal/kitty/graphics.zig | 1 + src/terminal/kitty/graphics_diacritics.zig | 3 +++ src/terminal/page.zig | 22 ++++++++++++++++++++-- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index c58377374..16b8a07b9 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -379,7 +379,11 @@ pub fn print(self: *Terminal, c: u21) !void { } } - log.debug("c={x} grapheme attach to left={}", .{ c, prev.left }); + log.debug("c={X} grapheme attach to left={} primary_cp={X}", .{ + c, + prev.left, + prev.cell.codepoint(), + }); self.screen.cursorMarkDirty(); try self.screen.appendGrapheme(prev.cell, c); return; diff --git a/src/terminal/kitty/graphics.zig b/src/terminal/kitty/graphics.zig index 0fa52fab0..14ab6babb 100644 --- a/src/terminal/kitty/graphics.zig +++ b/src/terminal/kitty/graphics.zig @@ -21,6 +21,7 @@ pub usingnamespace @import("graphics_exec.zig"); pub usingnamespace @import("graphics_image.zig"); pub usingnamespace @import("graphics_storage.zig"); pub const diacritics = @import("graphics_diacritics.zig"); +pub const placeholder = diacritics.placeholder; test { @import("std").testing.refAllDecls(@This()); diff --git a/src/terminal/kitty/graphics_diacritics.zig b/src/terminal/kitty/graphics_diacritics.zig index db587f407..92fb816eb 100644 --- a/src/terminal/kitty/graphics_diacritics.zig +++ b/src/terminal/kitty/graphics_diacritics.zig @@ -2,6 +2,9 @@ const std = @import("std"); const assert = std.debug.assert; const testing = std.testing; +/// Codepoint for the unicode placeholder character. +pub const placeholder: u21 = 0x10EEEE; + /// Get the row/col index for a diacritic codepoint. pub fn get(cp: u21) ?usize { return std.sort.binarySearch(u21, cp, diacritics, {}, (struct { diff --git a/src/terminal/page.zig b/src/terminal/page.zig index 677e3fb4a..457207782 100644 --- a/src/terminal/page.zig +++ b/src/terminal/page.zig @@ -8,6 +8,7 @@ const posix = std.posix; const fastmem = @import("../fastmem.zig"); const color = @import("color.zig"); const hyperlink = @import("hyperlink.zig"); +const kitty = @import("kitty.zig"); const sgr = @import("sgr.zig"); const style = @import("style.zig"); const size = @import("size.zig"); @@ -1673,11 +1674,18 @@ pub const Cell = packed struct(u64) { return @as(u64, @bitCast(self)) == 0; } + /// Returns true if this cell represents a cell with text to render. + /// + /// Cases this returns false: + /// - Cell text is blank + /// - Cell is styled but only with a background color and no text + /// - Cell has a unicode placeholder for Kitty graphics protocol pub fn hasText(self: Cell) bool { return switch (self.content_tag) { .codepoint, .codepoint_grapheme, - => self.content.codepoint != 0, + => self.content.codepoint != 0 and + self.content.codepoint != kitty.graphics.placeholder, .bg_color_palette, .bg_color_rgb, @@ -1709,7 +1717,8 @@ pub const Cell = packed struct(u64) { return self.style_id != style.default_id; } - /// Returns true if the cell has no text or styling. + /// Returns true if the cell has no text or styling. This also returns + /// true if the cell represents a Kitty graphics unicode placeholder. pub fn isEmpty(self: Cell) bool { return switch (self.content_tag) { // Textual cells are empty if they have no text and are narrow. @@ -2641,3 +2650,12 @@ test "Page verifyIntegrity zero cols" { page.verifyIntegrity(testing.allocator), ); } + +test "Cell isEmpty for kitty placeholder" { + var c: Cell = .{ + .content_tag = .codepoint_grapheme, + .content = .{ .codepoint = kitty.graphics.placeholder }, + }; + try testing.expectEqual(@as(u21, kitty.graphics.placeholder), c.codepoint()); + try testing.expect(c.isEmpty()); +}