Skip to content

fix: wrap and indent spinner messages#584

Open
beeequeue wants to merge 2 commits into
bombshell-dev:mainfrom
beeequeue:spinners-indent
Open

fix: wrap and indent spinner messages#584
beeequeue wants to merge 2 commits into
bombshell-dev:mainfrom
beeequeue:spinners-indent

Conversation

@beeequeue

@beeequeue beeequeue commented Jul 10, 2026

Copy link
Copy Markdown

What does this PR do?

makes sure the printed messages in spinner and its dependent prompts are correctly wrapped and indented.

Screenshots

Before:

image image

After:

image image

Type of change

  • Bug fix
  • Feature
  • Refactor (no behavior change)
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Checklist

  • pnpm test passes (or targeted tests for my change)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable)
  • I have added a changeset

AI-generated code disclosure

  • This PR includes AI-generated code

i spotted #479 which might also fix this issue, but it seems to have lost momentum and i think this is a reasonable patch until it's done

@changeset-bot

changeset-bot Bot commented Jul 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a259bea

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@clack/prompts Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 10, 2026

Copy link
Copy Markdown

commit: a259bea

@dreyfus92 dreyfus92 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome job @beeequeue left a few comments, it would be nice that @43081j also jumps into this ✌🏻

trim: false,
});
output.write(wrapped);
output.write(outputMessage);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like message() slipped thru, it still sets _message raw in line 203 but the per frame wrap that used to catch it is gone now. so anything long/multiline set mid-spin renders unwrapped until stop. should probable mirror what start() does on line 136 and also a test calling .message() with a columns + 10 string would cover the gap.

return min > 0 ? `[${min}m ${secs}s]` : `[${secs}s]`;
};

const prefix = `${styleText('gray', S_BAR)} `;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

head up that wrapTextWithPrefix does column - prefix.length and this prefix has ansi codes in it, so it's ~13 chars instead of 3 visible cols. messages wrap ~ 10 columns early. not this PR's fault necessarily but passing a styled prefix here surfaces it, might be worth stripping ansi (or using visible width) in core as follow up.

_origin = performance.now();
if (hasGuide) {
output.write(`${styleText('gray', S_BAR)}\n`);
output.write(`${prefix}\n`);

@dreyfus92 dreyfus92 Jul 13, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we keep this as just the bar? the 2 trailing spaces from prefix are why basically every snapshot in both files changed. writing trailing whitespace doesn't buy anything and would shrink the diff a ton.

hard: true,
trim: false,
});
output.write(wrapped);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pre-existing rather than introduced here, but this diff changes its failure mode: clearPrevMessage counts erase lines from _prevMessage alone, but what's on screen is ${frame} ${_message}${loadingDots} which is 3 cols wider. with withGuide: false and a near-full-width message, the output soft-wraps one row more than counted and a stale line survives the erase. repro (fake 40-col output, start('x'.repeat(40))):

main:        ""                                        <- stale stub
             "o  done"
this branch: "•  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"   <- stale full line
             "o  done"

so same bug, but without the write-time wrap the leftover is now a full line of content instead of a 3-char stub. proper fix is probably counting from the actually-written string (needs its own var, the isCI dedup compares _message === _prevMessage and the frame changes every tick). fine as a follow-up, just wanted it on record

@43081j

43081j commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

there's been a few attempts at this same change but i've always held off on it since the real fix is to make the spinner use the prompt API.

we're a bit blocked there though since we'd end up reintroducing the windows spinner bug (main has one too, just a different bug, including in this PR).

i think lets hold off on merging this until i can catch myself up on the state of the prompt PR. if we can land that anytime soon then it'd make this one redundant

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants