From 7630dd541839af68379ac5a6e0e90221608e2dc1 Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Mon, 8 Apr 2024 14:32:55 +1000 Subject: [PATCH] deprecation(console): copy `std/console` APIs into `std/cli` and deprecate `std/console` (#4547) deprecation(console): merge `std/console` into `std/cli` --- _tools/check_deprecation.ts | 1 + {console => cli}/_data.json | 0 {console => cli}/_run_length.ts | 0 {console => cli}/_run_length_test.ts | 0 {console => cli}/_tools/compare_with_rust.ts | 0 {console => cli}/_tools/generate_data.ts | 0 cli/mod.ts | 1 + .../testdata/unicode_width_crate/Cargo.lock | 0 .../testdata/unicode_width_crate/Cargo.toml | 0 .../testdata/unicode_width_crate/src/lib.rs | 0 cli/unicode_width.ts | 79 +++++++++++++++++++ {console => cli}/unicode_width_test.ts | 0 console/mod.ts | 4 + console/unicode_width.ts | 42 ++-------- 14 files changed, 90 insertions(+), 37 deletions(-) rename {console => cli}/_data.json (100%) rename {console => cli}/_run_length.ts (100%) rename {console => cli}/_run_length_test.ts (100%) rename {console => cli}/_tools/compare_with_rust.ts (100%) rename {console => cli}/_tools/generate_data.ts (100%) rename {console => cli}/testdata/unicode_width_crate/Cargo.lock (100%) rename {console => cli}/testdata/unicode_width_crate/Cargo.toml (100%) rename {console => cli}/testdata/unicode_width_crate/src/lib.rs (100%) create mode 100644 cli/unicode_width.ts rename {console => cli}/unicode_width_test.ts (100%) diff --git a/_tools/check_deprecation.ts b/_tools/check_deprecation.ts index 7088ea12a7cb..0f237df5277b 100644 --- a/_tools/check_deprecation.ts +++ b/_tools/check_deprecation.ts @@ -47,6 +47,7 @@ for await ( /crypto(\/|\\)_wasm$/, /encoding(\/|\\)_yaml$/, /encoding(\/|\\)_toml$/, + /console$/, /_tools$/, /_util$/, /docs$/, diff --git a/console/_data.json b/cli/_data.json similarity index 100% rename from console/_data.json rename to cli/_data.json diff --git a/console/_run_length.ts b/cli/_run_length.ts similarity index 100% rename from console/_run_length.ts rename to cli/_run_length.ts diff --git a/console/_run_length_test.ts b/cli/_run_length_test.ts similarity index 100% rename from console/_run_length_test.ts rename to cli/_run_length_test.ts diff --git a/console/_tools/compare_with_rust.ts b/cli/_tools/compare_with_rust.ts similarity index 100% rename from console/_tools/compare_with_rust.ts rename to cli/_tools/compare_with_rust.ts diff --git a/console/_tools/generate_data.ts b/cli/_tools/generate_data.ts similarity index 100% rename from console/_tools/generate_data.ts rename to cli/_tools/generate_data.ts diff --git a/cli/mod.ts b/cli/mod.ts index ea40381bffb1..555c05caee37 100644 --- a/cli/mod.ts +++ b/cli/mod.ts @@ -17,3 +17,4 @@ export * from "./parse_args.ts"; export * from "./prompt_secret.ts"; export * from "./spinner.ts"; +export * from "./unicode_width.ts"; diff --git a/console/testdata/unicode_width_crate/Cargo.lock b/cli/testdata/unicode_width_crate/Cargo.lock similarity index 100% rename from console/testdata/unicode_width_crate/Cargo.lock rename to cli/testdata/unicode_width_crate/Cargo.lock diff --git a/console/testdata/unicode_width_crate/Cargo.toml b/cli/testdata/unicode_width_crate/Cargo.toml similarity index 100% rename from console/testdata/unicode_width_crate/Cargo.toml rename to cli/testdata/unicode_width_crate/Cargo.toml diff --git a/console/testdata/unicode_width_crate/src/lib.rs b/cli/testdata/unicode_width_crate/src/lib.rs similarity index 100% rename from console/testdata/unicode_width_crate/src/lib.rs rename to cli/testdata/unicode_width_crate/src/lib.rs diff --git a/cli/unicode_width.ts b/cli/unicode_width.ts new file mode 100644 index 000000000000..2266f59563a6 --- /dev/null +++ b/cli/unicode_width.ts @@ -0,0 +1,79 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +// Ported from unicode_width rust crate, Copyright (c) 2015 The Rust Project Developers. MIT license. + +import data from "./_data.json" with { type: "json" }; +import { runLengthDecode } from "./_run_length.ts"; + +let tables: Uint8Array[] | null = null; +function lookupWidth(cp: number) { + if (!tables) tables = data.tables.map(runLengthDecode); + + const t1Offset = (tables[0] as Uint8Array)[(cp >> 13) & 0xff] as number; + const t2Offset = + (tables[1] as Uint8Array)[128 * t1Offset + ((cp >> 6) & 0x7f)] as number; + const packedWidths = + (tables[2] as Uint8Array)[16 * t2Offset + ((cp >> 2) & 0xf)] as number; + + const width = (packedWidths >> (2 * (cp & 0b11))) & 0b11; + + return width === 3 ? 1 : width; +} + +const cache = new Map(); +function charWidth(ch: string) { + if (cache.has(ch)) return cache.get(ch)!; + + const cp = ch.codePointAt(0)!; + let v: number | null = null; + + if (cp < 0x7f) { + v = cp >= 0x20 ? 1 : cp === 0 ? 0 : null; + } else if (cp >= 0xa0) { + v = lookupWidth(cp); + } else { + v = null; + } + + cache.set(ch, v); + return v; +} + +/** + * Calculate the physical width of a string in a TTY-like environment. This is + * useful for cases such as calculating where a line-wrap will occur and + * underlining strings. + * + * The physical width is given by the number of columns required to display + * the string. The number of columns a given unicode character occupies can + * vary depending on the character itself. + * + * @param str The string to measure. + * @returns The unicode width of the string. + * + * @example Calculating the unicode width of a string + * ```ts + * import { unicodeWidth } from "https://deno.land/std@$STD_VERSION/cli/unicode_width.ts"; + * + * unicodeWidth("hello world"); // 11 + * unicodeWidth("天地玄黃宇宙洪荒"); // 16 + * unicodeWidth("fullwidth"); // 18 + * ``` + * + * @example Calculating the unicode width of a color-encoded string + * ```ts + * import { unicodeWidth } from "https://deno.land/std@$STD_VERSION/cli/unicode_width.ts"; + * import { stripAnsiCode } from "https://deno.land/std@$STD_VERSION/fmt/colors.ts"; + * + * unicodeWidth(stripAnsiCode("\x1b[36mголубой\x1b[39m")); // 7 + * unicodeWidth(stripAnsiCode("\x1b[31m紅色\x1b[39m")); // 4 + * unicodeWidth(stripAnsiCode("\x1B]8;;https://deno.land\x07🦕\x1B]8;;\x07")); // 2 + * ``` + * + * Use + * {@linkcode https://jsr.io/@std/fmt/doc/colors/~/stripAnsiCode | stripAnsiCode} + * to remove ANSI escape codes from a string before passing it to + * {@linkcode unicodeWidth}. + */ +export function unicodeWidth(str: string): number { + return [...str].map((ch) => charWidth(ch) ?? 0).reduce((a, b) => a + b, 0); +} diff --git a/console/unicode_width_test.ts b/cli/unicode_width_test.ts similarity index 100% rename from console/unicode_width_test.ts rename to cli/unicode_width_test.ts diff --git a/console/mod.ts b/console/mod.ts index 02ca312481ac..04221fd0b569 100644 --- a/console/mod.ts +++ b/console/mod.ts @@ -14,6 +14,10 @@ * unicodeWidth("天地玄黃宇宙洪荒"); // 16 * ``` * + * @deprecated Use {@link https://jsr.io/@std/cli | std/cli} instead. This + * module will be removed once the Standard Library migrates to + * {@link https://jsr.io/ | JSR}. + * * @module */ diff --git a/console/unicode_width.ts b/console/unicode_width.ts index 175de3daefec..4461fd38e321 100644 --- a/console/unicode_width.ts +++ b/console/unicode_width.ts @@ -1,42 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Ported from unicode_width rust crate, Copyright (c) 2015 The Rust Project Developers. MIT license. -import data from "./_data.json" with { type: "json" }; -import { runLengthDecode } from "./_run_length.ts"; - -let tables: Uint8Array[] | null = null; -function lookupWidth(cp: number) { - if (!tables) tables = data.tables.map(runLengthDecode); - - const t1Offset = (tables[0] as Uint8Array)[(cp >> 13) & 0xff] as number; - const t2Offset = - (tables[1] as Uint8Array)[128 * t1Offset + ((cp >> 6) & 0x7f)] as number; - const packedWidths = - (tables[2] as Uint8Array)[16 * t2Offset + ((cp >> 2) & 0xf)] as number; - - const width = (packedWidths >> (2 * (cp & 0b11))) & 0b11; - - return width === 3 ? 1 : width; -} - -const cache = new Map(); -function charWidth(ch: string) { - if (cache.has(ch)) return cache.get(ch)!; - - const cp = ch.codePointAt(0)!; - let v: number | null = null; - - if (cp < 0x7f) { - v = cp >= 0x20 ? 1 : cp === 0 ? 0 : null; - } else if (cp >= 0xa0) { - v = lookupWidth(cp); - } else { - v = null; - } - - cache.set(ch, v); - return v; -} +import { unicodeWidth as _unicodeWidth } from "../cli/unicode_width.ts"; /** * Calculate the physical width of a string in a TTY-like environment. This is @@ -73,7 +38,10 @@ function charWidth(ch: string) { * {@linkcode https://jsr.io/@std/fmt/doc/colors/~/stripAnsiCode | stripAnsiCode} * to remove ANSI escape codes from a string before passing it to * {@linkcode unicodeWidth}. + * + * @deprecated Use {@linkcode unicodeWidth} from `std/cli` instead. This will be + * removed once the Standard Library migrates to {@link https://jsr.io/ | JSR}. */ export function unicodeWidth(str: string): number { - return [...str].map((ch) => charWidth(ch) ?? 0).reduce((a, b) => a + b, 0); + return _unicodeWidth(str); }