From 3f162c712a7f07f3e21f0fa931273f06d0dcb337 Mon Sep 17 00:00:00 2001 From: keelii Date: Fri, 24 Jan 2025 15:05:51 +0800 Subject: [PATCH] feat(fmt): make printf working with colors. --- fmt/printf.ts | 7 +++++++ fmt/printf_test.ts | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/fmt/printf.ts b/fmt/printf.ts index 99c767c5b49b..d07a7384baec 100644 --- a/fmt/printf.ts +++ b/fmt/printf.ts @@ -1,5 +1,7 @@ // Copyright 2018-2025 the Deno authors. MIT license. +import { stripAnsiCode } from "./colors.ts"; + /** * {@linkcode sprintf} and {@linkcode printf} for printing formatted strings to * stdout. @@ -389,6 +391,7 @@ class Printf { this.state = State.PERCENT; return; } + flags.width = flags.width === -1 ? 0 : flags.width; flags.width *= 10; flags.width += val; @@ -862,6 +865,10 @@ class Printf { if (this.flags.precision !== -1) { s = s.slice(0, this.flags.precision); } + const sac = stripAnsiCode(s); + if (sac.length !== s.length) { + this.flags.width += s.length - sac.length; + } return this.pad(s); } diff --git a/fmt/printf_test.ts b/fmt/printf_test.ts index 8d56275d6ef4..74ed85d8b1e3 100644 --- a/fmt/printf_test.ts +++ b/fmt/printf_test.ts @@ -8,6 +8,7 @@ import { printf, sprintf } from "./printf.ts"; import { assertEquals, assertThrows } from "@std/assert"; import { assertSpyCall, spy } from "@std/testing/mock"; +import * as c from "./colors.ts"; Deno.test("sprintf() handles noVerb", function () { assertEquals(sprintf("bla"), "bla"); @@ -169,6 +170,54 @@ Deno.test("sprintf() handles string", function () { assertEquals(sprintf("%s World%s", "Hello", "!"), "Hello World!"); }); +Deno.test("printf() handles string with colors", () => { + assertEquals(sprintf("%4s", c.bold("foo")), " foo"); + assertEquals(sprintf("%4s", c.dim("foo")), " foo"); + assertEquals(sprintf("%4s", c.italic("foo")), " foo"); + assertEquals(sprintf("%4s", c.underline("foo")), " foo"); + assertEquals(sprintf("%4s", c.inverse("foo")), " foo"); + assertEquals(sprintf("%4s", c.hidden("foo")), " foo"); + assertEquals(sprintf("%4s", c.strikethrough("foo")), " foo"); + + assertEquals(sprintf("%4s", c.black("foo")), " foo"); + assertEquals(sprintf("%4s", c.red("foo")), " foo"); + assertEquals(sprintf("%4s", c.green("foo")), " foo"); + assertEquals(sprintf("%4s", c.yellow("foo")), " foo"); + assertEquals(sprintf("%4s", c.blue("foo")), " foo"); + assertEquals(sprintf("%4s", c.magenta("foo")), " foo"); + assertEquals(sprintf("%4s", c.cyan("foo")), " foo"); + assertEquals(sprintf("%4s", c.white("foo")), " foo"); + assertEquals(sprintf("%4s", c.gray("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightBlack("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightRed("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightGreen("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightYellow("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightBlue("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightMagenta("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightCyan("foo")), " foo"); + assertEquals(sprintf("%4s", c.brightWhite("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBlack("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgRed("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgGreen("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgYellow("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBlue("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgMagenta("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgCyan("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgWhite("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightBlack("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightRed("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightGreen("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightYellow("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightBlue("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightMagenta("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightCyan("foo")), " foo"); + assertEquals(sprintf("%4s", c.bgBrightWhite("foo")), " foo"); + assertEquals(sprintf("%4s", c.rgb8("foo", -10)), " foo"); + assertEquals(sprintf("%4s", c.rgb8("foo", 42.5)), " foo"); + assertEquals(sprintf("%4s", c.rgb8("foo", 42)), " foo"); + assertEquals(sprintf("%4s", c.bgRgb8("foo", 42)), " foo"); +}); + Deno.test("sprintf() handles hex", function () { assertEquals(sprintf("%x", "123"), "313233"); assertEquals(sprintf("%x", "n"), "6e");