scc-cli 1.5.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of scc-cli might be problematic. Click here for more details.
- scc_cli/__init__.py +15 -0
- scc_cli/audit/__init__.py +37 -0
- scc_cli/audit/parser.py +191 -0
- scc_cli/audit/reader.py +180 -0
- scc_cli/auth.py +145 -0
- scc_cli/claude_adapter.py +485 -0
- scc_cli/cli.py +311 -0
- scc_cli/cli_common.py +190 -0
- scc_cli/cli_helpers.py +244 -0
- scc_cli/commands/__init__.py +20 -0
- scc_cli/commands/admin.py +708 -0
- scc_cli/commands/audit.py +246 -0
- scc_cli/commands/config.py +528 -0
- scc_cli/commands/exceptions.py +696 -0
- scc_cli/commands/init.py +272 -0
- scc_cli/commands/launch/__init__.py +73 -0
- scc_cli/commands/launch/app.py +1247 -0
- scc_cli/commands/launch/render.py +309 -0
- scc_cli/commands/launch/sandbox.py +135 -0
- scc_cli/commands/launch/workspace.py +339 -0
- scc_cli/commands/org/__init__.py +49 -0
- scc_cli/commands/org/_builders.py +264 -0
- scc_cli/commands/org/app.py +41 -0
- scc_cli/commands/org/import_cmd.py +267 -0
- scc_cli/commands/org/init_cmd.py +269 -0
- scc_cli/commands/org/schema_cmd.py +76 -0
- scc_cli/commands/org/status_cmd.py +157 -0
- scc_cli/commands/org/update_cmd.py +330 -0
- scc_cli/commands/org/validate_cmd.py +138 -0
- scc_cli/commands/support.py +323 -0
- scc_cli/commands/team.py +910 -0
- scc_cli/commands/worktree/__init__.py +72 -0
- scc_cli/commands/worktree/_helpers.py +57 -0
- scc_cli/commands/worktree/app.py +170 -0
- scc_cli/commands/worktree/container_commands.py +385 -0
- scc_cli/commands/worktree/context_commands.py +61 -0
- scc_cli/commands/worktree/session_commands.py +128 -0
- scc_cli/commands/worktree/worktree_commands.py +734 -0
- scc_cli/config.py +647 -0
- scc_cli/confirm.py +20 -0
- scc_cli/console.py +562 -0
- scc_cli/contexts.py +394 -0
- scc_cli/core/__init__.py +68 -0
- scc_cli/core/constants.py +101 -0
- scc_cli/core/errors.py +297 -0
- scc_cli/core/exit_codes.py +91 -0
- scc_cli/core/workspace.py +57 -0
- scc_cli/deprecation.py +54 -0
- scc_cli/deps.py +189 -0
- scc_cli/docker/__init__.py +127 -0
- scc_cli/docker/core.py +467 -0
- scc_cli/docker/credentials.py +726 -0
- scc_cli/docker/launch.py +595 -0
- scc_cli/doctor/__init__.py +105 -0
- scc_cli/doctor/checks/__init__.py +166 -0
- scc_cli/doctor/checks/cache.py +314 -0
- scc_cli/doctor/checks/config.py +107 -0
- scc_cli/doctor/checks/environment.py +182 -0
- scc_cli/doctor/checks/json_helpers.py +157 -0
- scc_cli/doctor/checks/organization.py +264 -0
- scc_cli/doctor/checks/worktree.py +278 -0
- scc_cli/doctor/render.py +365 -0
- scc_cli/doctor/types.py +66 -0
- scc_cli/evaluation/__init__.py +27 -0
- scc_cli/evaluation/apply_exceptions.py +207 -0
- scc_cli/evaluation/evaluate.py +97 -0
- scc_cli/evaluation/models.py +80 -0
- scc_cli/git.py +84 -0
- scc_cli/json_command.py +166 -0
- scc_cli/json_output.py +159 -0
- scc_cli/kinds.py +65 -0
- scc_cli/marketplace/__init__.py +123 -0
- scc_cli/marketplace/adapter.py +74 -0
- scc_cli/marketplace/compute.py +377 -0
- scc_cli/marketplace/constants.py +87 -0
- scc_cli/marketplace/managed.py +135 -0
- scc_cli/marketplace/materialize.py +846 -0
- scc_cli/marketplace/normalize.py +548 -0
- scc_cli/marketplace/render.py +281 -0
- scc_cli/marketplace/resolve.py +459 -0
- scc_cli/marketplace/schema.py +506 -0
- scc_cli/marketplace/sync.py +279 -0
- scc_cli/marketplace/team_cache.py +195 -0
- scc_cli/marketplace/team_fetch.py +689 -0
- scc_cli/marketplace/trust.py +244 -0
- scc_cli/models/__init__.py +41 -0
- scc_cli/models/exceptions.py +273 -0
- scc_cli/models/plugin_audit.py +434 -0
- scc_cli/org_templates.py +269 -0
- scc_cli/output_mode.py +167 -0
- scc_cli/panels.py +113 -0
- scc_cli/platform.py +350 -0
- scc_cli/profiles.py +960 -0
- scc_cli/remote.py +443 -0
- scc_cli/schemas/__init__.py +1 -0
- scc_cli/schemas/org-v1.schema.json +456 -0
- scc_cli/schemas/team-config.v1.schema.json +163 -0
- scc_cli/services/__init__.py +1 -0
- scc_cli/services/git/__init__.py +79 -0
- scc_cli/services/git/branch.py +151 -0
- scc_cli/services/git/core.py +216 -0
- scc_cli/services/git/hooks.py +108 -0
- scc_cli/services/git/worktree.py +444 -0
- scc_cli/services/workspace/__init__.py +36 -0
- scc_cli/services/workspace/resolver.py +223 -0
- scc_cli/services/workspace/suspicious.py +200 -0
- scc_cli/sessions.py +425 -0
- scc_cli/setup.py +589 -0
- scc_cli/source_resolver.py +470 -0
- scc_cli/stats.py +378 -0
- scc_cli/stores/__init__.py +13 -0
- scc_cli/stores/exception_store.py +251 -0
- scc_cli/subprocess_utils.py +88 -0
- scc_cli/teams.py +383 -0
- scc_cli/templates/__init__.py +2 -0
- scc_cli/templates/org/__init__.py +0 -0
- scc_cli/templates/org/minimal.json +19 -0
- scc_cli/templates/org/reference.json +74 -0
- scc_cli/templates/org/strict.json +38 -0
- scc_cli/templates/org/teams.json +42 -0
- scc_cli/templates/statusline.sh +75 -0
- scc_cli/theme.py +348 -0
- scc_cli/ui/__init__.py +154 -0
- scc_cli/ui/branding.py +68 -0
- scc_cli/ui/chrome.py +401 -0
- scc_cli/ui/dashboard/__init__.py +62 -0
- scc_cli/ui/dashboard/_dashboard.py +794 -0
- scc_cli/ui/dashboard/loaders.py +452 -0
- scc_cli/ui/dashboard/models.py +185 -0
- scc_cli/ui/dashboard/orchestrator.py +735 -0
- scc_cli/ui/formatters.py +444 -0
- scc_cli/ui/gate.py +350 -0
- scc_cli/ui/git_interactive.py +869 -0
- scc_cli/ui/git_render.py +176 -0
- scc_cli/ui/help.py +157 -0
- scc_cli/ui/keys.py +615 -0
- scc_cli/ui/list_screen.py +437 -0
- scc_cli/ui/picker.py +763 -0
- scc_cli/ui/prompts.py +201 -0
- scc_cli/ui/quick_resume.py +116 -0
- scc_cli/ui/wizard.py +576 -0
- scc_cli/update.py +680 -0
- scc_cli/utils/__init__.py +39 -0
- scc_cli/utils/fixit.py +264 -0
- scc_cli/utils/fuzzy.py +124 -0
- scc_cli/utils/locks.py +114 -0
- scc_cli/utils/ttl.py +376 -0
- scc_cli/validate.py +455 -0
- scc_cli-1.5.3.dist-info/METADATA +401 -0
- scc_cli-1.5.3.dist-info/RECORD +153 -0
- scc_cli-1.5.3.dist-info/WHEEL +4 -0
- scc_cli-1.5.3.dist-info/entry_points.txt +2 -0
- scc_cli-1.5.3.dist-info/licenses/LICENSE +21 -0
scc_cli/ui/git_render.py
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"""Git rendering functions - pure UI components for git data display.
|
|
2
|
+
|
|
3
|
+
Pure functions with no side effects beyond console output. These take
|
|
4
|
+
data structures (like WorktreeInfo) and render them to Rich consoles.
|
|
5
|
+
|
|
6
|
+
Extracted from git.py to separate rendering from domain logic.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from rich import box
|
|
10
|
+
from rich.console import Console
|
|
11
|
+
from rich.table import Table
|
|
12
|
+
from rich.text import Text
|
|
13
|
+
|
|
14
|
+
from ..panels import create_warning_panel
|
|
15
|
+
from ..services.git.branch import PROTECTED_BRANCHES, get_display_branch
|
|
16
|
+
from ..services.git.worktree import WorktreeInfo
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def format_git_status(wt: WorktreeInfo) -> Text:
|
|
20
|
+
"""Format git status as compact symbols: +N!N?N, . for clean, or ... for timeout.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
wt: WorktreeInfo object with status fields populated.
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
Rich Text with styled git status symbols.
|
|
27
|
+
"""
|
|
28
|
+
# Show ellipsis if status timed out
|
|
29
|
+
if wt.status_timed_out:
|
|
30
|
+
return Text("...", style="dim")
|
|
31
|
+
|
|
32
|
+
if wt.staged_count == 0 and wt.modified_count == 0 and wt.untracked_count == 0:
|
|
33
|
+
return Text(".", style="green")
|
|
34
|
+
|
|
35
|
+
parts = Text()
|
|
36
|
+
if wt.staged_count > 0:
|
|
37
|
+
parts.append(f"+{wt.staged_count}", style="green")
|
|
38
|
+
if wt.modified_count > 0:
|
|
39
|
+
parts.append(f"!{wt.modified_count}", style="yellow")
|
|
40
|
+
if wt.untracked_count > 0:
|
|
41
|
+
parts.append(f"?{wt.untracked_count}", style="dim")
|
|
42
|
+
return parts
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def render_worktrees_table(
|
|
46
|
+
worktrees: list[WorktreeInfo],
|
|
47
|
+
console: Console,
|
|
48
|
+
*,
|
|
49
|
+
verbose: bool = False,
|
|
50
|
+
) -> None:
|
|
51
|
+
"""Render worktrees in a responsive table.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
worktrees: List of WorktreeInfo objects to display.
|
|
55
|
+
console: Rich console for output.
|
|
56
|
+
verbose: If True, show git status symbols.
|
|
57
|
+
"""
|
|
58
|
+
if not worktrees:
|
|
59
|
+
console.print()
|
|
60
|
+
console.print(
|
|
61
|
+
create_warning_panel(
|
|
62
|
+
"No Worktrees",
|
|
63
|
+
"No git worktrees found for this repository.",
|
|
64
|
+
"Create one with: scc worktree <repo> <feature-name>",
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
return
|
|
68
|
+
|
|
69
|
+
console.print()
|
|
70
|
+
|
|
71
|
+
# Responsive: check terminal width
|
|
72
|
+
width = console.width
|
|
73
|
+
wide_mode = width >= 110
|
|
74
|
+
|
|
75
|
+
# Create table with adaptive columns
|
|
76
|
+
table = Table(
|
|
77
|
+
title="[bold cyan]Git Worktrees[/bold cyan]",
|
|
78
|
+
box=box.ROUNDED,
|
|
79
|
+
header_style="bold cyan",
|
|
80
|
+
show_lines=False,
|
|
81
|
+
expand=True,
|
|
82
|
+
padding=(0, 1),
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
table.add_column("#", style="dim", width=3, justify="right")
|
|
86
|
+
table.add_column("Branch", style="cyan", no_wrap=True)
|
|
87
|
+
|
|
88
|
+
if verbose:
|
|
89
|
+
table.add_column("Status", no_wrap=True, width=10)
|
|
90
|
+
|
|
91
|
+
if wide_mode:
|
|
92
|
+
table.add_column("Path", style="dim", overflow="ellipsis", ratio=2)
|
|
93
|
+
if not verbose:
|
|
94
|
+
table.add_column("Status", style="dim", no_wrap=True, width=12)
|
|
95
|
+
else:
|
|
96
|
+
table.add_column("Path", style="dim", overflow="ellipsis", max_width=40)
|
|
97
|
+
|
|
98
|
+
for idx, wt in enumerate(worktrees, 1):
|
|
99
|
+
# Style the branch name with @ prefix for current
|
|
100
|
+
is_detached = not wt.branch
|
|
101
|
+
is_protected = wt.branch in PROTECTED_BRANCHES if wt.branch else False
|
|
102
|
+
# Use display-friendly name (strip SCC prefix)
|
|
103
|
+
branch_value = get_display_branch(wt.branch) if wt.branch else "detached"
|
|
104
|
+
|
|
105
|
+
# Add @ prefix for current worktree
|
|
106
|
+
if wt.is_current:
|
|
107
|
+
branch_display = Text("@ ", style="green bold")
|
|
108
|
+
branch_display.append(branch_value, style="cyan bold")
|
|
109
|
+
elif is_protected or is_detached:
|
|
110
|
+
branch_display = Text(branch_value, style="yellow")
|
|
111
|
+
else:
|
|
112
|
+
branch_display = Text(branch_value, style="cyan")
|
|
113
|
+
|
|
114
|
+
# Determine text status (for non-verbose wide mode)
|
|
115
|
+
text_status = wt.status or ("detached" if is_detached else "active")
|
|
116
|
+
if is_protected:
|
|
117
|
+
text_status = "protected"
|
|
118
|
+
|
|
119
|
+
status_style = {
|
|
120
|
+
"active": "green",
|
|
121
|
+
"protected": "yellow",
|
|
122
|
+
"detached": "yellow",
|
|
123
|
+
"bare": "dim",
|
|
124
|
+
}.get(text_status, "dim")
|
|
125
|
+
|
|
126
|
+
if verbose:
|
|
127
|
+
# Verbose mode: show git status symbols
|
|
128
|
+
git_status = format_git_status(wt)
|
|
129
|
+
if wide_mode:
|
|
130
|
+
table.add_row(
|
|
131
|
+
str(idx),
|
|
132
|
+
branch_display,
|
|
133
|
+
git_status,
|
|
134
|
+
wt.path,
|
|
135
|
+
)
|
|
136
|
+
else:
|
|
137
|
+
table.add_row(
|
|
138
|
+
str(idx),
|
|
139
|
+
branch_display,
|
|
140
|
+
git_status,
|
|
141
|
+
wt.path,
|
|
142
|
+
)
|
|
143
|
+
elif wide_mode:
|
|
144
|
+
table.add_row(
|
|
145
|
+
str(idx),
|
|
146
|
+
branch_display,
|
|
147
|
+
wt.path,
|
|
148
|
+
Text(text_status, style=status_style),
|
|
149
|
+
)
|
|
150
|
+
else:
|
|
151
|
+
table.add_row(
|
|
152
|
+
str(idx),
|
|
153
|
+
branch_display,
|
|
154
|
+
wt.path,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
console.print(table)
|
|
158
|
+
console.print()
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def render_worktrees(
|
|
162
|
+
worktrees: list[WorktreeInfo],
|
|
163
|
+
console: Console,
|
|
164
|
+
*,
|
|
165
|
+
verbose: bool = False,
|
|
166
|
+
) -> None:
|
|
167
|
+
"""Render worktrees with beautiful formatting.
|
|
168
|
+
|
|
169
|
+
Public interface used by cli.py for consistent styling across the application.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
worktrees: List of WorktreeInfo objects to display.
|
|
173
|
+
console: Rich console for output.
|
|
174
|
+
verbose: If True, show git status symbols.
|
|
175
|
+
"""
|
|
176
|
+
render_worktrees_table(worktrees, console, verbose=verbose)
|
scc_cli/ui/help.py
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""Help overlay for interactive UI screens.
|
|
2
|
+
|
|
3
|
+
Provides mode-aware help that shows only keys relevant to the current screen.
|
|
4
|
+
The overlay is triggered by pressing '?' and dismissed by any key.
|
|
5
|
+
|
|
6
|
+
Key categories shown per mode:
|
|
7
|
+
- ALL: Navigation (↑↓/j/k), typing to filter, backspace, t for teams
|
|
8
|
+
- PICKER: Enter to select, Esc to cancel
|
|
9
|
+
- MULTI_SELECT: Space to toggle, a to toggle all, Enter to confirm, Esc to cancel
|
|
10
|
+
- DASHBOARD: Tab/Shift+Tab for tabs, Enter for details, q to quit
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
>>> from scc_cli.ui.help import show_help_overlay
|
|
14
|
+
>>> from scc_cli.ui.list_screen import ListMode
|
|
15
|
+
>>> show_help_overlay(ListMode.SINGLE_SELECT)
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from enum import Enum, auto
|
|
21
|
+
from typing import TYPE_CHECKING
|
|
22
|
+
|
|
23
|
+
from rich.panel import Panel
|
|
24
|
+
from rich.table import Table
|
|
25
|
+
from rich.text import Text
|
|
26
|
+
|
|
27
|
+
from ..theme import Indicators
|
|
28
|
+
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
from rich.console import Console, RenderableType
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class HelpMode(Enum):
|
|
34
|
+
"""Screen mode for help overlay customization."""
|
|
35
|
+
|
|
36
|
+
PICKER = auto() # Single-select picker (team, worktree, etc.)
|
|
37
|
+
MULTI_SELECT = auto() # Multi-select list (containers, etc.)
|
|
38
|
+
DASHBOARD = auto() # Tabbed dashboard view
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# Mapping from HelpMode enum to string mode names used in KEYBINDING_DOCS
|
|
42
|
+
_MODE_NAMES: dict[HelpMode, str] = {
|
|
43
|
+
HelpMode.PICKER: "PICKER",
|
|
44
|
+
HelpMode.MULTI_SELECT: "MULTI_SELECT",
|
|
45
|
+
HelpMode.DASHBOARD: "DASHBOARD",
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def get_help_entries(mode: HelpMode) -> list[tuple[str, str]]:
|
|
50
|
+
"""Get help entries filtered for a specific mode.
|
|
51
|
+
|
|
52
|
+
This function uses KEYBINDING_DOCS from keys.py as the single source
|
|
53
|
+
of truth for keybinding documentation.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
mode: The current screen mode.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
List of (key, description) tuples for the given mode.
|
|
60
|
+
"""
|
|
61
|
+
from .keys import get_keybindings_for_mode
|
|
62
|
+
|
|
63
|
+
mode_name = _MODE_NAMES[mode]
|
|
64
|
+
return get_keybindings_for_mode(mode_name)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def get_help_entries_grouped(mode: HelpMode) -> dict[str, list[tuple[str, str]]]:
|
|
68
|
+
"""Get help entries grouped by section for a specific mode.
|
|
69
|
+
|
|
70
|
+
This function uses KEYBINDING_DOCS from keys.py as the single source
|
|
71
|
+
of truth for keybinding documentation.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
mode: The current screen mode.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Dict mapping section names to lists of (key, description) tuples.
|
|
78
|
+
"""
|
|
79
|
+
from .keys import get_keybindings_grouped_by_section
|
|
80
|
+
|
|
81
|
+
mode_name = _MODE_NAMES[mode]
|
|
82
|
+
return get_keybindings_grouped_by_section(mode_name)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def render_help_content(mode: HelpMode) -> RenderableType:
|
|
86
|
+
"""Render help content for a given mode with section headers.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
mode: The current screen mode.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
A Rich renderable with the help content organized by section.
|
|
93
|
+
"""
|
|
94
|
+
from rich.console import Group
|
|
95
|
+
|
|
96
|
+
grouped = get_help_entries_grouped(mode)
|
|
97
|
+
|
|
98
|
+
renderables: list[RenderableType] = []
|
|
99
|
+
|
|
100
|
+
for section_name, entries in grouped.items():
|
|
101
|
+
# Section header
|
|
102
|
+
section_header = Text()
|
|
103
|
+
sep = Indicators.get("HORIZONTAL_LINE")
|
|
104
|
+
section_header.append(f"{sep}{sep}{sep} {section_name} ", style="dim")
|
|
105
|
+
section_header.append(sep * max(0, 30 - len(section_name)), style="dim")
|
|
106
|
+
renderables.append(section_header)
|
|
107
|
+
|
|
108
|
+
# Section table
|
|
109
|
+
table = Table(show_header=False, box=None, padding=(0, 2, 0, 0))
|
|
110
|
+
table.add_column("Key", style="cyan bold", width=12)
|
|
111
|
+
table.add_column("Action", style="dim")
|
|
112
|
+
|
|
113
|
+
for key, desc in entries:
|
|
114
|
+
table.add_row(key, desc)
|
|
115
|
+
|
|
116
|
+
renderables.append(table)
|
|
117
|
+
renderables.append(Text("")) # Spacing between sections
|
|
118
|
+
|
|
119
|
+
# Mode indicator
|
|
120
|
+
mode_display = {
|
|
121
|
+
HelpMode.PICKER: "Picker",
|
|
122
|
+
HelpMode.MULTI_SELECT: "Multi-Select",
|
|
123
|
+
HelpMode.DASHBOARD: "Dashboard",
|
|
124
|
+
}.get(mode, "Unknown")
|
|
125
|
+
|
|
126
|
+
footer = Text()
|
|
127
|
+
footer.append("Press any key to dismiss", style="dim italic")
|
|
128
|
+
renderables.append(footer)
|
|
129
|
+
|
|
130
|
+
return Panel(
|
|
131
|
+
Group(*renderables),
|
|
132
|
+
title=f"[bold]Keyboard Shortcuts[/bold] {Indicators.get('VERTICAL_LINE')} {mode_display}",
|
|
133
|
+
title_align="left",
|
|
134
|
+
border_style="blue",
|
|
135
|
+
padding=(1, 2),
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def show_help_overlay(mode: HelpMode, console: Console | None = None) -> None:
|
|
140
|
+
"""Display help overlay and wait for any key to dismiss.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
mode: The current screen mode (affects which keys are shown).
|
|
144
|
+
console: Optional console to use. If None, creates a new one.
|
|
145
|
+
"""
|
|
146
|
+
if console is None:
|
|
147
|
+
from ..console import get_err_console
|
|
148
|
+
|
|
149
|
+
console = get_err_console()
|
|
150
|
+
|
|
151
|
+
content = render_help_content(mode)
|
|
152
|
+
console.print(content)
|
|
153
|
+
|
|
154
|
+
# Wait for any key to dismiss
|
|
155
|
+
from .keys import read_key
|
|
156
|
+
|
|
157
|
+
read_key()
|