cct-cli 0.7.9.0__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.
- calc_terminal/__init__.py +14 -0
- calc_terminal/__main__.py +14 -0
- calc_terminal/activity.py +1334 -0
- calc_terminal/agent.py +3387 -0
- calc_terminal/agent_runtime.py +519 -0
- calc_terminal/ai_context.py +447 -0
- calc_terminal/ai_modes.py +752 -0
- calc_terminal/ai_personalization.py +286 -0
- calc_terminal/ai_preview_feedback.py +213 -0
- calc_terminal/aicore.py +2572 -0
- calc_terminal/anim.py +367 -0
- calc_terminal/app.py +3685 -0
- calc_terminal/art.py +639 -0
- calc_terminal/atomsim.py +368 -0
- calc_terminal/attachments.py +743 -0
- calc_terminal/benchmark_system.py +414 -0
- calc_terminal/browser/__init__.py +36 -0
- calc_terminal/browser/browser_state.py +346 -0
- calc_terminal/browser/devserver.py +176 -0
- calc_terminal/browser/engine.py +494 -0
- calc_terminal/browser/navigation.py +84 -0
- calc_terminal/browser/preview.py +429 -0
- calc_terminal/browser/preview_entry.py +95 -0
- calc_terminal/browser/project_detector.py +144 -0
- calc_terminal/browser/server.py +449 -0
- calc_terminal/browser/state.py +75 -0
- calc_terminal/browser/watcher.py +99 -0
- calc_terminal/browser_gui/__init__.py +1 -0
- calc_terminal/browser_gui/__main__.py +3 -0
- calc_terminal/browser_gui/launcher.py +173 -0
- calc_terminal/browser_gui/playwright_browser.py +117 -0
- calc_terminal/browser_gui/qt_browser.py +1501 -0
- calc_terminal/browser_gui/webview_browser.py +57 -0
- calc_terminal/capabilities/__init__.py +35 -0
- calc_terminal/capabilities/adapters/__init__.py +33 -0
- calc_terminal/capabilities/adapters/bioinformatics.py +204 -0
- calc_terminal/capabilities/adapters/browser_adapter.py +205 -0
- calc_terminal/capabilities/adapters/filesystem.py +206 -0
- calc_terminal/capabilities/adapters/git_adapter.py +202 -0
- calc_terminal/capabilities/adapters/jupyter_adapter.py +138 -0
- calc_terminal/capabilities/adapters/ml_frameworks.py +158 -0
- calc_terminal/capabilities/adapters/platforms.py +200 -0
- calc_terminal/capabilities/adapters/python_exec.py +93 -0
- calc_terminal/capabilities/adapters/quantum_adapter.py +150 -0
- calc_terminal/capabilities/adapters/scientific_comp.py +123 -0
- calc_terminal/capabilities/adapters/structural_bio.py +161 -0
- calc_terminal/capabilities/adapters/terminal.py +99 -0
- calc_terminal/capabilities/bus.py +178 -0
- calc_terminal/capabilities/discovery.py +207 -0
- calc_terminal/capabilities/schema.py +221 -0
- calc_terminal/cat.ico +0 -0
- calc_terminal/cat_browser.py +2018 -0
- calc_terminal/chat_store.py +703 -0
- calc_terminal/cli.py +1178 -0
- calc_terminal/code_editor.py +640 -0
- calc_terminal/collaboration.py +723 -0
- calc_terminal/commands_data.py +139 -0
- calc_terminal/compatibility_engine.py +352 -0
- calc_terminal/compute/__init__.py +31 -0
- calc_terminal/compute/fabric.py +350 -0
- calc_terminal/config.py +227 -0
- calc_terminal/core/__init__.py +41 -0
- calc_terminal/core/checkpoint.py +156 -0
- calc_terminal/core/input/__init__.py +45 -0
- calc_terminal/core/mode_registry.py +300 -0
- calc_terminal/core/project_graph.py +172 -0
- calc_terminal/core/recovery.py +129 -0
- calc_terminal/core/security_layer.py +112 -0
- calc_terminal/core/task_graph.py +202 -0
- calc_terminal/core/unified_runtime.py +184 -0
- calc_terminal/core/verification.py +257 -0
- calc_terminal/customization.py +1566 -0
- calc_terminal/derivations.py +153 -0
- calc_terminal/device_control.py +263 -0
- calc_terminal/diagnostics/__init__.py +27 -0
- calc_terminal/diagnostics/doctor_engine.py +382 -0
- calc_terminal/diagnostics/self_test.py +247 -0
- calc_terminal/doctor.py +519 -0
- calc_terminal/easter_eggs.py +274 -0
- calc_terminal/editor/__init__.py +1 -0
- calc_terminal/editor/actions.py +263 -0
- calc_terminal/editor/commands.py +160 -0
- calc_terminal/editor/shortcuts.py +226 -0
- calc_terminal/engine.py +259 -0
- calc_terminal/errors.py +120 -0
- calc_terminal/event_stream.py +146 -0
- calc_terminal/eventbus.py +133 -0
- calc_terminal/extensions.py +733 -0
- calc_terminal/fallback_cli.py +1321 -0
- calc_terminal/first_run.py +265 -0
- calc_terminal/fomoji_auth.py +1043 -0
- calc_terminal/formulas.py +82 -0
- calc_terminal/fs_cache.py +121 -0
- calc_terminal/fs_watcher.py +277 -0
- calc_terminal/game.py +193 -0
- calc_terminal/gen1.py +5 -0
- calc_terminal/generators.py +245 -0
- calc_terminal/gestures/__init__.py +42 -0
- calc_terminal/gestures/bindings.py +175 -0
- calc_terminal/gestures/manager.py +477 -0
- calc_terminal/goodbye.py +363 -0
- calc_terminal/gpu3d.py +290 -0
- calc_terminal/graphs.py +358 -0
- calc_terminal/hardware_analyzer.py +440 -0
- calc_terminal/host/__init__.py +30 -0
- calc_terminal/host/browser_manager.py +187 -0
- calc_terminal/host/desktop.py +1386 -0
- calc_terminal/host/launcher.py +395 -0
- calc_terminal/host/terminal.py +279 -0
- calc_terminal/identity.py +216 -0
- calc_terminal/input/__init__.py +54 -0
- calc_terminal/input/capabilities.py +258 -0
- calc_terminal/input/focus.py +87 -0
- calc_terminal/input/gestures.py +64 -0
- calc_terminal/input/pointer.py +114 -0
- calc_terminal/input/touch.py +345 -0
- calc_terminal/keys.py +84 -0
- calc_terminal/live_automation.py +165 -0
- calc_terminal/mathtext.py +433 -0
- calc_terminal/mcp.py +386 -0
- calc_terminal/memory.py +337 -0
- calc_terminal/memory_v2.py +479 -0
- calc_terminal/metrics.py +333 -0
- calc_terminal/mode_detection.py +146 -0
- calc_terminal/model.py +2431 -0
- calc_terminal/model_router.py +665 -0
- calc_terminal/models/__init__.py +0 -0
- calc_terminal/models/active_state.py +187 -0
- calc_terminal/models/dynamic_registry.py +584 -0
- calc_terminal/models/manager.py +781 -0
- calc_terminal/models/model_metadata.json +3526 -0
- calc_terminal/models/profiles.py +194 -0
- calc_terminal/models/registry.py +265 -0
- calc_terminal/models/schema.py +197 -0
- calc_terminal/models/validator.py +287 -0
- calc_terminal/models/verification_engine.py +368 -0
- calc_terminal/native_picker.py +215 -0
- calc_terminal/ollama_catalog.py +279 -0
- calc_terminal/ollama_download.py +233 -0
- calc_terminal/orchestrator.py +304 -0
- calc_terminal/package_research.py +322 -0
- calc_terminal/packages.py +1024 -0
- calc_terminal/pc_specs.py +116 -0
- calc_terminal/permissions.py +334 -0
- calc_terminal/pet.py +106 -0
- calc_terminal/pipeline.py +505 -0
- calc_terminal/platform/__init__.py +491 -0
- calc_terminal/platform/desktop.py +491 -0
- calc_terminal/platform/web.py +781 -0
- calc_terminal/preview/__init__.py +1 -0
- calc_terminal/preview/dev_server.py +303 -0
- calc_terminal/preview/diagnostics.py +131 -0
- calc_terminal/preview/live_reload.py +66 -0
- calc_terminal/preview/manager.py +129 -0
- calc_terminal/project_stats.py +209 -0
- calc_terminal/projects.py +328 -0
- calc_terminal/providers/__init__.py +0 -0
- calc_terminal/providers/adapters/__init__.py +80 -0
- calc_terminal/providers/adapters/anthropic_adapter.py +127 -0
- calc_terminal/providers/adapters/base.py +106 -0
- calc_terminal/providers/adapters/chinese_adapters.py +420 -0
- calc_terminal/providers/adapters/gemini_adapter.py +101 -0
- calc_terminal/providers/adapters/ollama_adapter.py +83 -0
- calc_terminal/providers/adapters/openai_adapter.py +159 -0
- calc_terminal/providers/adapters/other_adapters.py +246 -0
- calc_terminal/providers/anthropic_provider.py +172 -0
- calc_terminal/providers/auto_update.py +416 -0
- calc_terminal/providers/base_provider.py +105 -0
- calc_terminal/providers/discovery_manager.py +207 -0
- calc_terminal/providers/gemini_provider.py +178 -0
- calc_terminal/providers/lifecycle.py +767 -0
- calc_terminal/providers/ollama_adapter.py +707 -0
- calc_terminal/providers/openai_provider.py +254 -0
- calc_terminal/providers/provider_manager.py +1827 -0
- calc_terminal/providers/providers.json +4075 -0
- calc_terminal/reactionsim.py +279 -0
- calc_terminal/registry.py +337 -0
- calc_terminal/report.py +162 -0
- calc_terminal/research/__init__.py +45 -0
- calc_terminal/research/artifact_intel.py +126 -0
- calc_terminal/research/data_lineage.py +123 -0
- calc_terminal/research/experiment_ledger.py +303 -0
- calc_terminal/research/reproducibility.py +131 -0
- calc_terminal/resilience/__init__.py +47 -0
- calc_terminal/resilience/agent_state.py +121 -0
- calc_terminal/resilience/capability_matcher.py +174 -0
- calc_terminal/resilience/circuit_breaker.py +158 -0
- calc_terminal/resilience/failover_engine.py +230 -0
- calc_terminal/resilience/health_monitor.py +192 -0
- calc_terminal/resilience/ollama_adapter.py +125 -0
- calc_terminal/resilience/orchestrator.py +312 -0
- calc_terminal/resilience/types.py +134 -0
- calc_terminal/sandbox.py +98 -0
- calc_terminal/scires.py +558 -0
- calc_terminal/security_scanner.py +126 -0
- calc_terminal/session.py +294 -0
- calc_terminal/sim3d.py +206 -0
- calc_terminal/solver.py +276 -0
- calc_terminal/sound.py +127 -0
- calc_terminal/task_reports.py +287 -0
- calc_terminal/terminal_host.py +201 -0
- calc_terminal/terminal_identity.py +411 -0
- calc_terminal/test_ai_mode_reliability.py +344 -0
- calc_terminal/test_browser.py +368 -0
- calc_terminal/test_code_editor_upgrade.py +485 -0
- calc_terminal/test_customization.py +1148 -0
- calc_terminal/test_customization_ui.py +612 -0
- calc_terminal/test_dynamic_registry.py +304 -0
- calc_terminal/test_extensions.py +436 -0
- calc_terminal/test_overhaul.py +557 -0
- calc_terminal/test_project_detect.py +255 -0
- calc_terminal/test_root_cause_fix.py +527 -0
- calc_terminal/test_stability.py +532 -0
- calc_terminal/test_terminal_identity.py +132 -0
- calc_terminal/test_v079_speed.py +460 -0
- calc_terminal/theme.py +1107 -0
- calc_terminal/timeline.py +139 -0
- calc_terminal/todos.py +246 -0
- calc_terminal/tool_call_normalizer.py +419 -0
- calc_terminal/tui.py +104 -0
- calc_terminal/ui/__init__.py +8 -0
- calc_terminal/ui/activity_panel.py +231 -0
- calc_terminal/ui/activity_stream_panel.py +238 -0
- calc_terminal/ui/animations.py +122 -0
- calc_terminal/ui/app.py +7271 -0
- calc_terminal/ui/attach_panel.py +597 -0
- calc_terminal/ui/attachments.py +424 -0
- calc_terminal/ui/backup_panel.py +810 -0
- calc_terminal/ui/browser_shell.py +887 -0
- calc_terminal/ui/cat_agent.py +357 -0
- calc_terminal/ui/chats_panel.py +899 -0
- calc_terminal/ui/command_palette.py +125 -0
- calc_terminal/ui/command_palette_modal.py +166 -0
- calc_terminal/ui/composer.py +1141 -0
- calc_terminal/ui/context_menu.py +197 -0
- calc_terminal/ui/conversation.py +1435 -0
- calc_terminal/ui/customization_panel.py +1229 -0
- calc_terminal/ui/dashboard.py +404 -0
- calc_terminal/ui/design_system.py +557 -0
- calc_terminal/ui/diff_panel.py +213 -0
- calc_terminal/ui/editor.py +2102 -0
- calc_terminal/ui/empty_state.py +302 -0
- calc_terminal/ui/events.py +487 -0
- calc_terminal/ui/extensions_panel.py +815 -0
- calc_terminal/ui/footer.py +166 -0
- calc_terminal/ui/gestures_panel.py +383 -0
- calc_terminal/ui/goodbye_screen.py +100 -0
- calc_terminal/ui/header.py +1034 -0
- calc_terminal/ui/help_panel.py +254 -0
- calc_terminal/ui/live_activities.py +914 -0
- calc_terminal/ui/mcp_panel.py +570 -0
- calc_terminal/ui/memory_center.py +524 -0
- calc_terminal/ui/mode_colors_panel.py +525 -0
- calc_terminal/ui/nav_screens.py +747 -0
- calc_terminal/ui/ollama_panel.py +536 -0
- calc_terminal/ui/palette.py +221 -0
- calc_terminal/ui/permission_panel.py +269 -0
- calc_terminal/ui/personalization_panel.py +517 -0
- calc_terminal/ui/personalize_center.py +1568 -0
- calc_terminal/ui/preview_panel.py +441 -0
- calc_terminal/ui/resizers.py +402 -0
- calc_terminal/ui/sidebar.py +1285 -0
- calc_terminal/ui/statusbar.py +168 -0
- calc_terminal/ui/theme_css.py +1396 -0
- calc_terminal/ui/thinking.py +226 -0
- calc_terminal/ui/timeline_panel.py +102 -0
- calc_terminal/ui/todo_panel.py +193 -0
- calc_terminal/ui/viewport.py +136 -0
- calc_terminal/ui/vision_panel.py +489 -0
- calc_terminal/ui/welcome_modal.py +343 -0
- calc_terminal/ui/widgets.py +160 -0
- calc_terminal/ui/workspace.py +831 -0
- calc_terminal/viewers/__init__.py +1 -0
- calc_terminal/viewers/document_viewer.py +252 -0
- calc_terminal/viewers/image_viewer.py +241 -0
- calc_terminal/viewers/pdf_viewer.py +203 -0
- calc_terminal/viewers/presentation_viewer.py +164 -0
- calc_terminal/viewers/registry.py +120 -0
- calc_terminal/viewers/spreadsheet_viewer.py +204 -0
- calc_terminal/vision/__init__.py +89 -0
- calc_terminal/vision/analysis.py +194 -0
- calc_terminal/vision/annotations.py +297 -0
- calc_terminal/vision/capture.py +171 -0
- calc_terminal/vision/context.py +231 -0
- calc_terminal/vision/correlation.py +169 -0
- calc_terminal/vision/cursor.py +258 -0
- calc_terminal/vision/events.py +66 -0
- calc_terminal/vision/frame_pipeline.py +259 -0
- calc_terminal/vision/priority.py +218 -0
- calc_terminal/vision/provider.py +180 -0
- calc_terminal/vision/safety.py +149 -0
- calc_terminal/vision/session.py +281 -0
- calc_terminal/vision/verify.py +162 -0
- calc_terminal/vision.py +514 -0
- calc_terminal/vscode_integration.py +113 -0
- calc_terminal/web/__init__.py +8 -0
- calc_terminal/web/cat_runtime.py +710 -0
- calc_terminal/web/server.py +2891 -0
- calc_terminal/web/static/css/app.css +3152 -0
- calc_terminal/web/static/icons/badge-72.png +0 -0
- calc_terminal/web/static/icons/cat.ico +0 -0
- calc_terminal/web/static/icons/icon-128.png +0 -0
- calc_terminal/web/static/icons/icon-144.png +0 -0
- calc_terminal/web/static/icons/icon-152.png +0 -0
- calc_terminal/web/static/icons/icon-192.png +0 -0
- calc_terminal/web/static/icons/icon-384.png +0 -0
- calc_terminal/web/static/icons/icon-512.png +0 -0
- calc_terminal/web/static/icons/icon-72.png +0 -0
- calc_terminal/web/static/icons/icon-96.png +0 -0
- calc_terminal/web/static/icons/icon.svg +34 -0
- calc_terminal/web/static/icons/new-project.png +0 -0
- calc_terminal/web/static/icons/open-project.png +0 -0
- calc_terminal/web/static/index.html +734 -0
- calc_terminal/web/static/js/app.js +2403 -0
- calc_terminal/web/static/manifest.json +88 -0
- calc_terminal/web/static/sw.js +230 -0
- calc_terminal/workflow_engine.py +769 -0
- calc_terminal/workspace.py +593 -0
- calc_terminal/workspace_index.py +385 -0
- cct_cli-0.7.9.0.dist-info/METADATA +210 -0
- cct_cli-0.7.9.0.dist-info/RECORD +325 -0
- cct_cli-0.7.9.0.dist-info/WHEEL +5 -0
- cct_cli-0.7.9.0.dist-info/entry_points.txt +4 -0
- cct_cli-0.7.9.0.dist-info/licenses/LICENSE +21 -0
- cct_cli-0.7.9.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CCT UI — command_palette.py (spec v0.7 project structure list + "Command
|
|
3
|
+
Highlighting" section: every command gets a category color, e.g. /solve
|
|
4
|
+
blue, /simulate purple, /gpu3d cyan, /build yellow, /plan green,
|
|
5
|
+
/websearch orange, /deepresearch magenta, /history gray, /help blue).
|
|
6
|
+
|
|
7
|
+
palette.py already implements the real engine this needs — fuzzy
|
|
8
|
+
subsequence matching (SuggestionEngine), live filtering as you type,
|
|
9
|
+
Up/Down navigation, Tab/Enter to accept (all driven from
|
|
10
|
+
composer.py's ComposerInput, unchanged here). Per the v0.7 brief ("Do
|
|
11
|
+
NOT rewrite working modules"), this file does not reimplement that;
|
|
12
|
+
it subclasses palette.CommandPalette and only changes how each row is
|
|
13
|
+
colored, then re-exports SuggestionEngine so callers can import either
|
|
14
|
+
name from this module going forward.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
if __name__ == "__main__":
|
|
18
|
+
print("This is a library file and is not meant to be run directly.")
|
|
19
|
+
import sys
|
|
20
|
+
sys.exit(1)
|
|
21
|
+
|
|
22
|
+
from .palette import SuggestionEngine, TEXTUAL_AVAILABLE as _PALETTE_OK # noqa: F401
|
|
23
|
+
|
|
24
|
+
TEXTUAL_AVAILABLE = True
|
|
25
|
+
try:
|
|
26
|
+
from textual.containers import Vertical
|
|
27
|
+
from textual.widgets import Static
|
|
28
|
+
except Exception:
|
|
29
|
+
TEXTUAL_AVAILABLE = False
|
|
30
|
+
|
|
31
|
+
TEXTUAL_AVAILABLE = TEXTUAL_AVAILABLE and _PALETTE_OK
|
|
32
|
+
|
|
33
|
+
# Command (stripped of leading "/") -> category, used only to pick a
|
|
34
|
+
# color below. Anything not listed here falls back to "default".
|
|
35
|
+
# Categories map 1:1 to the spec's "Command Highlighting" table.
|
|
36
|
+
_CATEGORY_OF = {
|
|
37
|
+
"solve": "solve", "calculator": "solve", "kinetics": "solve",
|
|
38
|
+
"derive": "solve", "electrochemistry": "solve", "formulas": "solve",
|
|
39
|
+
|
|
40
|
+
"sim3d": "simulate", "atomsim": "simulate", "orbitals": "simulate",
|
|
41
|
+
"orbitalgrid": "simulate", "bonding": "simulate", "bloch": "simulate",
|
|
42
|
+
"react": "simulate", "graph": "simulate",
|
|
43
|
+
|
|
44
|
+
"gpu3d": "gpu3d",
|
|
45
|
+
|
|
46
|
+
"build": "build", "codepad": "build", "edit": "build",
|
|
47
|
+
|
|
48
|
+
"plan": "plan", "mode": "plan", "notebook": "plan", "agent": "plan", "ai": "plan",
|
|
49
|
+
"research": "research", "debug": "debug",
|
|
50
|
+
|
|
51
|
+
"install": "install", "packages": "install", "pipeline": "pipeline",
|
|
52
|
+
"orchestrate": "pipeline", "devices": "devices",
|
|
53
|
+
|
|
54
|
+
"websearch": "websearch",
|
|
55
|
+
|
|
56
|
+
"history": "history", "memory": "history", "workspace": "history",
|
|
57
|
+
|
|
58
|
+
"help": "help", "about": "help", "shortcuts": "help",
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# Category -> semantic COLOR ROLE, resolved against the CURRENT theme at
|
|
62
|
+
# call time (theme.role_hex). v0.7.9.0 light-mode fix: these used to be
|
|
63
|
+
# hardcoded Tokyo-Night hexes whose pastels (#c0caf5 default!) were
|
|
64
|
+
# near-invisible on the light theme's white surfaces.
|
|
65
|
+
_CATEGORY_ROLE = {
|
|
66
|
+
"solve": "blue",
|
|
67
|
+
"simulate": "purple",
|
|
68
|
+
"gpu3d": "cyan",
|
|
69
|
+
"build": "amber",
|
|
70
|
+
"plan": "green",
|
|
71
|
+
"websearch": "amber",
|
|
72
|
+
"deepresearch": "purple",
|
|
73
|
+
"research": "cyan",
|
|
74
|
+
"debug": "red",
|
|
75
|
+
"install": "green",
|
|
76
|
+
"pipeline": "cyan",
|
|
77
|
+
"devices": "purple",
|
|
78
|
+
"history": "gray",
|
|
79
|
+
"help": "blue",
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def category_color(cmd):
|
|
84
|
+
"""`cmd` includes the leading '/'. Public so composer.py can color
|
|
85
|
+
a fully-typed command the same way the palette rows are colored.
|
|
86
|
+
Resolves through theme.role_hex so every theme stays readable —
|
|
87
|
+
v0.7.9.5: the old dependency-free Tokyo-Night fallback table is
|
|
88
|
+
gone (it leaked dark pastels onto light surfaces when the theme
|
|
89
|
+
module was briefly unimportable); the neutral gray fallback is
|
|
90
|
+
readable on BOTH dark and light backgrounds."""
|
|
91
|
+
role = _CATEGORY_ROLE.get(_CATEGORY_OF.get(cmd.lstrip("/"), ""), None)
|
|
92
|
+
try:
|
|
93
|
+
from .. import theme
|
|
94
|
+
if role:
|
|
95
|
+
return theme.role_hex(role)
|
|
96
|
+
r, g, b = theme.TEXT
|
|
97
|
+
return f"#{r:02x}{g:02x}{b:02x}"
|
|
98
|
+
except Exception:
|
|
99
|
+
return "#888888"
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
if TEXTUAL_AVAILABLE:
|
|
103
|
+
from .palette import CommandPalette as _BaseCommandPalette
|
|
104
|
+
|
|
105
|
+
class CommandPalette(_BaseCommandPalette):
|
|
106
|
+
"""Same behavior as palette.CommandPalette (fuzzy match, live
|
|
107
|
+
filter, arrow nav) — only `_redraw` changes, to paint each
|
|
108
|
+
command in its category color instead of the flat accent color.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
def _redraw(self):
|
|
112
|
+
from . import theme_css
|
|
113
|
+
accent = theme_css.current_hex("accent")
|
|
114
|
+
for child in list(self.children):
|
|
115
|
+
child.remove()
|
|
116
|
+
for i, (item, desc) in enumerate(self._matches):
|
|
117
|
+
classes = "cct-cmd-row" + (" cct-cmd-row-selected" if i == self._selected else "")
|
|
118
|
+
if item.startswith("/"):
|
|
119
|
+
color = category_color(item)
|
|
120
|
+
self.mount(Static(f"[{color} b]{item}[/] [dim]{desc}[/dim]", classes=classes))
|
|
121
|
+
else:
|
|
122
|
+
self.mount(Static(f"[{accent}]\u2726[/] [b]{item}[/] [dim]{desc}[/dim]", classes=classes))
|
|
123
|
+
|
|
124
|
+
else:
|
|
125
|
+
CommandPalette = None
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""CAT Code Editor — IDE Command Palette Modal (calc_terminal/ui/command_palette_modal.py).
|
|
2
|
+
|
|
3
|
+
VS Code-style Command Palette modal triggered by Ctrl+Shift+P:
|
|
4
|
+
- Fuzzy searches all registered IDE commands from CommandRegistry.
|
|
5
|
+
- Displays category, title, description, and keybinding badges.
|
|
6
|
+
- Up/Down navigation, Enter to execute, Esc to dismiss.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import List, Optional, Tuple
|
|
12
|
+
|
|
13
|
+
TEXTUAL_AVAILABLE = True
|
|
14
|
+
try:
|
|
15
|
+
from rich.text import Text
|
|
16
|
+
from textual.app import ComposeResult
|
|
17
|
+
from textual.binding import Binding
|
|
18
|
+
from textual.containers import Vertical, VerticalScroll
|
|
19
|
+
from textual.screen import ModalScreen
|
|
20
|
+
from textual.widgets import Input, Static
|
|
21
|
+
except Exception:
|
|
22
|
+
TEXTUAL_AVAILABLE = False
|
|
23
|
+
ModalScreen = object # type: ignore
|
|
24
|
+
|
|
25
|
+
from ..editor.commands import CATCommand, get_command_registry
|
|
26
|
+
from ..editor.shortcuts import get_shortcut_manager
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class CommandPaletteModal(ModalScreen):
|
|
30
|
+
"""Full-featured IDE Command Palette modal dialog."""
|
|
31
|
+
|
|
32
|
+
BINDINGS = [
|
|
33
|
+
Binding("escape", "dismiss_modal", "Dismiss", show=False),
|
|
34
|
+
Binding("up", "move_up", "Move Up", show=False),
|
|
35
|
+
Binding("down", "move_down", "Move Down", show=False),
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
DEFAULT_CSS = """
|
|
39
|
+
CommandPaletteModal {
|
|
40
|
+
align: center top;
|
|
41
|
+
background: rgba(0, 0, 0, 0.65);
|
|
42
|
+
padding-top: 3;
|
|
43
|
+
}
|
|
44
|
+
#cct-cmd-modal-box {
|
|
45
|
+
width: 76;
|
|
46
|
+
height: auto;
|
|
47
|
+
max-height: 24;
|
|
48
|
+
background: $surface;
|
|
49
|
+
border: round $accent;
|
|
50
|
+
padding: 0;
|
|
51
|
+
}
|
|
52
|
+
#cct-cmd-modal-input {
|
|
53
|
+
dock: top;
|
|
54
|
+
border: none;
|
|
55
|
+
border-bottom: solid $border;
|
|
56
|
+
background: $surface-alt;
|
|
57
|
+
padding: 0 1;
|
|
58
|
+
margin: 0;
|
|
59
|
+
}
|
|
60
|
+
#cct-cmd-modal-scroll {
|
|
61
|
+
height: auto;
|
|
62
|
+
max-height: 18;
|
|
63
|
+
padding: 0;
|
|
64
|
+
}
|
|
65
|
+
.cct-cmd-modal-row {
|
|
66
|
+
height: 1;
|
|
67
|
+
padding: 0 1;
|
|
68
|
+
background: transparent;
|
|
69
|
+
color: $text;
|
|
70
|
+
}
|
|
71
|
+
.cct-cmd-modal-row-selected {
|
|
72
|
+
background: $accent;
|
|
73
|
+
color: $app-background;
|
|
74
|
+
text-style: bold;
|
|
75
|
+
}
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
def __init__(self) -> None:
|
|
79
|
+
super().__init__()
|
|
80
|
+
self._matches: List[Tuple[CATCommand, str]] = []
|
|
81
|
+
self._selected_index: int = 0
|
|
82
|
+
|
|
83
|
+
def compose(self) -> ComposeResult:
|
|
84
|
+
with Vertical(id="cct-cmd-modal-box"):
|
|
85
|
+
yield Input(placeholder="Type a command or search actions...", id="cct-cmd-modal-input")
|
|
86
|
+
with VerticalScroll(id="cct-cmd-modal-scroll"):
|
|
87
|
+
yield Static("", id="cct-cmd-modal-list")
|
|
88
|
+
|
|
89
|
+
def on_mount(self) -> None:
|
|
90
|
+
self._filter_commands("")
|
|
91
|
+
try:
|
|
92
|
+
self.query_one("#cct-cmd-modal-input", Input).focus()
|
|
93
|
+
except Exception:
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
def on_input_changed(self, event: Input.Changed) -> None:
|
|
97
|
+
if event.input.id == "cct-cmd-modal-input":
|
|
98
|
+
self._filter_commands(event.value.strip())
|
|
99
|
+
|
|
100
|
+
def on_input_submitted(self, event: Input.Submitted) -> None:
|
|
101
|
+
self._execute_selected()
|
|
102
|
+
|
|
103
|
+
def _filter_commands(self, query: str) -> None:
|
|
104
|
+
reg = get_command_registry()
|
|
105
|
+
shortcut_mgr = get_shortcut_manager()
|
|
106
|
+
all_cmds = reg.list_commands()
|
|
107
|
+
q = query.lower()
|
|
108
|
+
|
|
109
|
+
matches = []
|
|
110
|
+
for cmd in all_cmds:
|
|
111
|
+
keys = shortcut_mgr.get_keybindings_for_command(cmd.id)
|
|
112
|
+
key_str = f" [{keys[0].upper()}]" if keys else ""
|
|
113
|
+
if not q or q in cmd.title.lower() or q in cmd.id.lower() or q in cmd.category.lower():
|
|
114
|
+
matches.append((cmd, key_str))
|
|
115
|
+
|
|
116
|
+
self._matches = matches
|
|
117
|
+
self._selected_index = 0
|
|
118
|
+
self._render_rows()
|
|
119
|
+
|
|
120
|
+
def _render_rows(self) -> None:
|
|
121
|
+
try:
|
|
122
|
+
list_widget = self.query_one("#cct-cmd-modal-list", Static)
|
|
123
|
+
if not self._matches:
|
|
124
|
+
list_widget.update("[dim italic] No matching commands found.[/dim italic]")
|
|
125
|
+
return
|
|
126
|
+
|
|
127
|
+
lines = []
|
|
128
|
+
for i, (cmd, key_str) in enumerate(self._matches[:40]):
|
|
129
|
+
is_sel = (i == self._selected_index)
|
|
130
|
+
prefix = "▶ " if is_sel else " "
|
|
131
|
+
cat_tag = f"[{cmd.category}] " if cmd.category else ""
|
|
132
|
+
badge = f" [dim]{key_str}[/dim]" if key_str else ""
|
|
133
|
+
|
|
134
|
+
if is_sel:
|
|
135
|
+
lines.append(f"[reverse bold]{prefix}{cat_tag}{cmd.title}{badge}[/reverse bold]")
|
|
136
|
+
else:
|
|
137
|
+
lines.append(f"{prefix}[cyan]{cat_tag}[/cyan]{cmd.title}{badge}")
|
|
138
|
+
|
|
139
|
+
list_widget.update("\n".join(lines))
|
|
140
|
+
except Exception:
|
|
141
|
+
pass
|
|
142
|
+
|
|
143
|
+
def action_move_up(self) -> None:
|
|
144
|
+
if self._matches:
|
|
145
|
+
self._selected_index = max(0, self._selected_index - 1)
|
|
146
|
+
self._render_rows()
|
|
147
|
+
|
|
148
|
+
def action_move_down(self) -> None:
|
|
149
|
+
if self._matches:
|
|
150
|
+
self._selected_index = min(len(self._matches) - 1, self._selected_index + 1)
|
|
151
|
+
self._render_rows()
|
|
152
|
+
|
|
153
|
+
def action_dismiss_modal(self) -> None:
|
|
154
|
+
self.dismiss(None)
|
|
155
|
+
|
|
156
|
+
def _execute_selected(self) -> None:
|
|
157
|
+
if self._matches and 0 <= self._selected_index < len(self._matches):
|
|
158
|
+
cmd, _ = self._matches[self._selected_index]
|
|
159
|
+
self.dismiss(None)
|
|
160
|
+
try:
|
|
161
|
+
reg = get_command_registry()
|
|
162
|
+
app = getattr(self, "app", None)
|
|
163
|
+
ctx = {"app": app}
|
|
164
|
+
reg.execute(cmd.id, context=ctx)
|
|
165
|
+
except Exception:
|
|
166
|
+
pass
|