Skip to content

Commit a067994

Browse files
committed
Fix word wrapping for extremely small terminals
1 parent c14b889 commit a067994

3 files changed

Lines changed: 23 additions & 5 deletions

File tree

.changeset/polite-socks-follow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"hereby": patch
3+
---
4+
5+
Fix word wrapping for extremely small terminals

src/__tests__/cli/formatTasks.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,17 @@ test("breaks long words after short words", (t) => {
8989
t.snapshot(normalizeOutput(output));
9090
});
9191

92+
test("handles very narrow columns", (t) => {
93+
const a = task({
94+
name: "a",
95+
description: "description",
96+
run: async () => {},
97+
});
98+
99+
const output = formatTasks("normal", [a], undefined, 5);
100+
t.regex(normalizeOutput(output), /Available tasks[\s\S]*a/);
101+
});
102+
92103
test("handles multiline descriptions", (t) => {
93104
const a = task({
94105
name: "a",

src/cli/formatTasks.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ export function formatTasks(format: TaskFormat, tasks: Iterable<Task>, defaultTa
2626
});
2727

2828
// There's a 2 space indent plus 3 spaces between columns, hence take away 5
29-
// padding spaces from the available width
30-
const maxTotalWidth = columns - 5;
31-
const maxNameWidth = Math.max(...names.map(visibleLength));
29+
// padding spaces from the available width. Keep widths positive so narrow
30+
// terminals still wrap safely.
31+
const maxTotalWidth = Math.max(1, columns - 5);
32+
const maxNameWidth = Math.max(1, ...names.map(visibleLength));
3233

3334
// Check the name doesn't take up more than half the space
34-
const nameWidth = Math.min(maxNameWidth, maxTotalWidth >> 1);
35-
const descriptionWidth = maxTotalWidth - nameWidth;
35+
const nameWidth = Math.min(maxNameWidth, Math.max(1, maxTotalWidth >> 1));
36+
const descriptionWidth = Math.max(1, maxTotalWidth - nameWidth);
3637
const formatted = names.map((name, i) => formatAsColumns(" ", name, nameWidth, descriptions[i], descriptionWidth));
3738

3839
return `
@@ -76,6 +77,7 @@ const TOKEN_REGEX = /[^\s-]+?-\b|\S+|\s+/g;
7677

7778
function wrapText(text: string, maxWidth: number): string[] {
7879
const result: string[] = [];
80+
maxWidth = Math.max(1, maxWidth);
7981
for (const line of text.split(/\r?\n/)) {
8082
let current = "";
8183
for (const token of line.match(TOKEN_REGEX) ?? []) {

0 commit comments

Comments
 (0)