mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
console output with format (#1565)
This commit is contained in:
parent
7f88b5fff3
commit
6904628aaa
2 changed files with 193 additions and 22 deletions
127
js/console.ts
127
js/console.ts
|
@ -14,6 +14,16 @@ type ConsoleOptions = Partial<{
|
|||
// Default depth of logging nested objects
|
||||
const DEFAULT_MAX_DEPTH = 4;
|
||||
|
||||
// Char codes
|
||||
const CHAR_PERCENT = 37; /* % */
|
||||
const CHAR_LOWERCASE_S = 115; /* s */
|
||||
const CHAR_LOWERCASE_D = 100; /* d */
|
||||
const CHAR_LOWERCASE_I = 105; /* i */
|
||||
const CHAR_LOWERCASE_F = 102; /* f */
|
||||
const CHAR_LOWERCASE_O = 111; /* o */
|
||||
const CHAR_UPPERCASE_O = 79; /* O */
|
||||
const CHAR_LOWERCASE_C = 99; /* c */
|
||||
|
||||
// tslint:disable-next-line:no-any
|
||||
function getClassInstanceName(instance: any): string {
|
||||
if (typeof instance !== "object") {
|
||||
|
@ -342,38 +352,125 @@ export function stringifyArgs(
|
|||
args: any[],
|
||||
options: ConsoleOptions = {}
|
||||
): string {
|
||||
const out: string[] = [];
|
||||
const { collapsedAt, indentLevel } = options;
|
||||
for (const a of args) {
|
||||
if (typeof a === "string") {
|
||||
out.push(a);
|
||||
const first = args[0];
|
||||
let a = 0;
|
||||
let str = "";
|
||||
let join = "";
|
||||
|
||||
if (typeof first === "string") {
|
||||
let tempStr: string;
|
||||
let lastPos = 0;
|
||||
|
||||
for (let i = 0; i < first.length - 1; i++) {
|
||||
if (first.charCodeAt(i) === CHAR_PERCENT) {
|
||||
const nextChar = first.charCodeAt(++i);
|
||||
if (a + 1 !== args.length) {
|
||||
switch (nextChar) {
|
||||
case CHAR_LOWERCASE_S:
|
||||
// format as a string
|
||||
tempStr = String(args[++a]);
|
||||
break;
|
||||
case CHAR_LOWERCASE_D:
|
||||
case CHAR_LOWERCASE_I:
|
||||
// format as an integer
|
||||
const tempInteger = args[++a];
|
||||
if (typeof tempInteger === "bigint") {
|
||||
tempStr = `${tempInteger}n`;
|
||||
} else if (typeof tempInteger === "symbol") {
|
||||
tempStr = "NaN";
|
||||
} else {
|
||||
out.push(
|
||||
// use default maximum depth for null or undefined argument
|
||||
stringify(
|
||||
a,
|
||||
tempStr = `${parseInt(tempInteger, 10)}`;
|
||||
}
|
||||
break;
|
||||
case CHAR_LOWERCASE_F:
|
||||
// format as a floating point value
|
||||
const tempFloat = args[++a];
|
||||
if (typeof tempFloat === "symbol") {
|
||||
tempStr = "NaN";
|
||||
} else {
|
||||
tempStr = `${parseFloat(tempFloat)}`;
|
||||
}
|
||||
break;
|
||||
case CHAR_LOWERCASE_O:
|
||||
case CHAR_UPPERCASE_O:
|
||||
// format as an object
|
||||
tempStr = stringify(
|
||||
args[++a],
|
||||
// tslint:disable-next-line:no-any
|
||||
new Set<any>(),
|
||||
0,
|
||||
// tslint:disable-next-line:triple-equals
|
||||
options.depth != undefined ? options.depth : DEFAULT_MAX_DEPTH
|
||||
);
|
||||
break;
|
||||
case CHAR_PERCENT:
|
||||
str += first.slice(lastPos, i);
|
||||
lastPos = i + 1;
|
||||
continue;
|
||||
case CHAR_LOWERCASE_C:
|
||||
// TODO: applies CSS style rules to the output string as specified
|
||||
continue;
|
||||
default:
|
||||
// any other character is not a correct placeholder
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastPos !== i - 1) {
|
||||
str += first.slice(lastPos, i - 1);
|
||||
}
|
||||
|
||||
str += tempStr;
|
||||
lastPos = i + 1;
|
||||
} else if (nextChar === CHAR_PERCENT) {
|
||||
str += first.slice(lastPos, i);
|
||||
lastPos = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lastPos !== 0) {
|
||||
a++;
|
||||
join = " ";
|
||||
if (lastPos < first.length) {
|
||||
str += first.slice(lastPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (a < args.length) {
|
||||
const value = args[a];
|
||||
str += join;
|
||||
if (typeof value === "string") {
|
||||
str += value;
|
||||
} else {
|
||||
// use default maximum depth for null or undefined argument
|
||||
str += stringify(
|
||||
value,
|
||||
// tslint:disable-next-line:no-any
|
||||
new Set<any>(),
|
||||
0,
|
||||
// tslint:disable-next-line:triple-equals
|
||||
options.depth != undefined ? options.depth : DEFAULT_MAX_DEPTH
|
||||
)
|
||||
);
|
||||
}
|
||||
join = " ";
|
||||
a++;
|
||||
}
|
||||
let outstr = out.join(" ");
|
||||
|
||||
const { collapsedAt, indentLevel } = options;
|
||||
if (
|
||||
!isCollapsed(collapsedAt, indentLevel) &&
|
||||
indentLevel != null &&
|
||||
indentLevel > 0
|
||||
) {
|
||||
const groupIndent = " ".repeat(indentLevel);
|
||||
if (outstr.indexOf("\n") !== -1) {
|
||||
outstr = outstr.replace(/\n/g, `\n${groupIndent}`);
|
||||
if (str.indexOf("\n") !== -1) {
|
||||
str = str.replace(/\n/g, `\n${groupIndent}`);
|
||||
}
|
||||
outstr = groupIndent + outstr;
|
||||
str = groupIndent + str;
|
||||
}
|
||||
return outstr;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
type PrintFunc = (x: string, isErr?: boolean, printsNewline?: boolean) => void;
|
||||
|
|
|
@ -145,6 +145,80 @@ test(function consoleTestStringifyWithDepth() {
|
|||
);
|
||||
});
|
||||
|
||||
test(function consoleTestWithIntegerFormatSpecifier() {
|
||||
assertEqual(stringify("%i"), "%i");
|
||||
assertEqual(stringify("%i", 42.0), "42");
|
||||
assertEqual(stringify("%i", 42), "42");
|
||||
assertEqual(stringify("%i", "42"), "42");
|
||||
assertEqual(stringify("%i", "42.0"), "42");
|
||||
assertEqual(stringify("%i", 1.5), "1");
|
||||
assertEqual(stringify("%i", -0.5), "0");
|
||||
assertEqual(stringify("%i", ""), "NaN");
|
||||
assertEqual(stringify("%i", Symbol()), "NaN");
|
||||
assertEqual(stringify("%i %d", 42, 43), "42 43");
|
||||
assertEqual(stringify("%d %i", 42), "42 %i");
|
||||
assertEqual(stringify("%d", 12345678901234567890123), "1");
|
||||
assertEqual(
|
||||
stringify("%i", 12345678901234567890123n),
|
||||
"12345678901234567890123n"
|
||||
);
|
||||
});
|
||||
|
||||
test(function consoleTestWithFloatFormatSpecifier() {
|
||||
assertEqual(stringify("%f"), "%f");
|
||||
assertEqual(stringify("%f", 42.0), "42");
|
||||
assertEqual(stringify("%f", 42), "42");
|
||||
assertEqual(stringify("%f", "42"), "42");
|
||||
assertEqual(stringify("%f", "42.0"), "42");
|
||||
assertEqual(stringify("%f", 1.5), "1.5");
|
||||
assertEqual(stringify("%f", -0.5), "-0.5");
|
||||
assertEqual(stringify("%f", Math.PI), "3.141592653589793");
|
||||
assertEqual(stringify("%f", ""), "NaN");
|
||||
assertEqual(stringify("%f", Symbol("foo")), "NaN");
|
||||
assertEqual(stringify("%f", 5n), "5");
|
||||
assertEqual(stringify("%f %f", 42, 43), "42 43");
|
||||
assertEqual(stringify("%f %f", 42), "42 %f");
|
||||
});
|
||||
|
||||
test(function consoleTestWithStringFormatSpecifier() {
|
||||
assertEqual(stringify("%s"), "%s");
|
||||
assertEqual(stringify("%s", undefined), "undefined");
|
||||
assertEqual(stringify("%s", "foo"), "foo");
|
||||
assertEqual(stringify("%s", 42), "42");
|
||||
assertEqual(stringify("%s", "42"), "42");
|
||||
assertEqual(stringify("%s %s", 42, 43), "42 43");
|
||||
assertEqual(stringify("%s %s", 42), "42 %s");
|
||||
assertEqual(stringify("%s", Symbol("foo")), "Symbol(foo)");
|
||||
});
|
||||
|
||||
test(function consoleTestWithObjectFormatSpecifier() {
|
||||
assertEqual(stringify("%o"), "%o");
|
||||
assertEqual(stringify("%o", 42), "42");
|
||||
assertEqual(stringify("%o", "foo"), "foo");
|
||||
assertEqual(stringify("o: %o, a: %O", {}, []), "o: {}, a: []");
|
||||
assertEqual(stringify("%o", { a: 42 }), "{ a: 42 }");
|
||||
assertEqual(
|
||||
stringify("%o", { a: { b: { c: { d: new Set([1]) } } } }),
|
||||
"{ a: { b: { c: { d: [Set] } } } }"
|
||||
);
|
||||
});
|
||||
|
||||
test(function consoleTestWithVariousOrInvalidFormatSpecifier() {
|
||||
assertEqual(stringify("%s:%s"), "%s:%s");
|
||||
assertEqual(stringify("%i:%i"), "%i:%i");
|
||||
assertEqual(stringify("%d:%d"), "%d:%d");
|
||||
assertEqual(stringify("%%s%s", "foo"), "%sfoo");
|
||||
assertEqual(stringify("%s:%s", undefined), "undefined:%s");
|
||||
assertEqual(stringify("%s:%s", "foo", "bar"), "foo:bar");
|
||||
assertEqual(stringify("%s:%s", "foo", "bar", "baz"), "foo:bar baz");
|
||||
assertEqual(stringify("%%%s%%", "hi"), "%hi%");
|
||||
assertEqual(stringify("%d:%d", 12), "12:%d");
|
||||
assertEqual(stringify("%i:%i", 12), "12:%i");
|
||||
assertEqual(stringify("%f:%f", 12), "12:%f");
|
||||
assertEqual(stringify("o: %o, a: %o", {}), "o: {}, a: %o");
|
||||
assertEqual(stringify("abc%", 1), "abc% 1");
|
||||
});
|
||||
|
||||
test(function consoleTestCallToStringOnLabel() {
|
||||
const methods = ["count", "countReset", "time", "timeLog", "timeEnd"];
|
||||
|
||||
|
|
Loading…
Reference in a new issue