Skip to content

Commit 91331c1

Browse files
committed
Added additional prompt-toolkit completion styles to cmd2's rich theme
Also: - Updated outdated docstring that was insufficiently broad - Updated rich_theme.py example to use new completion styles - Updated CHANGELOG and documentation
1 parent 60ca50d commit 91331c1

7 files changed

Lines changed: 56 additions & 23 deletions

File tree

CHANGELOG.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,16 @@ prompt is displayed.
151151
- Added `Cmd2ArgumentParser.output_to()` context manager to temporarily set the output stream
152152
during `argparse` operations. This is helpful for directing output for functions like
153153
`parse_args()`, which default to `sys.stdout` and lack a `file` argument.
154-
- Added ability to customize `prompt-toolkit` completion menu colors by overriding
155-
`Cmd2Style.COMPLETION_MENU_ITEM` and `Cmd2Style.COMPLETION_MENU_META` in the `cmd2` theme.
154+
- Added ability to customize `prompt-toolkit` completion menu colors by overriding the following
155+
fields in the `cmd2` theme:
156+
- `Cmd2Style.COMPLETION_MENU` - Base style for the entire completion menu container (sets
157+
the background)
158+
- `Cmd2Style.COMPLETION_MENU_COMPLETION` -Style for an individual, non-selected completion
159+
item
160+
- `Cmd2Style.COMPLETION_MENU_CURRENT` - Style for the currently selected completion item
161+
- `Cmd2Style.COMPLETION_MENU_META` - Style for "meta" information shown alongside a
162+
completion
163+
- `Cmd2Style.COMPLETION_MENU_META_CURRENT`- Style for meta info of current item
156164

157165
## 3.5.1 (April 24, 2026)
158166

cmd2/cmd2.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ def __init__(
529529

530530
# Cache for prompt_toolkit completion menu styles
531531
self._cached_pt_style: PtStyle | None = None
532-
self._cached_pt_style_params: tuple[StyleType, StyleType] | None = None
532+
self._cached_pt_style_params: tuple[StyleType, StyleType, StyleType, StyleType, StyleType] | None = None
533533

534534
# Create the main PromptSession
535535
self.bottom_toolbar = bottom_toolbar
@@ -725,24 +725,33 @@ def _should_continue_multiline(self) -> bool:
725725
return False
726726

727727
def _get_pt_style(self) -> "PtStyle":
728-
"""Return the prompt_toolkit style for the completion menu."""
728+
"""Return the cached prompt_toolkit style."""
729729
theme = ru.get_theme()
730-
rich_item_style = theme.styles.get(Cmd2Style.COMPLETION_MENU_ITEM, "")
730+
rich_menu_style = theme.styles.get(Cmd2Style.COMPLETION_MENU, "")
731+
rich_completion_style = theme.styles.get(Cmd2Style.COMPLETION_MENU_COMPLETION, "")
732+
rich_current_style = theme.styles.get(Cmd2Style.COMPLETION_MENU_CURRENT, "")
731733
rich_meta_style = theme.styles.get(Cmd2Style.COMPLETION_MENU_META, "")
734+
rich_meta_current_style = theme.styles.get(Cmd2Style.COMPLETION_MENU_META_CURRENT, "")
732735

733-
current_params = (rich_item_style, rich_meta_style)
736+
current_params = (rich_menu_style, rich_completion_style, rich_current_style, rich_meta_style, rich_meta_current_style)
734737
if self._cached_pt_style is not None and self._cached_pt_style_params == current_params:
735738
return self._cached_pt_style
736739

737-
item_style = rich_to_pt_style(rich_item_style)
740+
menu_style = rich_to_pt_style(rich_menu_style)
741+
completion_style = rich_to_pt_style(rich_completion_style)
742+
current_style = rich_to_pt_style(rich_current_style)
738743
meta_style = rich_to_pt_style(rich_meta_style)
744+
meta_current_style = rich_to_pt_style(rich_meta_current_style)
739745

740746
self._cached_pt_style_params = current_params
741747
self._cached_pt_style = PtStyle.from_dict(
742748
{
743-
"completion-menu.completion.current": item_style,
744-
"completion-menu.meta.completion.current": meta_style,
745-
"completion-menu.multi-column-meta": meta_style,
749+
"completion-menu": menu_style,
750+
"completion-menu.completion": completion_style,
751+
"completion-menu.completion.current": current_style,
752+
"completion-menu.meta.completion": meta_style,
753+
"completion-menu.meta.completion.current": meta_current_style,
754+
"completion-menu.multi-column-meta": meta_current_style,
746755
}
747756
)
748757

cmd2/styles.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
For rich-argparse, the style names are defined in the
2323
`rich_argparse.RichHelpFormatter.styles` dictionary.
2424
25+
For prompt-toolkit default styles, see:
26+
https://github.com/prompt-toolkit/python-prompt-toolkit/blob/main/src/prompt_toolkit/styles/defaults.py
2527
"""
2628

2729
import sys
@@ -51,8 +53,11 @@ class Cmd2Style(StrEnum):
5153
"""
5254

5355
COMMAND_LINE = "cmd2.example" # Command line examples in help text
54-
COMPLETION_MENU_ITEM = "cmd2.completion_menu.item" # Selected completion item
55-
COMPLETION_MENU_META = "cmd2.completion_menu.meta" # Selected completion help/meta text
56+
COMPLETION_MENU = "cmd2.completion_menu" # Base style for the entire completion menu container (sets the background)
57+
COMPLETION_MENU_COMPLETION = "cmd2.completion-menu.completion" # Style for an individual, non-selected completion item
58+
COMPLETION_MENU_CURRENT = "cmd2.completion-menu.completion.current" # Style for the currently selected completion item
59+
COMPLETION_MENU_META = "cmd2.completion-menu.meta.completion" # Style for "meta" information shown alongside a completion
60+
COMPLETION_MENU_META_CURRENT = "cmd2.completion-menu.meta.completion.current" # Style for meta info of current item
5661
ERROR = "cmd2.error" # Error text (used by perror())
5762
HELP_HEADER = "cmd2.help.header" # Help table header text
5863
HELP_LEADER = "cmd2.help.leader" # Text right before the help tables are listed
@@ -70,8 +75,11 @@ class Cmd2Style(StrEnum):
7075
# Tightly coupled with the Cmd2Style enum.
7176
DEFAULT_CMD2_STYLES: dict[str, StyleType] = {
7277
Cmd2Style.COMMAND_LINE: Style(color=Color.CYAN, bold=True),
73-
Cmd2Style.COMPLETION_MENU_ITEM: Style(color=Color.BLACK, bgcolor=Color.GREEN),
74-
Cmd2Style.COMPLETION_MENU_META: Style(color=Color.BLACK, bgcolor=Color.BRIGHT_GREEN),
78+
Cmd2Style.COMPLETION_MENU: Style(color="#000000", bgcolor="#bbbbbb"), # prompt-toolkit default
79+
Cmd2Style.COMPLETION_MENU_COMPLETION: Style(), # prompt-toolkit default
80+
Cmd2Style.COMPLETION_MENU_CURRENT: Style(color=Color.GREEN, bgcolor=Color.BLACK), # This style swaps FG and BG colors
81+
Cmd2Style.COMPLETION_MENU_META: Style(color="#000000", bgcolor="#bbbbbb"), # prompt-toolkit default
82+
Cmd2Style.COMPLETION_MENU_META_CURRENT: Style(color=Color.BLACK, bgcolor=Color.BRIGHT_GREEN),
7583
Cmd2Style.ERROR: Style(color=Color.BRIGHT_RED),
7684
Cmd2Style.HELP_HEADER: Style(color=Color.BRIGHT_GREEN),
7785
Cmd2Style.HELP_LEADER: Style(color=Color.CYAN),

docs/features/theme.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,17 @@ that is appealing to your user base.
1111
`cmd2` leverages `prompt-toolkit` for its tab completion menu. You can customize the colors of the
1212
completion menu by overriding the following styles in your `cmd2` theme:
1313

14-
- `Cmd2Style.COMPLETION_MENU_ITEM`: The background and foreground color of the selected completion
15-
item.
16-
- `Cmd2Style.COMPLETION_MENU_META`: The background and foreground color of the selected completion
17-
item's help/meta text.
14+
- `Cmd2Style.COMPLETION_MENU` - Base style for the entire completion menu container (sets the
15+
background)
16+
- `Cmd2Style.COMPLETION_MENU_COMPLETION` -Style for an individual, non-selected completion item
17+
- `Cmd2Style.COMPLETION_MENU_CURRENT` - Style for the currently selected completion item
18+
- `Cmd2Style.COMPLETION_MENU_META` - Style for "meta" information shown alongside a completion
19+
- `Cmd2Style.COMPLETION_MENU_META_CURRENT`- Style for meta info of current item
1820

19-
By default, these are styled with black text on a green background to provide contrast.
21+
By default, the currently selected completion item and metadata are styled with black text on a
22+
green background to provide contrast. All others are left at `prompt-toolkit` defaults by default.
23+
However, `cmd2` application authors are free to customimze these as they see fit in order to match a
24+
desired visual style and/or branding.
2025

2126
## Example
2227

docs/upgrades.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ periodically.
5151
`cmd2` now leverages `prompt-toolkit` for its tab completion menu and provides the ability to
5252
customize its appearance using the `cmd2` theme.
5353

54-
- **Customization**: Override the `Cmd2Style.COMPLETION_MENU_ITEM` and
54+
- **Customization**: Override the `Cmd2Style.COMPLETION_MENU_CURRENT` and
5555
`Cmd2Style.COMPLETION_MENU_META` styles using `cmd2.rich_utils.set_theme()`. See
5656
[Customizing Completion Menu Colors](features/theme.md#customizing-completion-menu-colors) for
5757
more details.

examples/rich_theme.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@ def __init__(self, *args, **kwargs):
3434
Cmd2Style.LEXER_MACRO: Style(color=Color.LIGHT_CORAL),
3535
Cmd2Style.LEXER_FLAG: Style(color=Color.LIGHT_PINK3),
3636
Cmd2Style.LEXER_ARGUMENT: Style(color=Color.LIGHT_GOLDENROD1),
37-
Cmd2Style.COMPLETION_MENU_ITEM: Style(color=Color.WHITE, bgcolor=Color.NAVY_BLUE),
38-
Cmd2Style.COMPLETION_MENU_META: Style(color=Color.WHITE, bgcolor=Color.DARK_SLATE_GRAY2),
37+
Cmd2Style.COMPLETION_MENU: Style(color="#000000", bgcolor=Color.SKY_BLUE1),
38+
Cmd2Style.COMPLETION_MENU_COMPLETION: Style(color=Color.MAGENTA),
39+
Cmd2Style.COMPLETION_MENU_CURRENT: Style(color=Color.WHITE, bgcolor=Color.NAVY_BLUE),
40+
Cmd2Style.COMPLETION_MENU_META: Style(color="#000000", bgcolor=Color.CYAN),
41+
Cmd2Style.COMPLETION_MENU_META_CURRENT: Style(color=Color.WHITE, bgcolor=Color.DARK_SLATE_GRAY2),
3942
"traceback.exc_type": Style(color=Color.RED, bgcolor=Color.LIGHT_YELLOW3, bold=True),
4043
"argparse.args": Style(color=Color.AQUAMARINE3, underline=True),
4144
}

tests/test_cmd2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1889,7 +1889,7 @@ def test_get_pt_style_caching(base_app) -> None:
18891889
orig_theme = ru.get_theme()
18901890

18911891
try:
1892-
ru.set_theme({Cmd2Style.COMPLETION_MENU_ITEM: Style(color="red")})
1892+
ru.set_theme({Cmd2Style.COMPLETION_MENU_CURRENT: Style(color="red")})
18931893

18941894
# Getting the style now should return a new object
18951895
style3 = base_app._get_pt_style()

0 commit comments

Comments
 (0)