Skip to content

Commit

Permalink
Merge pull request #4401 from Textualize/more-inline-fix
Browse files Browse the repository at this point in the history
More inline fix
  • Loading branch information
willmcgugan authored Apr 7, 2024
2 parents fe24cc2 + 916b66a commit 1a7f9ff
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 25 deletions.
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

0 comments on commit 1a7f9ff

Please sign in to comment.