machineconfig 8.14__py3-none-any.whl → 8.50__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 machineconfig might be problematic. Click here for more details.
- machineconfig/cluster/remote/run_cluster.py +1 -1
- machineconfig/cluster/remote/run_remote.py +1 -1
- machineconfig/cluster/sessions_managers/utils/maker.py +10 -8
- machineconfig/cluster/sessions_managers/wt_local.py +1 -1
- machineconfig/cluster/sessions_managers/wt_local_manager.py +1 -1
- machineconfig/cluster/sessions_managers/zellij_local.py +1 -1
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +1 -1
- machineconfig/jobs/installer/checks/check_installations.py +133 -0
- machineconfig/jobs/installer/checks/install_utils.py +132 -0
- machineconfig/jobs/installer/checks/report_utils.py +39 -0
- machineconfig/jobs/installer/checks/vt_utils.py +89 -0
- machineconfig/jobs/installer/installer_data.json +225 -140
- machineconfig/jobs/installer/linux_scripts/docker.sh +6 -9
- machineconfig/jobs/installer/package_groups.py +10 -9
- machineconfig/jobs/installer/python_scripts/boxes.py +1 -2
- machineconfig/jobs/installer/python_scripts/code.py +10 -8
- machineconfig/jobs/installer/python_scripts/hx.py +30 -13
- machineconfig/jobs/installer/python_scripts/nerfont_windows_helper.py +6 -5
- machineconfig/jobs/installer/python_scripts/sysabc.py +25 -19
- machineconfig/jobs/installer/python_scripts/yazi.py +33 -17
- machineconfig/jobs/scripts/powershell_scripts/cmatrix.ps1 +52 -0
- machineconfig/jobs/scripts/powershell_scripts/mount_ssh.ps1 +1 -1
- machineconfig/jobs/scripts_dynamic/a.py +413 -10
- machineconfig/profile/create_links.py +77 -20
- machineconfig/profile/create_links_export.py +63 -58
- machineconfig/profile/mapper_data.toml +30 -0
- machineconfig/profile/mapper_dotfiles.toml +253 -0
- machineconfig/scripts/python/agents.py +70 -172
- machineconfig/scripts/python/ai/initai.py +3 -1
- machineconfig/scripts/python/ai/scripts/__init__.py +1 -0
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +2 -0
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +7 -5
- machineconfig/scripts/python/ai/solutions/claude/claude.py +1 -1
- machineconfig/scripts/python/ai/solutions/cline/cline.py +1 -1
- machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +1 -1
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +29 -0
- machineconfig/scripts/python/ai/solutions/crush/crush.py +1 -1
- machineconfig/scripts/python/ai/solutions/cursor/cursors.py +1 -1
- machineconfig/scripts/python/ai/solutions/gemini/gemini.py +1 -1
- machineconfig/scripts/python/ai/solutions/gemini/settings.json +3 -0
- machineconfig/scripts/python/ai/{solutions → utils}/generic.py +2 -15
- machineconfig/scripts/python/ai/utils/vscode_tasks.py +6 -3
- machineconfig/scripts/python/cloud.py +58 -11
- machineconfig/scripts/python/croshell.py +4 -156
- machineconfig/scripts/python/devops.py +57 -40
- machineconfig/scripts/python/devops_navigator.py +17 -3
- machineconfig/scripts/python/fire_jobs.py +8 -207
- machineconfig/scripts/python/ftpx.py +5 -225
- machineconfig/scripts/python/graph/cli_graph.json +8743 -0
- machineconfig/scripts/python/{env_manager → helper_env}/path_manager_tui.py +2 -2
- machineconfig/scripts/python/{env_manager → helpers/helper_env}/env_manager_tui.py +1 -1
- machineconfig/scripts/python/helpers/helper_env/path_manager_tui.py +228 -0
- machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/agentic_frameworks/fire_crush.py +1 -1
- machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/agentic_frameworks/fire_cursor_agents.py +1 -1
- machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/agentic_frameworks/fire_gemini.py +1 -1
- machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/agentic_frameworks/fire_qwen.py +1 -1
- machineconfig/scripts/python/helpers/helpers_agents/agents_impl.py +168 -0
- machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/fire_agents_help_launch.py +5 -5
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_copy.py +6 -6
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_mount.py +10 -5
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_sync.py +3 -3
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers2.py +1 -1
- machineconfig/scripts/python/helpers/helpers_croshell/croshell_impl.py +225 -0
- machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/scheduler.py +4 -4
- machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/start_slidev.py +7 -6
- machineconfig/scripts/python/helpers/helpers_devops/backup_config.py +149 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_backup_retrieve.py +267 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_config.py +98 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_config_dotfile.py +274 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_data.py +76 -0
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/cli_nw.py +52 -72
- machineconfig/scripts/python/helpers/helpers_devops/cli_repos.py +274 -0
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/cli_self.py +40 -23
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/cli_share_file.py +44 -30
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/cli_share_server.py +26 -43
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/cli_share_terminal.py +12 -6
- machineconfig/scripts/python/helpers/helpers_devops/cli_ssh.py +167 -0
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_status.py +12 -6
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_update_repos.py +1 -1
- machineconfig/scripts/python/{interactive.py → helpers/helpers_devops/interactive.py} +68 -52
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/run_script.py +75 -58
- machineconfig/scripts/python/helpers/helpers_devops/themes/choose_starship_theme.ps1 +41 -0
- machineconfig/scripts/python/helpers/helpers_devops/themes/choose_starship_theme.sh +48 -0
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/themes/choose_wezterm_theme.py +3 -3
- machineconfig/scripts/python/helpers/helpers_fire_command/fire_jobs_impl.py +233 -0
- machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_route_helper.py +3 -3
- machineconfig/scripts/python/helpers/helpers_msearch/msearch_impl.py +248 -0
- machineconfig/scripts/python/{helpers_msearch → helpers/helpers_msearch}/scripts_linux/fzfg +4 -3
- machineconfig/scripts/python/helpers/helpers_msearch/scripts_linux/search_with_context.sh +48 -0
- machineconfig/scripts/python/{helpers_msearch → helpers/helpers_msearch}/scripts_windows/fzfg.ps1 +1 -1
- machineconfig/scripts/python/helpers/helpers_navigator/__init__.py +20 -0
- machineconfig/scripts/python/helpers/helpers_navigator/cli_graph_loader.py +234 -0
- machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/command_builder.py +61 -13
- machineconfig/scripts/python/helpers/helpers_navigator/command_detail.py +153 -0
- machineconfig/scripts/python/helpers/helpers_navigator/command_tree.py +45 -0
- machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/data_models.py +18 -11
- machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/main_app.py +5 -5
- machineconfig/scripts/python/helpers/helpers_network/__init__.py +0 -0
- machineconfig/scripts/python/{helpers_network → helpers/helpers_network}/address.py +15 -17
- machineconfig/scripts/python/{helpers_network → helpers/helpers_network}/address_switch.py +1 -1
- machineconfig/scripts/python/helpers/helpers_network/ftpx_impl.py +276 -0
- machineconfig/scripts/python/{helpers_network → helpers/helpers_network}/mount_ssh.py +2 -2
- machineconfig/scripts/python/helpers/helpers_network/ssh_add_identity.py +73 -0
- machineconfig/scripts/python/helpers/helpers_network/ssh_add_ssh_key.py +175 -0
- machineconfig/scripts/python/helpers/helpers_network/ssh_debug_linux.py +319 -0
- machineconfig/scripts/python/helpers/helpers_network/ssh_debug_windows.py +275 -0
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/action.py +3 -3
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/action_helper.py +3 -3
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/cloud_repo_sync.py +117 -33
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/grource.py +3 -2
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/record.py +33 -13
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/repo_analyzer_2.py +63 -19
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/update.py +0 -6
- machineconfig/scripts/python/helpers/helpers_search/script_help.py +81 -0
- machineconfig/scripts/python/helpers/helpers_sessions/__init__.py +0 -0
- machineconfig/scripts/python/helpers/helpers_sessions/sessions_impl.py +186 -0
- machineconfig/scripts/python/{helpers_sessions → helpers/helpers_sessions}/sessions_multiprocess.py +1 -1
- machineconfig/scripts/python/helpers/helpers_terminal/__init__.py +0 -0
- machineconfig/scripts/python/helpers/helpers_terminal/terminal_impl.py +96 -0
- machineconfig/scripts/python/{helpers_utils → helpers/helpers_utils}/download.py +1 -1
- machineconfig/scripts/python/{helpers_utils → helpers/helpers_utils}/python.py +47 -26
- machineconfig/scripts/python/helpers/helpers_utils/specs.py +246 -0
- machineconfig/scripts/python/mcfg_entry.py +133 -48
- machineconfig/scripts/python/msearch.py +15 -61
- machineconfig/scripts/python/sessions.py +59 -194
- machineconfig/scripts/python/terminal.py +18 -96
- machineconfig/scripts/python/utils.py +101 -20
- machineconfig/settings/atuin/config.toml +294 -0
- machineconfig/settings/atuin/themes/catppuccin-mocha-mauve.toml +12 -0
- machineconfig/settings/linters/.ruff.toml +1 -0
- machineconfig/settings/mprocs/windows/mprocs.yaml +2 -2
- machineconfig/settings/shells/bash/init.sh +6 -3
- machineconfig/settings/shells/pwsh/init.ps1 +69 -1
- machineconfig/settings/shells/pwsh/search_pwsh_history.ps1 +99 -0
- machineconfig/settings/shells/wezterm/wezterm.lua +4 -1
- machineconfig/settings/shells/wt/settings.json +20 -7
- machineconfig/settings/shells/zsh/init.sh +25 -4
- machineconfig/settings/television/cable_unix/bash-history.toml +1 -1
- machineconfig/settings/television/cable_windows/pwsh-history.toml +1 -1
- machineconfig/settings/tv/config.toml +234 -0
- machineconfig/settings/tv/themes/catppuccin-mocha-sky.toml +22 -0
- machineconfig/settings/wsl/.wslconfig +5 -30
- machineconfig/settings/yazi/yazi_linux.toml +18 -8
- machineconfig/settings/zellij/layouts/st.kdl +2 -2
- machineconfig/settings/zellij/layouts/st2.kdl +1 -1
- machineconfig/setup_linux/web_shortcuts/interactive.sh +10 -10
- machineconfig/setup_linux/web_shortcuts/live_from_github.sh +3 -0
- machineconfig/setup_mac/__init__.py +0 -2
- machineconfig/setup_windows/__init__.py +0 -1
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +14 -13
- machineconfig/setup_windows/web_shortcuts/live_from_github.ps1 +4 -3
- machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +3 -3
- machineconfig/type_hinting/sql/__init__.py +1 -0
- machineconfig/type_hinting/sql/base.py +216 -0
- machineconfig/type_hinting/sql/core_schema.py +64 -0
- machineconfig/type_hinting/sql/core_schema_typeddict.py +41 -0
- machineconfig/type_hinting/sql/typeddict_codegen.py +222 -0
- machineconfig/type_hinting/typedict/__init__.py +1 -0
- machineconfig/type_hinting/typedict/ast_utils.py +130 -0
- machineconfig/type_hinting/typedict/generator_helpers.py +319 -0
- machineconfig/type_hinting/typedict/generators.py +231 -0
- machineconfig/type_hinting/typedict/polars_schema.py +24 -0
- machineconfig/type_hinting/typedict/polars_schema_typeddict.py +63 -0
- machineconfig/utils/accessories.py +24 -0
- machineconfig/utils/code.py +41 -13
- machineconfig/utils/files/ascii_art.py +10 -14
- machineconfig/utils/files/headers.py +3 -5
- machineconfig/utils/files/read.py +8 -1
- machineconfig/utils/installer_utils/github_release_bulk.py +11 -91
- machineconfig/utils/installer_utils/github_release_scraper.py +99 -0
- machineconfig/utils/installer_utils/install_from_url.py +1 -1
- machineconfig/utils/installer_utils/installer_class.py +12 -4
- machineconfig/utils/installer_utils/installer_cli.py +1 -15
- machineconfig/utils/installer_utils/installer_helper.py +2 -2
- machineconfig/utils/installer_utils/installer_locator_utils.py +13 -13
- machineconfig/utils/installer_utils/installer_runner.py +4 -4
- machineconfig/utils/io.py +25 -8
- machineconfig/utils/meta.py +6 -4
- machineconfig/utils/options.py +49 -19
- machineconfig/utils/options_utils/__init__.py +0 -0
- machineconfig/utils/options_utils/options_tv_linux.py +211 -0
- machineconfig/utils/options_utils/options_tv_windows.py +88 -0
- machineconfig/utils/options_utils/tv_options.py +37 -0
- machineconfig/utils/path_extended.py +6 -6
- machineconfig/utils/scheduler.py +8 -2
- machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
- machineconfig/utils/source_of_truth.py +6 -1
- machineconfig/utils/ssh.py +69 -18
- machineconfig/utils/ssh_utils/abc.py +1 -1
- machineconfig/utils/ssh_utils/copy_from_here.py +17 -12
- machineconfig/utils/ssh_utils/utils.py +21 -5
- machineconfig/utils/ssh_utils/wsl.py +107 -170
- machineconfig/utils/ssh_utils/wsl_helper.py +217 -0
- machineconfig/utils/upgrade_packages.py +4 -8
- {machineconfig-8.14.dist-info → machineconfig-8.50.dist-info}/METADATA +29 -22
- {machineconfig-8.14.dist-info → machineconfig-8.50.dist-info}/RECORD +251 -211
- machineconfig/jobs/installer/check_installations.py +0 -248
- machineconfig/profile/backup.toml +0 -49
- machineconfig/profile/mapper.toml +0 -263
- machineconfig/scripts/python/helpers_devops/cli_config.py +0 -105
- machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +0 -89
- machineconfig/scripts/python/helpers_devops/cli_data.py +0 -25
- machineconfig/scripts/python/helpers_devops/cli_repos.py +0 -208
- machineconfig/scripts/python/helpers_devops/devops_backup_retrieve.py +0 -80
- machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +0 -3
- machineconfig/scripts/python/helpers_navigator/__init__.py +0 -20
- machineconfig/scripts/python/helpers_navigator/command_detail.py +0 -44
- machineconfig/scripts/python/helpers_navigator/command_tree.py +0 -620
- machineconfig/scripts/python/helpers_network/ssh_add_identity.py +0 -116
- machineconfig/scripts/python/helpers_network/ssh_add_ssh_key.py +0 -153
- machineconfig/scripts/python/helpers_network/ssh_debug_linux.py +0 -391
- machineconfig/scripts/python/helpers_network/ssh_debug_windows.py +0 -338
- machineconfig/scripts/python/helpers_repos/entrypoint.py +0 -77
- machineconfig/setup_mac/ssh/openssh_setup.sh +0 -114
- machineconfig/setup_windows/ssh/add-sshkey.ps1 +0 -29
- machineconfig/setup_windows/ssh/openssh-server.ps1 +0 -37
- machineconfig/utils/options_tv.py +0 -119
- machineconfig/utils/tst.py +0 -20
- /machineconfig/{scripts/python/helpers_agents → jobs/installer/checks}/__init__.py +0 -0
- /machineconfig/scripts/python/ai/{solutions/_shared.py → utils/shared.py} +0 -0
- /machineconfig/scripts/python/{helpers_agents/agentic_frameworks → graph}/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_cloud → helpers}/__init__.py +0 -0
- /machineconfig/scripts/python/{env_manager → helpers/helper_env}/__init__.py +0 -0
- /machineconfig/scripts/python/{env_manager → helpers/helper_env}/path_manager_backend.py +0 -0
- /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_agents}/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_devops → helpers/helpers_agents/agentic_frameworks}/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/agentic_frameworks/fire_crush.json +0 -0
- /machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/fire_agents_help_search.py +0 -0
- /machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/fire_agents_helper_types.py +0 -0
- /machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/fire_agents_load_balancer.py +0 -0
- /machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/privacy/configs/aichat/config.yaml +0 -0
- /machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/privacy/configs/aider/.aider.conf.yml +0 -0
- /machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/privacy/configs/copilot/config.yml +0 -0
- /machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/privacy/configs/crush/crush.json +0 -0
- /machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/privacy/configs/gemini/settings.json +0 -0
- /machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/privacy/privacy.py +0 -0
- /machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/templates/prompt.txt +0 -0
- /machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/templates/template.ps1 +0 -0
- /machineconfig/scripts/python/{helpers_agents → helpers/helpers_agents}/templates/template.sh +0 -0
- /machineconfig/scripts/python/{helpers_devops/themes → helpers/helpers_cloud}/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_helpers.py +0 -0
- /machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers5.py +0 -0
- /machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_croshell}/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/crosh.py +0 -0
- /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/pomodoro.py +0 -0
- /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/viewer.py +0 -0
- /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/viewer_template.py +0 -0
- /machineconfig/scripts/python/{helpers_network → helpers/helpers_devops}/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_sessions → helpers/helpers_devops/themes}/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/themes/choose_pwsh_theme.ps1 +0 -0
- /machineconfig/scripts/python/{helpers_devops/themes/choose_starship_theme.ps1 → helpers/helpers_fire_command/__init__.py} +0 -0
- /machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/cloud_manager.py +0 -0
- /machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/f.py +0 -0
- /machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/file_wrangler.py +0 -0
- /machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_args_helper.py +0 -0
- /machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_streamlit_helper.py +0 -0
- /machineconfig/scripts/python/{helpers_msearch → helpers/helpers_msearch}/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/search_bar.py +0 -0
- /machineconfig/scripts/python/{helpers_network → helpers/helpers_network}/mount_nfs.py +0 -0
- /machineconfig/scripts/python/{helpers_network → helpers/helpers_network}/mount_nw_drive.py +0 -0
- /machineconfig/scripts/python/{helpers_network → helpers/helpers_network}/onetimeshare.py +0 -0
- /machineconfig/scripts/python/{helpers_network → helpers/helpers_network}/wifi_conn.py +0 -0
- /machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/clone.py +0 -0
- /machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/repo_analyzer_1.py +0 -0
- /machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/sync.py +0 -0
- /machineconfig/scripts/python/helpers/{ast_search.py → helpers_search/ast_search.py} +0 -0
- /machineconfig/scripts/python/helpers/{qr_code.py → helpers_search/qr_code.py} +0 -0
- /machineconfig/scripts/python/helpers/{repo_rag.py → helpers_search/repo_rag.py} +0 -0
- /machineconfig/scripts/python/helpers/{symantic_search.py → helpers_search/symantic_search.py} +0 -0
- /machineconfig/scripts/python/{helpers_utils → helpers/helpers_utils}/pdf.py +0 -0
- {machineconfig-8.14.dist-info → machineconfig-8.50.dist-info}/WHEEL +0 -0
- {machineconfig-8.14.dist-info → machineconfig-8.50.dist-info}/entry_points.txt +0 -0
- {machineconfig-8.14.dist-info → machineconfig-8.50.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Load and normalize CLI graph data for the command navigator.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
import json
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from machineconfig.scripts.python.helpers.helpers_navigator.data_models import (
|
|
11
|
+
CommandInfo,
|
|
12
|
+
ArgumentInfo,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
DEFAULT_CLI_GRAPH_PATH = Path(__file__).resolve().parents[2] / "graph" / "cli_graph.json"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class CommandNode:
|
|
21
|
+
"""Command info plus its children."""
|
|
22
|
+
info: CommandInfo
|
|
23
|
+
children: list["CommandNode"]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def load_cli_graph(path: Path | None = None) -> dict[str, Any]:
|
|
27
|
+
"""Load the CLI graph JSON file."""
|
|
28
|
+
graph_path = path or DEFAULT_CLI_GRAPH_PATH
|
|
29
|
+
with graph_path.open("r", encoding="utf-8") as handle:
|
|
30
|
+
return json.load(handle)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def build_command_nodes(graph: dict[str, Any], *, include_root: bool = False) -> list[CommandNode]:
|
|
34
|
+
"""Build command nodes from the CLI graph."""
|
|
35
|
+
root = graph.get("root", {})
|
|
36
|
+
root_name = root.get("name") if include_root else None
|
|
37
|
+
parent_tokens = [root_name] if root_name else []
|
|
38
|
+
children = root.get("children", [])
|
|
39
|
+
return [_build_node(child, parent_tokens, parent_name=root_name) for child in children]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _build_node(node: dict[str, Any], parent_tokens: list[str], parent_name: str | None) -> CommandNode:
|
|
43
|
+
kind = node.get("kind", "command")
|
|
44
|
+
name = node.get("name", "")
|
|
45
|
+
tokens = parent_tokens + ([name] if name else [])
|
|
46
|
+
command = " ".join(tokens).strip()
|
|
47
|
+
is_group = kind == "group"
|
|
48
|
+
description = _node_description(node)
|
|
49
|
+
long_description = _node_long_description(node, description)
|
|
50
|
+
module_path = _node_module_path(node)
|
|
51
|
+
arguments = _parse_signature(node.get("signature"))
|
|
52
|
+
help_text = _build_usage(command, arguments) if (command and not is_group) else ""
|
|
53
|
+
|
|
54
|
+
info = CommandInfo(
|
|
55
|
+
name=name,
|
|
56
|
+
description=description,
|
|
57
|
+
command=command,
|
|
58
|
+
parent=parent_name,
|
|
59
|
+
is_group=is_group,
|
|
60
|
+
help_text=help_text,
|
|
61
|
+
module_path=module_path,
|
|
62
|
+
arguments=arguments,
|
|
63
|
+
long_description=long_description,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
children = [
|
|
67
|
+
_build_node(child, tokens, parent_name=name)
|
|
68
|
+
for child in node.get("children", [])
|
|
69
|
+
]
|
|
70
|
+
return CommandNode(info=info, children=children)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _node_description(node: dict[str, Any]) -> str:
|
|
74
|
+
if node.get("kind") == "group":
|
|
75
|
+
return (
|
|
76
|
+
node.get("app", {}).get("help")
|
|
77
|
+
or node.get("help")
|
|
78
|
+
or node.get("doc")
|
|
79
|
+
or node.get("name", "")
|
|
80
|
+
)
|
|
81
|
+
return (
|
|
82
|
+
node.get("short_help")
|
|
83
|
+
or node.get("help")
|
|
84
|
+
or node.get("doc")
|
|
85
|
+
or node.get("name", "")
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _node_long_description(node: dict[str, Any], fallback: str) -> str:
|
|
90
|
+
if node.get("kind") == "group":
|
|
91
|
+
return (
|
|
92
|
+
node.get("app", {}).get("help")
|
|
93
|
+
or node.get("help")
|
|
94
|
+
or node.get("doc")
|
|
95
|
+
or fallback
|
|
96
|
+
)
|
|
97
|
+
return node.get("help") or node.get("doc") or fallback
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _node_module_path(node: dict[str, Any]) -> str:
|
|
101
|
+
source = node.get("source") or {}
|
|
102
|
+
return source.get("dispatches_to") or source.get("module") or ""
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _parse_signature(signature: dict[str, Any] | None) -> list[ArgumentInfo]:
|
|
106
|
+
if not signature:
|
|
107
|
+
return []
|
|
108
|
+
|
|
109
|
+
arguments: list[ArgumentInfo] = []
|
|
110
|
+
for param in signature.get("parameters", []):
|
|
111
|
+
typer_info = param.get("typer") or {}
|
|
112
|
+
kind = typer_info.get("kind") or ""
|
|
113
|
+
name = param.get("name", "")
|
|
114
|
+
is_required = bool(param.get("required", False))
|
|
115
|
+
description = typer_info.get("help") or ""
|
|
116
|
+
|
|
117
|
+
if kind == "argument":
|
|
118
|
+
arguments.append(
|
|
119
|
+
ArgumentInfo(
|
|
120
|
+
name=name,
|
|
121
|
+
is_required=is_required,
|
|
122
|
+
is_flag=False,
|
|
123
|
+
placeholder=name,
|
|
124
|
+
description=description,
|
|
125
|
+
is_positional=True,
|
|
126
|
+
)
|
|
127
|
+
)
|
|
128
|
+
continue
|
|
129
|
+
|
|
130
|
+
if kind == "option":
|
|
131
|
+
flag, negated_flag = _select_flags(typer_info, name)
|
|
132
|
+
long_flags = list(typer_info.get("long_flags") or [])
|
|
133
|
+
short_flags = list(typer_info.get("short_flags") or [])
|
|
134
|
+
is_flag = _is_bool_type(param.get("type"))
|
|
135
|
+
arguments.append(
|
|
136
|
+
ArgumentInfo(
|
|
137
|
+
name=name,
|
|
138
|
+
is_required=is_required,
|
|
139
|
+
is_flag=is_flag,
|
|
140
|
+
placeholder=name,
|
|
141
|
+
description=description,
|
|
142
|
+
flag=flag,
|
|
143
|
+
negated_flag=negated_flag,
|
|
144
|
+
long_flags=long_flags,
|
|
145
|
+
short_flags=short_flags,
|
|
146
|
+
)
|
|
147
|
+
)
|
|
148
|
+
continue
|
|
149
|
+
|
|
150
|
+
return arguments
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _is_bool_type(type_value: Any) -> bool:
|
|
154
|
+
if type_value is None:
|
|
155
|
+
return False
|
|
156
|
+
normalized = str(type_value).replace(" ", "").lower()
|
|
157
|
+
return "bool" in normalized
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _select_flags(typer_info: dict[str, Any], name: str) -> tuple[str, str]:
|
|
161
|
+
long_flags = list(typer_info.get("long_flags") or [])
|
|
162
|
+
short_flags = list(typer_info.get("short_flags") or [])
|
|
163
|
+
param_decls = list(typer_info.get("param_decls") or [])
|
|
164
|
+
|
|
165
|
+
candidates = long_flags or _split_param_decls(param_decls)
|
|
166
|
+
if not candidates and short_flags:
|
|
167
|
+
candidates = short_flags
|
|
168
|
+
|
|
169
|
+
flag, negated_flag = _pick_positive_negative(candidates)
|
|
170
|
+
if not flag:
|
|
171
|
+
flag = _default_flag(name)
|
|
172
|
+
|
|
173
|
+
return flag, negated_flag
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _split_param_decls(param_decls: list[str]) -> list[str]:
|
|
177
|
+
candidates: list[str] = []
|
|
178
|
+
for decl in param_decls:
|
|
179
|
+
parts = [part.strip() for part in decl.split("/") if part.strip()]
|
|
180
|
+
candidates.extend(parts)
|
|
181
|
+
return candidates
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _pick_positive_negative(flags: list[str]) -> tuple[str, str]:
|
|
185
|
+
if not flags:
|
|
186
|
+
return "", ""
|
|
187
|
+
|
|
188
|
+
positives = [flag for flag in flags if not _is_negative_flag(flag)]
|
|
189
|
+
negatives = [flag for flag in flags if _is_negative_flag(flag)]
|
|
190
|
+
|
|
191
|
+
if positives:
|
|
192
|
+
return positives[0], negatives[0] if negatives else ""
|
|
193
|
+
|
|
194
|
+
return flags[0], ""
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _is_negative_flag(flag: str) -> bool:
|
|
198
|
+
token = flag.lstrip("-")
|
|
199
|
+
return token.startswith("no-")
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def _default_flag(name: str) -> str:
|
|
203
|
+
return f"--{name.replace('_', '-')}"
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _build_usage(command: str, arguments: list[ArgumentInfo]) -> str:
|
|
207
|
+
if not arguments:
|
|
208
|
+
return command
|
|
209
|
+
|
|
210
|
+
parts = [command]
|
|
211
|
+
for arg in arguments:
|
|
212
|
+
if arg.is_positional:
|
|
213
|
+
token = f"<{arg.name}>"
|
|
214
|
+
if not arg.is_required:
|
|
215
|
+
token = f"[{token}]"
|
|
216
|
+
parts.append(token)
|
|
217
|
+
continue
|
|
218
|
+
|
|
219
|
+
flag = arg.flag or _default_flag(arg.name)
|
|
220
|
+
if arg.is_flag:
|
|
221
|
+
if arg.negated_flag:
|
|
222
|
+
token = f"[{flag}|{arg.negated_flag}]"
|
|
223
|
+
else:
|
|
224
|
+
token = f"[{flag}]"
|
|
225
|
+
parts.append(token)
|
|
226
|
+
continue
|
|
227
|
+
|
|
228
|
+
placeholder = arg.placeholder or arg.name
|
|
229
|
+
token = f"{flag} <{placeholder}>"
|
|
230
|
+
if not arg.is_required:
|
|
231
|
+
token = f"[{token}]"
|
|
232
|
+
parts.append(token)
|
|
233
|
+
|
|
234
|
+
return " ".join(parts)
|
machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/command_builder.py
RENAMED
|
@@ -7,7 +7,7 @@ from textual.app import ComposeResult
|
|
|
7
7
|
from textual.containers import Horizontal, VerticalScroll
|
|
8
8
|
from textual.widgets import Static, Input, Label, Button
|
|
9
9
|
from textual.screen import ModalScreen
|
|
10
|
-
from machineconfig.scripts.python.helpers_navigator.data_models import CommandInfo, ArgumentInfo
|
|
10
|
+
from machineconfig.scripts.python.helpers.helpers_navigator.data_models import CommandInfo, ArgumentInfo
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class CommandBuilderScreen(ModalScreen[str]):
|
|
@@ -16,7 +16,11 @@ class CommandBuilderScreen(ModalScreen[str]):
|
|
|
16
16
|
def __init__(self, command_info: CommandInfo) -> None:
|
|
17
17
|
super().__init__()
|
|
18
18
|
self.command_info = command_info
|
|
19
|
-
self.arguments =
|
|
19
|
+
self.arguments = (
|
|
20
|
+
command_info.arguments
|
|
21
|
+
if command_info.arguments is not None
|
|
22
|
+
else self._parse_arguments()
|
|
23
|
+
)
|
|
20
24
|
self.input_widgets: dict[str, Input] = {}
|
|
21
25
|
|
|
22
26
|
def _parse_arguments(self) -> list[ArgumentInfo]:
|
|
@@ -34,21 +38,40 @@ class CommandBuilderScreen(ModalScreen[str]):
|
|
|
34
38
|
arg_name = match.group(1)
|
|
35
39
|
placeholder = match.group(2)
|
|
36
40
|
if arg_name not in seen_names:
|
|
37
|
-
args.append(ArgumentInfo(
|
|
41
|
+
args.append(ArgumentInfo(
|
|
42
|
+
name=arg_name,
|
|
43
|
+
is_required=False,
|
|
44
|
+
is_flag=False,
|
|
45
|
+
placeholder=placeholder,
|
|
46
|
+
flag=f"--{arg_name}",
|
|
47
|
+
long_flags=[f"--{arg_name}"],
|
|
48
|
+
))
|
|
38
49
|
seen_names.add(arg_name)
|
|
39
50
|
|
|
40
51
|
flag_pattern = re.compile(r'--(\w+(?:-\w+)*)(?:\s|$)')
|
|
41
52
|
for match in flag_pattern.finditer(help_text):
|
|
42
53
|
arg_name = match.group(1)
|
|
43
54
|
if arg_name not in seen_names:
|
|
44
|
-
args.append(ArgumentInfo(
|
|
55
|
+
args.append(ArgumentInfo(
|
|
56
|
+
name=arg_name,
|
|
57
|
+
is_required=False,
|
|
58
|
+
is_flag=True,
|
|
59
|
+
flag=f"--{arg_name}",
|
|
60
|
+
long_flags=[f"--{arg_name}"],
|
|
61
|
+
))
|
|
45
62
|
seen_names.add(arg_name)
|
|
46
63
|
|
|
47
64
|
positional_pattern = re.compile(r'<(\w+)>(?!\s*>)')
|
|
48
65
|
for match in positional_pattern.finditer(help_text):
|
|
49
66
|
arg_name = match.group(1)
|
|
50
67
|
if arg_name not in seen_names and not re.search(rf'--\w+\s+<{arg_name}>', help_text):
|
|
51
|
-
args.append(ArgumentInfo(
|
|
68
|
+
args.append(ArgumentInfo(
|
|
69
|
+
name=arg_name,
|
|
70
|
+
is_required=True,
|
|
71
|
+
is_flag=False,
|
|
72
|
+
placeholder=arg_name,
|
|
73
|
+
is_positional=True,
|
|
74
|
+
))
|
|
52
75
|
seen_names.add(arg_name)
|
|
53
76
|
|
|
54
77
|
return args
|
|
@@ -63,12 +86,22 @@ class CommandBuilderScreen(ModalScreen[str]):
|
|
|
63
86
|
else:
|
|
64
87
|
for arg in self.arguments:
|
|
65
88
|
if arg.is_flag:
|
|
66
|
-
|
|
89
|
+
flag = arg.flag or f"--{arg.name}"
|
|
90
|
+
if arg.negated_flag:
|
|
91
|
+
label_text = f"{flag} / {arg.negated_flag} (flag, leave empty to skip)"
|
|
92
|
+
else:
|
|
93
|
+
label_text = f"{flag} (flag, leave empty to skip)"
|
|
67
94
|
yield Label(label_text)
|
|
68
95
|
input_widget = Input(placeholder="yes/no or leave empty", id=f"arg_{arg.name}")
|
|
96
|
+
elif arg.is_positional:
|
|
97
|
+
required_marker = "[red]*[/red]" if arg.is_required else "[dim](optional)[/dim]"
|
|
98
|
+
label_text = f"{arg.name} {required_marker}"
|
|
99
|
+
yield Label(label_text)
|
|
100
|
+
input_widget = Input(placeholder=arg.placeholder or arg.name, id=f"arg_{arg.name}")
|
|
69
101
|
else:
|
|
102
|
+
flag = arg.flag or f"--{arg.name}"
|
|
70
103
|
required_marker = "[red]*[/red]" if arg.is_required else "[dim](optional)[/dim]"
|
|
71
|
-
label_text = f"
|
|
104
|
+
label_text = f"{flag} {required_marker}"
|
|
72
105
|
yield Label(label_text)
|
|
73
106
|
input_widget = Input(placeholder=arg.placeholder or arg.name, id=f"arg_{arg.name}")
|
|
74
107
|
|
|
@@ -96,16 +129,31 @@ class CommandBuilderScreen(ModalScreen[str]):
|
|
|
96
129
|
def _build_command(self) -> str:
|
|
97
130
|
"""Build the complete command with arguments."""
|
|
98
131
|
parts = [self.command_info.command]
|
|
132
|
+
yes_values = {"yes", "y", "true", "1", "on"}
|
|
133
|
+
no_values = {"no", "n", "false", "0", "off"}
|
|
99
134
|
|
|
100
135
|
for arg in self.arguments:
|
|
101
136
|
input_widget = self.input_widgets.get(arg.name)
|
|
102
137
|
if input_widget:
|
|
103
138
|
value = input_widget.value.strip()
|
|
104
139
|
if value:
|
|
105
|
-
if arg.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
else:
|
|
109
|
-
parts.append(f"--{arg.name} {value}")
|
|
140
|
+
if arg.is_positional:
|
|
141
|
+
parts.append(value)
|
|
142
|
+
continue
|
|
110
143
|
|
|
111
|
-
|
|
144
|
+
if arg.is_flag:
|
|
145
|
+
flag_value = value.lower()
|
|
146
|
+
flag = arg.flag or f"--{arg.name}"
|
|
147
|
+
if flag_value in yes_values:
|
|
148
|
+
parts.append(flag)
|
|
149
|
+
elif flag_value in no_values:
|
|
150
|
+
if arg.negated_flag:
|
|
151
|
+
parts.append(arg.negated_flag)
|
|
152
|
+
elif value.startswith("-"):
|
|
153
|
+
parts.append(value)
|
|
154
|
+
continue
|
|
155
|
+
|
|
156
|
+
flag = arg.flag or f"--{arg.name}"
|
|
157
|
+
parts.append(f"{flag} {value}")
|
|
158
|
+
|
|
159
|
+
return " ".join(parts)
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command detail widget for displaying command information.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from textual.widgets import Static
|
|
7
|
+
from rich.text import Text
|
|
8
|
+
from rich.panel import Panel
|
|
9
|
+
from rich.console import Group
|
|
10
|
+
from rich.table import Table
|
|
11
|
+
from rich import box
|
|
12
|
+
from machineconfig.scripts.python.helpers.helpers_navigator.data_models import CommandInfo
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CommandDetail(Static):
|
|
16
|
+
"""Widget for displaying command details."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, *, id: str) -> None: # type: ignore
|
|
19
|
+
super().__init__(id=id)
|
|
20
|
+
self.command_info: Optional[CommandInfo] = None
|
|
21
|
+
|
|
22
|
+
def update_command(self, command_info: Optional[CommandInfo]) -> None:
|
|
23
|
+
"""Update displayed command information."""
|
|
24
|
+
self.command_info = command_info
|
|
25
|
+
if command_info is None:
|
|
26
|
+
self.update("Select a command to view details")
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
if command_info.is_group:
|
|
30
|
+
self.update(self._render_group(command_info))
|
|
31
|
+
return
|
|
32
|
+
|
|
33
|
+
self.update(self._render_command(command_info))
|
|
34
|
+
|
|
35
|
+
def _render_group(self, command_info: CommandInfo) -> Panel:
|
|
36
|
+
content = Text()
|
|
37
|
+
content.append("Group: ", style="bold cyan")
|
|
38
|
+
content.append(f"{command_info.name}\n\n", style="bold yellow")
|
|
39
|
+
|
|
40
|
+
content.append("Description: ", style="bold green")
|
|
41
|
+
content.append(f"{command_info.long_description or command_info.description}\n\n", style="white")
|
|
42
|
+
|
|
43
|
+
content.append("Command: ", style="bold blue")
|
|
44
|
+
content.append(f"{command_info.command}\n\n", style="bold white")
|
|
45
|
+
|
|
46
|
+
if command_info.module_path:
|
|
47
|
+
content.append("Module: ", style="bold red")
|
|
48
|
+
content.append(f"{command_info.module_path}\n", style="white")
|
|
49
|
+
|
|
50
|
+
return Panel(content, title=f"[bold]{command_info.name}[/bold]", border_style="blue")
|
|
51
|
+
|
|
52
|
+
def _render_command(self, command_info: CommandInfo) -> Panel:
|
|
53
|
+
renderables = []
|
|
54
|
+
usage_text = Text()
|
|
55
|
+
usage_text.append("Usage: ", style="bold cyan")
|
|
56
|
+
usage_text.append(self._format_usage(command_info), style="white")
|
|
57
|
+
renderables.append(usage_text)
|
|
58
|
+
|
|
59
|
+
description = command_info.long_description or command_info.description
|
|
60
|
+
if description:
|
|
61
|
+
renderables.append(Text(description, style="green"))
|
|
62
|
+
|
|
63
|
+
arguments = command_info.arguments or []
|
|
64
|
+
positional_args = [arg for arg in arguments if arg.is_positional]
|
|
65
|
+
option_args = [arg for arg in arguments if not arg.is_positional]
|
|
66
|
+
|
|
67
|
+
if positional_args:
|
|
68
|
+
renderables.append(self._build_arguments_table(positional_args))
|
|
69
|
+
|
|
70
|
+
renderables.append(self._build_options_table(option_args))
|
|
71
|
+
|
|
72
|
+
if command_info.module_path:
|
|
73
|
+
renderables.append(Text(f"Module: {command_info.module_path}", style="dim"))
|
|
74
|
+
|
|
75
|
+
content = Group(*renderables)
|
|
76
|
+
return Panel(content, title=f"[bold]{command_info.name}[/bold]", border_style="blue")
|
|
77
|
+
|
|
78
|
+
def _format_usage(self, command_info: CommandInfo) -> str:
|
|
79
|
+
arguments = command_info.arguments or []
|
|
80
|
+
positional_args = [arg for arg in arguments if arg.is_positional]
|
|
81
|
+
option_args = [arg for arg in arguments if not arg.is_positional]
|
|
82
|
+
|
|
83
|
+
parts = [command_info.command or command_info.name]
|
|
84
|
+
if option_args:
|
|
85
|
+
parts.append("[OPTIONS]")
|
|
86
|
+
|
|
87
|
+
for arg in positional_args:
|
|
88
|
+
placeholder = self._placeholder(arg)
|
|
89
|
+
token = placeholder if arg.is_required else f"[{placeholder}]"
|
|
90
|
+
parts.append(token)
|
|
91
|
+
|
|
92
|
+
usage = " ".join(parts).strip()
|
|
93
|
+
return usage or command_info.help_text or command_info.name
|
|
94
|
+
|
|
95
|
+
def _build_arguments_table(self, arguments) -> Table: # type: ignore
|
|
96
|
+
table = Table(box=box.MINIMAL, show_header=False, pad_edge=False)
|
|
97
|
+
table.add_column("Argument", style="bold cyan", no_wrap=True)
|
|
98
|
+
table.add_column("Description", style="white")
|
|
99
|
+
|
|
100
|
+
for arg in arguments:
|
|
101
|
+
placeholder = self._placeholder(arg)
|
|
102
|
+
token = f"{arg.name} {placeholder}" if arg.is_required else f"{arg.name} [{placeholder}]"
|
|
103
|
+
table.add_row(token, arg.description or "")
|
|
104
|
+
|
|
105
|
+
table.title = "Arguments"
|
|
106
|
+
table.title_style = "bold green"
|
|
107
|
+
return table
|
|
108
|
+
|
|
109
|
+
def _build_options_table(self, options) -> Table: # type: ignore
|
|
110
|
+
table = Table(box=box.MINIMAL, show_header=False, pad_edge=False)
|
|
111
|
+
table.add_column("Option", style="bold cyan", no_wrap=True)
|
|
112
|
+
table.add_column("Description", style="white")
|
|
113
|
+
|
|
114
|
+
for opt in options:
|
|
115
|
+
flag_text = self._format_option_flags(opt)
|
|
116
|
+
if not opt.is_flag:
|
|
117
|
+
placeholder = self._placeholder(opt)
|
|
118
|
+
flag_text = f"{flag_text} <{placeholder}>"
|
|
119
|
+
table.add_row(flag_text, opt.description or "")
|
|
120
|
+
|
|
121
|
+
table.add_row("--help", "Show this message and exit.")
|
|
122
|
+
table.title = "Options"
|
|
123
|
+
table.title_style = "bold magenta"
|
|
124
|
+
return table
|
|
125
|
+
|
|
126
|
+
def _format_option_flags(self, arg) -> str: # type: ignore
|
|
127
|
+
parts = []
|
|
128
|
+
if arg.long_flags:
|
|
129
|
+
parts.append(self._combine_flags(arg.long_flags))
|
|
130
|
+
if arg.short_flags:
|
|
131
|
+
parts.append(self._combine_flags(arg.short_flags))
|
|
132
|
+
|
|
133
|
+
if not parts:
|
|
134
|
+
if arg.flag and arg.negated_flag:
|
|
135
|
+
parts.append(f"{arg.flag} / {arg.negated_flag}")
|
|
136
|
+
elif arg.flag:
|
|
137
|
+
parts.append(arg.flag)
|
|
138
|
+
else:
|
|
139
|
+
parts.append(f"--{arg.name.replace('_', '-')}")
|
|
140
|
+
|
|
141
|
+
return ", ".join(parts)
|
|
142
|
+
|
|
143
|
+
def _combine_flags(self, flags) -> str: # type: ignore
|
|
144
|
+
if len(flags) == 2 and self._is_negative_flag(flags[1]) and not self._is_negative_flag(flags[0]):
|
|
145
|
+
return f"{flags[0]} / {flags[1]}"
|
|
146
|
+
return ", ".join(flags)
|
|
147
|
+
|
|
148
|
+
def _is_negative_flag(self, flag: str) -> bool:
|
|
149
|
+
token = flag.lstrip("-")
|
|
150
|
+
return token.startswith("no-")
|
|
151
|
+
|
|
152
|
+
def _placeholder(self, arg) -> str: # type: ignore
|
|
153
|
+
return (arg.placeholder or arg.name).upper()
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command tree widget for displaying command hierarchy.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from textual.widgets import Tree
|
|
6
|
+
|
|
7
|
+
from machineconfig.scripts.python.helpers.helpers_navigator.cli_graph_loader import (
|
|
8
|
+
CommandNode,
|
|
9
|
+
build_command_nodes,
|
|
10
|
+
load_cli_graph,
|
|
11
|
+
)
|
|
12
|
+
from machineconfig.scripts.python.helpers.helpers_navigator.data_models import CommandInfo
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CommandTree(Tree[CommandInfo]):
|
|
16
|
+
"""Tree widget for displaying command hierarchy."""
|
|
17
|
+
|
|
18
|
+
def on_mount(self) -> None:
|
|
19
|
+
"""Build the command tree when mounted."""
|
|
20
|
+
self.show_root = False
|
|
21
|
+
self.guide_depth = 2
|
|
22
|
+
self._build_command_tree()
|
|
23
|
+
|
|
24
|
+
def _build_command_tree(self) -> None:
|
|
25
|
+
"""Build the hierarchical command structure from the CLI graph."""
|
|
26
|
+
try:
|
|
27
|
+
graph = load_cli_graph()
|
|
28
|
+
nodes = build_command_nodes(graph)
|
|
29
|
+
except Exception as exc:
|
|
30
|
+
self.root.add(f"Error loading CLI graph: {exc}", data=None)
|
|
31
|
+
return
|
|
32
|
+
|
|
33
|
+
for node in nodes:
|
|
34
|
+
self._add_command_node(self.root, node)
|
|
35
|
+
|
|
36
|
+
def _add_command_node(self, parent, node: CommandNode) -> None: # type: ignore
|
|
37
|
+
label = self._format_label(node.info)
|
|
38
|
+
tree_node = parent.add(label, data=node.info)
|
|
39
|
+
for child in node.children:
|
|
40
|
+
self._add_command_node(tree_node, child)
|
|
41
|
+
|
|
42
|
+
def _format_label(self, info: CommandInfo) -> str:
|
|
43
|
+
if info.description and info.description != info.name:
|
|
44
|
+
return f"{info.name} - {info.description}"
|
|
45
|
+
return info.name
|
|
@@ -3,7 +3,22 @@ Data models for the command navigator.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from typing import Optional
|
|
6
|
-
from dataclasses import dataclass
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class ArgumentInfo:
|
|
11
|
+
"""Information about a command argument."""
|
|
12
|
+
name: str
|
|
13
|
+
is_required: bool
|
|
14
|
+
is_flag: bool
|
|
15
|
+
placeholder: str = ""
|
|
16
|
+
description: str = ""
|
|
17
|
+
is_positional: bool = False
|
|
18
|
+
flag: str = ""
|
|
19
|
+
negated_flag: str = ""
|
|
20
|
+
long_flags: list[str] = field(default_factory=list)
|
|
21
|
+
short_flags: list[str] = field(default_factory=list)
|
|
7
22
|
|
|
8
23
|
|
|
9
24
|
@dataclass
|
|
@@ -16,13 +31,5 @@ class CommandInfo:
|
|
|
16
31
|
is_group: bool = False
|
|
17
32
|
help_text: str = ""
|
|
18
33
|
module_path: str = ""
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
@dataclass
|
|
22
|
-
class ArgumentInfo:
|
|
23
|
-
"""Information about a command argument."""
|
|
24
|
-
name: str
|
|
25
|
-
is_required: bool
|
|
26
|
-
is_flag: bool
|
|
27
|
-
placeholder: str = ""
|
|
28
|
-
description: str = ""
|
|
34
|
+
arguments: Optional[list[ArgumentInfo]] = None
|
|
35
|
+
long_description: str = ""
|
|
@@ -6,11 +6,11 @@ import subprocess
|
|
|
6
6
|
from textual.app import App, ComposeResult
|
|
7
7
|
from textual.widgets import Header, Footer, Input, Tree
|
|
8
8
|
from textual.binding import Binding
|
|
9
|
-
from machineconfig.scripts.python.helpers_navigator.command_builder import CommandBuilderScreen
|
|
10
|
-
from machineconfig.scripts.python.helpers_navigator.command_tree import CommandTree
|
|
11
|
-
from machineconfig.scripts.python.helpers_navigator.command_detail import CommandDetail
|
|
12
|
-
from machineconfig.scripts.python.helpers_navigator.search_bar import SearchBar
|
|
13
|
-
from machineconfig.scripts.python.helpers_navigator.data_models import CommandInfo
|
|
9
|
+
from machineconfig.scripts.python.helpers.helpers_navigator.command_builder import CommandBuilderScreen
|
|
10
|
+
from machineconfig.scripts.python.helpers.helpers_navigator.command_tree import CommandTree
|
|
11
|
+
from machineconfig.scripts.python.helpers.helpers_navigator.command_detail import CommandDetail
|
|
12
|
+
from machineconfig.scripts.python.helpers.helpers_navigator.search_bar import SearchBar
|
|
13
|
+
from machineconfig.scripts.python.helpers.helpers_navigator.data_models import CommandInfo
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class CommandNavigatorApp(App[None]):
|
|
File without changes
|