Fix #58: mapValidated on MultipleChoice prompts and move error display to bottom#59
Fix #58: mapValidated on MultipleChoice prompts and move error display to bottom#59kevin-lee wants to merge 1 commit into
mapValidated on MultipleChoice prompts and move error display to bottom#59Conversation
…ve error display to bottom Two bugs existed in `PromptFramework.mapValidated` when used with `MultipleChoice` prompts: 1. After a validation rejection showed an error message, subsequent non-ENTER actions (TAB toggle, arrow keys) did not clear the error. The inner framework's status was permanently stuck at `Running(Left(err))` because non-ENTER handlers use `identity` for status, causing stale error rendering and visual artifacts (duplicate/shifted items on terminal). 2. After a first rejection, selecting then deselecting and pressing ENTER again produced no visible feedback because the rendering was already identical to the displayed error state. Fix in `PromptFramework.mapValidated` (two coordinated changes): - `renderState`: translate the outer wrapper's `Running(Left(err))` status directly into an inner `self.Status.Running(Left(err))` for rendering, instead of always reading `self.currentStatus()` which could be stale. - `handleEvent`: backward-propagate `self.Status.Init` instead of `self.Status.Running(Left(err))`, guarded by `innerWasFinished` to only apply when the inner was actually `Finished` (not when it was `Running` with its own validation error, e.g. `InteractiveTextInput`). Fix in `InteractiveMultipleChoice.renderState`: - Move the error message rendering from between instructions and options to after the options list. When no error is present, a blank line is rendered in its place. This keeps the line count constant across error/non-error states, preventing terminal scroll-induced cursor offset issues that caused duplicate rendering when the prompt was near the terminal bottom. Also adds a `validated-multi` interactive example for manual testing.
5ce1547 to
022c09e
Compare
|
@kevin-lee thanks for the PR and issue. Derived prompts are the bane of my existence and I have already been working on a rewrite of the internals in #53, this PR fixes one symptom, but it's building on my original bad design. I converted your example to a test and finally got it to behave as expected: https://github.com/neandertech/cue4s/pull/53/changes#diff-732c817c2758f69e8e28a40ff53de8321a77e2bd7fc5a6032f819447bbadc6f4 You can publish that PR locally (it should be source compatible) and see how it behaves in your project. I'm close to finishing it and will release a new version |
|
@keynmol Oh, that's great! Thank you, and I will test it. |
|
Superseded by #60 |
|
@keynmol Sorry, I didn’t have time to test it due to trip preparations. I’ve just tested mine with cue4s |
|
Excellent, thanks |
Fix #58:
mapValidatedonMultipleChoiceprompts and move error display to bottomBug:
cue4s-multiple-choice-bug.mp4
Why was the error moved to the bottom?
After the first fix, the list rendering was fine, but it had another issue. Please watch this video.
cue4s-multiple-choice-bug-fixed-but-another-bug.mp4
The error message at the bottom (SOLUTION IN THIS PR)
This is a demo of the fix that this PR offers.
cue4s-multiple-choice-bug-fixed-all.mp4
Two bugs existed in
PromptFramework.mapValidatedwhen used withMultipleChoiceprompts:After a validation rejection showed an error message, subsequent non-ENTER
actions (TAB toggle, arrow keys) did not clear the error. The inner
framework's status was permanently stuck at
Running(Left(err))becausenon-ENTER handlers use
identityfor status, causing stale error renderingand visual artifacts (duplicate/shifted items on terminal).
After a first rejection, selecting then deselecting and pressing ENTER again
produced no visible feedback because the rendering was already identical to
the displayed error state.
Fix in
PromptFramework.mapValidated(two coordinated changes):renderState: translate the outer wrapper'sRunning(Left(err))statusdirectly into an inner
self.Status.Running(Left(err))for rendering,instead of always reading
self.currentStatus()which could be stale.handleEvent: backward-propagateself.Status.Initinstead ofself.Status.Running(Left(err)), guarded byinnerWasFinishedto onlyapply when the inner was actually
Finished(not when it wasRunningwith its own validation error, e.g.
InteractiveTextInput).Fix in
InteractiveMultipleChoice.renderState:after the options list. When no error is present, a blank line is rendered
in its place. This keeps the line count constant across error/non-error
states, preventing terminal scroll-induced cursor offset issues that caused
duplicate rendering when the prompt was near the terminal bottom.
Also adds a
validated-multiinteractive example for manual testing.