Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More inline fix #4401

Merged
merged 7 commits into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [0.56.1] - 2024-04-07

### Fixed

- Fixed flicker when non-current screen updates https://github.com/Textualize/textual/pull/4401

### Changed

- Removed additional line at the end of an inline app https://github.com/Textualize/textual/pull/4401

## [0.56.0] - 2024-04-06

### Added
Expand Down Expand Up @@ -1843,6 +1853,7 @@ https://textual.textualize.io/blog/2022/11/08/version-040/#version-040
- New handler system for messages that doesn't require inheritance
- Improved traceback handling

[0.56.1]: https://github.com/Textualize/textual/compare/v0.56.0...v0.56.1
[0.56.0]: https://github.com/Textualize/textual/compare/v0.55.1...v0.56.0
[0.55.1]: https://github.com/Textualize/textual/compare/v0.55.0...v0.55.1
[0.55.0]: https://github.com/Textualize/textual/compare/v0.54.0...v0.55.0
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "textual"
version = "0.56.0"
version = "0.56.1"
homepage = "https://github.com/Textualize/textual"
repository = "https://github.com/Textualize/textual"
documentation = "https://textual.textualize.io/"
Expand Down
23 changes: 17 additions & 6 deletions src/textual/_compositor.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,9 @@ def __rich_repr__(self) -> rich.repr.Result:
class InlineUpdate(CompositorUpdate):
"""A renderable to write an inline update."""

def __init__(self, strips: list[Strip]) -> None:
def __init__(self, strips: list[Strip], clear: bool = False) -> None:
self.strips = strips
self.clear = clear

def __rich_console__(
self, console: Console, options: ConsoleOptions
Expand All @@ -175,14 +176,15 @@ def render_segments(self, console: Console) -> str:
append(strip.render(console))
if not last:
append("\n")
append("\n\x1b[J") # Clear down
if self.clear:
append("\n\x1b[J") # Clear down
if len(self.strips) > 1:
append(
f"\x1b[{len(self.strips)}A\r"
) # Move cursor back to original position
back_lines = len(self.strips) if self.clear else len(self.strips) - 1
append(f"\x1b[{back_lines}A\r") # Move cursor back to original position
else:
append("\r")
append("\x1b[6n") # Query new cursor position

return "".join(sequences)


Expand Down Expand Up @@ -336,6 +338,9 @@ def __init__(self) -> None:
# Mapping of line numbers on to lists of widget and regions
self._layers_visible: list[list[tuple[Widget, Region, Region]]] | None = None

# Size of previous inline update
self._previous_inline_height: int | None = None

@classmethod
def _regions_to_spans(
cls, regions: Iterable[Region]
Expand Down Expand Up @@ -1030,7 +1035,13 @@ def render_inline(
A renderable.
"""
visible_screen_stack.set([] if screen_stack is None else screen_stack)
return InlineUpdate(self.render_strips(size))
strips = self.render_strips(size)
clear = (
self._previous_inline_height is not None
and len(strips) < self._previous_inline_height
)
self._previous_inline_height = len(strips)
return InlineUpdate(strips, clear=clear)

def render_full_update(self) -> LayoutUpdate:
"""Render a full update.
Expand Down
4 changes: 4 additions & 0 deletions src/textual/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,10 @@ class CommandPalette(_SystemModalScreen[CallbackType]):
"""

DEFAULT_CSS = """
CommandPalette:inline {
/* If the command palette is invoked in inline mode, we may need additional lines. */
min-height: 20;
}
CommandPalette {
background: $background 30%;
align-horizontal: center;
Expand Down
11 changes: 11 additions & 0 deletions src/textual/drivers/linux_inline_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,17 @@ def on_terminal_resize(signum, stack) -> None:
self._key_thread = Thread(target=self._run_input_thread)
send_size_event()
self._key_thread.start()
self._request_terminal_sync_mode_support()
self._enable_bracketed_paste()

def _request_terminal_sync_mode_support(self) -> None:
"""Writes an escape sequence to query the terminal support for the sync protocol."""
# Terminals should ignore this sequence if not supported.
# Apple terminal doesn't, and writes a single 'p' in to the terminal,
# so we will make a special case for Apple terminal (which doesn't support sync anyway).
if os.environ.get("TERM_PROGRAM", "") != "Apple_Terminal":
self.write("\033[?2026$p")
self.flush()

@classmethod
def _patch_lflag(cls, attrs: int) -> int:
Expand Down
37 changes: 19 additions & 18 deletions src/textual/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,24 +673,25 @@ def _compositor_refresh(self) -> None:
"""Perform a compositor refresh."""

app = self.app
if app.is_inline:
app._display(
self,
self._compositor.render_inline(
app.size.with_height(app._get_inline_height()),
screen_stack=app._background_screens,
),
)
self._dirty_widgets.clear()
self._compositor._dirty_regions.clear()

elif self is app.screen:
# Top screen
update = self._compositor.render_update(
screen_stack=app._background_screens
)
app._display(self, update)
self._dirty_widgets.clear()
if self is app.screen:
if app.is_inline:
app._display(
self,
self._compositor.render_inline(
app.size.with_height(app._get_inline_height()),
screen_stack=app._background_screens,
),
)
self._dirty_widgets.clear()
self._compositor._dirty_regions.clear()
else:
# Top screen
update = self._compositor.render_update(
screen_stack=app._background_screens
)
app._display(self, update)
self._dirty_widgets.clear()
elif self in self.app._background_screens and self._compositor._dirty_regions:
# Background screen
app.screen.refresh(*self._compositor._dirty_regions)
Expand Down Expand Up @@ -892,7 +893,7 @@ def _get_inline_height(self, size: Size) -> int:
inline_height = max(inline_height, int(min_height.resolve(size, size)))
if max_height is not None:
inline_height = min(inline_height, int(max_height.resolve(size, size)))
inline_height = min(self.app.size.height - 1, inline_height)
inline_height = min(self.app.size.height, inline_height)
return inline_height

def _screen_resized(self, size: Size):
Expand Down
Loading