Skip to content

Commit ca96b77

Browse files
committed
feat: option to efficiently use horizontal space
1 parent dc8adec commit ca96b77

2 files changed

Lines changed: 68 additions & 23 deletions

File tree

pretty/formatter.test.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import { assertEquals } from "@std/assert/equals";
55
import { assertMatch } from "@std/assert/match";
66
import { assertStringIncludes } from "@std/assert/string-includes";
77
import {
8-
type CategoryColorMap,
9-
getPrettyFormatter,
10-
prettyFormatter,
8+
type CategoryColorMap,
9+
getPrettyFormatter,
10+
prettyFormatter,
1111
} from "./formatter.ts";
1212

1313
const test = suite(import.meta);
@@ -829,3 +829,29 @@ test("properties set to true", () => {
829829
"Deno" in globalThis ? 'bar: "baz"' : "bar: 'baz'",
830830
);
831831
});
832+
833+
test("newLine set to true", () => {
834+
const formatter = getPrettyFormatter({
835+
properties: true,
836+
colors: false,
837+
messageNewLine: true,
838+
inspectOptions: { colors: false },
839+
});
840+
841+
const record = createLogRecord("info", ["test"], ["FooBar"], Date.now(), {
842+
foo: "bar",
843+
bar: "baz",
844+
});
845+
const result = formatter(record);
846+
// Should contain multiple lines due to wrapping
847+
const lines = result.split("\n");
848+
assertEquals(lines.length, 5); // Normal log line + 1 for horizontal space + formatted properties + newline
849+
assertEquals(
850+
lines[2].trim(),
851+
"Deno" in globalThis ? 'foo: "bar"' : "foo: 'bar'",
852+
);
853+
assertEquals(
854+
lines[3].trim(),
855+
"Deno" in globalThis ? 'bar: "baz"' : "bar: 'baz'",
856+
);
857+
});

pretty/formatter.ts

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1+
import { inspect, type InspectOptions } from "#util";
12
import {
2-
getLogLevels,
3-
type LogLevel,
4-
type LogRecord,
5-
type TextFormatter,
6-
type TextFormatterOptions,
3+
getLogLevels,
4+
type LogLevel,
5+
type LogRecord,
6+
type TextFormatter,
7+
type TextFormatterOptions,
78
} from "@logtape/logtape";
8-
import { inspect, type InspectOptions } from "#util";
99
import { getOptimalWordWrapWidth } from "./terminal.ts";
1010
import { truncateCategory, type TruncationStrategy } from "./truncate.ts";
1111
import { getDisplayWidth, stripAnsi } from "./wcwidth.ts";
@@ -476,7 +476,15 @@ export interface PrettyFormatterOptions
476476
* @default `"rgb(148,163,184)"` (light slate gray)
477477
*/
478478
readonly messageColor?: Color;
479-
479+
/**
480+
* Visual style applied to save some horizontal space
481+
*
482+
* Controls whether the message will start after the category, or whether
483+
* it will wrap below the categories, where the categories appear as a heading
484+
*
485+
* @default false
486+
*/
487+
readonly messageNewLine?: boolean;
480488
/**
481489
* Visual style applied to log message text.
482490
*
@@ -672,6 +680,7 @@ export function getPrettyFormatter(
672680
categoryTruncate = "middle",
673681
messageColor = "rgb(148,163,184)",
674682
messageStyle = "dim",
683+
messageNewLine = false,
675684
colors: useColors = true,
676685
align = true,
677686
inspectOptions = {},
@@ -822,6 +831,9 @@ export function getPrettyFormatter(
822831
let message = "";
823832
const messageColorCode = useColors ? colorToAnsi(messageColor) : "";
824833
const messageStyleCode = useColors ? styleToAnsi(messageStyle) : "";
834+
const messageStart = messageNewLine ? "\n" : "";
835+
const messageNewLineIdentation = 4
836+
const messageNewLineIdentationProperties = messageNewLine ? messageNewLineIdentation + 2 :undefined
825837
const messagePrefix = useColors
826838
? `${messageStyleCode}${messageColorCode}`
827839
: "";
@@ -932,12 +944,14 @@ export function getPrettyFormatter(
932944
);
933945

934946
let result =
935-
`${formattedTimestamp}${formattedIcon} ${paddedLevel} ${paddedCategory} ${formattedMessage}`;
936-
const indentWidth = getDisplayWidth(
937-
stripAnsi(
938-
`${formattedTimestamp}${formattedIcon} ${paddedLevel} ${paddedCategory} `,
939-
),
940-
);
947+
`${formattedTimestamp}${formattedIcon} ${paddedLevel} ${paddedCategory} ${messageStart}${formattedMessage}`;
948+
const indentWidth = !messageNewLine
949+
? getDisplayWidth(
950+
stripAnsi(
951+
`${formattedTimestamp}${formattedIcon} ${paddedLevel} ${paddedCategory} `,
952+
),
953+
)
954+
: messageNewLineIdentation;
941955

942956
// Apply word wrapping if enabled, or if there are multiline interpolated values
943957
if (wordWrapEnabled || message.includes("\n")) {
@@ -955,18 +969,21 @@ export function getPrettyFormatter(
955969
wordWrapEnabled ? wordWrapWidth : Infinity,
956970
useColors,
957971
inspectOptions,
972+
messageNewLineIdentationProperties
958973
);
959974
}
960975

961976
return result + "\n";
962977
} else {
963978
let result =
964-
`${formattedTimestamp}${formattedIcon} ${formattedLevel} ${formattedCategory} ${formattedMessage}`;
965-
const indentWidth = getDisplayWidth(
966-
stripAnsi(
967-
`${formattedTimestamp}${formattedIcon} ${formattedLevel} ${formattedCategory} `,
968-
),
969-
);
979+
`${formattedTimestamp}${formattedIcon} ${formattedLevel} ${formattedCategory} ${messageStart}${formattedMessage}`;
980+
const indentWidth = !messageNewLine
981+
? getDisplayWidth(
982+
stripAnsi(
983+
`${formattedTimestamp}${formattedIcon} ${formattedLevel} ${formattedCategory} `,
984+
),
985+
)
986+
: messageNewLineIdentation;
970987

971988
// Apply word wrapping if enabled, or if there are multiline interpolated values
972989
if (wordWrapEnabled || message.includes("\n")) {
@@ -984,6 +1001,7 @@ export function getPrettyFormatter(
9841001
wordWrapEnabled ? wordWrapWidth : Infinity,
9851002
useColors,
9861003
inspectOptions,
1004+
messageNewLineIdentationProperties
9871005
);
9881006
}
9891007

@@ -998,11 +1016,12 @@ function formatProperties(
9981016
maxWidth: number,
9991017
useColors: boolean,
10001018
inspectOptions: InspectOptions,
1019+
messageNewLineIdentationProperties?: number
10011020
): string {
10021021
let result = "";
10031022
for (const prop in record.properties) {
10041023
const propValue = record.properties[prop];
1005-
const pad = indentWidth - getDisplayWidth(prop) - 2;
1024+
const pad = messageNewLineIdentationProperties ?? indentWidth - getDisplayWidth(prop);
10061025
result += "\n" + wrapText(
10071026
`${" ".repeat(pad)}${useColors ? DIM : ""}${prop}:${
10081027
useColors ? RESET : ""

0 commit comments

Comments
 (0)