mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Help & automatic examples for string enum properties
This commit is contained in:
@@ -7,9 +7,8 @@
|
||||
}
|
||||
|
||||
.list-item {
|
||||
height: 8x;
|
||||
height: 8;
|
||||
min-width: 80;
|
||||
background: dark_blue;
|
||||
padding: 2%;
|
||||
opacity: x;
|
||||
padding: 2;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,8 @@ class BasicApp(App):
|
||||
def action_increase_margin(self):
|
||||
old_margin = self.focused.styles.margin
|
||||
# new_margin = old_margin + (1,1,1)
|
||||
self.focused.styles.padding = (1, 1, 1)
|
||||
# self.focused.styles.padding = (1, 1, 1)
|
||||
self.focused.styles.display = "banana"
|
||||
|
||||
|
||||
BasicApp.run(css_file="uber.css", log="textual.log", log_verbosity=1)
|
||||
|
||||
@@ -172,3 +172,37 @@ def scalar_help_text(
|
||||
).get_by_context(context),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def string_enum_help_text(
|
||||
property_name: str, valid_values: list[str], context: StylingContext | None = None
|
||||
) -> HelpText:
|
||||
property_name = _contextualize_property_name(property_name, context)
|
||||
return HelpText(
|
||||
summary=f"Invalid value for the [i]{property_name}[/] property",
|
||||
bullets=[
|
||||
Bullet(
|
||||
f"The '{property_name}' property can only be set to {friendly_list(valid_values)}"
|
||||
),
|
||||
*ContextSpecificBullets(
|
||||
inline=[
|
||||
Bullet(
|
||||
"In Python, you can assign any of the valid strings to the property",
|
||||
examples=[
|
||||
Example(f'widget.styles.{property_name} = "{valid_value}"')
|
||||
for valid_value in valid_values
|
||||
],
|
||||
)
|
||||
],
|
||||
css=[
|
||||
Bullet(
|
||||
"In Textual CSS, you can assign any of the valid strings to the property",
|
||||
examples=[
|
||||
Example(f"{property_name}: {valid_value};")
|
||||
for valid_value in valid_values
|
||||
],
|
||||
)
|
||||
],
|
||||
).get_by_context(context),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -15,7 +15,11 @@ from typing import Iterable, NamedTuple, TYPE_CHECKING, cast
|
||||
import rich.repr
|
||||
from rich.style import Style
|
||||
|
||||
from ._help_text import spacing_wrong_number_of_values, scalar_help_text
|
||||
from ._help_text import (
|
||||
spacing_wrong_number_of_values,
|
||||
scalar_help_text,
|
||||
string_enum_help_text,
|
||||
)
|
||||
from ..color import Color, ColorPair
|
||||
from ._error_tools import friendly_list
|
||||
from .constants import NULL_SPACING
|
||||
@@ -603,7 +607,12 @@ class StringEnumProperty:
|
||||
else:
|
||||
if value not in self._valid_values:
|
||||
raise StyleValueError(
|
||||
f"{self.name} must be one of {friendly_list(self._valid_values)}"
|
||||
f"{self.name} must be one of {friendly_list(self._valid_values)}",
|
||||
help_text=string_enum_help_text(
|
||||
self.name,
|
||||
valid_values=list(self._valid_values),
|
||||
context="inline",
|
||||
),
|
||||
)
|
||||
if obj.set_rule(self.name, value):
|
||||
obj.refresh(layout=self._layout)
|
||||
|
||||
@@ -10,6 +10,7 @@ from ._help_text import (
|
||||
spacing_wrong_number_of_values,
|
||||
scalar_help_text,
|
||||
spacing_invalid_value,
|
||||
string_enum_help_text,
|
||||
)
|
||||
from .constants import (
|
||||
VALID_BORDER,
|
||||
@@ -26,7 +27,7 @@ from .styles import DockGroup, Styles
|
||||
from .tokenize import Token
|
||||
from .transition import Transition
|
||||
from .types import BoxSizing, Edge, Display, Overflow, Visibility
|
||||
from ..color import Color
|
||||
from ..color import Color, ColorParseError
|
||||
from .._duration import _duration_as_seconds
|
||||
from .._easing import EASING
|
||||
from ..geometry import Spacing, SpacingDimensions, clamp
|
||||
@@ -130,7 +131,7 @@ class StylesBuilder:
|
||||
"""
|
||||
|
||||
if len(tokens) != 1:
|
||||
self.error(name, tokens[0], "expected a single token here")
|
||||
string_enum_help_text(name, valid_values=list(valid_values), context="css"),
|
||||
|
||||
token = tokens[0]
|
||||
token_name, value, _, _, location, _ = token
|
||||
@@ -138,13 +139,17 @@ class StylesBuilder:
|
||||
self.error(
|
||||
name,
|
||||
token,
|
||||
f"invalid token {value!r}, expected {friendly_list(valid_values)}",
|
||||
string_enum_help_text(
|
||||
name, valid_values=list(valid_values), context="css"
|
||||
),
|
||||
)
|
||||
if value not in valid_values:
|
||||
self.error(
|
||||
name,
|
||||
token,
|
||||
f"invalid value {value!r} for {name}, expected {friendly_list(valid_values)}",
|
||||
string_enum_help_text(
|
||||
name, valid_values=list(valid_values), context="css"
|
||||
),
|
||||
)
|
||||
return value
|
||||
|
||||
@@ -160,10 +165,18 @@ class StylesBuilder:
|
||||
self.error(
|
||||
name,
|
||||
token,
|
||||
f"invalid value for display (received {value!r}, expected {friendly_list(VALID_DISPLAY)})",
|
||||
string_enum_help_text(
|
||||
"display", valid_values=list(VALID_DISPLAY), context="css"
|
||||
),
|
||||
)
|
||||
else:
|
||||
self.error(name, token, f"invalid token {value!r} in this context")
|
||||
self.error(
|
||||
name,
|
||||
token,
|
||||
string_enum_help_text(
|
||||
"display", valid_values=list(VALID_DISPLAY), context="css"
|
||||
),
|
||||
)
|
||||
|
||||
def _process_scalar(self, name: str, tokens: list[Token]) -> None:
|
||||
def scalar_error():
|
||||
@@ -195,10 +208,20 @@ class StylesBuilder:
|
||||
self.error(
|
||||
name,
|
||||
token,
|
||||
f"invalid value for box-sizing (received {value!r}, expected {friendly_list(VALID_BOX_SIZING)})",
|
||||
string_enum_help_text(
|
||||
"box-sizing",
|
||||
valid_values=list(VALID_BOX_SIZING),
|
||||
context="css",
|
||||
),
|
||||
)
|
||||
else:
|
||||
self.error(name, token, f"invalid token {value!r} in this context")
|
||||
self.error(
|
||||
name,
|
||||
token,
|
||||
string_enum_help_text(
|
||||
"box-sizing", valid_values=list(VALID_BOX_SIZING), context="css"
|
||||
),
|
||||
)
|
||||
|
||||
def process_width(self, name: str, tokens: list[Token]) -> None:
|
||||
self._process_scalar(name, tokens)
|
||||
@@ -247,10 +270,16 @@ class StylesBuilder:
|
||||
self.error(
|
||||
name,
|
||||
token,
|
||||
f"property 'visibility' has invalid value {value!r}; expected {friendly_list(VALID_VISIBILITY)}",
|
||||
string_enum_help_text(
|
||||
"visibility",
|
||||
valid_values=list(VALID_VISIBILITY),
|
||||
context="css",
|
||||
),
|
||||
)
|
||||
else:
|
||||
self.error(name, token, f"invalid token {value!r} in this context")
|
||||
string_enum_help_text(
|
||||
"visibility", valid_values=list(VALID_VISIBILITY), context="css"
|
||||
)
|
||||
|
||||
def process_opacity(self, name: str, tokens: list[Token]) -> None:
|
||||
if not tokens:
|
||||
@@ -356,7 +385,13 @@ class StylesBuilder:
|
||||
if value in VALID_BORDER:
|
||||
border_type = value
|
||||
else:
|
||||
border_color = Color.parse(value)
|
||||
try:
|
||||
border_color = Color.parse(value)
|
||||
except ColorParseError:
|
||||
# TODO: Raise specific error here
|
||||
self.error(
|
||||
name, token, f"unexpected token {value!r} in declaration"
|
||||
)
|
||||
|
||||
elif token_name == "color":
|
||||
border_color = Color.parse(value)
|
||||
|
||||
Reference in New Issue
Block a user