machineconfig 6.82__py3-none-any.whl → 8.51__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.
- machineconfig/cluster/remote/cloud_manager.py +1 -1
- machineconfig/cluster/remote/run_cluster.py +1 -1
- machineconfig/cluster/remote/run_remote.py +1 -1
- machineconfig/cluster/sessions_managers/utils/maker.py +29 -15
- machineconfig/cluster/sessions_managers/wt_local.py +17 -222
- machineconfig/cluster/sessions_managers/wt_local_manager.py +56 -194
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +42 -198
- machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
- machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
- machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
- machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
- machineconfig/cluster/sessions_managers/zellij_local.py +1 -1
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +4 -2
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +3 -2
- machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +2 -2
- 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 +1500 -310
- machineconfig/jobs/installer/linux_scripts/docker.sh +6 -9
- machineconfig/jobs/installer/linux_scripts/q.sh +10 -7
- machineconfig/jobs/installer/linux_scripts/redis.sh +1 -0
- machineconfig/jobs/installer/package_groups.py +62 -91
- machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1 +129 -34
- machineconfig/jobs/installer/{custom → python_scripts}/boxes.py +2 -3
- machineconfig/jobs/installer/{custom_dev → python_scripts}/brave.py +5 -3
- machineconfig/jobs/installer/python_scripts/cloudflare_warp_cli.py +23 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/code.py +14 -9
- machineconfig/jobs/installer/{custom_dev → python_scripts}/dubdb_adbc.py +1 -1
- machineconfig/jobs/installer/python_scripts/hx.py +214 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/nerdfont.py +2 -2
- machineconfig/jobs/installer/{custom_dev → python_scripts}/nerfont_windows_helper.py +32 -26
- machineconfig/jobs/installer/python_scripts/sysabc.py +145 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/wezterm.py +2 -19
- machineconfig/jobs/installer/{custom_dev → python_scripts}/winget.py +10 -14
- machineconfig/jobs/installer/python_scripts/yazi.py +139 -0
- machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nfs +0 -1
- machineconfig/jobs/scripts/powershell_scripts/cmatrix.ps1 +52 -0
- machineconfig/jobs/scripts/powershell_scripts/mount_ssh.ps1 +13 -0
- machineconfig/jobs/scripts/powershell_scripts/obs.ps1 +4 -0
- machineconfig/jobs/scripts_dynamic/a.py +428 -0
- machineconfig/logger.py +1 -2
- machineconfig/profile/create_helper.py +56 -18
- machineconfig/profile/create_links.py +79 -21
- machineconfig/profile/create_links_export.py +87 -36
- machineconfig/profile/create_shell_profile.py +92 -127
- machineconfig/profile/mapper_data.toml +45 -0
- machineconfig/profile/mapper_dotfiles.toml +249 -0
- machineconfig/scripts/__init__.py +0 -4
- machineconfig/scripts/linux/wrap_mcfg +46 -0
- machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
- machineconfig/scripts/python/agents.py +85 -165
- machineconfig/scripts/python/ai/initai.py +4 -2
- machineconfig/scripts/python/ai/scripts/__init__.py +1 -0
- machineconfig/scripts/python/ai/scripts/command_runner.ps1 +33 -0
- machineconfig/scripts/python/ai/{command_runner → scripts}/command_runner.sh +1 -1
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +2 -0
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +8 -6
- 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/{chatmodes/Thinking-Beast-Mode.chatmode.md → agents/Thinking-Beast-Mode.agent.md} +0 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md → agents/Ultimate-Transparent-Thinking-Beast-Mode.agent.md} +0 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/deepResearch.chatmode.md → agents/deepResearch.agent.md} +2 -2
- machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +6 -6
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +33 -0
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/watch_exec.prompt.md +20 -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/{generate_files.py → utils/generate_files.py} +2 -2
- machineconfig/scripts/python/ai/{solutions → utils}/generic.py +2 -15
- machineconfig/scripts/python/ai/{vscode_tasks.py → utils/vscode_tasks.py} +13 -5
- machineconfig/scripts/python/cloud.py +58 -11
- machineconfig/scripts/python/croshell.py +10 -162
- machineconfig/scripts/python/devops.py +73 -36
- machineconfig/scripts/python/devops_navigator.py +16 -6
- machineconfig/scripts/python/fire_jobs.py +8 -222
- machineconfig/scripts/python/ftpx.py +7 -200
- 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/helpers/helper_env/env_manager_tui.py +204 -0
- machineconfig/scripts/python/helpers/helper_env/path_manager_tui.py +228 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/fire_crush.json +1 -1
- machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_crush.py +39 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/fire_cursor_agents.py +3 -4
- machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_gemini.py +55 -0
- machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
- machineconfig/scripts/python/helpers/helpers_agents/agents_impl.py +168 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_help_launch.py +38 -16
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_helper_types.py +11 -14
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/aichat/config.yaml +5 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/aider/.aider.conf.yml +2 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/copilot/config.yml +1 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/crush/crush.json +10 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/gemini/settings.json +12 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/privacy.py +109 -0
- machineconfig/scripts/python/helpers/helpers_agents/templates/prompt.txt +10 -0
- machineconfig/scripts/python/helpers/helpers_agents/templates/template.sh +34 -0
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_copy.py +32 -25
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_mount.py +29 -22
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_sync.py +9 -8
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers2.py +1 -1
- machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/crosh.py +3 -3
- 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 +12 -12
- machineconfig/scripts/python/helpers/helpers_devops/backup_config.py +149 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_backup_retrieve.py +262 -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 +67 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_nw.py +201 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_repos.py +274 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_self.py +197 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_share_file.py +151 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_share_server.py +125 -0
- machineconfig/scripts/python/{helpers_devops/cli_terminal.py → helpers/helpers_devops/cli_share_terminal.py} +26 -22
- machineconfig/scripts/python/helpers/helpers_devops/cli_ssh.py +167 -0
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_status.py +17 -23
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_update_repos.py +1 -1
- machineconfig/scripts/python/{interactive.py → helpers/helpers_devops/interactive.py} +78 -71
- machineconfig/scripts/python/helpers/helpers_devops/run_script.py +197 -0
- 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 +4 -4
- machineconfig/scripts/python/{helpers_fire/helpers4.py → helpers/helpers_fire_command/file_wrangler.py} +57 -20
- machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_args_helper.py +1 -0
- 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 +26 -16
- machineconfig/scripts/python/helpers/helpers_msearch/__init__.py +5 -0
- machineconfig/scripts/python/helpers/helpers_msearch/msearch_impl.py +248 -0
- machineconfig/scripts/{linux → python/helpers/helpers_msearch/scripts_linux}/fzfg +6 -5
- machineconfig/scripts/python/helpers/helpers_msearch/scripts_linux/search_with_context.sh +48 -0
- machineconfig/scripts/python/helpers/helpers_msearch/scripts_windows/fzfg.ps1 +59 -0
- 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/address.py +174 -0
- machineconfig/scripts/python/helpers/helpers_network/address_switch.py +78 -0
- machineconfig/scripts/python/helpers/helpers_network/ftpx_impl.py +276 -0
- machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_nfs.py +2 -2
- machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_ssh.py +3 -3
- 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/{nw → helpers/helpers_network}/wifi_conn.py +1 -53
- 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}/clone.py +0 -1
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/cloud_repo_sync.py +159 -48
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/grource.py +4 -3
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/record.py +33 -12
- machineconfig/scripts/python/helpers/helpers_repos/repo_analyzer_1.py +160 -0
- machineconfig/scripts/python/{helpers_repos/count_lines.py → helpers/helpers_repos/repo_analyzer_2.py} +156 -191
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/update.py +0 -6
- machineconfig/scripts/python/helpers/helpers_search/ast_search.py +74 -0
- machineconfig/scripts/python/helpers/helpers_search/qr_code.py +166 -0
- machineconfig/scripts/python/helpers/helpers_search/repo_rag.py +325 -0
- machineconfig/scripts/python/helpers/helpers_search/script_help.py +81 -0
- machineconfig/scripts/python/helpers/helpers_search/symantic_search.py +25 -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 +20 -14
- 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/helpers_utils/download.py +150 -0
- machineconfig/scripts/python/helpers/helpers_utils/pdf.py +96 -0
- machineconfig/scripts/python/helpers/helpers_utils/python.py +210 -0
- machineconfig/scripts/python/helpers/helpers_utils/specs.py +246 -0
- machineconfig/scripts/python/mcfg_entry.py +143 -0
- machineconfig/scripts/python/msearch.py +26 -0
- machineconfig/scripts/python/sessions.py +69 -135
- machineconfig/scripts/python/terminal.py +58 -0
- machineconfig/scripts/python/utils.py +115 -38
- machineconfig/scripts/windows/wrap_mcfg.ps1 +63 -0
- machineconfig/settings/atuin/config.toml +294 -0
- machineconfig/settings/atuin/themes/catppuccin-mocha-mauve.toml +12 -0
- machineconfig/settings/broot/conf.toml +1 -1
- machineconfig/settings/helix/config.toml +16 -0
- machineconfig/settings/helix/languages.toml +13 -4
- machineconfig/settings/helix/yazi-picker.sh +12 -0
- machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
- machineconfig/settings/lf/linux/exe/previewer.sh +3 -2
- machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
- machineconfig/settings/lf/windows/lfrc +14 -16
- machineconfig/settings/linters/.ruff.toml +2 -1
- machineconfig/settings/marimo/marimo.toml +1 -1
- machineconfig/settings/marimo/snippets/globalize.py +34 -0
- machineconfig/settings/mprocs/windows/mprocs.yaml +2 -2
- machineconfig/settings/shells/bash/init.sh +47 -12
- machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +1 -1
- machineconfig/settings/shells/nushell/config.nu +25 -33
- machineconfig/settings/shells/nushell/env.nu +21 -8
- machineconfig/settings/shells/nushell/init.nu +138 -0
- machineconfig/settings/shells/pwsh/init.ps1 +111 -17
- machineconfig/settings/shells/pwsh/search_pwsh_history.ps1 +99 -0
- machineconfig/settings/shells/starship/starship.toml +16 -0
- machineconfig/settings/shells/wezterm/wezterm.lua +6 -1
- machineconfig/settings/shells/wt/settings.json +27 -18
- machineconfig/settings/shells/zsh/init.sh +42 -23
- machineconfig/settings/television/cable_unix/alias.toml +8 -0
- machineconfig/settings/television/cable_unix/aws-buckets.toml +14 -0
- machineconfig/settings/television/cable_unix/aws-instances.toml +13 -0
- machineconfig/settings/television/cable_unix/bash-history.toml +8 -0
- machineconfig/settings/television/cable_unix/channels.toml +19 -0
- machineconfig/settings/television/cable_unix/dirs.toml +13 -0
- machineconfig/settings/television/cable_unix/distrobox-list.toml +42 -0
- machineconfig/settings/television/cable_unix/docker-images.toml +13 -0
- machineconfig/settings/television/cable_unix/dotfiles.toml +11 -0
- machineconfig/settings/television/cable_unix/env.toml +17 -0
- machineconfig/settings/television/cable_unix/files.toml +11 -0
- machineconfig/settings/television/cable_unix/fish-history.toml +8 -0
- machineconfig/settings/television/cable_unix/git-branch.toml +11 -0
- machineconfig/settings/television/cable_unix/git-diff.toml +10 -0
- machineconfig/settings/television/cable_unix/git-log.toml +12 -0
- machineconfig/settings/television/cable_unix/git-reflog.toml +12 -0
- machineconfig/settings/television/cable_unix/git-repos.toml +16 -0
- machineconfig/settings/television/cable_unix/guix.toml +20 -0
- machineconfig/settings/television/cable_unix/just-recipes.toml +18 -0
- machineconfig/settings/television/cable_unix/k8s-deployments.toml +36 -0
- machineconfig/settings/television/cable_unix/k8s-pods.toml +50 -0
- machineconfig/settings/television/cable_unix/k8s-services.toml +36 -0
- machineconfig/settings/television/cable_unix/man-pages.toml +24 -0
- machineconfig/settings/television/cable_unix/nu-history.toml +7 -0
- machineconfig/settings/television/cable_unix/procs.toml +20 -0
- machineconfig/settings/television/cable_unix/text.toml +17 -0
- machineconfig/settings/television/cable_unix/tldr.toml +18 -0
- machineconfig/settings/television/cable_unix/zsh-history.toml +9 -0
- machineconfig/settings/television/cable_windows/alias.toml +7 -0
- machineconfig/settings/television/cable_windows/dirs.toml +13 -0
- machineconfig/settings/television/cable_windows/docker-images.toml +13 -0
- machineconfig/settings/television/cable_windows/dotfiles.toml +11 -0
- machineconfig/settings/television/cable_windows/env.toml +17 -0
- machineconfig/settings/television/cable_windows/files.toml +14 -0
- machineconfig/settings/television/cable_windows/git-branch.toml +11 -0
- machineconfig/settings/television/cable_windows/git-diff.toml +10 -0
- machineconfig/settings/television/cable_windows/git-log.toml +11 -0
- machineconfig/settings/television/cable_windows/git-reflog.toml +11 -0
- machineconfig/settings/television/cable_windows/git-repos.toml +15 -0
- machineconfig/settings/television/cable_windows/nu-history.toml +7 -0
- machineconfig/settings/television/cable_windows/pwsh-history.toml +6 -0
- machineconfig/settings/television/cable_windows/text.toml +17 -0
- 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/wt/__init__.py +0 -0
- machineconfig/settings/yazi/init.lua +61 -0
- machineconfig/settings/yazi/keymap_linux.toml +94 -0
- machineconfig/settings/yazi/keymap_windows.toml +78 -0
- machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
- machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
- machineconfig/settings/yazi/theme.toml +4 -0
- machineconfig/settings/yazi/yazi_linux.toml +94 -0
- machineconfig/settings/yazi/yazi_windows.toml +58 -0
- machineconfig/settings/zellij/layouts/st.kdl +40 -9
- machineconfig/settings/zellij/layouts/st2.kdl +1 -1
- machineconfig/setup_linux/__init__.py +2 -2
- machineconfig/setup_linux/apps_desktop.sh +8 -27
- machineconfig/setup_linux/web_shortcuts/interactive.sh +27 -12
- machineconfig/setup_linux/web_shortcuts/live_from_github.sh +34 -0
- machineconfig/setup_mac/__init__.py +1 -4
- machineconfig/setup_mac/apps_gui.sh +248 -0
- machineconfig/setup_windows/__init__.py +2 -5
- machineconfig/setup_windows/uv.ps1 +8 -1
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +28 -12
- machineconfig/setup_windows/web_shortcuts/live_from_github.ps1 +31 -0
- machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
- 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 +31 -4
- machineconfig/utils/code.py +163 -51
- machineconfig/utils/files/ascii_art.py +11 -15
- machineconfig/utils/files/headers.py +6 -7
- machineconfig/utils/files/read.py +8 -1
- machineconfig/utils/installer_utils/github_release_bulk.py +95 -138
- machineconfig/utils/installer_utils/github_release_scraper.py +99 -0
- machineconfig/utils/installer_utils/install_from_url.py +183 -0
- machineconfig/utils/installer_utils/installer_class.py +53 -102
- machineconfig/utils/installer_utils/installer_cli.py +161 -0
- machineconfig/utils/installer_utils/installer_helper.py +129 -0
- machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +42 -91
- machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +20 -65
- machineconfig/utils/io.py +94 -9
- machineconfig/utils/links.py +56 -38
- machineconfig/utils/meta.py +38 -21
- machineconfig/utils/options.py +81 -23
- 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 +52 -102
- machineconfig/utils/path_helper.py +76 -23
- machineconfig/utils/procs.py +1 -1
- machineconfig/utils/scheduler.py +26 -53
- machineconfig/utils/scheduling.py +0 -2
- machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
- machineconfig/utils/schemas/layouts/layout_types.py +1 -1
- machineconfig/utils/source_of_truth.py +6 -1
- machineconfig/utils/ssh.py +216 -419
- machineconfig/utils/ssh_utils/abc.py +5 -0
- machineconfig/utils/ssh_utils/copy_from_here.py +116 -0
- machineconfig/utils/ssh_utils/copy_to_here.py +303 -0
- machineconfig/utils/ssh_utils/utils.py +158 -0
- machineconfig/utils/ssh_utils/wsl.py +147 -0
- machineconfig/utils/ssh_utils/wsl_helper.py +217 -0
- machineconfig/utils/terminal.py +1 -0
- machineconfig/utils/upgrade_packages.py +107 -35
- machineconfig/utils/ve.py +12 -4
- machineconfig-8.51.dist-info/METADATA +140 -0
- machineconfig-8.51.dist-info/RECORD +543 -0
- {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/entry_points.txt +4 -1
- machineconfig/jobs/installer/check_installations.py +0 -248
- machineconfig/jobs/installer/custom/hx.py +0 -140
- machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -41
- machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -71
- machineconfig/jobs/installer/powershell_scripts/archive_pygraphviz.ps1 +0 -12
- machineconfig/jobs/installer/powershell_scripts/openssh-server_add_key.ps1 +0 -7
- machineconfig/jobs/installer/powershell_scripts/openssh-server_copy-ssh-id.ps1 +0 -14
- machineconfig/profile/backup.toml +0 -49
- machineconfig/profile/mapper.toml +0 -256
- machineconfig/scripts/linux/fzf2g +0 -21
- machineconfig/scripts/linux/fzfag +0 -17
- machineconfig/scripts/linux/fzffg +0 -25
- machineconfig/scripts/linux/fzfrga +0 -21
- machineconfig/scripts/linux/mcfgs +0 -38
- machineconfig/scripts/linux/other/share_smb +0 -1
- machineconfig/scripts/linux/other/switch_ip +0 -20
- machineconfig/scripts/linux/skrg +0 -4
- machineconfig/scripts/linux/warp-cli.sh +0 -122
- machineconfig/scripts/linux/z_ls +0 -104
- machineconfig/scripts/python/ai/command_runner/prompt.txt +0 -9
- machineconfig/scripts/python/helpers_devops/cli_config.py +0 -120
- machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +0 -77
- machineconfig/scripts/python/helpers_devops/cli_data.py +0 -25
- machineconfig/scripts/python/helpers_devops/cli_nw.py +0 -73
- machineconfig/scripts/python/helpers_devops/cli_repos.py +0 -181
- machineconfig/scripts/python/helpers_devops/cli_self.py +0 -122
- machineconfig/scripts/python/helpers_devops/cli_share_server.py +0 -104
- machineconfig/scripts/python/helpers_devops/cli_utils.py +0 -221
- 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_fire/agentic_frameworks/fire_crush.py +0 -37
- machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_gemini.py +0 -44
- machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_qwen.py +0 -43
- machineconfig/scripts/python/helpers_fire/prompt.txt +0 -2
- machineconfig/scripts/python/helpers_fire/template.sh +0 -15
- 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 -588
- machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +0 -17
- machineconfig/scripts/python/helpers_repos/entrypoint.py +0 -76
- machineconfig/scripts/python/helpers_repos/secure_repo.py +0 -15
- machineconfig/scripts/python/mcfg.py +0 -48
- machineconfig/scripts/python/nw/add_ssh_key.py +0 -148
- machineconfig/scripts/python/nw/devops_add_identity.py +0 -82
- machineconfig/scripts/python/nw/devops_add_ssh_key.py +0 -134
- machineconfig/scripts/python/nw/ssh_debug_linux.py +0 -391
- machineconfig/scripts/python/nw/ssh_debug_windows.py +0 -338
- machineconfig/scripts/python/nw/wsl_windows_transfer.py +0 -66
- machineconfig/scripts/windows/fzfb.ps1 +0 -3
- machineconfig/scripts/windows/fzfg.ps1 +0 -2
- machineconfig/scripts/windows/fzfrga.bat +0 -20
- machineconfig/scripts/windows/mcfgs.ps1 +0 -17
- machineconfig/scripts/windows/mounts/mount_ssh.ps1 +0 -13
- machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
- machineconfig/settings/lf/windows/fzf_edit.ps1 +0 -6
- machineconfig/settings/lf/windows/tst.ps1 +0 -1
- machineconfig/settings/yazi/yazi.toml +0 -4
- machineconfig/setup_linux/apps.sh +0 -66
- machineconfig/setup_linux/others/cli_installation.sh +0 -137
- machineconfig/setup_linux/others/mint_keyboard_shortcuts.sh +0 -30
- machineconfig/setup_linux/ssh/openssh_all.sh +0 -25
- machineconfig/setup_linux/ssh/openssh_wsl.sh +0 -38
- machineconfig/setup_mac/apps.sh +0 -73
- machineconfig/setup_mac/ssh/openssh_setup.sh +0 -114
- machineconfig/setup_windows/apps.ps1 +0 -62
- machineconfig/setup_windows/others/obs.ps1 +0 -4
- machineconfig/setup_windows/ssh/add-sshkey.ps1 +0 -29
- machineconfig/setup_windows/ssh/add_identity.ps1 +0 -11
- machineconfig/setup_windows/ssh/openssh-server.ps1 +0 -37
- machineconfig/utils/installer_utils/installer.py +0 -225
- machineconfig/utils/tst.py +0 -20
- machineconfig-6.82.dist-info/METADATA +0 -82
- machineconfig-6.82.dist-info/RECORD +0 -441
- machineconfig/jobs/installer/{custom_dev → checks}/__init__.py +0 -0
- machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +0 -0
- machineconfig/{scripts/python/helpers_cloud → jobs/installer/python_scripts}/__init__.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/alacritty.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/bypass_paywall.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/cursor.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/espanso.py +0 -0
- machineconfig/jobs/installer/{custom → python_scripts}/gh.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/goes.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/lvim.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/redis.py +0 -0
- machineconfig/{setup_linux/others → jobs/scripts/bash_scripts}/android.sh +0 -0
- machineconfig/jobs/{installer/linux_scripts → scripts/bash_scripts}/lid.sh +0 -0
- machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_drive +0 -0
- machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nw_drive +0 -0
- machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_smb +0 -0
- machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_cloud.sh +0 -0
- machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_nfs +0 -0
- machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/start_docker +0 -0
- machineconfig/{scripts → jobs/scripts/powershell_scripts}/Restore-ThunderbirdProfile.ps1 +0 -0
- machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/docker.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nfs.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nw.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_smb.ps1 +0 -0
- machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/power_options.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_cloud.cmd +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_smb.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/unlock_bitlocker.ps1 +0 -0
- machineconfig/scripts/python/{helpers_croshell → ai/utils}/__init__.py +0 -0
- machineconfig/scripts/python/ai/{solutions/_shared.py → utils/shared.py} +0 -0
- machineconfig/scripts/python/{helpers_devops → graph}/__init__.py +0 -0
- machineconfig/scripts/python/{helpers_devops/themes → 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_fire → helpers/helpers_agents}/__init__.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/__init__.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_help_search.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_load_balancer.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents/templates}/template.ps1 +0 -0
- machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_cloud}/__init__.py +0 -0
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_helpers.py +1 -1
- /machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers5.py +0 -0
- /machineconfig/scripts/python/{helpers_sessions → helpers/helpers_croshell}/__init__.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/{nw → helpers/helpers_devops}/__init__.py +0 -0
- /machineconfig/{setup_windows/wt_and_pwsh → scripts/python/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/fire_jobs_streamlit_helper.py → helpers/helpers_fire_command/f.py} +0 -0
- /machineconfig/{settings/shells/pwsh/profile.ps1 → scripts/python/helpers/helpers_fire_command/fire_jobs_streamlit_helper.py} +0 -0
- /machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/search_bar.py +0 -0
- /machineconfig/{settings/yazi/keymap.toml → scripts/python/helpers/helpers_network/__init__.py} +0 -0
- /machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_nw_drive.py +0 -0
- /machineconfig/scripts/python/{nw → helpers/helpers_network}/onetimeshare.py +0 -0
- /machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/sync.py +0 -0
- /machineconfig/{setup_windows/wt_and_pwsh → settings/wt}/set_wt_settings.py +0 -0
- {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/WHEEL +0 -0
- {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/top_level.txt +0 -0
machineconfig/utils/meta.py
CHANGED
|
@@ -5,7 +5,7 @@ from typing import Any
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def get_import_module_string(py_file: str) -> str:
|
|
8
|
-
from machineconfig.scripts.python.
|
|
8
|
+
from machineconfig.scripts.python.helpers.helpers_fire_command.file_wrangler import get_import_module_code
|
|
9
9
|
from machineconfig.utils.accessories import get_repo_root
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
repo_root = get_repo_root(Path(py_file))
|
|
@@ -29,7 +29,8 @@ except (ImportError, ModuleNotFoundError) as ex:
|
|
|
29
29
|
return txt
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def lambda_to_python_script(lmb: Callable[[], Any],
|
|
32
|
+
def lambda_to_python_script(lmb: Callable[[], Any],
|
|
33
|
+
in_global: bool, import_module: bool) -> str:
|
|
33
34
|
"""
|
|
34
35
|
caveats: always use keyword arguments in the lambda call for best results.
|
|
35
36
|
return statement not allowed in the wrapped function (otherwise it can be put in the global space)
|
|
@@ -55,9 +56,19 @@ def lambda_to_python_script(lmb: Callable[[], Any], in_global: bool, import_modu
|
|
|
55
56
|
import types as _types
|
|
56
57
|
from pathlib import Path as _Path
|
|
57
58
|
|
|
59
|
+
def _stringify_annotation(annotation: Any) -> Any:
|
|
60
|
+
if annotation is _inspect.Signature.empty or annotation is _inspect.Parameter.empty:
|
|
61
|
+
return annotation
|
|
62
|
+
if isinstance(annotation, str):
|
|
63
|
+
return annotation
|
|
64
|
+
try:
|
|
65
|
+
return _inspect.formatannotation(annotation)
|
|
66
|
+
except Exception:
|
|
67
|
+
return str(annotation)
|
|
68
|
+
|
|
58
69
|
# sanity checks
|
|
59
70
|
if not (callable(lmb) and isinstance(lmb, _types.LambdaType)):
|
|
60
|
-
raise TypeError("Expected a lambda function object")
|
|
71
|
+
raise TypeError(f"Expected a lambda function object, got {type(lmb)}")
|
|
61
72
|
|
|
62
73
|
src = _inspect.getsource(lmb)
|
|
63
74
|
src = _textwrap.dedent(src)
|
|
@@ -70,7 +81,7 @@ def lambda_to_python_script(lmb: Callable[[], Any], in_global: bool, import_modu
|
|
|
70
81
|
lambda_node = n
|
|
71
82
|
break
|
|
72
83
|
if lambda_node is None:
|
|
73
|
-
raise ValueError("Could not find a lambda expression in source")
|
|
84
|
+
raise ValueError(f"""Could not find a lambda expression in source, got:\n{lmb}\nwhich is not a lambda, its a {src}""")
|
|
74
85
|
|
|
75
86
|
body = lambda_node.body
|
|
76
87
|
if not isinstance(body, _ast.Call):
|
|
@@ -102,7 +113,7 @@ def lambda_to_python_script(lmb: Callable[[], Any], in_global: bool, import_modu
|
|
|
102
113
|
if not callable(func_obj):
|
|
103
114
|
raise TypeError("Resolved object is not callable")
|
|
104
115
|
|
|
105
|
-
func_name = getattr(func_obj, "__name__", "<unknown>")
|
|
116
|
+
func_name = getattr(getattr(func_obj, "__code__", None), "co_name", None) or getattr(func_obj, "__name__", "<unknown>")
|
|
106
117
|
|
|
107
118
|
import_prefix: str = ""
|
|
108
119
|
if import_module:
|
|
@@ -174,16 +185,18 @@ def lambda_to_python_script(lmb: Callable[[], Any], in_global: bool, import_modu
|
|
|
174
185
|
else:
|
|
175
186
|
new_default = param.default
|
|
176
187
|
|
|
177
|
-
|
|
188
|
+
normalized_annotation = _stringify_annotation(param.annotation)
|
|
189
|
+
|
|
178
190
|
if new_default is _inspect.Parameter.empty:
|
|
179
|
-
new_param = _inspect.Parameter(name, param.kind, annotation=
|
|
191
|
+
new_param = _inspect.Parameter(name, param.kind, annotation=normalized_annotation)
|
|
180
192
|
else:
|
|
181
193
|
new_param = _inspect.Parameter(
|
|
182
|
-
name, param.kind, default=new_default, annotation=
|
|
194
|
+
name, param.kind, default=new_default, annotation=normalized_annotation
|
|
183
195
|
)
|
|
184
196
|
new_params.append(new_param)
|
|
185
197
|
|
|
186
|
-
|
|
198
|
+
return_annotation = _stringify_annotation(sig.return_annotation)
|
|
199
|
+
new_sig = _inspect.Signature(parameters=new_params, return_annotation=return_annotation)
|
|
187
200
|
|
|
188
201
|
# If in_global mode, return kwargs as global assignments + dedented body
|
|
189
202
|
if in_global:
|
|
@@ -200,15 +213,11 @@ def lambda_to_python_script(lmb: Callable[[], Any], in_global: bool, import_modu
|
|
|
200
213
|
|
|
201
214
|
# Build type annotation string if available
|
|
202
215
|
if param.annotation is not _inspect.Parameter.empty:
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
type_str = str(param.annotation)
|
|
209
|
-
except Exception:
|
|
210
|
-
type_str = str(param.annotation)
|
|
211
|
-
global_assignments.append(f"{name}: {type_str} = {repr(value)}")
|
|
216
|
+
annotation_literal = _stringify_annotation(param.annotation)
|
|
217
|
+
if isinstance(annotation_literal, str):
|
|
218
|
+
global_assignments.append(f"{name}: {repr(annotation_literal)} = {repr(value)}")
|
|
219
|
+
else:
|
|
220
|
+
global_assignments.append(f"{name} = {repr(value)}")
|
|
212
221
|
else:
|
|
213
222
|
global_assignments.append(f"{name} = {repr(value)}")
|
|
214
223
|
|
|
@@ -230,12 +239,20 @@ def lambda_to_python_script(lmb: Callable[[], Any], in_global: bool, import_modu
|
|
|
230
239
|
if lines[-1].startswith("return "):
|
|
231
240
|
lines[-1] = lines[-1].replace("return ", "# return ", 1)
|
|
232
241
|
result_text = "\n".join(lines)
|
|
233
|
-
if "Optional[" in result_text or "Any" in result_text or "Union[" in result_text or "Literal[" in result_text:
|
|
234
|
-
result_text = "from typing import *\n\n" + result_text
|
|
235
242
|
|
|
243
|
+
if "Optional" in result_text or "Any" in result_text or "Union" in result_text or "Literal" in result_text:
|
|
244
|
+
result_text = "from typing import Optional, Any, Union, Literal\n\n" + result_text
|
|
236
245
|
if import_prefix:
|
|
237
246
|
result_text = f"{import_prefix}{result_text}"
|
|
238
247
|
return result_text
|
|
239
248
|
|
|
240
249
|
if __name__ == "__main__":
|
|
241
|
-
|
|
250
|
+
from machineconfig.utils.code import print_code
|
|
251
|
+
import_code_robust = "<import_code_robust>"
|
|
252
|
+
print_code.__name__ = "blah"
|
|
253
|
+
res = lambda_to_python_script(
|
|
254
|
+
lambda: print_code(code=import_code_robust, lexer="python", desc="import as module code"),
|
|
255
|
+
in_global=True, import_module=False
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
print(res)
|
machineconfig/utils/options.py
CHANGED
|
@@ -1,40 +1,99 @@
|
|
|
1
|
+
|
|
1
2
|
from pathlib import Path
|
|
2
|
-
from machineconfig.utils.installer_utils.installer_abc import check_tool_exists
|
|
3
3
|
from rich.text import Text
|
|
4
4
|
from rich.panel import Panel
|
|
5
5
|
from rich.console import Console
|
|
6
6
|
import subprocess
|
|
7
|
-
from typing import Optional, Union, Iterable, overload, Literal
|
|
7
|
+
from typing import Optional, Union, Iterable, overload, Literal, cast
|
|
8
8
|
|
|
9
9
|
@overload
|
|
10
|
-
def choose_from_options[T](
|
|
10
|
+
def choose_from_options[T](options: Iterable[T], msg: str, multi: Literal[False], custom_input: bool = False, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, tv: bool = False, preview: Optional[Literal["bat"]]=None) -> T: ...
|
|
11
11
|
@overload
|
|
12
|
-
def choose_from_options[T](
|
|
13
|
-
def choose_from_options[T](
|
|
12
|
+
def choose_from_options[T](options: Iterable[T], msg: str, multi: Literal[True], custom_input: bool = True, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, tv: bool = False, preview: Optional[Literal["bat"]]=None) -> list[T]: ...
|
|
13
|
+
def choose_from_options[T](options: Iterable[T], msg: str, multi: bool, custom_input: bool = True, header: str = "", tail: str = "", prompt: str = "", default: Optional[T] = None, tv: bool = False, preview: Optional[Literal["bat"]]=None, ) -> Union[T, list[T]]:
|
|
14
14
|
# TODO: replace with https://github.com/tmbo/questionary
|
|
15
15
|
# # also see https://github.com/charmbracelet/gum
|
|
16
16
|
options_strings: list[str] = [str(x) for x in options]
|
|
17
17
|
default_string = str(default) if default is not None else None
|
|
18
18
|
console = Console()
|
|
19
|
-
|
|
20
|
-
#
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
from machineconfig.utils.installer_utils.installer_locator_utils import check_tool_exists
|
|
20
|
+
# from machineconfig.utils.installer_utils.installer_cli import check_tool_exists
|
|
21
|
+
# print("ch1")
|
|
22
|
+
if tv and check_tool_exists("tv"):
|
|
23
|
+
from machineconfig.utils.accessories import randstr
|
|
24
|
+
options_txt_path = Path.home().joinpath("tmp_results/tmp_files/choices_" + randstr(6) + ".txt")
|
|
25
|
+
options_txt_path.parent.mkdir(parents=True, exist_ok=True)
|
|
26
|
+
options_txt_path.write_text("\n".join(options_strings), encoding="utf-8")
|
|
27
|
+
|
|
28
|
+
# Run `tv` interactively so the user can make selections. We redirect tv's
|
|
29
|
+
# stdout to a temporary output file so we can read the chosen lines after
|
|
30
|
+
# the interactive session completes. Do not capture_output or redirect
|
|
31
|
+
# stdin/stderr here so `tv` stays attached to the terminal.
|
|
32
|
+
tv_out_path = options_txt_path.with_name(options_txt_path.stem + "_out.txt")
|
|
33
|
+
if preview is None:
|
|
34
|
+
preview_line = ""
|
|
35
|
+
elif preview == "bat":
|
|
36
|
+
preview_line = r"""--preview-command "bat -n --color=always {}" --preview-size 70 """
|
|
37
|
+
|
|
38
|
+
import platform
|
|
39
|
+
if platform.system() == "Windows":
|
|
40
|
+
# PowerShell + TUI apps can be finicky when stdin is a pipe. Avoid piping into `tv` and
|
|
41
|
+
# instead provide a `--source-command` so `tv` can keep stdin attached to the console.
|
|
42
|
+
# Also: `tv --ansi` is a flag (no value). Passing `true` makes it a positional argument
|
|
43
|
+
# (channel/path/command), which can lead to confusing behavior.
|
|
44
|
+
source_cmd = f"cmd /C type \"{options_txt_path}\""
|
|
45
|
+
tv_cmd = f"""
|
|
46
|
+
$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
|
|
47
|
+
tv {preview_line} --ansi --source-command '{source_cmd}' --source-output "{{}}" | Out-File -Encoding utf8 -FilePath "{tv_out_path}" """
|
|
48
|
+
else:
|
|
49
|
+
source_cmd = f'cat "{options_txt_path}"'
|
|
50
|
+
tv_cmd = f"""tv {preview_line} --ansi --source-command "{source_cmd}" --source-output "{{}}" > "{tv_out_path}" """
|
|
51
|
+
|
|
52
|
+
# print(f"Running tv command: {tv_cmd}")
|
|
53
|
+
# print(f"Options file: {options_txt_path}")
|
|
54
|
+
# print(f"Content:\n{options_txt_path.read_text(encoding='utf-8')}")
|
|
55
|
+
# print(f"tv output file: {tv_out_path}")
|
|
56
|
+
from machineconfig.utils.code import run_shell_script
|
|
57
|
+
res = run_shell_script(tv_cmd, display_script=False, clean_env=False)
|
|
58
|
+
|
|
59
|
+
# If tv returned a non-zero code and there is no output file, treat it as an error.
|
|
60
|
+
if res.returncode != 0 and not tv_out_path.exists():
|
|
61
|
+
raise RuntimeError(f"Got error running tv command: {tv_cmd}\nreturncode: {res.returncode}")
|
|
62
|
+
|
|
63
|
+
# Read selections (if any) from the output file created by tv.
|
|
64
|
+
print(f"Reading tv output from: {tv_out_path}")
|
|
65
|
+
out_text = tv_out_path.read_text(encoding="utf-8-sig")
|
|
66
|
+
choice_string_multi = [x for x in out_text.splitlines() if x.strip() != ""]
|
|
67
|
+
|
|
68
|
+
# if len(choice_string_multi) == 0: # e.g. user pressed escape
|
|
69
|
+
# console.print(Panel("❓ No option selected!", title="Error", expand=False))
|
|
70
|
+
# return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, tv=tv, multi=multi, custom_input=custom_input)
|
|
71
|
+
|
|
72
|
+
# Cleanup temporary files
|
|
73
|
+
options_txt_path.unlink(missing_ok=True)
|
|
74
|
+
tv_out_path.unlink(missing_ok=True)
|
|
27
75
|
if not multi:
|
|
28
76
|
try:
|
|
29
77
|
choice_one_string = choice_string_multi[0]
|
|
78
|
+
if isinstance(list(options)[0], str):
|
|
79
|
+
print(f"✅ Selected option: {choice_one_string}")
|
|
80
|
+
return cast(T, choice_one_string)
|
|
30
81
|
choice_idx = options_strings.index(choice_one_string)
|
|
31
|
-
|
|
82
|
+
choice_made = list(options)[choice_idx]
|
|
83
|
+
print(f"✅ Selected option: {choice_made}")
|
|
84
|
+
return choice_made
|
|
32
85
|
except IndexError as ie:
|
|
33
|
-
print(f"❌ Error: {options=}, {choice_string_multi=}")
|
|
34
|
-
print(f"🔍 Available choices: {choice_string_multi}")
|
|
86
|
+
# print(f"❌ Error: {options=}, {choice_string_multi=}")
|
|
87
|
+
print(f"🔍 Available choices: {len(choice_string_multi)}")
|
|
35
88
|
raise ie
|
|
89
|
+
if isinstance(list(options)[0], str):
|
|
90
|
+
result2 = cast(list[T], choice_string_multi)
|
|
91
|
+
print(f"✅ Selected options: {result2}")
|
|
92
|
+
return result2
|
|
36
93
|
choice_idx_s = [options_strings.index(x) for x in choice_string_multi]
|
|
37
|
-
|
|
94
|
+
result = [list(options)[x] for x in choice_idx_s]
|
|
95
|
+
print(f"✅ Selected options: {result}")
|
|
96
|
+
return result
|
|
38
97
|
else:
|
|
39
98
|
if default is not None:
|
|
40
99
|
assert default in options, f"Default `{default}` option not in options `{list(options)}`"
|
|
@@ -55,7 +114,7 @@ def choose_from_options[T](msg: str, options: Iterable[T], multi: bool, custom_i
|
|
|
55
114
|
if choice_string == "":
|
|
56
115
|
if default_string is None:
|
|
57
116
|
console.print(Panel("🧨 Default option not available!", title="Error", expand=False))
|
|
58
|
-
return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default,
|
|
117
|
+
return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, tv=tv, multi=multi, custom_input=custom_input)
|
|
59
118
|
choice_idx = options_strings.index(default_string)
|
|
60
119
|
assert default is not None, "🧨 Default option not available!"
|
|
61
120
|
choice_one: T = default
|
|
@@ -73,7 +132,7 @@ def choose_from_options[T](msg: str, options: Iterable[T], multi: bool, custom_i
|
|
|
73
132
|
_ = ie
|
|
74
133
|
# raise ValueError(f"Unknown choice. {choice_string}") from ie
|
|
75
134
|
console.print(Panel(f"❓ Unknown choice: '{choice_string}'", title="Error", expand=False))
|
|
76
|
-
return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default,
|
|
135
|
+
return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, tv=tv, multi=multi, custom_input=custom_input)
|
|
77
136
|
except (TypeError, ValueError) as te: # int(choice_string) failed due to # either the number is invalid, or the input is custom.
|
|
78
137
|
if choice_string in options_strings: # string input
|
|
79
138
|
choice_idx = options_strings.index(choice_one) # type: ignore
|
|
@@ -84,7 +143,7 @@ def choose_from_options[T](msg: str, options: Iterable[T], multi: bool, custom_i
|
|
|
84
143
|
_ = te
|
|
85
144
|
# raise ValueError(f"Unknown choice. {choice_string}") from te
|
|
86
145
|
console.print(Panel(f"❓ Unknown choice: '{choice_string}'", title="Error", expand=False))
|
|
87
|
-
return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default,
|
|
146
|
+
return choose_from_options(msg=msg, options=options, header=header, tail=tail, prompt=prompt, default=default, tv=tv, multi=multi, custom_input=custom_input)
|
|
88
147
|
console.print(Panel(f"✅ Selected option {choice_idx}: {choice_one}", title="Selected", expand=False))
|
|
89
148
|
if multi:
|
|
90
149
|
return [choice_one]
|
|
@@ -103,14 +162,13 @@ def choose_cloud_interactively() -> str:
|
|
|
103
162
|
raise ValueError(f"Got {tmp} from rclone listremotes")
|
|
104
163
|
if len(remotes) == 0:
|
|
105
164
|
raise RuntimeError("You don't have remotes. Configure your rclone first to get cloud services access.")
|
|
106
|
-
cloud: str = choose_from_options(msg="WHICH CLOUD?", multi=False, options=list(remotes), default=remotes[0],
|
|
165
|
+
cloud: str = choose_from_options(msg="WHICH CLOUD?", multi=False, options=list(remotes), default=remotes[0], tv=True)
|
|
107
166
|
console.print(Panel(f"✅ SELECTED CLOUD | {cloud}", border_style="bold blue", expand=False))
|
|
108
167
|
return cloud
|
|
109
168
|
|
|
110
169
|
|
|
111
170
|
def get_ssh_hosts() -> list[str]:
|
|
112
171
|
from paramiko import SSHConfig
|
|
113
|
-
|
|
114
172
|
c = SSHConfig()
|
|
115
173
|
c.parse(open(Path.home().joinpath(".ssh/config"), encoding="utf-8"))
|
|
116
174
|
return list(c.get_hostnames())
|
|
@@ -121,4 +179,4 @@ def choose_ssh_host(multi: Literal[False]) -> str: ...
|
|
|
121
179
|
@overload
|
|
122
180
|
def choose_ssh_host(multi: Literal[True]) -> list[str]: ...
|
|
123
181
|
def choose_ssh_host(multi: bool):
|
|
124
|
-
return choose_from_options(msg="", options=get_ssh_hosts(), multi=multi,
|
|
182
|
+
return choose_from_options(msg="", options=get_ssh_hosts(), multi=multi, tv=True)
|
|
File without changes
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
|
|
2
|
+
#!/usr/bin/env python3
|
|
3
|
+
import base64
|
|
4
|
+
import pathlib
|
|
5
|
+
import pprint
|
|
6
|
+
import shutil
|
|
7
|
+
import subprocess
|
|
8
|
+
import tempfile
|
|
9
|
+
import os
|
|
10
|
+
from typing import Any, overload, Literal, Union
|
|
11
|
+
|
|
12
|
+
from git import Optional
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _format_preview_value(value: Any) -> str:
|
|
16
|
+
if isinstance(value, str):
|
|
17
|
+
return value
|
|
18
|
+
return pprint.pformat(value, width=88, sort_dicts=True)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _toml_inline_table(values: dict[str, str]) -> str:
|
|
22
|
+
if not values:
|
|
23
|
+
return ""
|
|
24
|
+
parts: list[str] = []
|
|
25
|
+
for key in sorted(values.keys()):
|
|
26
|
+
raw_value = values[key]
|
|
27
|
+
escaped = raw_value.replace("\\", "\\\\").replace('"', '\\"')
|
|
28
|
+
parts.append(f'{key} = "{escaped}"')
|
|
29
|
+
return "env = { " + ", ".join(parts) + " }\n"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _normalize_extension(extension: str | None) -> str | None:
|
|
33
|
+
if extension is None:
|
|
34
|
+
return None
|
|
35
|
+
trimmed = extension.strip()
|
|
36
|
+
if trimmed.startswith("."):
|
|
37
|
+
trimmed = trimmed[1:]
|
|
38
|
+
if not trimmed:
|
|
39
|
+
return None
|
|
40
|
+
return trimmed
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _infer_extension_from_key(key: Optional[str]) -> str | None:
|
|
44
|
+
if not isinstance(key, str):
|
|
45
|
+
return None
|
|
46
|
+
candidate = key.strip()
|
|
47
|
+
if not candidate or any(char.isspace() for char in candidate):
|
|
48
|
+
return None
|
|
49
|
+
suffix = pathlib.Path(candidate).suffix
|
|
50
|
+
if not suffix:
|
|
51
|
+
return None
|
|
52
|
+
return _normalize_extension(suffix)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@overload
|
|
56
|
+
def select_from_options(options_to_preview_mapping: dict[str, Any], extension: str | None, multi: Literal[True], preview_size_percent: float) -> list[str]: ...
|
|
57
|
+
@overload
|
|
58
|
+
def select_from_options(options_to_preview_mapping: dict[str, Any], extension: str | None, multi: Literal[False], preview_size_percent: float) -> Union[str, None]: ...
|
|
59
|
+
def select_from_options(options_to_preview_mapping: dict[str, Any], extension: str | None, multi: bool, preview_size_percent: float) -> Union[Union[str, None], list[str]]:
|
|
60
|
+
keys = list(options_to_preview_mapping.keys())
|
|
61
|
+
if not keys:
|
|
62
|
+
return [] if multi else None
|
|
63
|
+
normalized_extension = _normalize_extension(extension)
|
|
64
|
+
preview_panel_size = max(10, min(90, int(preview_size_percent)))
|
|
65
|
+
terminal_width = shutil.get_terminal_size(fallback=(120, 40)).columns
|
|
66
|
+
preview_width = max(20, int(terminal_width * preview_panel_size / 100) - 4)
|
|
67
|
+
with tempfile.TemporaryDirectory(prefix="tv_channel_") as tmpdir:
|
|
68
|
+
tempdir = pathlib.Path(tmpdir)
|
|
69
|
+
entries: list[str] = []
|
|
70
|
+
index_map: dict[int, str] = {}
|
|
71
|
+
preview_map_path = tempdir / "previews.tsv"
|
|
72
|
+
preview_rows: list[str] = []
|
|
73
|
+
for idx, key in enumerate(keys):
|
|
74
|
+
display_key = key.replace("\t", " ").replace("\n", " ")
|
|
75
|
+
entries.append(f"{idx}\t{display_key}")
|
|
76
|
+
index_map[idx] = key
|
|
77
|
+
preview_value = _format_preview_value(options_to_preview_mapping[key])
|
|
78
|
+
encoded_preview = base64.b64encode(preview_value.encode("utf-8")).decode("ascii")
|
|
79
|
+
entry_extension = normalized_extension or _infer_extension_from_key(key) or ""
|
|
80
|
+
preview_rows.append(f"{idx}\t{encoded_preview}\t{entry_extension}")
|
|
81
|
+
preview_map_path.write_text("\n".join(preview_rows), encoding="utf-8")
|
|
82
|
+
entries_path = tempdir / "entries.tsv"
|
|
83
|
+
entries_path.write_text("\n".join(entries), encoding="utf-8")
|
|
84
|
+
preview_script = tempdir / "preview.sh"
|
|
85
|
+
preview_script.write_text(
|
|
86
|
+
"""#!/usr/bin/env bash
|
|
87
|
+
set -euo pipefail
|
|
88
|
+
|
|
89
|
+
idx="$1"
|
|
90
|
+
script_dir="$(cd -- "$(dirname -- "$0")" && pwd)"
|
|
91
|
+
previews_file="${script_dir}/previews.tsv"
|
|
92
|
+
|
|
93
|
+
if [[ ! -f "${previews_file}" ]]; then
|
|
94
|
+
exit 0
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
encoded_preview="$(awk -F '\t' -v idx="${idx}" '($1==idx){print $2; exit}' "${previews_file}" || true)"
|
|
98
|
+
|
|
99
|
+
if [[ -z "${encoded_preview}" ]]; then
|
|
100
|
+
exit 0
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
preview_content="$(printf '%s' "${encoded_preview}" | base64 --decode)"
|
|
104
|
+
|
|
105
|
+
preview_ext_from_row="$(awk -F '\t' -v idx="${idx}" '($1==idx){print $3; exit}' "${previews_file}" || true)"
|
|
106
|
+
preview_ext="${MCFG_PREVIEW_EXT:-${preview_ext_from_row}}"
|
|
107
|
+
preview_width="${MCFG_PREVIEW_WIDTH:-}"
|
|
108
|
+
preview_size_pct="${MCFG_PREVIEW_SIZE_PCT:-}"
|
|
109
|
+
|
|
110
|
+
if [[ -z "${preview_width}" && -n "${COLUMNS:-}" ]]; then
|
|
111
|
+
if [[ "${preview_size_pct}" =~ ^[0-9]+$ ]]; then
|
|
112
|
+
preview_width=$((COLUMNS * preview_size_pct / 100))
|
|
113
|
+
else
|
|
114
|
+
preview_width="${COLUMNS}"
|
|
115
|
+
fi
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
if command -v bat >/dev/null 2>&1; then
|
|
119
|
+
bat_args=(--force-colorization --style=plain --paging=never --wrap=character)
|
|
120
|
+
if [[ -n "${preview_ext}" ]]; then
|
|
121
|
+
bat_args+=(--language "${preview_ext}")
|
|
122
|
+
fi
|
|
123
|
+
if [[ "${preview_width}" =~ ^[0-9]+$ ]]; then
|
|
124
|
+
bat_args+=(--terminal-width "${preview_width}")
|
|
125
|
+
fi
|
|
126
|
+
printf '%s' "${preview_content}" | bat "${bat_args[@]}"
|
|
127
|
+
elif command -v glow >/dev/null 2>&1; then
|
|
128
|
+
printf '%s' "${preview_content}" | glow -
|
|
129
|
+
elif command -v fold >/dev/null 2>&1 && [[ "${preview_width}" =~ ^[0-9]+$ ]]; then
|
|
130
|
+
printf '%s' "${preview_content}" | fold -s -w "${preview_width}"
|
|
131
|
+
else
|
|
132
|
+
printf '%s' "${preview_content}"
|
|
133
|
+
fi
|
|
134
|
+
""",
|
|
135
|
+
encoding="utf-8"
|
|
136
|
+
)
|
|
137
|
+
preview_script.chmod(0o755)
|
|
138
|
+
preview_env: dict[str, str] = {
|
|
139
|
+
"BAT_THEME": "ansi",
|
|
140
|
+
"MCFG_PREVIEW_SIZE_PCT": str(preview_panel_size),
|
|
141
|
+
}
|
|
142
|
+
if normalized_extension is not None:
|
|
143
|
+
preview_env["MCFG_PREVIEW_EXT"] = normalized_extension
|
|
144
|
+
if preview_width > 0:
|
|
145
|
+
preview_env["MCFG_PREVIEW_WIDTH"] = str(preview_width)
|
|
146
|
+
preview_env_line = _toml_inline_table(preview_env)
|
|
147
|
+
channel_config = f"""[metadata]
|
|
148
|
+
name = "temp_options"
|
|
149
|
+
description = "Temporary channel for selecting options"
|
|
150
|
+
|
|
151
|
+
[source]
|
|
152
|
+
command = "bat '{entries_path}'"
|
|
153
|
+
display = "{{split:\\t:1}}"
|
|
154
|
+
output = "{{split:\\t:0}}"
|
|
155
|
+
|
|
156
|
+
[preview]
|
|
157
|
+
command = "{preview_script} {{split:\\t:0}}"
|
|
158
|
+
{preview_env_line}
|
|
159
|
+
|
|
160
|
+
[ui.preview_panel]
|
|
161
|
+
size = {preview_panel_size}
|
|
162
|
+
"""
|
|
163
|
+
channel_path = tempdir / "temp_options.toml"
|
|
164
|
+
channel_path.write_text(channel_config, encoding="utf-8")
|
|
165
|
+
env = os.environ.copy()
|
|
166
|
+
tv_config_dir = pathlib.Path.home() / ".config" / "television"
|
|
167
|
+
if not tv_config_dir.exists():
|
|
168
|
+
tv_config_dir = pathlib.Path(os.getenv("XDG_CONFIG_HOME", str(pathlib.Path.home() / ".config"))) / "television"
|
|
169
|
+
cable_dir = tv_config_dir / "cable"
|
|
170
|
+
cable_dir.mkdir(parents=True, exist_ok=True)
|
|
171
|
+
temp_channel_link = cable_dir / "temp_options.toml"
|
|
172
|
+
if temp_channel_link.exists() or temp_channel_link.is_symlink():
|
|
173
|
+
temp_channel_link.unlink()
|
|
174
|
+
temp_channel_link.symlink_to(channel_path)
|
|
175
|
+
output_file = tempdir / "selection.txt"
|
|
176
|
+
try:
|
|
177
|
+
result = subprocess.run(["tv", "temp_options"], check=False, stdout=output_file.open("w"), text=True, env=env)
|
|
178
|
+
finally:
|
|
179
|
+
if temp_channel_link.exists() or temp_channel_link.is_symlink():
|
|
180
|
+
temp_channel_link.unlink()
|
|
181
|
+
if result.returncode not in (0, 130):
|
|
182
|
+
raise SystemExit(result.returncode)
|
|
183
|
+
if result.returncode == 130:
|
|
184
|
+
return [] if multi else None
|
|
185
|
+
if not output_file.exists():
|
|
186
|
+
return [] if multi else None
|
|
187
|
+
selected_lines = [line.strip() for line in output_file.read_text().splitlines() if line.strip()]
|
|
188
|
+
if not selected_lines:
|
|
189
|
+
return [] if multi else None
|
|
190
|
+
selected_keys: list[str] = []
|
|
191
|
+
for line in selected_lines:
|
|
192
|
+
try:
|
|
193
|
+
index = int(line)
|
|
194
|
+
key = index_map.get(index)
|
|
195
|
+
if key is not None:
|
|
196
|
+
selected_keys.append(key)
|
|
197
|
+
except ValueError:
|
|
198
|
+
continue
|
|
199
|
+
if multi:
|
|
200
|
+
return selected_keys
|
|
201
|
+
return selected_keys[0] if selected_keys else None
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
if __name__ == "__main__":
|
|
205
|
+
demo_mapping: dict[str, str] = {
|
|
206
|
+
"Option 1": "# Option 1\nThis is the preview for option 1.",
|
|
207
|
+
"Option 2": "# Option 2\nThis is the preview for option 2.",
|
|
208
|
+
"Option 3": "# Option 3\nThis is the preview for option 3."
|
|
209
|
+
}
|
|
210
|
+
result = select_from_options(demo_mapping, multi=True, extension="md", preview_size_percent=50)
|
|
211
|
+
print(f"Selected: {result}")
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import pathlib
|
|
3
|
+
import pprint
|
|
4
|
+
import shutil
|
|
5
|
+
from typing import Any, Literal, Union, overload
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _format_preview_value(value: Any) -> str:
|
|
9
|
+
if isinstance(value, str):
|
|
10
|
+
return value
|
|
11
|
+
return pprint.pformat(value, width=88, sort_dicts=True)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _normalize_extension(extension: str | None) -> str | None:
|
|
15
|
+
if extension is None:
|
|
16
|
+
return None
|
|
17
|
+
trimmed = extension.strip()
|
|
18
|
+
if trimmed.startswith("."):
|
|
19
|
+
trimmed = trimmed[1:]
|
|
20
|
+
if not trimmed:
|
|
21
|
+
return None
|
|
22
|
+
return trimmed
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@overload
|
|
26
|
+
def select_from_options(options_to_preview_mapping: dict[str, Any], extension: str | None, multi: Literal[True], preview_size_percent: float) -> list[str]: ...
|
|
27
|
+
@overload
|
|
28
|
+
def select_from_options(options_to_preview_mapping: dict[str, Any], extension: str | None, multi: Literal[False], preview_size_percent: float) -> str | None: ...
|
|
29
|
+
def select_from_options(options_to_preview_mapping: dict[str, Any], extension: str | None, multi: bool, preview_size_percent: float) -> Union[list[str], Union[str, None]]:
|
|
30
|
+
keys = list(options_to_preview_mapping.keys())
|
|
31
|
+
if not keys:
|
|
32
|
+
return [] if multi else None
|
|
33
|
+
normalized_extension = _normalize_extension(extension)
|
|
34
|
+
preview_panel_size = max(10, min(90, int(preview_size_percent)))
|
|
35
|
+
from machineconfig.utils.accessories import randstr
|
|
36
|
+
tempdir = pathlib.Path.home() / "tmp_results" / "tmp_files" / f"tv_channel_{randstr(6)}"
|
|
37
|
+
tempdir.mkdir(parents=True, exist_ok=True)
|
|
38
|
+
try:
|
|
39
|
+
index_map: dict[str, str] = {}
|
|
40
|
+
ext_for_preview = normalized_extension or "txt"
|
|
41
|
+
entries_lines: list[str] = []
|
|
42
|
+
for idx, key in enumerate(keys):
|
|
43
|
+
display_key = key.replace("\n", " ")
|
|
44
|
+
entries_lines.append(f"{idx}|{display_key}")
|
|
45
|
+
index_map[str(idx)] = key
|
|
46
|
+
preview_value = _format_preview_value(options_to_preview_mapping[key])
|
|
47
|
+
preview_file = tempdir / f"{idx}.{ext_for_preview}"
|
|
48
|
+
preview_file.write_text(preview_value, encoding="utf-8")
|
|
49
|
+
entries_path = tempdir / "entries.txt"
|
|
50
|
+
entries_path.write_text("\n".join(entries_lines), encoding="utf-8")
|
|
51
|
+
output_file = tempdir / "selection.txt"
|
|
52
|
+
tempdir_fwd = str(tempdir).replace("\\", "/")
|
|
53
|
+
source_cmd = f"cmd /C type \"{entries_path}\""
|
|
54
|
+
preview_cmd = f"bat --force-colorization --style=plain --paging=never {tempdir_fwd}/{{split:|:0}}.{ext_for_preview}"
|
|
55
|
+
tv_cmd = f'''$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
|
|
56
|
+
tv --ansi --source-command '{source_cmd}' --source-display '{{split:|:1}}' --source-output '{{split:|:0}}' --preview-command '{preview_cmd}' --preview-size {preview_panel_size} --no-remote | Out-File -Encoding utf8 -FilePath "{output_file}"
|
|
57
|
+
'''
|
|
58
|
+
from machineconfig.utils.code import run_shell_script
|
|
59
|
+
result = run_shell_script(tv_cmd, display_script=False, clean_env=False)
|
|
60
|
+
if result.returncode not in (0, 130) and not output_file.exists():
|
|
61
|
+
raise SystemExit(result.returncode)
|
|
62
|
+
if result.returncode == 130:
|
|
63
|
+
return [] if multi else None
|
|
64
|
+
if not output_file.exists():
|
|
65
|
+
return [] if multi else None
|
|
66
|
+
selected_lines = [line.strip() for line in output_file.read_text(encoding="utf-8-sig").splitlines() if line.strip()]
|
|
67
|
+
if not selected_lines:
|
|
68
|
+
return [] if multi else None
|
|
69
|
+
selected_keys: list[str] = []
|
|
70
|
+
for line in selected_lines:
|
|
71
|
+
key = index_map.get(line)
|
|
72
|
+
if key is not None:
|
|
73
|
+
selected_keys.append(key)
|
|
74
|
+
if multi:
|
|
75
|
+
return selected_keys
|
|
76
|
+
return selected_keys[0] if selected_keys else None
|
|
77
|
+
finally:
|
|
78
|
+
shutil.rmtree(tempdir, ignore_errors=True)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
if __name__ == "__main__":
|
|
82
|
+
demo_mapping: dict[str, str] = {
|
|
83
|
+
"Option 1": "# Option 1\nThis is the preview for option 1.",
|
|
84
|
+
"Option 2": "# Option 2\nThis is the preview for option 2.",
|
|
85
|
+
"Option 3": "# Option 3\nThis is the preview for option 3."
|
|
86
|
+
}
|
|
87
|
+
result = select_from_options(demo_mapping, multi=True, extension="md", preview_size_percent=50)
|
|
88
|
+
print(f"Selected: {result}")
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from typing import Any, Literal, overload
|
|
2
|
+
import platform
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@overload
|
|
6
|
+
def choose_from_dict_with_preview(options_to_preview_mapping: dict[str, Any], extension: str | None, multi: Literal[False], preview_size_percent: float) -> str | None: ...
|
|
7
|
+
@overload
|
|
8
|
+
def choose_from_dict_with_preview(options_to_preview_mapping: dict[str, Any], extension: str | None, multi: Literal[True], preview_size_percent: float) -> list[str]: ...
|
|
9
|
+
def choose_from_dict_with_preview(options_to_preview_mapping: dict[str, Any], extension: str | None, multi: bool, preview_size_percent: float) -> str | list[str] | None:
|
|
10
|
+
if not options_to_preview_mapping:
|
|
11
|
+
return [] if multi else None
|
|
12
|
+
system = platform.system()
|
|
13
|
+
if system == "Windows":
|
|
14
|
+
from machineconfig.utils.options_utils.options_tv_windows import select_from_options
|
|
15
|
+
return select_from_options(options_to_preview_mapping, extension=extension, multi=multi, preview_size_percent=preview_size_percent)
|
|
16
|
+
else:
|
|
17
|
+
from machineconfig.utils.options_utils.options_tv_linux import select_from_options
|
|
18
|
+
return select_from_options(options_to_preview_mapping, extension=extension, multi=multi, preview_size_percent=preview_size_percent)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
if __name__ == "__main__":
|
|
22
|
+
demo_mapping: dict[str, str] = {
|
|
23
|
+
"config.py": """from pathlib import Path
|
|
24
|
+
|
|
25
|
+
CONFIG_DIR = Path.home() / ".config"
|
|
26
|
+
DEBUG = True
|
|
27
|
+
""",
|
|
28
|
+
"utils.py": """def greet(name: str) -> str:
|
|
29
|
+
return f"Hello, {name}!"
|
|
30
|
+
""",
|
|
31
|
+
"main.rs": """fn main() {
|
|
32
|
+
println!("Hello, world!");
|
|
33
|
+
}
|
|
34
|
+
""",
|
|
35
|
+
}
|
|
36
|
+
result = choose_from_dict_with_preview(demo_mapping, extension="py", multi=True, preview_size_percent=50)
|
|
37
|
+
print(f"Selected: {result}")
|