diff --git a/cli/python/base_cli_profile.py b/cli/python/base_cli_profile.py index f5060058..fd4a2373 100644 --- a/cli/python/base_cli_profile.py +++ b/cli/python/base_cli_profile.py @@ -12,6 +12,7 @@ from base_cli.config import read_user_config from base_cli.history import HISTORY_SCOPE_INTERNAL from base_cli.history import write_finished_record +from base_history.display import display_command as history_display_command from base_cli.paths import base_cache_root from base_cli.paths import discover_manifest from base_cli.paths import make_run_id @@ -19,6 +20,7 @@ from base_cli.paths import resolve_base_home from base_cli.paths import runtime_project_name from base_cli.paths import runtime_project_root +from base_setup.ide_schema import SUPPORTED_IDES # Keep the legacy patch point available while Base supports released base-cli @@ -103,7 +105,7 @@ def resolve_runtime( return base_cli.CliProfile( discover_project=discover, - load_user_config=read_user_config, + load_user_config=_read_user_config, load_config=lambda project, explicit: load_config( project.root if project is not None else None, explicit, @@ -111,9 +113,14 @@ def resolve_runtime( resolve_runtime=resolve_runtime, history_writer=_write_finished_record, display_command=_display_command, + history_display_command=history_display_command, ) +def _read_user_config() -> base_cli.UserConfig: + return read_user_config(supported_ides=SUPPORTED_IDES) + + def _write_finished_record(*args: Any) -> None: base_cli_app_module.write_finished_record(*args) diff --git a/cli/python/base_config/engine.py b/cli/python/base_config/engine.py index 82f9f74e..1bd34fcb 100644 --- a/cli/python/base_config/engine.py +++ b/cli/python/base_config/engine.py @@ -9,6 +9,7 @@ from base_cli_profile import base_cli_app from base_cli.config import UserConfig, load_user_config, read_user_config, user_config_path from base_cli.redaction import REDACTED, is_secret_key, redact_text_value +from base_setup.ide_schema import SUPPORTED_IDES app = base_cli_app( @@ -109,7 +110,7 @@ def doctor_config_command() -> int: print_finding("ok", "yaml", "Config YAML is valid.") print_finding("ok", "mapping", f"Config contains {len(config)} top-level key(s).") try: - user_config = read_user_config() + user_config = read_user_config(supported_ides=SUPPORTED_IDES) except (RuntimeError, ValueError) as exc: print_finding("error", "schema", str(exc)) return base_cli.ExitCode.FAILURE diff --git a/cli/python/base_history/display.py b/cli/python/base_history/display.py new file mode 100644 index 00000000..23b516d6 --- /dev/null +++ b/cli/python/base_history/display.py @@ -0,0 +1,54 @@ +from __future__ import annotations + + +_BASE_DISPLAY_COMMANDS = frozenset( + { + "base_activate", + "base_build", + "base_check", + "base_ci", + "base_clean", + "base_config", + "base_demo", + "base_dev", + "base_devcontainer", + "base_devenv", + "base_devenv_report", + "base_docs", + "base_export_context", + "base_gh", + "base_github_projects", + "base_history", + "base_logs", + "base_onboard", + "base_pr_policy", + "base_projects", + "base_prompt", + "base_release", + "base_repo", + "base_run", + "base_setup", + "base_test", + "base_trust", + "base_update", + "base_update_profile", + "base_workspace", + } +) + + +def display_command(cli_name: str, argv: list[str]) -> str: + if cli_name == "base_setup": + return base_setup_action(argv) or "setup" + if cli_name in _BASE_DISPLAY_COMMANDS: + return cli_name.removeprefix("base_").replace("_", "-") + return cli_name.replace("_", "-") + + +def base_setup_action(argv: list[str]) -> str | None: + for index, arg in enumerate(argv): + if arg == "--action" and index + 1 < len(argv): + return argv[index + 1] + if arg.startswith("--action="): + return arg.partition("=")[2] + return None diff --git a/cli/python/base_history/tests/test_display.py b/cli/python/base_history/tests/test_display.py new file mode 100644 index 00000000..f3e3a0c4 --- /dev/null +++ b/cli/python/base_history/tests/test_display.py @@ -0,0 +1,15 @@ +from __future__ import annotations + +import unittest + +from base_history.display import display_command + + +class BaseHistoryDisplayTests(unittest.TestCase): + def test_base_commands_use_user_facing_aliases(self) -> None: + self.assertEqual(display_command("base_history", []), "history") + self.assertEqual(display_command("base_setup", ["--action", "check"]), "check") + + def test_non_base_names_keep_generic_formatting(self) -> None: + self.assertEqual(display_command("base_something", []), "base-something") + self.assertEqual(display_command("my_tool", []), "my-tool") diff --git a/cli/python/base_logs/engine.py b/cli/python/base_logs/engine.py index 8fb33095..ad330cdb 100644 --- a/cli/python/base_logs/engine.py +++ b/cli/python/base_logs/engine.py @@ -19,7 +19,6 @@ from base_cli.command_filters import normalize_command_filters from base_cli.history import HISTORY_PATH from base_cli.history import compact_path -from base_cli.history import display_command from base_cli.history import optional_int from base_cli.history import optional_string from base_cli.history import parse_finished_history_record_line @@ -29,6 +28,7 @@ from base_cli.paths import base_cache_root from base_cli.redaction import REDACTED from base_cli.redaction import redact_text_value +from base_history.display import display_command RUN_ID_RE = re.compile(r"^(?P\d{8}T\d{6})_[A-Za-z0-9]+(?:__.*)?$") diff --git a/cli/python/base_setup/ide.py b/cli/python/base_setup/ide.py index 988d7ec2..6a2ae581 100644 --- a/cli/python/base_setup/ide.py +++ b/cli/python/base_setup/ide.py @@ -2,8 +2,8 @@ import base_cli from base_cli.config import UserConfig -from base_cli.ide_schema import IDE_DEFINITIONS -from base_cli.ide_schema import IdeDefinition +from .ide_schema import IDE_DEFINITIONS +from .ide_schema import IdeDefinition from .checks import ArtifactCheck from .ide_diagnostics import IdeDiagnosticSnapshot diff --git a/cli/python/base_setup/ide_diagnostics.py b/cli/python/base_setup/ide_diagnostics.py index 154ed773..be6289e9 100644 --- a/cli/python/base_setup/ide_diagnostics.py +++ b/cli/python/base_setup/ide_diagnostics.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from pathlib import Path -from base_cli.ide_schema import IdeDefinition +from .ide_schema import IdeDefinition from . import process from .errors import ArtifactError diff --git a/cli/python/base_setup/ide_extensions.py b/cli/python/base_setup/ide_extensions.py index 4c5b7ea6..b7af9f4e 100644 --- a/cli/python/base_setup/ide_extensions.py +++ b/cli/python/base_setup/ide_extensions.py @@ -4,8 +4,8 @@ from typing import TYPE_CHECKING import base_cli -from base_cli.ide_schema import IDE_DEFINITIONS -from base_cli.ide_schema import IdeDefinition +from .ide_schema import IDE_DEFINITIONS +from .ide_schema import IdeDefinition from . import process from .checks import ArtifactCheck diff --git a/cli/python/base_setup/ide_installs.py b/cli/python/base_setup/ide_installs.py index 882adf91..ec6d0026 100644 --- a/cli/python/base_setup/ide_installs.py +++ b/cli/python/base_setup/ide_installs.py @@ -3,8 +3,8 @@ import subprocess import base_cli -from base_cli.ide_schema import IDE_DEFINITIONS -from base_cli.ide_schema import IdeDefinition +from .ide_schema import IDE_DEFINITIONS +from .ide_schema import IdeDefinition from . import process from .checks import ArtifactCheck diff --git a/cli/python/base_setup/ide_schema.py b/cli/python/base_setup/ide_schema.py new file mode 100644 index 00000000..147de718 --- /dev/null +++ b/cli/python/base_setup/ide_schema.py @@ -0,0 +1,45 @@ +from __future__ import annotations + +from dataclasses import dataclass + +from base_cli.ide_schema import parse_ide_extensions +from base_cli.ide_schema import parse_ide_settings + + +@dataclass(frozen=True) +class IdeDefinition: + name: str + label: str + cli: str + cask: str + settings_app_dir: str + + +IDE_DEFINITIONS = { + "vscode": IdeDefinition( + name="vscode", + label="VS Code", + cli="code", + cask="visual-studio-code", + settings_app_dir="Code", + ), + "cursor": IdeDefinition( + name="cursor", + label="Cursor", + cli="cursor", + cask="cursor", + settings_app_dir="Cursor", + ), +} + +SUPPORTED_IDES = frozenset(IDE_DEFINITIONS) +PROJECT_AUTO_SETTING_KEYS = frozenset({"python.defaultInterpreterPath"}) + +__all__ = [ + "IDE_DEFINITIONS", + "IdeDefinition", + "PROJECT_AUTO_SETTING_KEYS", + "SUPPORTED_IDES", + "parse_ide_extensions", + "parse_ide_settings", +] diff --git a/cli/python/base_setup/ide_settings.py b/cli/python/base_setup/ide_settings.py index 318db3ec..1f6ca6ac 100644 --- a/cli/python/base_setup/ide_settings.py +++ b/cli/python/base_setup/ide_settings.py @@ -8,8 +8,8 @@ from typing import TYPE_CHECKING import base_cli -from base_cli.ide_schema import IDE_DEFINITIONS -from base_cli.ide_schema import IdeDefinition +from .ide_schema import IDE_DEFINITIONS +from .ide_schema import IdeDefinition from .checks import ArtifactCheck from .errors import ArtifactError diff --git a/cli/python/base_setup/manifest.py b/cli/python/base_setup/manifest.py index e1ee182d..fff5aa93 100644 --- a/cli/python/base_setup/manifest.py +++ b/cli/python/base_setup/manifest.py @@ -3,8 +3,6 @@ from pathlib import Path from typing import Any -from base_cli.ide_schema import PROJECT_AUTO_SETTING_KEYS -from base_cli.ide_schema import SUPPORTED_IDES from base_cli.ide_schema import parse_ide_extensions from base_cli.ide_schema import parse_ide_settings from base_setup.github_manifest import GithubConfig @@ -41,6 +39,9 @@ from base_setup.manifest_schema import has_control_line_break from base_setup.manifest_schema import normalize_project_language +from .ide_schema import PROJECT_AUTO_SETTING_KEYS +from .ide_schema import SUPPORTED_IDES + def read_manifest(path: Path) -> BaseManifest: data = read_manifest_mapping(path) diff --git a/docs/base-cli.md b/docs/base-cli.md index 9a4783b6..77a84bb2 100644 --- a/docs/base-cli.md +++ b/docs/base-cli.md @@ -153,6 +153,7 @@ ctx.temp_dir # run_root/tmp// ctx.log_file # run_root/logs/primary.log, or None when disabled ctx.config # dict ctx.user_config # typed user config from ~/.base.d/config.yaml +ctx.history_display_command # consumer policy for persisted command labels ctx.environment # str ctx.debug # bool ctx.dry_run # bool diff --git a/tests/test_base_cli_profile.py b/tests/test_base_cli_profile.py index c17b915a..578cb2ab 100644 --- a/tests/test_base_cli_profile.py +++ b/tests/test_base_cli_profile.py @@ -38,3 +38,4 @@ def test_base_profile_owns_base_runtime_and_history_policies(tmp_path: Path, mon assert binding.layout.owner_root == cache_root.resolve() / "base" assert profile.history_writer is not None assert profile.display_command() is None + assert profile.history_display_command("base_setup", ["--action", "check"]) == "check"