laravel / prompts

Beautiful and user-friendly forms for your command-line PHP applications.
https://laravel.com/docs/prompts
MIT License
531 stars 94 forks source link

Remove terminal height requirement #128

Closed jessarcher closed 7 months ago

jessarcher commented 7 months ago

This PR removes the exception that is thrown when the terminal is not at least eight lines tall.

This was previously required because rendering would get out of sync if the previous frame fell partially outside of the visible terminal area. Prompts assumed that the cursor was moved to the top of the previous frame, when in reality, this may not have been possible if the terminal height was shorter than the previous frame, causing an offset between frames.

With this PR, Prompts will determine how much of the previous frame is visible and only re-render that portion. The only consequence of this is if the prompt does not fit within the terminal, and the user scrolls back or increases their terminal height, the previously hidden lines of the prompt will show the state of a previous render. The first line of a prompt is always blank (for spacing) and won't be noticeable, so we can immediately handle seven-line tall terminals without any issue. Beyond that, the differences between frames may become more noticeable; for example, the border colour on the label line may not change on a validation error if it is outside the visible area. However, if the label is outside the visible area, the user may naturally want to increase the terminal height after the initial render, and all subsequent renders will re-render the entire prompt correctly. The worst-case scenario is that the user doesn't increase their terminal height and may see some weirdness if they scroll back later, but this seems preferable to just throwing an exception.

Note that re-rendering lines that have left the visible area is not possible (as far as I'm aware).

There is also a weird issue when using tmux when the pane is not tall enough to render the prompt. Each new frame will be rendered to the scrollback history in addition to the visible area. The only workaround I could find was to move the cursor to the second column, which seems to avoid the behaviour, but then additional logic would be required to not render the first character on the first line to keep things aligned. Any prompts that change characters in that left-most column on subsequent renders would suffer (although none currently do, as the left-most column is always blank for spacing). In any case, the new behaviour seems preferable to an exception, and we can always implement the workaround later if needed.

Another improvement we can investigate later is to not render the blank line below the prompt if the terminal height is too short, giving us an additional line before issues could occur. On the final render (submit or cancel) we can output the blank line so that the spacing between the next prompt remains unchanged.

Closes #127