From 5d897901211330c16025aaf16eee0c2a1b715419 Mon Sep 17 00:00:00 2001 From: Joshua Reusch Date: Sat, 14 Sep 2024 20:53:13 +0200 Subject: [PATCH] ffi string_fold on js for performance --- bench/fstw.mjs | 2 +- bench/sw.mjs | 7 ++++--- gleam.toml | 2 +- src/string_width.gleam | 20 +++++++++++++++----- src/string_width_ffi.mjs | 7 +++++++ 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/bench/fstw.mjs b/bench/fstw.mjs index b01ba46..dbe504e 100644 --- a/bench/fstw.mjs +++ b/bench/fstw.mjs @@ -1,4 +1,4 @@ -import _string_width from './node_modules/fast-string-truncated-width/dist/index.js' +import _string_width from '../node_modules/fast-string-truncated-width/dist/index.js' const string_width = (input) => _string_width(input, {limit:Infinity, ellipsis:""}).width let sum = 0; diff --git a/bench/sw.mjs b/bench/sw.mjs index de3a454..0672867 100644 --- a/bench/sw.mjs +++ b/bench/sw.mjs @@ -1,8 +1,9 @@ -import { line as string_width } from './build/dev/javascript/string_width/string_width.mjs' -import { toList } from './build/dev/javascript/string_width/gleam.mjs' +import { line as string_width, HandleGraphemeClusters } from '../build/dev/javascript/string_width/string_width.mjs' +import { toList } from '../build/dev/javascript/string_width/gleam.mjs' let sum = 0; +let options = toList([new HandleGraphemeClusters()]); for(let i = 0; i < 10000; ++i) { - sum += string_width("\x1b[1;95m· \x1b[0m\x1b[K\x1b[33mdeno\x1b[0m\x1b[K, \x1b[33mtypescript\x1b[0m\x1b[K, \x1b[33mts\x1b[0m\x1b[K", toList([])) + sum += string_width("\x1b[1;95m· \x1b[0m\x1b[K\x1b[33mdeno\x1b[0m\x1b[K, \x1b[33mtypescript\x1b[0m\x1b[K, \x1b[33mts\x1b[0m\x1b[K", options) } console.log(sum) diff --git a/gleam.toml b/gleam.toml index bebb538..2579409 100644 --- a/gleam.toml +++ b/gleam.toml @@ -1,5 +1,5 @@ name = "string_width" -version = "2.0.2" +version = "2.0.3" description = "Estimate the dimensions of a string when printed in the terminal." licences = ["BSD-3-Clause"] diff --git a/src/string_width.gleam b/src/string_width.gleam index 6d702ce..03f5fa8 100644 --- a/src/string_width.gleam +++ b/src/string_width.gleam @@ -121,12 +121,22 @@ pub fn dimensions(str: String, options: List(Option)) -> #(Int, Int) { } fn graphemes_width(options: Options, str: String, width: Int) { + use width, grapheme <- string_fold(str, width) + width + do_grapheme_cluster(options, grapheme) + // case string.pop_grapheme(str) { + // Ok(#(grapheme, str)) -> { + // let grapheme_width = do_grapheme_cluster(options, grapheme) + // graphemes_width(options, str, width + grapheme_width) + // } + // Error(Nil) -> width + // } +} + +@external(javascript, "./string_width_ffi.mjs", "string_fold") +fn string_fold(str: String, state: a, fun: fn(a, String) -> a) -> a { case string.pop_grapheme(str) { - Ok(#(grapheme, str)) -> { - let grapheme_width = do_grapheme_cluster(options, grapheme) - graphemes_width(options, str, width + grapheme_width) - } - Error(Nil) -> width + Ok(#(grapheme, str)) -> string_fold(str, fun(state, grapheme), fun) + Error(Nil) -> state } } diff --git a/src/string_width_ffi.mjs b/src/string_width_ffi.mjs index e32acda..830aa86 100644 --- a/src/string_width_ffi.mjs +++ b/src/string_width_ffi.mjs @@ -9,3 +9,10 @@ export function table_lookup(table, value) { return ((table.byteAt(table.byteAt(hi) * 32 + md) >> lo) & 1) > 0; } +const segmenter = new Intl.Segmenter(); +export function string_fold(str, state, fun) { + for(const { segment } of segmenter.segment(str)) { + state = fun(state, segment) + } + return state +} -- 2.51.2