diff --git a/.gitignore b/.gitignore index 599be4e..b01f73b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ *.ez /build erl_crash.dump +/node_modules +/build_* diff --git a/bench/fstw.mjs b/bench/fstw.mjs new file mode 100644 index 0000000..b01ba46 --- /dev/null +++ b/bench/fstw.mjs @@ -0,0 +1,8 @@ +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; +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") +} +console.log(sum) diff --git a/bench/sw.mjs b/bench/sw.mjs new file mode 100644 index 0000000..de3a454 --- /dev/null +++ b/bench/sw.mjs @@ -0,0 +1,8 @@ +import { line as string_width } from './build/dev/javascript/string_width/string_width.mjs' +import { toList } from './build/dev/javascript/string_width/gleam.mjs' + +let sum = 0; +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([])) +} +console.log(sum) diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..f7cb58e --- /dev/null +++ b/package-lock.json @@ -0,0 +1,17 @@ +{ + "name": "string-width", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "fast-string-truncated-width": "^1.1.0" + } + }, + "node_modules/fast-string-truncated-width": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-1.1.0.tgz", + "integrity": "sha512-FfsFREOllHpnSl6cxpLi6wvqd9UebrZPxWlOJCCcWoOJzy02xyjPbafF9tyg2Usnf3GLmRr5Q6s7n+GO+6VB5A==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..702e7eb --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "fast-string-truncated-width": "^1.1.0" + } +} diff --git a/src/string_width.gleam b/src/string_width.gleam index 3dc1e23..6d702ce 100644 --- a/src/string_width.gleam +++ b/src/string_width.gleam @@ -1,4 +1,3 @@ -import gleam/bit_array import gleam/int import gleam/list import gleam/regex @@ -237,26 +236,20 @@ fn is_wide(cp: Int) -> Bool { } } +@external(javascript, "./string_width_ffi.mjs", "table_lookup") fn table_lookup(table: BitArray, value: Int) -> Bool { let hi = int.bitwise_shift_right(value, 8) let md = int.bitwise_shift_right(int.bitwise_and(value, 0xff), 3) let lo = int.bitwise_and(value, 7) - int.bitwise_shift_right(at(table, at(table, hi) * 32 + md), lo) % 2 != 0 -} + let lvl1_skip = hi * 8 + let assert <<_:size(lvl1_skip), lvl1:int, _:bits>> = table -fn at(bits: BitArray, at position: Int) -> Int { - // NOTE: This bit array size option is in patterns is not supported for JavaScript compilation. - // let bit_index = position * 8 - // case bits { - // <<_:size(bit_index), x:int, _:bits>> -> x - // _ -> panic - // } + let lvl2_skip = { lvl1 * 32 + md } * 8 + let assert <<_:size(lvl2_skip), lvl3:int, _:bits>> = table - case bit_array.slice(bits, at: position, take: 1) { - Ok(<>) -> x - _ -> panic - } + // TODO: worth collapsing into a single skip? + int.bitwise_shift_right(lvl3, lo) % 2 != 0 } const nonspacing = << diff --git a/src/string_width_ffi.mjs b/src/string_width_ffi.mjs new file mode 100644 index 0000000..e32acda --- /dev/null +++ b/src/string_width_ffi.mjs @@ -0,0 +1,11 @@ +export function table_lookup(table, value) { + let hi = value >> 8; // $int.bitwise_shift_right(value, 8); + let md = (value & 0xff) >> 3; // $int.bitwise_shift_right($int.bitwise_and(value, 0xff), 3); + let lo = value & 7; // $int.bitwise_and(value, 7); + // return (remainderInt( + // $int.bitwise_shift_right(at(table, at(table, hi) * 32 + md), lo), + // 2 + // )) !== 0; + return ((table.byteAt(table.byteAt(hi) * 32 + md) >> lo) & 1) > 0; +} +