topmark.cli.presentation¶
CLI presentation layer for semantic styling.
This module maps backend-agnostic semantic style roles
(StyleRole) to concrete terminal styling callables
(currently backed by Rich).
Design goals
- Keep all ANSI / terminal styling confined to the CLI layer.
- Centralize the mapping from semantic roles → concrete styles.
- Allow theming and stackable style overrides.
- Keep core and rendering layers free of presentation backends.
Key concepts¶
StyleRole: Semantic meaning (ERROR, WARNING, CHANGED, etc.).Theme: A mapping fromStyleRoleto a concrete text styler.DEFAULT_THEME: The built-in theme used by default.style_for_role(role, theme=...): Resolve a styler for a role.
Theme and overrides¶
Themes support stackable overrides. A Theme consists of:
- `base`: The default mapping from `StyleRole` → styler.
- `overrides`: Optional per-role overrides.
Lookup order:
overrides → base → no-op (identity function)
Example: custom theme with overrides¶
from topmark.cli.presentation import DEFAULT_THEME
from topmark.cli.presentation import Theme
from topmark.cli.presentation import rich_styler
from topmark.cli.presentation import style_for_role
from topmark.core.presentation import StyleRole
custom_theme = Theme(
base=DEFAULT_THEME.base,
overrides={
StyleRole.ERROR: rich_styler("bold white on red"),
StyleRole.WARNING: rich_styler("yellow"),
},
)
styler = style_for_role(StyleRole.ERROR, theme=custom_theme)
print(styler("Something went wrong"))
Stacking overrides¶
Overrides can be layered by reusing the same base mapping and adding new override dictionaries:
soft_theme = Theme(
base=DEFAULT_THEME.base,
overrides={
StyleRole.CHANGED: rich_styler("cyan"),
},
)
minimal_theme = Theme(
base=soft_theme.base,
overrides={
StyleRole.ERROR: rich_styler("red"),
},
)
This design keeps styling flexible while maintaining a single semantic source of truth(StyleRole)
across the application.
Theme
dataclass
¶
Theme for mapping StyleRole values to concrete terminal stylers.
A theme consists of a required base mapping plus optional per-role overrides.
Lookups are performed in this order
1) overrides (if provided)
2) base mapping
3) no_style_for_role fallback
This keeps the default styling stable while allowing caller-controlled theming (e.g., alternate palettes, accessibility themes, tests).
Themes intentionally remain immutable, mapping-based value objects. This keeps the semantic styling boundary small, strictly typed, and independent from any future user-facing theme configuration format.
Attributes:
| Name | Type | Description |
|---|---|---|
base |
Mapping[StyleRole, TextStyler]
|
Base mapping from |
overrides |
Mapping[StyleRole, TextStyler] | None
|
Optional role-specific overrides. |
styler_for ¶
Return the concrete TextStyler for a semantic role.
Source code in src/topmark/cli/presentation.py
rich_styler ¶
Return a TextStyler backed by Rich.
The returned callable preserves the existing TopMark presentation contract: callers pass a plain string and receive a string containing terminal styling sequences. Rich renderables remain confined to this CLI adapter module.
This helper is intended for programmatic theme definitions and test-specific theme overrides. It is not a user-facing configuration API; serialized theme configuration should be designed separately if TopMark adds configurable palettes in the future.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
style
|
str
|
Rich style expression, such as |
required |
Returns:
| Type | Description |
|---|---|
TextStyler
|
A callable that renders text using the requested Rich style. |
Source code in src/topmark/cli/presentation.py
no_style_for_role ¶
style_for_role ¶
Return a string styler for the given semantic StyleRole.
This function maps core semantic roles onto concrete terminal styling. It is intentionally CLI-only and depends on Rich through this adapter module.
Callers should still gate styling themselves when color is disabled and fall back to a no-op.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
role
|
StyleRole
|
The semantic style role to map. |
required |
styled
|
bool
|
Whether to render styled. |
True
|
theme
|
Theme
|
Theme used to resolve the concrete |
DEFAULT_THEME
|
Returns:
| Type | Description |
|---|---|
TextStyler
|
A callable that styles a string. |
Source code in src/topmark/cli/presentation.py
maybe_style ¶
Conditionally apply a styling function.
This is a tiny helper used by TEXT emitters to avoid scattering if color: checks throughout
rendering code.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str
|
Input text to render. |
required |
styler
|
TextStyler
|
Callable that applies styling to a string. |
required |
styled
|
bool
|
When False, return |
required |
Returns:
| Type | Description |
|---|---|
str
|
Styled text when enabled; otherwise the original |