From 4a9e36481fc682d9e21bedef81e06a8335246de3 Mon Sep 17 00:00:00 2001 From: Julian Hurst Date: Thu, 20 Mar 2025 11:19:35 +0100 Subject: Update comment --- tui/widget/widget.ha | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tui/widget/widget.ha b/tui/widget/widget.ha index 6c7ec7b..05ade80 100644 --- a/tui/widget/widget.ha +++ b/tui/widget/widget.ha @@ -198,7 +198,7 @@ export fn print(w: *widget) void = { w.state.clear = false; }; -// Applies styling (style) to the given string. +// Applies styling (style) to the given string slice. fn applystyles(st: (*style | void), s: []str) []str = { return match (st) { case let st: *style => -- cgit v1.2.3 From 5d8a0a6ce5dbb12963323f97220767fcf7c08b5c Mon Sep 17 00:00:00 2001 From: Julian Hurst Date: Thu, 20 Mar 2025 11:24:13 +0100 Subject: Add initial wide-character support Adds support for the emoticon, hiragana, katakana and CJK unicode blocks. --- .gitignore | 1 + cmd/runewidth.ha | 10 ++++++++++ tests/runewidth.ha | 9 +++++++++ tui/widget/widget.ha | 4 ++-- tui/width.ha | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 cmd/runewidth.ha create mode 100644 tests/runewidth.ha create mode 100644 tui/width.ha diff --git a/.gitignore b/.gitignore index 5f9fd69..2b08464 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /list_nostyle /scrolllist /il +/runewidth diff --git a/cmd/runewidth.ha b/cmd/runewidth.ha new file mode 100644 index 0000000..2e288e9 --- /dev/null +++ b/cmd/runewidth.ha @@ -0,0 +1,10 @@ +use fmt; +use tui; + +export fn main() void = { + fmt::println(tui::runewidth('f'))!; + fmt::println(tui::runewidth('ๅคง'))!; + fmt::println(tui::runewidth('ใ'))!; + fmt::println(tui::runewidth('๐Ÿ˜€'))!; + fmt::println(tui::strwidth("๐Ÿ˜€ใๅคงf"))!; +}; diff --git a/tests/runewidth.ha b/tests/runewidth.ha new file mode 100644 index 0000000..5e570a5 --- /dev/null +++ b/tests/runewidth.ha @@ -0,0 +1,9 @@ +use tui; + +@test +fn runewidth() void = { + assert(tui::runewidth('f') == 1); + assert(tui::runewidth('ๅคง') == 2); + assert(tui::runewidth('ใ') == 2); + assert(tui::runewidth('๐Ÿ˜€') == 2); +}; diff --git a/tui/widget/widget.ha b/tui/widget/widget.ha index 05ade80..7c82dfa 100644 --- a/tui/widget/widget.ha +++ b/tui/widget/widget.ha @@ -234,11 +234,11 @@ fn truncate_to_size(w: *widget) []str = { const line = w.buf.lines[i]; let item = match (w.sz) { case let sz: tty::ttysize => - const s = if (len(line) > sz.columns) strings::sub(line, 0z, sz.columns) else line; + const s = if (tui::strwidth(line) > sz.columns) strings::sub(line, 0z, sz.columns) else line; yield strings::rpad(s, ' ', sz.columns); case void => const wsz = tty::winsize(w.state.out)!; - const s = if (len(line) > wsz.columns) strings::sub(line, 0z, wsz.columns) else line; + const s = if (tui::strwidth(line) > wsz.columns) strings::sub(line, 0z, wsz.columns) else line; yield strings::dup(s); }; append(lines, item); diff --git a/tui/width.ha b/tui/width.ha new file mode 100644 index 0000000..6f9631c --- /dev/null +++ b/tui/width.ha @@ -0,0 +1,32 @@ +use strings; + +export fn runewidth(r: rune) uint = { + let ru = r: u32; + // emoticons: https://en.wikipedia.org/wiki/Emoticons_(Unicode_block) + if (ru >= '\U0001F600' && ru <= '\U0001F64F') { + return 2; + }; + // hiragana: https://en.wikipedia.org/wiki/Hiragana_%28Unicode_block%29 + if (ru >= '\U00003040' && ru <= '\U0000309F') { + return 2; + }; + // katakana: https://en.wikipedia.org/wiki/Katakana_(Unicode_block) + if (ru >= '\U000030A0' && ru <= '\U000030FF') { + return 2; + }; + // CJK: https://en.wikipedia.org/wiki/CJK_Unified_Ideographs_(Unicode_block) + if (ru >= '\U00004E00' && ru <= '\U00009FFF') { + return 2; + }; + return 1; +}; + +export fn strwidth(s: str) uint = { + const runes = strings::torunes(s); + defer free(runes); + let sum = 0u; + for (let r .. runes) { + sum += runewidth(r); + }; + return sum; +}; -- cgit v1.2.3 From 6e8a2af6bd47fd05e6b22937c5da7397549e7cbb Mon Sep 17 00:00:00 2001 From: Julian Hurst Date: Thu, 20 Mar 2025 11:30:58 +0100 Subject: Add tests for width and rm cmd/runewidth.ha --- cmd/runewidth.ha | 10 ---------- tests/strwidth.ha | 6 ++++++ 2 files changed, 6 insertions(+), 10 deletions(-) delete mode 100644 cmd/runewidth.ha create mode 100644 tests/strwidth.ha diff --git a/cmd/runewidth.ha b/cmd/runewidth.ha deleted file mode 100644 index 2e288e9..0000000 --- a/cmd/runewidth.ha +++ /dev/null @@ -1,10 +0,0 @@ -use fmt; -use tui; - -export fn main() void = { - fmt::println(tui::runewidth('f'))!; - fmt::println(tui::runewidth('ๅคง'))!; - fmt::println(tui::runewidth('ใ'))!; - fmt::println(tui::runewidth('๐Ÿ˜€'))!; - fmt::println(tui::strwidth("๐Ÿ˜€ใๅคงf"))!; -}; diff --git a/tests/strwidth.ha b/tests/strwidth.ha new file mode 100644 index 0000000..e3863d6 --- /dev/null +++ b/tests/strwidth.ha @@ -0,0 +1,6 @@ +use tui; + +@test +fn strwidth() void = { + assert(tui::strwidth("ๅคงใ๐Ÿ˜€f") == 7); +}; -- cgit v1.2.3