Help & automatic examples for string enum properties

This commit is contained in:
Darren Burns
2022-04-22 15:19:40 +01:00
parent 78f6c115c0
commit 62c3f9e945
5 changed files with 95 additions and 17 deletions

View File

@@ -7,9 +7,8 @@
}
.list-item {
height: 8x;
height: 8;
min-width: 80;
background: dark_blue;
padding: 2%;
opacity: x;
padding: 2;
}

View File

@@ -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)

View File

@@ -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),
],
)

View File

@@ -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)

View File

@@ -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)