Skip to content

Commit

Permalink
Merge pull request #5294 from Textualize/command-markup
Browse files Browse the repository at this point in the history
Allow console markup in commands
  • Loading branch information
willmcgugan authored Nov 27, 2024
2 parents b276fd2 + 8e4ba84 commit 74a2c90
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed

- Fixed infinite loop in `Widget.anchor` https://github.com/Textualize/textual/pull/5290
- Restores the ability to supply console markup to command list https://github.com/Textualize/textual/pull/5294
- Fixed delayed App Resize event https://github.com/Textualize/textual/pull/5296

## [0.87.1] - 2024-11-24
Expand Down
8 changes: 6 additions & 2 deletions src/textual/color.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
from rich.color import Color as RichColor
from rich.color import ColorType
from rich.color_triplet import ColorTriplet
from rich.terminal_theme import TerminalTheme
from typing_extensions import Final

from textual._color_constants import ANSI_COLORS, COLOR_NAME_TO_RGB
Expand Down Expand Up @@ -176,18 +177,21 @@ def automatic(cls, alpha_percentage: float = 100.0) -> Color:
return cls(0, 0, 0, alpha_percentage / 100.0, auto=True)

@classmethod
def from_rich_color(cls, rich_color: RichColor | None) -> Color:
def from_rich_color(
cls, rich_color: RichColor | None, theme: TerminalTheme | None = None
) -> Color:
"""Create a new color from Rich's Color class.
Args:
rich_color: An instance of [Rich color][rich.color.Color].
theme: Optional Rich [terminal theme][rich.terminal_theme.TerminalTheme].
Returns:
A new Color instance.
"""
if rich_color is None:
return TRANSPARENT
r, g, b = rich_color.get_truecolor()
r, g, b = rich_color.get_truecolor(theme)
return cls(r, g, b)

@classmethod
Expand Down
2 changes: 1 addition & 1 deletion src/textual/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -1120,7 +1120,7 @@ def build_prompt() -> Iterable[Content]:
help_style = VisualStyle.from_styles(
self.get_component_styles("command-palette--help-text")
)
yield Content.styled(hit.help, help_style)
yield Content.from_rich_text(hit.help).stylize_before(help_style)

prompt = Content("\n").join(build_prompt())

Expand Down
41 changes: 31 additions & 10 deletions src/textual/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
from rich.cells import set_cell_size
from rich.console import OverflowMethod
from rich.segment import Segment, Segments
from rich.terminal_theme import TerminalTheme
from rich.text import Text

from textual._cells import cell_len
from textual._context import active_app
from textual._loop import loop_last
from textual.color import Color
from textual.css.types import TextAlign
Expand Down Expand Up @@ -180,15 +182,28 @@ def from_rich_text(
New Content.
"""
if isinstance(text, str):
return cls(text, align=align, no_wrap=no_wrap, ellipsis=ellipsis)
spans = [
Span(
start,
end,
style if isinstance(style, str) else Style.from_rich_style(style),
)
for start, end, style in text._spans
]
text = Text.from_markup(text)
if text._spans:
ansi_theme: TerminalTheme | None
try:
ansi_theme = active_app.get().ansi_theme
except LookupError:
ansi_theme = None
spans = [
Span(
start,
end,
(
style
if isinstance(style, str)
else Style.from_rich_style(style, ansi_theme)
),
)
for start, end, style in text._spans
]
else:
spans = []

return cls(
text.plain,
spans,
Expand Down Expand Up @@ -681,9 +696,15 @@ def render(
return

if parse_style is None:
app = active_app.get()
# TODO: Update when we add Content.from_markup

def get_style(style: str, /) -> Style:
return TRANSPARENT_STYLE if isinstance(style, str) else style
return (
Style.from_rich_style(app.console.get_style(style), app.ansi_theme)
if isinstance(style, str)
else style
)

else:
get_style = parse_style
Expand Down
10 changes: 7 additions & 3 deletions src/textual/visual.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from rich.protocol import is_renderable, rich_cast
from rich.segment import Segment
from rich.style import Style as RichStyle
from rich.terminal_theme import TerminalTheme
from rich.text import Text

from textual._context import active_app
Expand Down Expand Up @@ -141,18 +142,21 @@ def __add__(self, other: object) -> Style:
return new_style

@classmethod
def from_rich_style(cls, rich_style: RichStyle) -> Style:
def from_rich_style(
cls, rich_style: RichStyle, theme: TerminalTheme | None = None
) -> Style:
"""Build a Style from a (Rich) Style.
Args:
rich_style: A Rich Style object.
theme: Optional Rich [terminal theme][rich.terminal_theme.TerminalTheme].
Returns:
New Style.
"""
return Style(
Color.from_rich_color(rich_style.bgcolor),
Color.from_rich_color(rich_style.color),
Color.from_rich_color(rich_style.bgcolor, theme),
Color.from_rich_color(rich_style.color, theme),
bold=rich_style.bold,
dim=rich_style.dim,
italic=rich_style.italic,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 74a2c90

Please sign in to comment.