Skip to content

Commit c1ecc62

Browse files
committed
Addressing code review comments.
1 parent c1fb768 commit c1ecc62

3 files changed

Lines changed: 44 additions & 8 deletions

File tree

cmd2/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
register_pt_mapping,
6161
register_synchronized_prefix,
6262
set_theme,
63+
unregister_pt_mapping,
64+
unregister_synchronized_prefix,
6365
)
6466
from .utils import (
6567
CustomCompletionSettings,
@@ -119,6 +121,8 @@
119121
"register_pt_mapping",
120122
"register_synchronized_prefix",
121123
"set_theme",
124+
"unregister_pt_mapping",
125+
"unregister_synchronized_prefix",
122126
# Utilities
123127
"categorize",
124128
"CustomCompletionSettings",

cmd2/theme.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
prompt-toolkit theme.
1717
"""
1818

19-
from collections.abc import Mapping
19+
from collections.abc import (
20+
Iterable,
21+
Mapping,
22+
)
2023
from typing import cast
2124

2225
from prompt_toolkit.styles import Style as PtStyle
@@ -150,7 +153,7 @@ def _create_default_theme() -> Theme:
150153
return Theme(app_styles, inherit=True)
151154

152155

153-
def register_pt_mapping(style_name: str, pt_ui_names: str | list[str]) -> None:
156+
def register_pt_mapping(style_name: str, pt_ui_names: str | Iterable[str]) -> None:
154157
"""Map a Rich theme style name to one or more prompt-toolkit UI components.
155158
156159
This enables styling of prompt-toolkit's internal elements (such as the
@@ -162,19 +165,28 @@ def register_pt_mapping(style_name: str, pt_ui_names: str | list[str]) -> None:
162165
if isinstance(pt_ui_names, str):
163166
pt_ui_names = [pt_ui_names]
164167

168+
# Register the style in the map. Presence in this map, even with an empty set,
169+
# is the trigger that flags this style for synchronization to prompt-toolkit.
170+
# This is helpful for styles which do not begin with a registered prefix.
165171
if style_name not in _PT_UI_MAP:
166172
_PT_UI_MAP[style_name] = set()
173+
changed = True
174+
else:
175+
changed = False
176+
177+
# Add UI aliases, excluding 'style_name' which the sync handles by default.
178+
original_size = len(_PT_UI_MAP[style_name])
179+
_PT_UI_MAP[style_name].update(n for n in pt_ui_names if n != style_name)
167180

168-
# Only add UI names that differ from the style name to avoid redundant rules in PtStyle
169-
unique_names = [n for n in pt_ui_names if n != style_name]
170-
_PT_UI_MAP[style_name].update(unique_names)
181+
if len(_PT_UI_MAP[style_name]) > original_size:
182+
changed = True
171183

172184
# Trigger a re-sync if the theme is already initialized
173-
if _PT_THEME is not None:
185+
if changed and _PT_THEME is not None:
174186
_sync_pt_theme()
175187

176188

177-
def unregister_pt_mapping(style_name: str, pt_ui_names: str | list[str] | None = None) -> None:
189+
def unregister_pt_mapping(style_name: str, pt_ui_names: str | Iterable[str] | None = None) -> None:
178190
"""Remove one or more prompt-toolkit UI component mappings.
179191
180192
If pt_ui_names is None, all mappings for the given style_name are removed.
@@ -194,9 +206,11 @@ def unregister_pt_mapping(style_name: str, pt_ui_names: str | list[str] | None =
194206
if isinstance(pt_ui_names, str):
195207
pt_ui_names = [pt_ui_names]
196208

209+
original_size = len(_PT_UI_MAP[style_name])
197210
for name in pt_ui_names:
198211
_PT_UI_MAP[style_name].discard(name)
199-
changed = True
212+
213+
changed = len(_PT_UI_MAP[style_name]) < original_size
200214

201215
# Clean up the key if no mappings remain
202216
if not _PT_UI_MAP[style_name]:

tests/test_theme.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,24 @@ def test_register_pt_mapping_redundant() -> None:
128128
assert "other" in theme._PT_UI_MAP[style_name]
129129

130130

131+
def test_register_pt_mapping_existing_style() -> None:
132+
"""Test calling register_pt_mapping with an existing style name."""
133+
style_name = "existing_style"
134+
ui_name = "ui_component"
135+
136+
# First registration
137+
register_pt_mapping(style_name, ui_name)
138+
139+
# Second registration with the same name
140+
register_pt_mapping(style_name, ui_name)
141+
142+
# Verify contents of _PT_UI_MAP
143+
from cmd2 import theme
144+
145+
assert style_name in theme._PT_UI_MAP
146+
assert ui_name in theme._PT_UI_MAP[style_name]
147+
148+
131149
def test_unregister_pt_mapping() -> None:
132150
"""Test unmapping styles from UI components."""
133151
from prompt_toolkit.styles import DEFAULT_ATTRS

0 commit comments

Comments
 (0)