Skip to content

fix(app): fix garbled inline app output#6080

Merged
willmcgugan merged 3 commits into
Textualize:mainfrom
TomJGooding:fix-garbled-inline-output
Aug 31, 2025
Merged

fix(app): fix garbled inline app output#6080
willmcgugan merged 3 commits into
Textualize:mainfrom
TomJGooding:fix-garbled-inline-output

Conversation

@TomJGooding

@TomJGooding TomJGooding commented Aug 28, 2025

Copy link
Copy Markdown
Contributor

Fix garbled inline app output when inline_no_clear=True.

Currently the terminal cursor isn't actually "reset" before printing the screen contents. This doesn't matter for most inline apps as the cursor is already offset at (0, 0). But if the app contains an Input widget, this will update the cursor position so the output will be garbled.

Fixes #6064

Please review the following checklist.

  • Docstrings on all new or modified functions / classes
  • Updated documentation
  • Updated CHANGELOG.md (where appropriate)

Fix garbled inline app output when `inline_no_clear=True`.

Currently the terminal cursor isn't actually "reset" before printing the
screen contents. This doesn't matter for most inline apps as the cursor
is already offset at (0, 0). But if the app contains an `Input` widget,
this will update the cursor position so the output will be garbled.

Fixes #6064
@TomJGooding

Copy link
Copy Markdown
Contributor Author

Example app for testing:

from textual.app import App, ComposeResult
from textual.widgets import Input


class ExampleApp(App):
    def compose(self) -> ComposeResult:
        yield Input("Press ctrl+q to quit")

    def on_mount(self) -> None:
        # Workaround possible bug with the initial input cursor position
        # https://github.com/Textualize/textual/issues/6064#issuecomment-3217177954
        self.simulate_key("right")

        # Show the terminal cursor for debugging
        self._driver.write("\x1b[?25h")


if __name__ == "__main__":
    app = ExampleApp()
    app.run(
        inline=True,
        inline_no_clear=True,
    )

Comment thread src/textual/app.py
cursor_x, cursor_y = self._previous_cursor_position
self._driver.write(
Control.move(-cursor_x, -cursor_y + 1).segment.text
Control.move(-cursor_x, -cursor_y).segment.text

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

-cursor_y + 1 will duplicate the first line in the output. But I think this was included in case the app crashes so the traceback doesn't overwrite the prompt?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Another test app to check the prompt is correctly restored:

from textual.app import App, ComposeResult
from textual.widgets import Button

INLINE_NO_CLEAR = False

INVALID_CSS = False


class ExitRenderablesApp(App):
    CSS = "Screen { background: invalid; }" if INVALID_CSS else ""

    def compose(self) -> ComposeResult:
        yield Button.error("Runtime Error")

    def on_mount(self) -> None:
        # Show the terminal cursor for debugging
        self._driver.write("\x1b[?25h")

    def on_button_pressed(self) -> None:
        raise RuntimeError()


if __name__ == "__main__":
    app = ExitRenderablesApp()
    app.run(
        inline=True,
        inline_no_clear=INLINE_NO_CLEAR,
    )

Following the fix for garbled inline app outputs in d7e9168, update the
other terminal cursor move accordingly to correctly restore the prompt.
@TomJGooding

Copy link
Copy Markdown
Contributor Author

Currently there is an empty line after the app output, which is removed with this change. But I'm not sure if this bottom 'padding' was intentional or not, since the INLINE_PADDING attribute is the "number of blank lines above an inline app".

I've marked as ready for review - I'm annoyed that I spent so long debugging this for what might be a simple 4 line change!

@TomJGooding TomJGooding marked this pull request as ready for review August 29, 2025 15:35
@willmcgugan

Copy link
Copy Markdown
Member

I've marked as ready for review - I'm annoyed that I spent so long debugging this for what might be a simple 4 line change!

It's not the total number of lines that counts, but knowing which 4 lines to change!

@willmcgugan willmcgugan merged commit fd14d10 into Textualize:main Aug 31, 2025
23 checks passed
@TomJGooding TomJGooding deleted the fix-garbled-inline-output branch August 31, 2025 16:06
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.

Inline app output after exit is garbled for Input widget

2 participants