summaryrefslogtreecommitdiff
path: root/std/fmt
diff options
context:
space:
mode:
authorCasper Beyer <caspervonb@pm.me>2021-02-02 19:05:46 +0800
committerGitHub <noreply@github.com>2021-02-02 12:05:46 +0100
commit6abf126c2a7a451cded8c6b5e6ddf1b69c84055d (patch)
treefd94c013a19fcb38954844085821ec1601c20e18 /std/fmt
parenta2b5d44f1aa9d64f448a2a3cc2001272e2f60b98 (diff)
chore: remove std directory (#9361)
This removes the std folder from the tree. Various parts of the tests are pretty tightly dependent on std (47 direct imports and 75 indirect imports, not counting the cli tests that use them as fixtures) so I've added std as a submodule for now.
Diffstat (limited to 'std/fmt')
-rw-r--r--std/fmt/README.md240
-rw-r--r--std/fmt/TODO13
-rw-r--r--std/fmt/colors.ts522
-rw-r--r--std/fmt/colors_test.ts230
-rw-r--r--std/fmt/printf.ts757
-rw-r--r--std/fmt/printf_test.ts674
6 files changed, 0 insertions, 2436 deletions
diff --git a/std/fmt/README.md b/std/fmt/README.md
deleted file mode 100644
index 8c44d78a7..000000000
--- a/std/fmt/README.md
+++ /dev/null
@@ -1,240 +0,0 @@
-# Printf for Deno
-
-This is very much a work-in-progress. I'm actively soliciting feedback. What
-immediately follows are points for discussion.
-
-If you are looking for the documentation proper, skip to:
-
- "printf: prints formatted output"
-
-and
-
- "Colors"
-
-below.
-
-## Discussion
-
-This is very much a work-in-progress. I'm actively soliciting feedback.
-
-- What useful features are available in other languages apart from Golang and C?
-
-- behaviour of `%v` verb. In Golang, this is a shortcut verb to "print the
- default format" of the argument. It is currently implemented to format using
- `toString` in the default case and `inspect` if the `%#v` alternative format
- flag is used in the format directive. Alternatively, `%V` could be used to
- distinguish the two.
-
- `inspect` output is not defined, however. This may be problematic if using
- this code on other platforms (and expecting interoperability). To my
- knowledge, no suitable specification of object representation aside from JSON
- and `toString` exist. ( Aside: see "[Common object formats][3]" in the
- "Console Living Standard" which basically says "do whatever" )
-
-- `%j` verb. This is an extension particular to this implementation. Currently
- not very sophisticated, it just runs `JSON.stringify` on the argument.
- Consider possible modifier flags, etc.
-
-- `<` verb. This is an extension that assumes the argument is an array and will
- format each element according to the format (surrounded by [] and separated by
- comma) (`<` Mnemonic: pull each element out of array)
-
-- how to deal with more newfangled JavaScript features (generic Iterables, Map
- and Set types, typed Arrays, ...)
-
-- the implementation is fairly rough around the edges:
-
-- currently contains little in the way of checking for correctness. Conceivably,
- there will be a 'strict' form, e.g. that ensures only Number-ish arguments are
- passed to %f flags.
-
-- assembles output using string concatenation instead of utilizing buffers or
- other optimizations. It would be nice to have printf / sprintf / fprintf (etc)
- all in one.
-
-- float formatting is handled by toString() and to `toExponential` along with a
- mess of Regexp. Would be nice to use fancy match.
-
-- some flags that are potentially applicable ( POSIX long and unsigned modifiers
- are not likely useful) are missing, namely %q (print quoted), %U (unicode
- format)
-
-# printf: prints formatted output
-
-sprintf converts and formats a variable number of arguments as is specified by a
-`format string`. In it's basic form, a format string may just be a literal. In
-case arguments are meant to be formatted, a `directive` is contained in the
-format string, preceded by a '%' character:
-
- %<verb>
-
-E.g. the verb `s` indicates the directive should be replaced by the string
-representation of the argument in the corresponding position of the argument
-list. E.g.:
-
- Hello %s!
-
-applied to the arguments "World" yields "Hello World!".
-
-The meaning of the format string is modelled after [POSIX][1] format strings as
-well as well as [Golang format strings][2]. Both contain elements specific to
-the respective programming language that don't apply to JavaScript, so they can
-not be fully supported. Furthermore we implement some functionality that is
-specific to JS.
-
-## Verbs
-
-The following verbs are supported:
-
-| Verb | Meaning |
-| ----- | -------------------------------------------------------------- |
-| `%` | print a literal percent |
-| `t` | evaluate arg as boolean, print `true` or `false` |
-| `b` | eval as number, print binary |
-| `c` | eval as number, print character corresponding to the codePoint |
-| `o` | eval as number, print octal |
-| `x X` | print as hex (ff FF), treat string as list of bytes |
-| `e E` | print number in scientific/exponent format 1.123123e+01 |
-| `f F` | print number as float with decimal point and no exponent |
-| `g G` | use %e %E or %f %F depending on size of argument |
-| `s` | interpolate string |
-| `T` | type of arg, as returned by `typeof` |
-| `v` | value of argument in 'default' format (see below) |
-| `j` | argument as formatted by `JSON.stringify` |
-
-## Width and Precision
-
-Verbs may be modified by providing them with width and precision, either or both
-may be omitted:
-
- %9f width 9, default precision
- %.9f default width, precision 9
- %8.9f width 8, precision 9
- %8.f width 9, precision 0
-
-In general, 'width' describes the minimum length of the output, while
-'precision' limits the output.
-
-| verb | precision |
-| --------- | --------------------------------------------------------------- |
-| `t` | n/a |
-| `b c o` | n/a |
-| `x X` | n/a for number, strings are truncated to p bytes(!) |
-| `e E f F` | number of places after decimal, default 6 |
-| `g G` | set maximum number of digits |
-| `s` | truncate input |
-| `T` | truncate |
-| `v` | truncate, or depth if used with # see "'default' format", below |
-| `j` | n/a |
-
-Numerical values for width and precision can be substituted for the `*` char, in
-which case the values are obtained from the next args, e.g.:
-
- sprintf("%*.*f", 9, 8, 456.0)
-
-is equivalent to:
-
- sprintf("%9.8f", 456.0)
-
-## Flags
-
-The effects of the verb may be further influenced by using flags to modify the
-directive:
-
-| Flag | Verb | Meaning |
-| ----- | --------- | -------------------------------------------------------------------------- |
-| `+` | numeric | always print sign |
-| `-` | all | pad to the right (left justify) |
-| `#` | | alternate format |
-| `#` | `b o x X` | prefix with `0b 0 0x` |
-| `#` | `g G` | don't remove trailing zeros |
-| `#` | `v` | ues output of `inspect` instead of `toString` |
-| `' '` | | space character |
-| `' '` | `x X` | leave spaces between bytes when printing string |
-| `' '` | `d` | insert space for missing `+` sign character |
-| `0` | all | pad with zero, `-` takes precedence, sign is appended in front of padding |
-| `<` | all | format elements of the passed array according to the directive (extension) |
-
-## 'default' format
-
-The default format used by `%v` is the result of calling `toString()` on the
-relevant argument. If the `#` flags is used, the result of calling `inspect()`
-is interpolated. In this case, the precision, if set is passed to `inspect()` as
-the 'depth' config parameter.
-
-## Positional arguments
-
-Arguments do not need to be consumed in the order they are provided and may be
-consumed more than once. E.g.:
-
- sprintf("%[2]s %[1]s", "World", "Hello")
-
-returns "Hello World". The presence of a positional indicator resets the arg
-counter allowing args to be reused:
-
- sprintf("dec[%d]=%d hex[%[1]d]=%x oct[%[1]d]=%#o %s", 1, 255, "Third")
-
-returns `dec[1]=255 hex[1]=0xff oct[1]=0377 Third`
-
-Width and precision my also use positionals:
-
- "%[2]*.[1]*d", 1, 2
-
-This follows the golang conventions and not POSIX.
-
-## Errors
-
-The following errors are handled:
-
-Incorrect verb:
-
- S("%h", "") %!(BAD VERB 'h')
-
-Too few arguments:
-
- S("%d") %!(MISSING 'd')"
-
-# Colors
-
-Adds functions used for displaying colored text.
-
-## Usage
-
-```typescript
-import {
- bgBlue,
- bgRgb24,
- bgRgb8,
- bold,
- italic,
- red,
- rgb24,
- rgb8,
-} from "https://deno.land/std@$STD_VERSION/fmt/colors.ts";
-
-console.log(bgBlue(italic(red(bold("Hello, World!")))));
-
-// also supports 8bit colors
-
-console.log(rgb8("Hello, World!", 42));
-
-console.log(bgRgb8("Hello, World!", 42));
-
-// and 24bit rgb
-
-console.log(rgb24("Hello, World!", {
- r: 41,
- g: 42,
- b: 43,
-}));
-
-console.log(bgRgb24("Hello, World!", {
- r: 41,
- g: 42,
- b: 43,
-}));
-```
-
-[1]: https://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
-[2]: https://golang.org/pkg/fmt/
-[3]: https://console.spec.whatwg.org/#object-formats
diff --git a/std/fmt/TODO b/std/fmt/TODO
deleted file mode 100644
index 7f95c7a78..000000000
--- a/std/fmt/TODO
+++ /dev/null
@@ -1,13 +0,0 @@
-
-* "native" formatting, json, arrays, object/structs, functions ...
-* %q %U
-* Java has a %n flag to print the platform native newline... in POSIX
- that means "number of chars printed so far", though.
-* Use of Writer and Buffer internally in order to make fprintf, printf, etc.
- easier and more elegant.
-
-* See "Discussion" in README
-
-* scanf, pack, unpack, annotated hex
-* Consistent error handling.
-* Rewrite (probably), now that I know how it's done.
diff --git a/std/fmt/colors.ts b/std/fmt/colors.ts
deleted file mode 100644
index 3596638f5..000000000
--- a/std/fmt/colors.ts
+++ /dev/null
@@ -1,522 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-// A module to print ANSI terminal colors. Inspired by chalk, kleur, and colors
-// on npm.
-//
-// ```
-// import { bgBlue, red, bold } from "https://deno.land/std/fmt/colors.ts";
-// console.log(bgBlue(red(bold("Hello world!"))));
-// ```
-//
-// This module supports `NO_COLOR` environmental variable disabling any coloring
-// if `NO_COLOR` is set.
-//
-// This module is browser compatible.
-
-const noColor = globalThis.Deno?.noColor ?? true;
-
-interface Code {
- open: string;
- close: string;
- regexp: RegExp;
-}
-
-/** RGB 8-bits per channel. Each in range `0->255` or `0x00->0xff` */
-interface Rgb {
- r: number;
- g: number;
- b: number;
-}
-
-let enabled = !noColor;
-
-/**
- * Set changing text color to enabled or disabled
- * @param value
- */
-export function setColorEnabled(value: boolean): void {
- if (noColor) {
- return;
- }
-
- enabled = value;
-}
-
-/** Get whether text color change is enabled or disabled. */
-export function getColorEnabled(): boolean {
- return enabled;
-}
-
-/**
- * Builds color code
- * @param open
- * @param close
- */
-function code(open: number[], close: number): Code {
- return {
- open: `\x1b[${open.join(";")}m`,
- close: `\x1b[${close}m`,
- regexp: new RegExp(`\\x1b\\[${close}m`, "g"),
- };
-}
-
-/**
- * Applies color and background based on color code and its associated text
- * @param str text to apply color settings to
- * @param code color code to apply
- */
-function run(str: string, code: Code): string {
- return enabled
- ? `${code.open}${str.replace(code.regexp, code.open)}${code.close}`
- : str;
-}
-
-/**
- * Reset the text modified
- * @param str text to reset
- */
-export function reset(str: string): string {
- return run(str, code([0], 0));
-}
-
-/**
- * Make the text bold.
- * @param str text to make bold
- */
-export function bold(str: string): string {
- return run(str, code([1], 22));
-}
-
-/**
- * The text emits only a small amount of light.
- * @param str text to dim
- */
-export function dim(str: string): string {
- return run(str, code([2], 22));
-}
-
-/**
- * Make the text italic.
- * @param str text to make italic
- */
-export function italic(str: string): string {
- return run(str, code([3], 23));
-}
-
-/**
- * Make the text underline.
- * @param str text to underline
- */
-export function underline(str: string): string {
- return run(str, code([4], 24));
-}
-
-/**
- * Invert background color and text color.
- * @param str text to invert its color
- */
-export function inverse(str: string): string {
- return run(str, code([7], 27));
-}
-
-/**
- * Make the text hidden.
- * @param str text to hide
- */
-export function hidden(str: string): string {
- return run(str, code([8], 28));
-}
-
-/**
- * Put horizontal line through the center of the text.
- * @param str text to strike through
- */
-export function strikethrough(str: string): string {
- return run(str, code([9], 29));
-}
-
-/**
- * Set text color to black.
- * @param str text to make black
- */
-export function black(str: string): string {
- return run(str, code([30], 39));
-}
-
-/**
- * Set text color to red.
- * @param str text to make red
- */
-export function red(str: string): string {
- return run(str, code([31], 39));
-}
-
-/**
- * Set text color to green.
- * @param str text to make green
- */
-export function green(str: string): string {
- return run(str, code([32], 39));
-}
-
-/**
- * Set text color to yellow.
- * @param str text to make yellow
- */
-export function yellow(str: string): string {
- return run(str, code([33], 39));
-}
-
-/**
- * Set text color to blue.
- * @param str text to make blue
- */
-export function blue(str: string): string {
- return run(str, code([34], 39));
-}
-
-/**
- * Set text color to magenta.
- * @param str text to make magenta
- */
-export function magenta(str: string): string {
- return run(str, code([35], 39));
-}
-
-/**
- * Set text color to cyan.
- * @param str text to make cyan
- */
-export function cyan(str: string): string {
- return run(str, code([36], 39));
-}
-
-/**
- * Set text color to white.
- * @param str text to make white
- */
-export function white(str: string): string {
- return run(str, code([37], 39));
-}
-
-/**
- * Set text color to gray.
- * @param str text to make gray
- */
-export function gray(str: string): string {
- return brightBlack(str);
-}
-
-/**
- * Set text color to bright black.
- * @param str text to make bright-black
- */
-export function brightBlack(str: string): string {
- return run(str, code([90], 39));
-}
-
-/**
- * Set text color to bright red.
- * @param str text to make bright-red
- */
-export function brightRed(str: string): string {
- return run(str, code([91], 39));
-}
-
-/**
- * Set text color to bright green.
- * @param str text to make bright-green
- */
-export function brightGreen(str: string): string {
- return run(str, code([92], 39));
-}
-
-/**
- * Set text color to bright yellow.
- * @param str text to make bright-yellow
- */
-export function brightYellow(str: string): string {
- return run(str, code([93], 39));
-}
-
-/**
- * Set text color to bright blue.
- * @param str text to make bright-blue
- */
-export function brightBlue(str: string): string {
- return run(str, code([94], 39));
-}
-
-/**
- * Set text color to bright magenta.
- * @param str text to make bright-magenta
- */
-export function brightMagenta(str: string): string {
- return run(str, code([95], 39));
-}
-
-/**
- * Set text color to bright cyan.
- * @param str text to make bright-cyan
- */
-export function brightCyan(str: string): string {
- return run(str, code([96], 39));
-}
-
-/**
- * Set text color to bright white.
- * @param str text to make bright-white
- */
-export function brightWhite(str: string): string {
- return run(str, code([97], 39));
-}
-
-/**
- * Set background color to black.
- * @param str text to make its background black
- */
-export function bgBlack(str: string): string {
- return run(str, code([40], 49));
-}
-
-/**
- * Set background color to red.
- * @param str text to make its background red
- */
-export function bgRed(str: string): string {
- return run(str, code([41], 49));
-}
-
-/**
- * Set background color to green.
- * @param str text to make its background green
- */
-export function bgGreen(str: string): string {
- return run(str, code([42], 49));
-}
-
-/**
- * Set background color to yellow.
- * @param str text to make its background yellow
- */
-export function bgYellow(str: string): string {
- return run(str, code([43], 49));
-}
-
-/**
- * Set background color to blue.
- * @param str text to make its background blue
- */
-export function bgBlue(str: string): string {
- return run(str, code([44], 49));
-}
-
-/**
- * Set background color to magenta.
- * @param str text to make its background magenta
- */
-export function bgMagenta(str: string): string {
- return run(str, code([45], 49));
-}
-
-/**
- * Set background color to cyan.
- * @param str text to make its background cyan
- */
-export function bgCyan(str: string): string {
- return run(str, code([46], 49));
-}
-
-/**
- * Set background color to white.
- * @param str text to make its background white
- */
-export function bgWhite(str: string): string {
- return run(str, code([47], 49));
-}
-
-/**
- * Set background color to bright black.
- * @param str text to make its background bright-black
- */
-export function bgBrightBlack(str: string): string {
- return run(str, code([100], 49));
-}
-
-/**
- * Set background color to bright red.
- * @param str text to make its background bright-red
- */
-export function bgBrightRed(str: string): string {
- return run(str, code([101], 49));
-}
-
-/**
- * Set background color to bright green.
- * @param str text to make its background bright-green
- */
-export function bgBrightGreen(str: string): string {
- return run(str, code([102], 49));
-}
-
-/**
- * Set background color to bright yellow.
- * @param str text to make its background bright-yellow
- */
-export function bgBrightYellow(str: string): string {
- return run(str, code([103], 49));
-}
-
-/**
- * Set background color to bright blue.
- * @param str text to make its background bright-blue
- */
-export function bgBrightBlue(str: string): string {
- return run(str, code([104], 49));
-}
-
-/**
- * Set background color to bright magenta.
- * @param str text to make its background bright-magenta
- */
-export function bgBrightMagenta(str: string): string {
- return run(str, code([105], 49));
-}
-
-/**
- * Set background color to bright cyan.
- * @param str text to make its background bright-cyan
- */
-export function bgBrightCyan(str: string): string {
- return run(str, code([106], 49));
-}
-
-/**
- * Set background color to bright white.
- * @param str text to make its background bright-white
- */
-export function bgBrightWhite(str: string): string {
- return run(str, code([107], 49));
-}
-
-/* Special Color Sequences */
-
-/**
- * Clam and truncate color codes
- * @param n
- * @param max number to truncate to
- * @param min number to truncate from
- */
-function clampAndTruncate(n: number, max = 255, min = 0): number {
- return Math.trunc(Math.max(Math.min(n, max), min));
-}
-
-/**
- * Set text color using paletted 8bit colors.
- * https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit
- * @param str text color to apply paletted 8bit colors to
- * @param color code
- */
-export function rgb8(str: string, color: number): string {
- return run(str, code([38, 5, clampAndTruncate(color)], 39));
-}
-
-/**
- * Set background color using paletted 8bit colors.
- * https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit
- * @param str text color to apply paletted 8bit background colors to
- * @param color code
- */
-export function bgRgb8(str: string, color: number): string {
- return run(str, code([48, 5, clampAndTruncate(color)], 49));
-}
-
-/**
- * Set text color using 24bit rgb.
- * `color` can be a number in range `0x000000` to `0xffffff` or
- * an `Rgb`.
- *
- * To produce the color magenta:
- *
- * rgba24("foo", 0xff00ff);
- * rgba24("foo", {r: 255, g: 0, b: 255});
- * @param str text color to apply 24bit rgb to
- * @param color code
- */
-export function rgb24(str: string, color: number | Rgb): string {
- if (typeof color === "number") {
- return run(
- str,
- code(
- [38, 2, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff],
- 39,
- ),
- );
- }
- return run(
- str,
- code(
- [
- 38,
- 2,
- clampAndTruncate(color.r),
- clampAndTruncate(color.g),
- clampAndTruncate(color.b),
- ],
- 39,
- ),
- );
-}
-
-/**
- * Set background color using 24bit rgb.
- * `color` can be a number in range `0x000000` to `0xffffff` or
- * an `Rgb`.
- *
- * To produce the color magenta:
- *
- * bgRgba24("foo", 0xff00ff);
- * bgRgba24("foo", {r: 255, g: 0, b: 255});
- * @param str text color to apply 24bit rgb to
- * @param color code
- */
-export function bgRgb24(str: string, color: number | Rgb): string {
- if (typeof color === "number") {
- return run(
- str,
- code(
- [48, 2, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff],
- 49,
- ),
- );
- }
- return run(
- str,
- code(
- [
- 48,
- 2,
- clampAndTruncate(color.r),
- clampAndTruncate(color.g),
- clampAndTruncate(color.b),
- ],
- 49,
- ),
- );
-}
-
-// https://github.com/chalk/ansi-regex/blob/2b56fb0c7a07108e5b54241e8faec160d393aedb/index.js
-const ANSI_PATTERN = new RegExp(
- [
- "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
- "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))",
- ].join("|"),
- "g",
-);
-
-/**
- * Remove ANSI escape codes from the string.
- * @param string to remove ANSI escape codes from
- */
-export function stripColor(string: string): string {
- return string.replace(ANSI_PATTERN, "");
-}
diff --git a/std/fmt/colors_test.ts b/std/fmt/colors_test.ts
deleted file mode 100644
index 7f5940a4d..000000000
--- a/std/fmt/colors_test.ts
+++ /dev/null
@@ -1,230 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-import { assertEquals } from "../testing/asserts.ts";
-import * as c from "./colors.ts";
-import "../examples/colors.ts";
-
-Deno.test("singleColor", function (): void {
- assertEquals(c.red("foo bar"), "foo bar");
-});
-
-Deno.test("doubleColor", function (): void {
- assertEquals(c.bgBlue(c.red("foo bar")), "foo bar");
-});
-
-Deno.test("replacesCloseCharacters", function (): void {
- assertEquals(c.red("Hello"), "Hello");
-});
-
-Deno.test("enablingColors", function (): void {
- assertEquals(c.getColorEnabled(), true);
- c.setColorEnabled(false);
- assertEquals(c.bgBlue(c.red("foo bar")), "foo bar");
- c.setColorEnabled(true);
- assertEquals(c.red("foo bar"), "foo bar");
-});
-
-Deno.test("testBold", function (): void {
- assertEquals(c.bold("foo bar"), "foo bar");
-});
-
-Deno.test("testDim", function (): void {
- assertEquals(c.dim("foo bar"), "foo bar");
-});
-
-Deno.test("testItalic", function (): void {
- assertEquals(c.italic("foo bar"), "foo bar");
-});
-
-Deno.test("testUnderline", function (): void {
- assertEquals(c.underline("foo bar"), "foo bar");
-});
-
-Deno.test("testInverse", function (): void {
- assertEquals(c.inverse("foo bar"), "foo bar");
-});
-
-Deno.test("testHidden", function (): void {
- assertEquals(c.hidden("foo bar"), "foo bar");
-});
-
-Deno.test("testStrikethrough", function (): void {
- assertEquals(c.strikethrough("foo bar"), "foo bar");
-});
-
-Deno.test("testBlack", function (): void {
- assertEquals(c.black("foo bar"), "foo bar");
-});
-
-Deno.test("testRed", function (): void {
- assertEquals(c.red("foo bar"), "foo bar");
-});
-
-Deno.test("testGreen", function (): void {
- assertEquals(c.green("foo bar"), "foo bar");
-});
-
-Deno.test("testYellow", function (): void {
- assertEquals(c.yellow("foo bar"), "foo bar");
-});
-
-Deno.test("testBlue", function (): void {
- assertEquals(c.blue("foo bar"), "foo bar");
-});
-
-Deno.test("testMagenta", function (): void {
- assertEquals(c.magenta("foo bar"), "foo bar");
-});
-
-Deno.test("testCyan", function (): void {
- assertEquals(c.cyan("foo bar"), "foo bar");
-});
-
-Deno.test("testWhite", function (): void {
- assertEquals(c.white("foo bar"), "foo bar");
-});
-
-Deno.test("testGray", function (): void {
- assertEquals(c.gray("foo bar"), "foo bar");
-});
-
-Deno.test("testBrightBlack", function (): void {
- assertEquals(c.brightBlack("foo bar"), "foo bar");
-});
-
-Deno.test("testBrightRed", function (): void {
- assertEquals(c.brightRed("foo bar"), "foo bar");
-});
-
-Deno.test("testBrightGreen", function (): void {
- assertEquals(c.brightGreen("foo bar"), "foo bar");
-});
-
-Deno.test("testBrightYellow", function (): void {
- assertEquals(c.brightYellow("foo bar"), "foo bar");
-});
-
-Deno.test("testBrightBlue", function (): void {
- assertEquals(c.brightBlue("foo bar"), "foo bar");
-});
-
-Deno.test("testBrightMagenta", function (): void {
- assertEquals(c.brightMagenta("foo bar"), "foo bar");
-});
-
-Deno.test("testBrightCyan", function (): void {
- assertEquals(c.brightCyan("foo bar"), "foo bar");
-});
-
-Deno.test("testBrightWhite", function (): void {
- assertEquals(c.brightWhite("foo bar"), "foo bar");
-});
-
-Deno.test("testBgBlack", function (): void {
- assertEquals(c.bgBlack("foo bar"), "foo bar");
-});
-
-Deno.test("testBgRed", function (): void {
- assertEquals(c.bgRed("foo bar"), "foo bar");
-});
-
-Deno.test("testBgGreen", function (): void {
- assertEquals(c.bgGreen("foo bar"), "foo bar");
-});
-
-Deno.test("testBgYellow", function (): void {
- assertEquals(c.bgYellow("foo bar"), "foo bar");
-});
-
-Deno.test("testBgBlue", function (): void {
- assertEquals(c.bgBlue("foo bar"), "foo bar");
-});
-
-Deno.test("testBgMagenta", function (): void {
- assertEquals(c.bgMagenta("foo bar"), "foo bar");
-});
-
-Deno.test("testBgCyan", function (): void {
- assertEquals(c.bgCyan("foo bar"), "foo bar");
-});
-
-Deno.test("testBgWhite", function (): void {
- assertEquals(c.bgWhite("foo bar"), "foo bar");
-});
-
-Deno.test("testBgBrightBlack", function (): void {
- assertEquals(c.bgBrightBlack("foo bar"), "foo bar");
-});
-
-Deno.test("testBgBrightRed", function (): void {
- assertEquals(c.bgBrightRed("foo bar"), "foo bar");
-});
-
-Deno.test("testBgBrightGreen", function (): void {
- assertEquals(c.bgBrightGreen("foo bar"), "foo bar");
-});
-
-Deno.test("testBgBrightYellow", function (): void {
- assertEquals(c.bgBrightYellow("foo bar"), "foo bar");
-});
-
-Deno.test("testBgBrightBlue", function (): void {
- assertEquals(c.bgBrightBlue("foo bar"), "foo bar");
-});
-
-Deno.test("testBgBrightMagenta", function (): void {
- assertEquals(c.bgBrightMagenta("foo bar"), "foo bar");
-});
-
-Deno.test("testBgBrightCyan", function (): void {
- assertEquals(c.bgBrightCyan("foo bar"), "foo bar");
-});
-
-Deno.test("testBgBrightWhite", function (): void {
- assertEquals(c.bgBrightWhite("foo bar"), "foo bar");
-});
-
-Deno.test("testClampUsingRgb8", function (): void {
- assertEquals(c.rgb8("foo bar", -10), "foo bar");
-});
-
-Deno.test("testTruncateUsingRgb8", function (): void {
- assertEquals(c.rgb8("foo bar", 42.5), "foo bar");
-});
-
-Deno.test("testRgb8", function (): void {
- assertEquals(c.rgb8("foo bar", 42), "foo bar");
-});
-
-Deno.test("test_bgRgb8", function (): void {
- assertEquals(c.bgRgb8("foo bar", 42), "foo bar");
-});
-
-Deno.test("test_rgb24", function (): void {
- assertEquals(
- c.rgb24("foo bar", {
- r: 41,
- g: 42,
- b: 43,
- }),
- "foo bar",
- );
-});
-
-Deno.test("test_rgb24number", function (): void {
- assertEquals(c.rgb24("foo bar", 0x070809), "foo bar");
-});
-
-Deno.test("test_bgRgb24", function (): void {
- assertEquals(
- c.bgRgb24("foo bar", {
- r: 41,
- g: 42,
- b: 43,
- }),
- "foo bar",
- );
-});
-
-Deno.test("test_bgRgb24number", function (): void {
- assertEquals(c.bgRgb24("foo bar", 0x070809), "foo bar");
-});
diff --git a/std/fmt/printf.ts b/std/fmt/printf.ts
deleted file mode 100644
index 6a821f208..000000000
--- a/std/fmt/printf.ts
+++ /dev/null
@@ -1,757 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-/**
- * This implementation is inspired by POSIX and Golang but does not port
- * implementation code. */
-
-enum State {
- PASSTHROUGH,
- PERCENT,
- POSITIONAL,
- PRECISION,
- WIDTH,
-}
-
-enum WorP {
- WIDTH,
- PRECISION,
-}
-
-class Flags {
- plus?: boolean;
- dash?: boolean;
- sharp?: boolean;
- space?: boolean;
- zero?: boolean;
- lessthan?: boolean;
- width = -1;
- precision = -1;
-}
-
-const min = Math.min;
-const UNICODE_REPLACEMENT_CHARACTER = "\ufffd";
-const DEFAULT_PRECISION = 6;
-const FLOAT_REGEXP = /(-?)(\d)\.?(\d*)e([+-])(\d+)/;
-
-enum F {
- sign = 1,
- mantissa,
- fractional,
- esign,
- exponent,
-}
-
-class Printf {
- format: string;
- args: unknown[];
- i: number;
-
- state: State = State.PASSTHROUGH;
- verb = "";
- buf = "";
- argNum = 0;
- flags: Flags = new Flags();
-
- haveSeen: boolean[];
-
- // barf, store precision and width errors for later processing ...
- tmpError?: string;
-
- constructor(format: string, ...args: unknown[]) {
- this.format = format;
- this.args = args;
- this.haveSeen = new Array(args.length);
- this.i = 0;
- }
-
- doPrintf(): string {
- for (; this.i < this.format.length; ++this.i) {
- const c = this.format[this.i];
- switch (this.state) {
- case State.PASSTHROUGH:
- if (c === "%") {
- this.state = State.PERCENT;
- } else {
- this.buf += c;
- }
- break;
- case State.PERCENT:
- if (c === "%") {
- this.buf += c;
- this.state = State.PASSTHROUGH;
- } else {
- this.handleFormat();
- }
- break;
- default:
- throw Error("Should be unreachable, certainly a bug in the lib.");
- }
- }
- // check for unhandled args
- let extras = false;
- let err = "%!(EXTRA";
- for (let i = 0; i !== this.haveSeen.length; ++i) {
- if (!this.haveSeen[i]) {
- extras = true;
- err += ` '${Deno.inspect(this.args[i])}'`;
- }
- }
- err += ")";
- if (extras) {
- this.buf += err;
- }
- return this.buf;
- }
-
- // %[<positional>]<flag>...<verb>
- handleFormat(): void {
- this.flags = new Flags();
- const flags = this.flags;
- for (; this.i < this.format.length; ++this.i) {
- const c = this.format[this.i];
- switch (this.state) {
- case State.PERCENT:
- switch (c) {
- case "[":
- this.handlePositional();
- this.state = State.POSITIONAL;
- break;
- case "+":
- flags.plus = true;
- break;
- case "<":
- flags.lessthan = true;
- break;
- case "-":
- flags.dash = true;
- flags.zero = false; // only left pad zeros, dash takes precedence
- break;
- case "#":
- flags.sharp = true;
- break;
- case " ":
- flags.space = true;
- break;
- case "0":
- // only left pad zeros, dash takes precedence
- flags.zero = !flags.dash;
- break;
- default:
- if (("1" <= c && c <= "9") || c === "." || c === "*") {
- if (c === ".") {
- this.flags.precision = 0;
- this.state = State.PRECISION;
- this.i++;
- } else {
- this.state = State.WIDTH;
- }
- this.handleWidthAndPrecision(flags);
- } else {
- this.handleVerb();
- return; // always end in verb
- }
- } // switch c
- break;
- case State.POSITIONAL:
- // TODO(bartlomieju): either a verb or * only verb for now
- if (c === "*") {
- const worp = this.flags.precision === -1
- ? WorP.WIDTH
- : WorP.PRECISION;
- this.handleWidthOrPrecisionRef(worp);
- this.state = State.PERCENT;
- break;
- } else {
- this.handleVerb();
- return; // always end in verb
- }
- default:
- throw new Error(`Should not be here ${this.state}, library bug!`);
- } // switch state
- }
- }
-
- /**
- * Handle width or precision
- * @param wOrP
- */
- handleWidthOrPrecisionRef(wOrP: WorP): void {
- if (this.argNum >= this.args.length) {
- // handle Positional should have already taken care of it...
- return;
- }
- const arg = this.args[this.argNum];
- this.haveSeen[this.argNum] = true;
- if (typeof arg === "number") {
- switch (wOrP) {
- case WorP.WIDTH:
- this.flags.width = arg;
- break;
- default:
- this.flags.precision = arg;
- }
- } else {
- const tmp = wOrP === WorP.WIDTH ? "WIDTH" : "PREC";
- this.tmpError = `%!(BAD ${tmp} '${this.args[this.argNum]}')`;
- }
- this.argNum++;
- }
-
- /**
- * Handle width and precision
- * @param flags
- */
- handleWidthAndPrecision(flags: Flags): void {
- const fmt = this.format;
- for (; this.i !== this.format.length; ++this.i) {
- const c = fmt[this.i];
- switch (this.state) {
- case State.WIDTH:
- switch (c) {
- case ".":
- // initialize precision, %9.f -> precision=0
- this.flags.precision = 0;
- this.state = State.PRECISION;
- break;
- case "*":
- this.handleWidthOrPrecisionRef(WorP.WIDTH);
- // force . or flag at this point
- break;
- default: {
- const val = parseInt(c);
- // most likely parseInt does something stupid that makes
- // it unusable for this scenario ...
- // if we encounter a non (number|*|.) we're done with prec & wid
- if (isNaN(val)) {
- this.i--;
- this.state = State.PERCENT;
- return;
- }
- flags.width = flags.width == -1 ? 0 : flags.width;
- flags.width *= 10;
- flags.width += val;
- }
- } // switch c
- break;
- case State.PRECISION: {
- if (c === "*") {
- this.handleWidthOrPrecisionRef(WorP.PRECISION);
- break;
- }
- const val = parseInt(c);
- if (isNaN(val)) {
- // one too far, rewind
- this.i--;
- this.state = State.PERCENT;
- return;
- }
- flags.precision *= 10;
- flags.precision += val;
- break;
- }
- default:
- throw new Error("can't be here. bug.");
- } // switch state
- }
- }
-
- /** Handle positional */
- handlePositional(): void {
- if (this.format[this.i] !== "[") {
- // sanity only
- throw new Error("Can't happen? Bug.");
- }
- let positional = 0;
- const format = this.format;
- this.i++;
- let err = false;
- for (; this.i !== this.format.length; ++this.i) {
- if (format[this.i] === "]") {
- break;
- }
- positional *= 10;
- const val = parseInt(format[this.i]);
- if (isNaN(val)) {
- //throw new Error(
- // `invalid character in positional: ${format}[${format[this.i]}]`
- //);
- this.tmpError = "%!(BAD INDEX)";
- err = true;
- }
- positional += val;
- }
- if (positional - 1 >= this.args.length) {
- this.tmpError = "%!(BAD INDEX)";
- err = true;
- }
- this.argNum = err ? this.argNum : positional - 1;
- return;
- }
-
- /** Handle less than */
- handleLessThan(): string {
- // deno-lint-ignore no-explicit-any
- const arg = this.args[this.argNum] as any;
- if ((arg || {}).constructor.name !== "Array") {
- throw new Error(`arg ${arg} is not an array. Todo better error handling`);
- }
- let str = "[ ";
- for (let i = 0; i !== arg.length; ++i) {
- if (i !== 0) str += ", ";
- str += this._handleVerb(arg[i]);
- }
- return str + " ]";
- }
-
- /** Handle verb */
- handleVerb(): void {
- const verb = this.format[this.i];
- this.verb = verb;
- if (this.tmpError) {
- this.buf += this.tmpError;
- this.tmpError = undefined;
- if (this.argNum < this.haveSeen.length) {
- this.haveSeen[this.argNum] = true; // keep track of used args
- }
- } else if (this.args.length <= this.argNum) {
- this.buf += `%!(MISSING '${verb}')`;
- } else {
- const arg = this.args[this.argNum]; // check out of range
- this.haveSeen[this.argNum] = true; // keep track of used args
- if (this.flags.lessthan) {
- this.buf += this.handleLessThan();
- } else {
- this.buf += this._handleVerb(arg);
- }
- }
- this.argNum++; // if there is a further positional, it will reset.
- this.state = State.PASSTHROUGH;
- }
-
- // deno-lint-ignore no-explicit-any
- _handleVerb(arg: any): string {
- switch (this.verb) {
- case "t":
- return this.pad(arg.toString());
- case "b":
- return this.fmtNumber(arg as number, 2);
- case "c":
- return this.fmtNumberCodePoint(arg as number);
- case "d":
- return this.fmtNumber(arg as number, 10);
- case "o":
- return this.fmtNumber(arg as number, 8);
- case "x":
- return this.fmtHex(arg);
- case "X":
- return this.fmtHex(arg, true);
- case "e":
- return this.fmtFloatE(arg as number);
- case "E":
- return this.fmtFloatE(arg as number, true);
- case "f":
- case "F":
- return this.fmtFloatF(arg as number);
- case "g":
- return this.fmtFloatG(arg as number);
- case "G":
- return this.fmtFloatG(arg as number, true);
- case "s":
- return this.fmtString(arg as string);
- case "T":
- return this.fmtString(typeof arg);
- case "v":
- return this.fmtV(arg);
- case "j":
- return this.fmtJ(arg);
- default:
- return `%!(BAD VERB '${this.verb}')`;
- }
- }
-
- /**
- * Pad a string
- * @param s text to pad
- */
- pad(s: string): string {
- const padding = this.flags.zero ? "0" : " ";
-
- if (this.flags.dash) {
- return s.padEnd(this.flags.width, padding);
- }
-
- return s.padStart(this.flags.width, padding);
- }
-
- /**
- * Pad a number
- * @param nStr
- * @param neg
- */
- padNum(nStr: string, neg: boolean): string {
- let sign: string;
- if (neg) {
- sign = "-";
- } else if (this.flags.plus || this.flags.space) {
- sign = this.flags.plus ? "+" : " ";
- } else {
- sign = "";
- }
- const zero = this.flags.zero;
- if (!zero) {
- // sign comes in front of padding when padding w/ zero,
- // in from of value if padding with spaces.
- nStr = sign + nStr;
- }
-
- const pad = zero ? "0" : " ";
- const len = zero ? this.flags.width - sign.length : this.flags.width;
-
- if (this.flags.dash) {
- nStr = nStr.padEnd(len, pad);
- } else {
- nStr = nStr.padStart(len, pad);
- }
-
- if (zero) {
- // see above
- nStr = sign + nStr;
- }
- return nStr;
- }
-
- /**
- * Format a number
- * @param n
- * @param radix
- * @param upcase
- */
- fmtNumber(n: number, radix: number, upcase = false): string {
- let num = Math.abs(n).toString(radix);
- const prec = this.flags.precision;
- if (prec !== -1) {
- this.flags.zero = false;
- num = n === 0 && prec === 0 ? "" : num;
- while (num.length < prec) {
- num = "0" + num;
- }
- }
- let prefix = "";
- if (this.flags.sharp) {
- switch (radix) {
- case 2:
- prefix += "0b";
- break;
- case 8:
- // don't annotate octal 0 with 0...
- prefix += num.startsWith("0") ? "" : "0";
- break;
- case 16:
- prefix += "0x";
- break;
- default:
- throw new Error("cannot handle base: " + radix);
- }
- }
- // don't add prefix in front of value truncated by precision=0, val=0
- num = num.length === 0 ? num : prefix + num;
- if (upcase) {
- num = num.toUpperCase();
- }
- return this.padNum(num, n < 0);
- }
-
- /**
- * Format number with code points
- * @param n
- */
- fmtNumberCodePoint(n: number): string {
- let s = "";
- try {
- s = String.fromCodePoint(n);
- } catch (RangeError) {
- s = UNICODE_REPLACEMENT_CHARACTER;
- }
- return this.pad(s);
- }
-
- /**
- * Format special float
- * @param n
- */
- fmtFloatSpecial(n: number): string {
- // formatting of NaN and Inf are pants-on-head
- // stupid and more or less arbitrary.
-
- if (isNaN(n)) {
- this.flags.zero = false;
- return this.padNum("NaN", false);
- }
- if (n === Number.POSITIVE_INFINITY) {
- this.flags.zero = false;
- this.flags.plus = true;
- return this.padNum("Inf", false);
- }
- if (n === Number.NEGATIVE_INFINITY) {
- this.flags.zero = false;
- return this.padNum("Inf", true);
- }
- return "";
- }
-
- /**
- * Round fraction to precision
- * @param fractional
- * @param precision
- */
- roundFractionToPrecision(fractional: string, precision: number): string {
- if (fractional.length > precision) {
- fractional = "1" + fractional; // prepend a 1 in case of leading 0
- let tmp = parseInt(fractional.substr(0, precision + 2)) / 10;
- tmp = Math.round(tmp);
- fractional = Math.floor(tmp).toString();
- fractional = fractional.substr(1); // remove extra 1
- } else {
- while (fractional.length < precision) {
- fractional += "0";
- }
- }
- return fractional;
- }
-
- /**
- * Format float E
- * @param n
- * @param upcase
- */
- fmtFloatE(n: number, upcase = false): string {
- const special = this.fmtFloatSpecial(n);
- if (special !== "") {
- return special;
- }
-
- const m = n.toExponential().match(FLOAT_REGEXP);
- if (!m) {
- throw Error("can't happen, bug");
- }
-
- let fractional = m[F.fractional];
- const precision = this.flags.precision !== -1
- ? this.flags.precision
- : DEFAULT_PRECISION;
- fractional = this.roundFractionToPrecision(fractional, precision);
-
- let e = m[F.exponent];
- // scientific notation output with exponent padded to minlen 2
- e = e.length == 1 ? "0" + e : e;
-
- const val = `${m[F.mantissa]}.${fractional}${upcase ? "E" : "e"}${
- m[F.esign]
- }${e}`;
- return this.padNum(val, n < 0);
- }
-
- /**
- * Format float F
- * @param n
- */
- fmtFloatF(n: number): string {
- const special = this.fmtFloatSpecial(n);
- if (special !== "") {
- return special;
- }
-
- // stupid helper that turns a number into a (potentially)
- // VERY long string.
- function expandNumber(n: number): string {
- if (Number.isSafeInteger(n)) {
- return n.toString() + ".";
- }
-
- const t = n.toExponential().split("e");
- let m = t[0].replace(".", "");
- const e = parseInt(t[1]);
- if (e < 0) {
- let nStr = "0.";
- for (let i = 0; i !== Math.abs(e) - 1; ++i) {
- nStr += "0";
- }
- return (nStr += m);
- } else {
- const splIdx = e + 1;
- while (m.length < splIdx) {
- m += "0";
- }
- return m.substr(0, splIdx) + "." + m.substr(splIdx);
- }
- }
- // avoiding sign makes padding easier
- const val = expandNumber(Math.abs(n)) as string;
- const arr = val.split(".");
- const dig = arr[0];
- let fractional = arr[1];
-
- const precision = this.flags.precision !== -1
- ? this.flags.precision
- : DEFAULT_PRECISION;
- fractional = this.roundFractionToPrecision(fractional, precision);
-
- return this.padNum(`${dig}.${fractional}`, n < 0);
- }
-
- /**
- * Format float G
- * @param n
- * @param upcase
- */
- fmtFloatG(n: number, upcase = false): string {
- const special = this.fmtFloatSpecial(n);
- if (special !== "") {
- return special;
- }
-
- // The double argument representing a floating-point number shall be
- // converted in the style f or e (or in the style F or E in
- // the case of a G conversion specifier), depending on the
- // value converted and the precision. Let P equal the
- // precision if non-zero, 6 if the precision is omitted, or 1
- // if the precision is zero. Then, if a conversion with style E would
- // have an exponent of X:
-
- // - If P > X>=-4, the conversion shall be with style f (or F )
- // and precision P -( X+1).
-
- // - Otherwise, the conversion shall be with style e (or E )
- // and precision P -1.
-
- // Finally, unless the '#' flag is used, any trailing zeros shall be
- // removed from the fractional portion of the result and the
- // decimal-point character shall be removed if there is no
- // fractional portion remaining.
-
- // A double argument representing an infinity or NaN shall be
- // converted in the style of an f or F conversion specifier.
- // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
-
- let P = this.flags.precision !== -1
- ? this.flags.precision
- : DEFAULT_PRECISION;
- P = P === 0 ? 1 : P;
-
- const m = n.toExponential().match(FLOAT_REGEXP);
- if (!m) {
- throw Error("can't happen");
- }
-
- const X = parseInt(m[F.exponent]) * (m[F.esign] === "-" ? -1 : 1);
- let nStr = "";
- if (P > X && X >= -4) {
- this.flags.precision = P - (X + 1);
- nStr = this.fmtFloatF(n);
- if (!this.flags.sharp) {
- nStr = nStr.replace(/\.?0*$/, "");
- }
- } else {
- this.flags.precision = P - 1;
- nStr = this.fmtFloatE(n);
- if (!this.flags.sharp) {
- nStr = nStr.replace(/\.?0*e/, upcase ? "E" : "e");
- }
- }
- return nStr;
- }
-
- /**
- * Format string
- * @param s
- */
- fmtString(s: string): string {
- if (this.flags.precision !== -1) {
- s = s.substr(0, this.flags.precision);
- }
- return this.pad(s);
- }
-
- /**
- * Format hex
- * @param val
- * @param upper
- */
- fmtHex(val: string | number, upper = false): string {
- // allow others types ?
- switch (typeof val) {
- case "number":
- return this.fmtNumber(val as number, 16, upper);
- case "string": {
- const sharp = this.flags.sharp && val.length !== 0;
- let hex = sharp ? "0x" : "";
- const prec = this.flags.precision;
- const end = prec !== -1 ? min(prec, val.length) : val.length;
- for (let i = 0; i !== end; ++i) {
- if (i !== 0 && this.flags.space) {
- hex += sharp ? " 0x" : " ";
- }
- // TODO(bartlomieju): for now only taking into account the
- // lower half of the codePoint, ie. as if a string
- // is a list of 8bit values instead of UCS2 runes
- const c = (val.charCodeAt(i) & 0xff).toString(16);
- hex += c.length === 1 ? `0${c}` : c;
- }
- if (upper) {
- hex = hex.toUpperCase();
- }
- return this.pad(hex);
- }
- default:
- throw new Error(
- "currently only number and string are implemented for hex",
- );
- }
- }
-
- /**
- * Format value
- * @param val
- */
- fmtV(val: Record<string, unknown>): string {
- if (this.flags.sharp) {
- const options = this.flags.precision !== -1
- ? { depth: this.flags.precision }
- : {};
- return this.pad(Deno.inspect(val, options));
- } else {
- const p = this.flags.precision;
- return p === -1 ? val.toString() : val.toString().substr(0, p);
- }
- }
-
- /**
- * Format JSON
- * @param val
- */
- fmtJ(val: unknown): string {
- return JSON.stringify(val);
- }
-}
-
-/**
- * Converts and format a variable number of `args` as is specified by `format`.
- * `sprintf` returns the formatted string.
- *
- * @param format
- * @param args
- */
-export function sprintf(format: string, ...args: unknown[]): string {
- const printf = new Printf(format, ...args);
- return printf.doPrintf();
-}
-
-/**
- * Converts and format a variable number of `args` as is specified by `format`.
- * `printf` writes the formatted string to standard output.
- * @param format
- * @param args
- */
-export function printf(format: string, ...args: unknown[]): void {
- const s = sprintf(format, ...args);
- Deno.stdout.writeSync(new TextEncoder().encode(s));
-}
diff --git a/std/fmt/printf_test.ts b/std/fmt/printf_test.ts
deleted file mode 100644
index f24085848..000000000
--- a/std/fmt/printf_test.ts
+++ /dev/null
@@ -1,674 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-//
-// A number of test-cases based on:
-//
-// https://golang.org/src/fmt/fmt_test.go
-// BSD: Copyright (c) 2009 The Go Authors. All rights reserved.
-
-import { sprintf } from "./printf.ts";
-import { assertEquals } from "../testing/asserts.ts";
-
-const S = sprintf;
-
-Deno.test("noVerb", function (): void {
- assertEquals(sprintf("bla"), "bla");
-});
-
-Deno.test("percent", function (): void {
- assertEquals(sprintf("%%"), "%");
- assertEquals(sprintf("!%%!"), "!%!");
- assertEquals(sprintf("!%%"), "!%");
- assertEquals(sprintf("%%!"), "%!");
-});
-Deno.test("testBoolean", function (): void {
- assertEquals(sprintf("%t", true), "true");
- assertEquals(sprintf("%10t", true), " true");
- assertEquals(sprintf("%-10t", false), "false ");
- assertEquals(sprintf("%t", false), "false");
- assertEquals(sprintf("bla%t", true), "blatrue");
- assertEquals(sprintf("%tbla", false), "falsebla");
-});
-
-Deno.test("testIntegerB", function (): void {
- assertEquals(S("%b", 4), "100");
- assertEquals(S("%b", -4), "-100");
- assertEquals(
- S("%b", 4.1),
- "100.0001100110011001100110011001100110011001100110011",
- );
- assertEquals(
- S("%b", -4.1),
- "-100.0001100110011001100110011001100110011001100110011",
- );
- assertEquals(
- S("%b", Number.MAX_SAFE_INTEGER),
- "11111111111111111111111111111111111111111111111111111",
- );
- assertEquals(
- S("%b", Number.MIN_SAFE_INTEGER),
- "-11111111111111111111111111111111111111111111111111111",
- );
- // width
-
- assertEquals(S("%4b", 4), " 100");
-});
-
-Deno.test("testIntegerC", function (): void {
- assertEquals(S("%c", 0x31), "1");
- assertEquals(S("%c%b", 0x31, 1), "11");
- assertEquals(S("%c", 0x1f4a9), "💩");
- //width
- assertEquals(S("%4c", 0x31), " 1");
-});
-
-Deno.test("testIntegerD", function (): void {
- assertEquals(S("%d", 4), "4");
- assertEquals(S("%d", -4), "-4");
- assertEquals(S("%d", Number.MAX_SAFE_INTEGER), "9007199254740991");
- assertEquals(S("%d", Number.MIN_SAFE_INTEGER), "-9007199254740991");
-});
-
-Deno.test("testIntegerO", function (): void {
- assertEquals(S("%o", 4), "4");
- assertEquals(S("%o", -4), "-4");
- assertEquals(S("%o", 9), "11");
- assertEquals(S("%o", -9), "-11");
- assertEquals(S("%o", Number.MAX_SAFE_INTEGER), "377777777777777777");
- assertEquals(S("%o", Number.MIN_SAFE_INTEGER), "-377777777777777777");
- // width
- assertEquals(S("%4o", 4), " 4");
-});
-Deno.test("testIntegerx", function (): void {
- assertEquals(S("%x", 4), "4");
- assertEquals(S("%x", -4), "-4");
- assertEquals(S("%x", 9), "9");
- assertEquals(S("%x", -9), "-9");
- assertEquals(S("%x", Number.MAX_SAFE_INTEGER), "1fffffffffffff");
- assertEquals(S("%x", Number.MIN_SAFE_INTEGER), "-1fffffffffffff");
- // width
- assertEquals(S("%4x", -4), " -4");
- assertEquals(S("%-4x", -4), "-4 ");
- // plus
- assertEquals(S("%+4x", 4), " +4");
- assertEquals(S("%-+4x", 4), "+4 ");
-});
-Deno.test("testIntegerX", function (): void {
- assertEquals(S("%X", 4), "4");
- assertEquals(S("%X", -4), "-4");
- assertEquals(S("%X", 9), "9");
- assertEquals(S("%X", -9), "-9");
- assertEquals(S("%X", Number.MAX_SAFE_INTEGER), "1FFFFFFFFFFFFF");
- assertEquals(S("%X", Number.MIN_SAFE_INTEGER), "-1FFFFFFFFFFFFF");
-});
-
-Deno.test("testFloate", function (): void {
- assertEquals(S("%e", 4), "4.000000e+00");
- assertEquals(S("%e", -4), "-4.000000e+00");
- assertEquals(S("%e", 4.1), "4.100000e+00");
- assertEquals(S("%e", -4.1), "-4.100000e+00");
- assertEquals(S("%e", Number.MAX_SAFE_INTEGER), "9.007199e+15");
- assertEquals(S("%e", Number.MIN_SAFE_INTEGER), "-9.007199e+15");
-});
-Deno.test("testFloatE", function (): void {
- assertEquals(S("%E", 4), "4.000000E+00");
- assertEquals(S("%E", -4), "-4.000000E+00");
- assertEquals(S("%E", 4.1), "4.100000E+00");
- assertEquals(S("%E", -4.1), "-4.100000E+00");
- assertEquals(S("%E", Number.MAX_SAFE_INTEGER), "9.007199E+15");
- assertEquals(S("%E", Number.MIN_SAFE_INTEGER), "-9.007199E+15");
- assertEquals(S("%E", Number.MIN_VALUE), "5.000000E-324");
- assertEquals(S("%E", Number.MAX_VALUE), "1.797693E+308");
-});
-Deno.test("testFloatfF", function (): void {
- assertEquals(S("%f", 4), "4.000000");
- assertEquals(S("%F", 4), "4.000000");
- assertEquals(S("%f", -4), "-4.000000");
- assertEquals(S("%F", -4), "-4.000000");
- assertEquals(S("%f", 4.1), "4.100000");
- assertEquals(S("%F", 4.1), "4.100000");
- assertEquals(S("%f", -4.1), "-4.100000");
- assertEquals(S("%F", -4.1), "-4.100000");
- assertEquals(S("%f", Number.MAX_SAFE_INTEGER), "9007199254740991.000000");
- assertEquals(S("%F", Number.MAX_SAFE_INTEGER), "9007199254740991.000000");
- assertEquals(S("%f", Number.MIN_SAFE_INTEGER), "-9007199254740991.000000");
- assertEquals(S("%F", Number.MIN_SAFE_INTEGER), "-9007199254740991.000000");
- assertEquals(S("%f", Number.MIN_VALUE), "0.000000");
- assertEquals(
- S("%.324f", Number.MIN_VALUE),
- // eslint-disable-next-line max-len
- "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005",
- );
- assertEquals(S("%F", Number.MIN_VALUE), "0.000000");
- assertEquals(
- S("%f", Number.MAX_VALUE),
- // eslint-disable-next-line max-len
- "179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000",
- );
- assertEquals(
- S("%F", Number.MAX_VALUE),
- // eslint-disable-next-line max-len
- "179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000",
- );
-});
-
-Deno.test("testString", function (): void {
- assertEquals(S("%s World%s", "Hello", "!"), "Hello World!");
-});
-
-Deno.test("testHex", function (): void {
- assertEquals(S("%x", "123"), "313233");
- assertEquals(S("%x", "n"), "6e");
-});
-Deno.test("testHeX", function (): void {
- assertEquals(S("%X", "123"), "313233");
- assertEquals(S("%X", "n"), "6E");
-});
-
-Deno.test("testType", function (): void {
- assertEquals(S("%T", new Date()), "object");
- assertEquals(S("%T", 123), "number");
- assertEquals(S("%T", "123"), "string");
- assertEquals(S("%.3T", "123"), "str");
-});
-
-Deno.test("testPositional", function (): void {
- assertEquals(S("%[1]d%[2]d", 1, 2), "12");
- assertEquals(S("%[2]d%[1]d", 1, 2), "21");
-});
-
-Deno.test("testSharp", function (): void {
- assertEquals(S("%#x", "123"), "0x313233");
- assertEquals(S("%#X", "123"), "0X313233");
- assertEquals(S("%#x", 123), "0x7b");
- assertEquals(S("%#X", 123), "0X7B");
- assertEquals(S("%#o", 123), "0173");
- assertEquals(S("%#b", 4), "0b100");
-});
-
-Deno.test("testWidthAndPrecision", function (): void {
- assertEquals(
- S("%9.99d", 9),
- // eslint-disable-next-line max-len
- "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009",
- );
- assertEquals(S("%1.12d", 9), "000000000009");
- assertEquals(S("%2s", "a"), " a");
- assertEquals(S("%2d", 1), " 1");
- assertEquals(S("%#4x", 1), " 0x1");
-
- assertEquals(
- S("%*.99d", 9, 9),
- // eslint-disable-next-line max-len
- "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009",
- );
- assertEquals(
- S("%9.*d", 99, 9),
- // eslint-disable-next-line max-len
- "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009",
- );
- assertEquals(S("%*s", 2, "a"), " a");
- assertEquals(S("%*d", 2, 1), " 1");
- assertEquals(S("%#*x", 4, 1), " 0x1");
-});
-
-Deno.test("testDash", function (): void {
- assertEquals(S("%-2s", "a"), "a ");
- assertEquals(S("%-2d", 1), "1 ");
-});
-Deno.test("testPlus", function (): void {
- assertEquals(S("%-+3d", 1), "+1 ");
- assertEquals(S("%+3d", 1), " +1");
- assertEquals(S("%+3d", -1), " -1");
-});
-
-Deno.test("testSpace", function (): void {
- assertEquals(S("% -3d", 3), " 3 ");
-});
-
-Deno.test("testZero", function (): void {
- assertEquals(S("%04s", "a"), "000a");
-});
-
-// relevant test cases from fmt_test.go
-// deno-lint-ignore no-explicit-any
-const tests: Array<[string, any, string]> = [
- ["%d", 12345, "12345"],
- ["%v", 12345, "12345"],
- ["%t", true, "true"],
- // basic string
- ["%s", "abc", "abc"],
- // ["%q", "abc", `"abc"`], // TODO: need %q?
- ["%x", "abc", "616263"],
- ["%x", "\xff\xf0\x0f\xff", "fff00fff"],
- ["%X", "\xff\xf0\x0f\xff", "FFF00FFF"],
- ["%x", "", ""],
- ["% x", "", ""],
- ["%#x", "", ""],
- ["%# x", "", ""],
- ["%x", "xyz", "78797a"],
- ["%X", "xyz", "78797A"],
- ["% x", "xyz", "78 79 7a"],
- ["% X", "xyz", "78 79 7A"],
- ["%#x", "xyz", "0x78797a"],
- ["%#X", "xyz", "0X78797A"],
- ["%# x", "xyz", "0x78 0x79 0x7a"],
- ["%# X", "xyz", "0X78 0X79 0X7A"],
- // basic bytes : TODO special handling for Buffer? other std types?
- // escaped strings : TODO decide whether to have %q
-
- // characters
- ["%c", "x".charCodeAt(0), "x"],
- ["%c", 0xe4, "ä"],
- ["%c", 0x672c, "本"],
- ["%c", "æ—¥".charCodeAt(0), "æ—¥"],
- // Specifying precision should have no effect.
- ["%.0c", "⌘".charCodeAt(0), "⌘"],
- ["%3c", "⌘".charCodeAt(0), " ⌘"],
- ["%-3c", "⌘".charCodeAt(0), "⌘ "],
- // Runes that are not printable.
- // {"%c", '\U00000e00', "\u0e00"},
- // TODO(bartlomieju) check if \U escape exists in js
- //["%c", '\U0010ffff'.codePointAt(0), "\U0010ffff"],
-
- // Runes that are not valid.
- ["%c", -1, "�"],
- // TODO(bartomieju): surrogate half, doesn't make sense in itself, how
- // to determine in JS?
- // ["%c", 0xDC80, "�"],
- ["%c", 0x110000, "�"],
- ["%c", 0xfffffffff, "�"],
- // TODO(bartlomieju):
- // escaped characters
- // Runes that are not printable.
- // Runes that are not valid.
-
- // width
- ["%5s", "abc", " abc"],
- ["%2s", "\u263a", " ☺"],
- ["%-5s", "abc", "abc "],
- ["%05s", "abc", "00abc"],
- ["%5s", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"],
- ["%.5s", "abcdefghijklmnopqrstuvwxyz", "abcde"],
- ["%.0s", "日本語日本語", ""],
- ["%.5s", "日本語日本語", "日本語日本"],
- ["%.10s", "日本語日本語", "日本語日本語"],
- // ["%08q", "abc", `000"abc"`],
- // TODO(bartlomieju): verb q
- // ["%-8q", "abc", `"abc" `],
- //["%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`],
- ["%.5x", "abcdefghijklmnopqrstuvwxyz", "6162636465"],
- //["%.3q", "日本語日本語", `"日本語"`],
- //["%.1q", "日本語", `"日"`]
- // change of go testcase utf-8([æ—¥]) = 0xe697a5, utf-16= 65e5 and
- // our %x takes lower byte of string "%.1x", "日本語", "e6"],,
- ["%.1x", "日本語", "e5"],
- //["%10.1q", "日本語日本語", ` "日"`],
- // ["%10v", null, " <nil>"],
- // TODO(bartlomieju): null, undefined ...
- // ["%-10v", null, "<nil> "],
-
- // integers
- ["%d", 12345, "12345"],
- ["%d", -12345, "-12345"],
- // ["%d", ^uint8(0), "255"],
- //["%d", ^uint16(0), "65535"],
- //["%d", ^uint32(0), "4294967295"],
- //["%d", ^uint64(0), "18446744073709551615"],
- ["%d", -1 << 7, "-128"],
- ["%d", -1 << 15, "-32768"],
- ["%d", -1 << 31, "-2147483648"],
- //["%d", (-1 << 63), "-9223372036854775808"],
- ["%.d", 0, ""],
- ["%.0d", 0, ""],
- ["%6.0d", 0, " "],
- ["%06.0d", 0, " "], // 0 flag should be ignored
- ["% d", 12345, " 12345"],
- ["%+d", 12345, "+12345"],
- ["%+d", -12345, "-12345"],
- ["%b", 7, "111"],
- ["%b", -6, "-110"],
- // ["%b", ^uint32(0), "11111111111111111111111111111111"],
- // ["%b", ^uint64(0),
- // "1111111111111111111111111111111111111111111111111111111111111111"],
- // ["%b", int64(-1 << 63), zeroFill("-1", 63, "")],
- // 0 octal notation not allowed in struct node...
- ["%o", parseInt("01234", 8), "1234"],
- ["%#o", parseInt("01234", 8), "01234"],
- // ["%o", ^uint32(0), "37777777777"],
- // ["%o", ^uint64(0), "1777777777777777777777"],
- ["%#X", 0, "0X0"],
- ["%x", 0x12abcdef, "12abcdef"],
- ["%X", 0x12abcdef, "12ABCDEF"],
- // ["%x", ^uint32(0), "ffffffff"],
- // ["%X", ^uint64(0), "FFFFFFFFFFFFFFFF"],
- ["%.20b", 7, "00000000000000000111"],
- ["%10d", 12345, " 12345"],
- ["%10d", -12345, " -12345"],
- ["%+10d", 12345, " +12345"],
- ["%010d", 12345, "0000012345"],
- ["%010d", -12345, "-000012345"],
- ["%20.8d", 1234, " 00001234"],
- ["%20.8d", -1234, " -00001234"],
- ["%020.8d", 1234, " 00001234"],
- ["%020.8d", -1234, " -00001234"],
- ["%-20.8d", 1234, "00001234 "],
- ["%-20.8d", -1234, "-00001234 "],
- ["%-#20.8x", 0x1234abc, "0x01234abc "],
- ["%-#20.8X", 0x1234abc, "0X01234ABC "],
- ["%-#20.8o", parseInt("01234", 8), "00001234 "],
- // Test correct f.intbuf overflow checks.
- // TODO(bartlomieju): lazy
- // unicode format
- // TODO(bartlomieju): decide whether unicode verb makes sense %U
-
- // floats
- ["%+.3e", 0.0, "+0.000e+00"],
- ["%+.3e", 1.0, "+1.000e+00"],
- ["%+.3f", -1.0, "-1.000"],
- ["%+.3F", -1.0, "-1.000"],
- //["%+.3F", float32(-1.0), "-1.000"],
- ["%+07.2f", 1.0, "+001.00"],
- ["%+07.2f", -1.0, "-001.00"],
- ["%-07.2f", 1.0, "1.00 "],
- ["%-07.2f", -1.0, "-1.00 "],
- ["%+-07.2f", 1.0, "+1.00 "],
- ["%+-07.2f", -1.0, "-1.00 "],
- ["%-+07.2f", 1.0, "+1.00 "],
- ["%-+07.2f", -1.0, "-1.00 "],
- ["%+10.2f", +1.0, " +1.00"],
- ["%+10.2f", -1.0, " -1.00"],
- ["% .3E", -1.0, "-1.000E+00"],
- ["% .3e", 1.0, " 1.000e+00"],
- ["%+.3g", 0.0, "+0"],
- ["%+.3g", 1.0, "+1"],
- ["%+.3g", -1.0, "-1"],
- ["% .3g", -1.0, "-1"],
- ["% .3g", 1.0, " 1"],
- // //["%b", float32(1.0), "8388608p-23"],
- // ["%b", 1.0, "4503599627370496p-52"],
- // // Test sharp flag used with floats.
- ["%#g", 1e-323, "1.00000e-323"],
- ["%#g", -1.0, "-1.00000"],
- ["%#g", 1.1, "1.10000"],
- ["%#g", 123456.0, "123456."],
- //["%#g", 1234567.0, "1.234567e+06"],
- // the line above is incorrect in go (according to
- // my posix reading) %f-> prec = prec-1
- ["%#g", 1234567.0, "1.23457e+06"],
- ["%#g", 1230000.0, "1.23000e+06"],
- ["%#g", 1000000.0, "1.00000e+06"],
- ["%#.0f", 1.0, "1."],
- ["%#.0e", 1.0, "1.e+00"],
- ["%#.0g", 1.0, "1."],
- ["%#.0g", 1100000.0, "1.e+06"],
- ["%#.4f", 1.0, "1.0000"],
- ["%#.4e", 1.0, "1.0000e+00"],
- ["%#.4g", 1.0, "1.000"],
- ["%#.4g", 100000.0, "1.000e+05"],
- ["%#.0f", 123.0, "123."],
- ["%#.0e", 123.0, "1.e+02"],
- ["%#.0g", 123.0, "1.e+02"],
- ["%#.4f", 123.0, "123.0000"],
- ["%#.4e", 123.0, "1.2300e+02"],
- ["%#.4g", 123.0, "123.0"],
- ["%#.4g", 123000.0, "1.230e+05"],
- ["%#9.4g", 1.0, " 1.000"],
- // The sharp flag has no effect for binary float format.
- // ["%#b", 1.0, "4503599627370496p-52"], // TODO binary for floats
- // Precision has no effect for binary float format.
- //["%.4b", float32(1.0), "8388608p-23"], // TODO s.above
- // ["%.4b", -1.0, "-4503599627370496p-52"],
- // Test correct f.intbuf boundary checks.
- //["%.68f", 1.0, zeroFill("1.", 68, "")], // TODO zerofill
- //["%.68f", -1.0, zeroFill("-1.", 68, "")], //TODO s.a.
- // float infinites and NaNs
- ["%f", Number.POSITIVE_INFINITY, "+Inf"],
- ["%.1f", Number.NEGATIVE_INFINITY, "-Inf"],
- ["% f", NaN, " NaN"],
- ["%20f", Number.POSITIVE_INFINITY, " +Inf"],
- // ["% 20F", Number.POSITIVE_INFINITY, " Inf"], // TODO : wut?
- ["% 20e", Number.NEGATIVE_INFINITY, " -Inf"],
- ["%+20E", Number.NEGATIVE_INFINITY, " -Inf"],
- ["% +20g", Number.NEGATIVE_INFINITY, " -Inf"],
- ["%+-20G", Number.POSITIVE_INFINITY, "+Inf "],
- ["%20e", NaN, " NaN"],
- ["% +20E", NaN, " +NaN"],
- ["% -20g", NaN, " NaN "],
- ["%+-20G", NaN, "+NaN "],
- // Zero padding does not apply to infinities and NaN.
- ["%+020e", Number.POSITIVE_INFINITY, " +Inf"],
- ["%-020f", Number.NEGATIVE_INFINITY, "-Inf "],
- ["%-020E", NaN, "NaN "],
- // complex values // go specific
- // old test/fmt_test.go
- ["%e", 1.0, "1.000000e+00"],
- ["%e", 1234.5678e3, "1.234568e+06"],
- ["%e", 1234.5678e-8, "1.234568e-05"],
- ["%e", -7.0, "-7.000000e+00"],
- ["%e", -1e-9, "-1.000000e-09"],
- ["%f", 1234.5678e3, "1234567.800000"],
- ["%f", 1234.5678e-8, "0.000012"],
- ["%f", -7.0, "-7.000000"],
- ["%f", -1e-9, "-0.000000"],
- // ["%g", 1234.5678e3, "1.2345678e+06"],
- // I believe the above test from go is incorrect according to posix, s. above.
- ["%g", 1234.5678e3, "1.23457e+06"],
- //["%g", float32(1234.5678e3), "1.2345678e+06"],
- //["%g", 1234.5678e-8, "1.2345678e-05"], // posix, see above
- ["%g", 1234.5678e-8, "1.23457e-05"],
- ["%g", -7.0, "-7"],
- ["%g", -1e-9, "-1e-09"],
- //["%g", float32(-1e-9), "-1e-09"],
- ["%E", 1.0, "1.000000E+00"],
- ["%E", 1234.5678e3, "1.234568E+06"],
- ["%E", 1234.5678e-8, "1.234568E-05"],
- ["%E", -7.0, "-7.000000E+00"],
- ["%E", -1e-9, "-1.000000E-09"],
- //["%G", 1234.5678e3, "1.2345678E+06"], // posix, see above
- ["%G", 1234.5678e3, "1.23457E+06"],
- //["%G", float32(1234.5678e3), "1.2345678E+06"],
- //["%G", 1234.5678e-8, "1.2345678E-05"], // posic, see above
- ["%G", 1234.5678e-8, "1.23457E-05"],
- ["%G", -7.0, "-7"],
- ["%G", -1e-9, "-1E-09"],
- //["%G", float32(-1e-9), "-1E-09"],
- ["%20.5s", "qwertyuiop", " qwert"],
- ["%.5s", "qwertyuiop", "qwert"],
- ["%-20.5s", "qwertyuiop", "qwert "],
- ["%20c", "x".charCodeAt(0), " x"],
- ["%-20c", "x".charCodeAt(0), "x "],
- ["%20.6e", 1.2345e3, " 1.234500e+03"],
- ["%20.6e", 1.2345e-3, " 1.234500e-03"],
- ["%20e", 1.2345e3, " 1.234500e+03"],
- ["%20e", 1.2345e-3, " 1.234500e-03"],
- ["%20.8e", 1.2345e3, " 1.23450000e+03"],
- ["%20f", 1.23456789e3, " 1234.567890"],
- ["%20f", 1.23456789e-3, " 0.001235"],
- ["%20f", 12345678901.23456789, " 12345678901.234568"],
- ["%-20f", 1.23456789e3, "1234.567890 "],
- ["%20.8f", 1.23456789e3, " 1234.56789000"],
- ["%20.8f", 1.23456789e-3, " 0.00123457"],
- // ["%g", 1.23456789e3, "1234.56789"],
- // posix ... precision(2) = precision(def=6) - (exp(3)+1)
- ["%g", 1.23456789e3, "1234.57"],
- // ["%g", 1.23456789e-3, "0.00123456789"], posix...
- ["%g", 1.23456789e-3, "0.00123457"], // see above prec6 = precdef6 - (-3+1)
- //["%g", 1.23456789e20, "1.23456789e+20"],
- ["%g", 1.23456789e20, "1.23457e+20"],
- // arrays
- // TODO(bartlomieju):
- // slice : go specific
-
- // TODO(bartlomieju): decide how to handle deeper types, arrays, objects
- // byte arrays and slices with %b,%c,%d,%o,%U and %v
- // f.space should and f.plus should not have an effect with %v.
- // f.space and f.plus should have an effect with %d.
-
- // Padding with byte slices.
- // Same for strings
- ["%2x", "", " "], // 103
- ["%#2x", "", " "],
- ["% 02x", "", "00"],
- ["%# 02x", "", "00"],
- ["%-2x", "", " "],
- ["%-02x", "", " "],
- ["%8x", "\xab", " ab"],
- ["% 8x", "\xab", " ab"],
- ["%#8x", "\xab", " 0xab"],
- ["%# 8x", "\xab", " 0xab"],
- ["%08x", "\xab", "000000ab"],
- ["% 08x", "\xab", "000000ab"],
- ["%#08x", "\xab", "00000xab"],
- ["%# 08x", "\xab", "00000xab"],
- ["%10x", "\xab\xcd", " abcd"],
- ["% 10x", "\xab\xcd", " ab cd"],
- ["%#10x", "\xab\xcd", " 0xabcd"],
- ["%# 10x", "\xab\xcd", " 0xab 0xcd"],
- ["%010x", "\xab\xcd", "000000abcd"],
- ["% 010x", "\xab\xcd", "00000ab cd"],
- ["%#010x", "\xab\xcd", "00000xabcd"],
- ["%# 010x", "\xab\xcd", "00xab 0xcd"],
- ["%-10X", "\xab", "AB "],
- ["% -010X", "\xab", "AB "],
- ["%#-10X", "\xab\xcd", "0XABCD "],
- ["%# -010X", "\xab\xcd", "0XAB 0XCD "],
- // renamings
- // Formatter
- // GoStringer
-
- // %T TODO possibly %#T object(constructor)
- ["%T", {}, "object"],
- ["%T", 1, "number"],
- ["%T", "", "string"],
- ["%T", undefined, "undefined"],
- ["%T", null, "object"],
- ["%T", S, "function"],
- ["%T", true, "boolean"],
- ["%T", Symbol(), "symbol"],
- // %p with pointers
-
- // erroneous things
- // {"", nil, "%!(EXTRA <nil>)"},
- // {"", 2, "%!(EXTRA int=2)"},
- // {"no args", "hello", "no args%!(EXTRA string=hello)"},
- // {"%s %", "hello", "hello %!(NOVERB)"},
- // {"%s %.2", "hello", "hello %!(NOVERB)"},
- // {"%017091901790959340919092959340919017929593813360", 0,
- // "%!(NOVERB)%!(EXTRA int=0)"},
- // {"%184467440737095516170v", 0, "%!(NOVERB)%!(EXTRA int=0)"},
- // // Extra argument errors should format without flags set.
- // {"%010.2", "12345", "%!(NOVERB)%!(EXTRA string=12345)"},
- //
- // // Test that maps with non-reflexive keys print all keys and values.
- // {"%v", map[float64]int{NaN: 1, NaN: 1}, "map[NaN:1 NaN:1]"},
-
- // more floats
-
- ["%.2f", 1.0, "1.00"],
- ["%.2f", -1.0, "-1.00"],
- ["% .2f", 1.0, " 1.00"],
- ["% .2f", -1.0, "-1.00"],
- ["%+.2f", 1.0, "+1.00"],
- ["%+.2f", -1.0, "-1.00"],
- ["%7.2f", 1.0, " 1.00"],
- ["%7.2f", -1.0, " -1.00"],
- ["% 7.2f", 1.0, " 1.00"],
- ["% 7.2f", -1.0, " -1.00"],
- ["%+7.2f", 1.0, " +1.00"],
- ["%+7.2f", -1.0, " -1.00"],
- ["% +7.2f", 1.0, " +1.00"],
- ["% +7.2f", -1.0, " -1.00"],
- ["%07.2f", 1.0, "0001.00"],
- ["%07.2f", -1.0, "-001.00"],
- ["% 07.2f", 1.0, " 001.00"], //153 here
- ["% 07.2f", -1.0, "-001.00"],
- ["%+07.2f", 1.0, "+001.00"],
- ["%+07.2f", -1.0, "-001.00"],
- ["% +07.2f", 1.0, "+001.00"],
- ["% +07.2f", -1.0, "-001.00"],
-];
-
-Deno.test("testThorough", function (): void {
- tests.forEach((t, i): void => {
- // p(t)
- const is = S(t[0], t[1]);
- const should = t[2];
- assertEquals(
- is,
- should,
- `failed case[${i}] : is >${is}< should >${should}<`,
- );
- });
-});
-
-Deno.test("testWeirdos", function (): void {
- assertEquals(S("%.d", 9), "9");
- assertEquals(
- S("dec[%d]=%d hex[%[1]d]=%#x oct[%[1]d]=%#o %s", 1, 255, "Third"),
- "dec[1]=255 hex[1]=0xff oct[1]=0377 Third",
- );
-});
-
-Deno.test("formatV", function (): void {
- const a = { a: { a: { a: { a: { a: { a: { a: {} } } } } } } };
- assertEquals(S("%v", a), "[object Object]");
- assertEquals(S("%#v", a), `{ a: { a: { a: { a: [Object] } } } }`);
- assertEquals(
- S("%#.8v", a),
- "{ a: { a: { a: { a: { a: { a: { a: {} } } } } } } }",
- );
- assertEquals(S("%#.1v", a), `{ a: [Object] }`);
-});
-
-Deno.test("formatJ", function (): void {
- const a = { a: { a: { a: { a: { a: { a: { a: {} } } } } } } };
- assertEquals(S("%j", a), `{"a":{"a":{"a":{"a":{"a":{"a":{"a":{}}}}}}}}`);
-});
-
-Deno.test("flagLessThan", function (): void {
- const a = { a: { a: { a: { a: { a: { a: { a: {} } } } } } } };
- const aArray = [a, a, a];
- assertEquals(
- S("%<#.1v", aArray),
- `[ { a: [Object] }, { a: [Object] }, { a: [Object] } ]`,
- );
- const fArray = [1.2345, 0.98765, 123456789.5678];
- assertEquals(S("%<.2f", fArray), "[ 1.23, 0.99, 123456789.57 ]");
-});
-
-Deno.test("testErrors", function (): void {
- // wrong type : TODO strict mode ...
- //assertEquals(S("%f", "not a number"), "%!(BADTYPE flag=f type=string)")
- assertEquals(S("A %h", ""), "A %!(BAD VERB 'h')");
- assertEquals(S("%J", ""), "%!(BAD VERB 'J')");
- assertEquals(S("bla%J", ""), "bla%!(BAD VERB 'J')");
- assertEquals(S("%Jbla", ""), "%!(BAD VERB 'J')bla");
-
- assertEquals(S("%d"), "%!(MISSING 'd')");
- assertEquals(S("%d %d", 1), "1 %!(MISSING 'd')");
- assertEquals(S("%d %f A", 1), "1 %!(MISSING 'f') A");
-
- assertEquals(S("%*.2f", "a", 1.1), "%!(BAD WIDTH 'a')");
- assertEquals(S("%.*f", "a", 1.1), "%!(BAD PREC 'a')");
- assertEquals(
- S("%.[2]*f", 1.23, "p"),
- `%!(BAD PREC 'p')%!(EXTRA '1.23')`,
- );
- assertEquals(S("%.[2]*[1]f Yippie!", 1.23, "p"), "%!(BAD PREC 'p') Yippie!");
-
- assertEquals(S("%[1]*.2f", "a", "p"), "%!(BAD WIDTH 'a')");
-
- assertEquals(S("A", "a", "p"), `A%!(EXTRA '"a"' '"p"')`);
- assertEquals(S("%[2]s %[2]s", "a", "p"), `p p%!(EXTRA '"a"')`);
-
- // remains to be determined how to handle bad indices ...
- // (realistically) the entire error handling is still up for grabs.
- assertEquals(S("%[hallo]s %d %d %d", 1, 2, 3, 4), "%!(BAD INDEX) 2 3 4");
- assertEquals(
- S("%[5]s", 1, 2, 3, 4),
- `%!(BAD INDEX)%!(EXTRA '2' '3' '4')`,
- );
- assertEquals(S("%[5]f"), "%!(BAD INDEX)");
- assertEquals(S("%.[5]f"), "%!(BAD INDEX)");
- assertEquals(S("%.[5]*f"), "%!(BAD INDEX)");
-});