machineconfig 4.8__py3-none-any.whl → 4.91__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.

Files changed (25) hide show
  1. machineconfig/jobs/installer/custom_dev/winget.py +1 -0
  2. machineconfig/jobs/installer/installer_data.json +2403 -0
  3. machineconfig/jobs/installer/package_groups.py +157 -0
  4. machineconfig/scripts/linux/agents +2 -0
  5. machineconfig/scripts/linux/sessions +2 -0
  6. machineconfig/scripts/python/{fire_agents.py → agents.py} +7 -0
  7. machineconfig/scripts/python/croshell.py +13 -27
  8. machineconfig/scripts/python/devops.py +0 -13
  9. machineconfig/scripts/python/devops_devapps_install.py +148 -107
  10. machineconfig/scripts/python/interactive.py +30 -76
  11. machineconfig/scripts/python/{fire_jobs_layout_helper.py → sessions.py} +7 -0
  12. machineconfig/utils/installer.py +40 -16
  13. machineconfig/utils/installer_utils/github_release_bulk.py +2 -12
  14. machineconfig/utils/installer_utils/installer_abc.py +56 -60
  15. machineconfig/utils/schemas/installer/installer_types.py +0 -1
  16. {machineconfig-4.8.dist-info → machineconfig-4.91.dist-info}/METADATA +1 -1
  17. {machineconfig-4.8.dist-info → machineconfig-4.91.dist-info}/RECORD +20 -21
  18. {machineconfig-4.8.dist-info → machineconfig-4.91.dist-info}/entry_points.txt +2 -0
  19. machineconfig/jobs/installer/packages_custom_dev.json +0 -380
  20. machineconfig/jobs/installer/packages_custom_essential.json +0 -39
  21. machineconfig/jobs/installer/packages_github_dev.json +0 -1127
  22. machineconfig/jobs/installer/packages_github_essential.json +0 -787
  23. machineconfig/setup_linux/web_shortcuts/ascii_art.sh +0 -93
  24. {machineconfig-4.8.dist-info → machineconfig-4.91.dist-info}/WHEEL +0 -0
  25. {machineconfig-4.8.dist-info → machineconfig-4.91.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,157 @@
1
+ from typing import Literal, TypeAlias, Union
2
+
3
+ PACKAGES_NAMES_DEV = Literal[
4
+ "ngrok",
5
+ "Visual Studio Code",
6
+ "aider",
7
+ "github-copilot-cli",
8
+ "gemini",
9
+ "crush",
10
+ "opencode-ai",
11
+ "warp",
12
+ "q",
13
+ "cursor-cli",
14
+ "droid",
15
+ "Alacritty",
16
+ "Brave",
17
+ "bypass-paywalls-chrome",
18
+ "Cursor",
19
+ "espanso",
20
+ "Gorilla",
21
+ "lvim",
22
+ "nerdfont",
23
+ "Redis",
24
+ "Wezterm",
25
+ "winget",
26
+ "ytui-music",
27
+ "youtube-tui",
28
+ "termusic",
29
+ "kronos",
30
+ "transmission",
31
+ "nnn",
32
+ "exa",
33
+ "bytehound",
34
+ "atuin",
35
+ "browsh",
36
+ "carbonyl",
37
+ "patat",
38
+ "SqliteBrowser",
39
+ "DBeaver",
40
+ "rainfrog",
41
+ "duckdb",
42
+ "cpz",
43
+ "rmz",
44
+ "mermaid-cli",
45
+ "html2markdown",
46
+ "xcrawl3r",
47
+ "obsidian",
48
+ "marp",
49
+ "presenterm",
50
+ "pandoc",
51
+ "devcontainer",
52
+ "bitwarden",
53
+ "OBS Background removal",
54
+ "rustdesk",
55
+ "evcxr",
56
+ "forward-cli",
57
+ "bandwhich",
58
+ "ipinfo",
59
+ "dust",
60
+ "ots",
61
+ "ffsend",
62
+ "portal",
63
+ "qrcp",
64
+ "qrscan",
65
+ "termscp",
66
+ "qr",
67
+ "filebrowser",
68
+ "cloudreve",
69
+ "restic",
70
+ "syncthing",
71
+ "istio",
72
+ "openpomodoro-cli",
73
+ "rust-analyzer",
74
+ "kondo",
75
+ "tokei",
76
+ "lazygit",
77
+ "lazydocker",
78
+ "onefetch",
79
+ "gitcs",
80
+ "just",
81
+ "navi",
82
+ "tealdeer",
83
+ "sniffnet",
84
+ "hyperfine",
85
+ "ollama",
86
+ "cointop",
87
+ "vtm",
88
+ "edex-ui",
89
+ "extraterm",
90
+ "nushell",
91
+ "geckodriver",
92
+ "lolcatjs",
93
+ "figlet-cli",
94
+ "sharewifi",
95
+ "share-wifi",
96
+ ]
97
+
98
+ PACKAGES_NAMES_ESSENTIAL = Literal[
99
+ "gh",
100
+ "hx",
101
+ "speedtest",
102
+ "pistol",
103
+ "diskonaut",
104
+ "xplr",
105
+ "btop",
106
+ "gotty",
107
+ "joshuto",
108
+ "zellij",
109
+ "boxes",
110
+ "ugrep",
111
+ "zoomit",
112
+ "ntop",
113
+ "devtunnel",
114
+ "bat",
115
+ "broot",
116
+ "btm",
117
+ "chatgpt",
118
+ "cloudflared",
119
+ "cpufetch",
120
+ "delta",
121
+ "dua",
122
+ "fastfetch",
123
+ "fd",
124
+ "fzf",
125
+ "gitui",
126
+ "glow",
127
+ "gum",
128
+ "lf",
129
+ "lsd",
130
+ "m365",
131
+ "mcfly",
132
+ "mods",
133
+ "mprocs",
134
+ "ouch",
135
+ "procs",
136
+ "rclone",
137
+ "rg",
138
+ "rga",
139
+ "starship",
140
+ "tere",
141
+ "topgrade",
142
+ "ttyd",
143
+ "viu",
144
+ "watchexec",
145
+ "yazi",
146
+ "zoxide",
147
+ ]
148
+
149
+ PACKAGE_GROUPS: TypeAlias = Literal["ESSENTIAL", "DEV", "ESSENTIAL_SYSTEM", "DEV_SYSTEM"]
150
+ PACKAGE_GROUP2NAMES: dict[PACKAGE_GROUPS, list[str]] = {
151
+ "ESSENTIAL": list(PACKAGES_NAMES_ESSENTIAL.__args__),
152
+ "DEV": list(PACKAGES_NAMES_DEV.__args__),
153
+ "ESSENTIAL_SYSTEM": [],
154
+ "DEV_SYSTEM": [],
155
+ }
156
+
157
+ _ = Union
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bash
2
+ uv run --python 3.13 --no-dev --project $HOME/code/machineconfig agents "$@"
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bash
2
+ uv run --python 3.13 --no-dev --project $HOME/code/machineconfig sessions "$@"
@@ -193,5 +193,12 @@ fire_agents collect $AGENTS_DIR "$REPO_ROOT/.ai/agents/$JOB_NAME/collected.txt"
193
193
  typer.echo(f"Template bash script written to {save_path}")
194
194
 
195
195
 
196
+ def main_from_parser():
197
+ agents_app = typer.Typer(help="🤖 AI Agents management subcommands")
198
+ agents_app.command("create")(create)
199
+ agents_app.command("collect")(collect)
200
+ agents_app.command("template")(template)
201
+ return agents_app()
202
+
196
203
  if __name__ == "__main__": # pragma: no cover
197
204
  pass
@@ -10,10 +10,10 @@ from machineconfig.utils.path_extended import PathExtended as PathExtended
10
10
  from machineconfig.utils.accessories import randstr
11
11
 
12
12
  from machineconfig.utils.options import choose_from_options
13
- from machineconfig.utils.ve import get_ve_activate_line
13
+ # from machineconfig.utils.ve import get_ve_activate_line
14
14
  from rich.console import Console
15
15
  from rich.panel import Panel
16
- from rich.text import Text
16
+ # from rich.text import Text
17
17
 
18
18
  console = Console()
19
19
 
@@ -173,41 +173,27 @@ print(f"🐊 Crocodile Shell | Running @ {Path.cwd()}")
173
173
  title = "Running Python File"
174
174
  else:
175
175
  title = "Executed code"
176
- total_program = preprogram + add_print_header_pycode(str(pyfile), title=title) + program
177
-
178
- pyfile.write_text(total_program, encoding="utf-8")
179
-
176
+ python_program = preprogram + add_print_header_pycode(str(pyfile), title=title) + program
177
+ pyfile.write_text(python_program, encoding="utf-8")
180
178
  # ve_root_from_file, ipython_profile = get_ve_path_and_ipython_profile(PathExtended(file))
181
179
  ipython_profile = ipython_profile if ipython_profile is not None else "default"
182
180
  # ve_activateion_line = get_ve_activate_line(ve_name=args.ve or ve_profile_suggested, a_path=str(PathExtended.cwd()))
183
- activate_ve_line = get_ve_activate_line(ve_root="$HOME/code/machineconfig/.venv")
184
- final_program = f"""
181
+ shell_program = """
185
182
  #!/bin/bash
186
183
 
187
- {activate_ve_line}
188
-
189
184
  """
190
185
  if jupyter:
191
186
  fire_line = f"code --new-window {str(pyfile)}"
192
187
  else:
193
- fire_line = interpreter
194
- if interpreter == "ipython":
195
- fire_line += f" {interactivity} --profile {ipython_profile} --no-banner"
196
- fire_line += f" {str(pyfile)}"
197
-
198
- final_program += fire_line
199
-
200
- title = "🚀 LAUNCHING SCRIPT"
201
- text1 = f"📄 Script: {pyfile}"
202
- text2 = f"🔥 Command: {fire_line}"
203
- launch_message = f"{title} \n{text1}\n{text2}"
204
- console.print(Panel(Text(launch_message, justify="left"), expand=False, border_style="blue"))
205
-
206
- # PROGRAM_PATH.write_text(data=final_program, encoding="utf-8")
207
- # (PROGRAM_PATH + ".py").write_text(str(pyfile), encoding='utf-8')
188
+ fire_line = f"uv run --project $HOME/code/machineconfig/.venv {interpreter} {interactivity} "
189
+ if interpreter == "ipython": fire_line += f" --profile {ipython_profile} --no-banner"
190
+ fire_line += " " + str(pyfile)
191
+ shell_program += fire_line
192
+ from rich.syntax import Syntax
193
+ console.print(Syntax(shell_program, lexer="bash"))
194
+ print()
208
195
  import subprocess
209
-
210
- subprocess.run(final_program, shell=True, check=True)
196
+ subprocess.run(shell_program, shell=True, check=True)
211
197
 
212
198
 
213
199
  def arg_parser() -> None:
@@ -1,7 +1,5 @@
1
1
  """devops with emojis"""
2
2
 
3
- import machineconfig.scripts.python.fire_agents as fire_agents
4
- import machineconfig.scripts.python.fire_jobs_layout_helper as fire_jobs_layout_helper
5
3
  import machineconfig.scripts.python.devops_devapps_install as installer_entry_point
6
4
  import machineconfig.scripts.python.share_terminal as share_terminal
7
5
  import machineconfig.scripts.python.repos as repos
@@ -10,17 +8,6 @@ import typer
10
8
 
11
9
  app = typer.Typer(help="🛠️ DevOps operations with emojis", no_args_is_help=True)
12
10
 
13
-
14
- agents_app = typer.Typer(help="🤖 AI Agents management subcommands")
15
- agents_app.command("create")(fire_agents.create)
16
- agents_app.command("collect")(fire_agents.collect)
17
- app.add_typer(agents_app, name="agents")
18
-
19
- layouts_app = typer.Typer(help="Layouts management subcommands")
20
- layouts_app.command("launch")(fire_jobs_layout_helper.launch)
21
- layouts_app.command("load-balance")(fire_jobs_layout_helper.load_balance)
22
- app.add_typer(layouts_app, name="session")
23
-
24
11
  app.command(name="install", help="📦 Install essential packages")(installer_entry_point.main)
25
12
  app.command(name="share-terminal", help="📡 Share terminal via web browser")(share_terminal.main)
26
13
  app.command(name="repos", help="📁 Manage git repositories")(repos.main)
@@ -1,85 +1,79 @@
1
1
  """Devops Devapps Install"""
2
2
 
3
+ from machineconfig.utils.installer import get_installers_system_groups
3
4
  import typer
4
5
  from rich.progress import Progress, SpinnerColumn, TextColumn
6
+ from rich.console import Console
7
+ from rich.panel import Panel
8
+ from rich.table import Table
5
9
  from platform import system
6
- from typing import Optional, Literal, TypeAlias, cast, get_args, Annotated
10
+ from typing import Optional, cast, get_args
11
+ from machineconfig.jobs.installer.package_groups import PACKAGE_GROUPS
7
12
 
8
- WHICH_CAT: TypeAlias = Literal["essentials", "essentialsDev", "systymPackages", "precheckedPackages", "ia"]
13
+ console = Console()
9
14
 
10
15
 
11
16
  def _handle_installer_not_found(search_term: str, all_installers: list["InstallerData"]) -> None: # type: ignore
12
17
  """Handle installer not found with friendly suggestions using fuzzy matching."""
13
18
  from difflib import get_close_matches
14
-
15
- # Get all possible names (both exe names and app names)
19
+
16
20
  all_names = []
17
21
  for inst in all_installers:
18
22
  exe_name = inst["appName"]
19
23
  all_names.append(exe_name)
20
-
21
- # Find close matches using fuzzy matching
22
24
  close_matches = get_close_matches(search_term, all_names, n=5, cutoff=0.4)
23
-
24
- print(f"\n❌ '{search_term}' was not found.")
25
-
25
+ console.print(f"\n❌ '[red]{search_term}[/red]' was not found.", style="bold")
26
+
26
27
  if close_matches:
27
- print("🤔 Did you mean one of these?")
28
+ console.print("🤔 Did you mean one of these?", style="yellow")
29
+ table = Table(show_header=False, box=None, pad_edge=False)
28
30
  for i, match in enumerate(close_matches, 1):
29
- print(f" {i}. {match}")
31
+ table.add_row(f"[cyan]{i}.[/cyan]", f"[green]{match}[/green]")
32
+ console.print(table)
30
33
  else:
31
- print("📋 Here are some available options:")
34
+ console.print("📋 Here are some available options:", style="blue")
32
35
  # Show first 10 installers as examples
33
36
  sample_names = []
34
37
  for inst in all_installers[:10]:
35
38
  exe_name = inst["appName"]
36
- sample_names.append(exe_name)
39
+ sample_names.append(exe_name)
40
+
41
+ table = Table(show_header=False, box=None, pad_edge=False)
37
42
  for i, name in enumerate(sample_names, 1):
38
- print(f" {i}. {name}")
39
-
43
+ table.add_row(f"[cyan]{i}.[/cyan]", f"[green]{name}[/green]")
44
+ console.print(table)
45
+
40
46
  if len(all_installers) > 10:
41
- print(f" ... and {len(all_installers) - 10} more")
42
-
43
- print("\n💡 Use 'ia' to interactively browse all available installers.")
44
- print(f"💡 Use one of the categories: {list(get_args(WHICH_CAT))}")
47
+ console.print(f" [dim]... and {len(all_installers) - 10} more[/dim]")
48
+
49
+ panel = Panel(
50
+ f"[bold blue]💡 Use 'ia' to interactively browse all available installers.[/bold blue]\n[bold blue]💡 Use one of the categories: {list(get_args(PACKAGE_GROUPS))}[/bold blue]", title="[yellow]Helpful Tips[/yellow]", border_style="yellow"
51
+ )
52
+ console.print(panel)
45
53
 
46
54
 
47
55
  def main_with_parser():
48
56
  import typer
57
+
49
58
  app = typer.Typer()
50
59
  app.command()(main)
51
60
  app()
52
61
 
53
62
 
54
- def main(which: Annotated[Optional[str], typer.Argument(help=f"Choose a category or program to install, {list(get_args(WHICH_CAT))} or <program_name> or list of programs names separated by comma.")]) -> None:
55
- if which in get_args(WHICH_CAT): # install by category
56
- return get_programs_by_category(program_name=which) # type: ignore
57
- from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
58
- from machineconfig.utils.installer import get_installers
59
- from machineconfig.utils.installer_utils.installer_class import Installer
60
- if which != "ia" and which is not None: # install by name
61
- total_messages: list[str] = []
62
- for a_which in which.split(",") if type(which) == str else which:
63
- all_installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL", "GITHUB_DEV", "CUSTOM_DEV"])
64
-
65
- # Find installer by exe_name or name
66
- selected_installer = None
67
- for installer in all_installers:
68
- exe_name = installer["appName"]
69
- app_name = installer["appName"]
70
- if exe_name == a_which or app_name == a_which:
71
- selected_installer = installer
72
- break
73
-
74
- if selected_installer is None:
75
- _handle_installer_not_found(a_which, all_installers)
76
- return None
77
- message = Installer(selected_installer).install_robust(version=None) # finish the task
78
- total_messages.append(message)
79
- for a_message in total_messages:
80
- print(a_message)
81
- return None
82
-
63
+ def main(
64
+ which: Optional[str] = typer.Option(None, "--which", "-w", help="Comma-separated list of program names to install."),
65
+ group: Optional[PACKAGE_GROUPS] = typer.Option(None, "--group", "-g", help=f"Group name (one of {list(get_args(PACKAGE_GROUPS))})"),
66
+ interactive: bool = typer.Option(False, "--interactive", "-ia", help="Interactive selection of programs to install."),
67
+ ) -> None:
68
+ if which is not None:
69
+ return install_clis(clis_names=[x.strip() for x in which.split(",") if x.strip() != ""])
70
+ if group is not None:
71
+ return get_programs_by_category(package_group=group)
72
+ if interactive:
73
+ return install_interactively()
74
+ typer.echo("❌ You must provide either --which, --group, or --interactive/-ia option.")
75
+ # typer.help(main)
76
+ raise typer.Exit(1)
83
77
 
84
78
 
85
79
  def install_interactively():
@@ -87,84 +81,131 @@ def install_interactively():
87
81
  from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
88
82
  from machineconfig.utils.installer import get_installers
89
83
  from machineconfig.utils.installer_utils.installer_class import Installer
90
- installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL", "GITHUB_DEV", "CUSTOM_DEV"])
91
- with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
92
- task = progress.add_task("✅ Checking installed programs...", total=len(installers))
93
- installer_options = []
94
- for x in installers:
95
- installer_options.append(Installer(installer_data=x).get_description())
96
- progress.update(task, advance=1)
97
- category_options = [f"📦 {cat}" for cat in get_args(WHICH_CAT)]
98
- options = category_options + ["─" * 50] + installer_options
84
+ installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["ESSENTIAL", "DEV"])
85
+ installer_options = []
86
+ for x in installers:
87
+ installer_options.append(Installer(installer_data=x).get_description())
88
+ category_options = [f"📦 {cat}" for cat in get_args(PACKAGE_GROUPS)]
89
+ options = category_options + ["─" * 50] + installer_options
99
90
  program_names = choose_from_options(multi=True, msg="Categories are prefixed with 📦", options=options, header="🚀 CHOOSE DEV APP OR CATEGORY", default="📦 essentials", fzf=True)
100
91
  installation_messages: list[str] = []
101
92
  for _an_idx, a_program_name in enumerate(program_names):
102
- if a_program_name.startswith("─"):
93
+ if a_program_name.startswith("─"): # 50 dashes separator
103
94
  continue
104
95
  if a_program_name.startswith("📦 "):
105
96
  category_name = a_program_name[2:] # Remove "📦 " prefix
106
- if category_name in get_args(WHICH_CAT):
107
- get_programs_by_category(program_name=cast(WHICH_CAT, category_name))
97
+ if category_name in get_args(PACKAGE_GROUPS):
98
+ get_programs_by_category(package_group=cast(PACKAGE_GROUPS, category_name))
108
99
  else:
109
100
  installer_idx = installer_options.index(a_program_name)
110
101
  an_installer_data = installers[installer_idx]
111
102
  status_message = Installer(an_installer_data).install_robust(version=None) # finish the task - this returns a status message, not a command
112
103
  installation_messages.append(status_message)
113
- print("\n📊 INSTALLATION SUMMARY:")
114
- print("=" * 50)
115
- for message in installation_messages:
116
- print(message)
117
-
118
-
119
- def get_programs_by_category(program_name: WHICH_CAT):
120
- print(f"""
121
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
122
- ┃ 📦 Installing Category: {program_name}
123
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━""")
124
- from machineconfig.utils.source_of_truth import LIBRARY_ROOT
104
+ if installation_messages:
105
+ panel = Panel("\n".join([f"[blue]• {message}[/blue]" for message in installation_messages]), title="[bold green]📊 Installation Summary[/bold green]", border_style="green", padding=(1, 2))
106
+ console.print(panel)
107
+
108
+
109
+ def get_programs_by_category(package_group: PACKAGE_GROUPS):
110
+ panel = Panel(f"[bold yellow]Installing programs from category: [green]{package_group}[/green][/bold yellow]", title="[bold blue]📦 Category Installation[/bold blue]", border_style="blue", padding=(1, 2))
111
+ console.print(panel)
125
112
  from machineconfig.utils.installer import get_installers, install_all
126
- from machineconfig.utils.installer_utils.installer_abc import parse_apps_installer_linux, parse_apps_installer_windows
127
113
  from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
128
- from machineconfig.utils.options import choose_from_options
129
- match program_name:
130
- case "essentials":
131
- installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL"])
114
+ match package_group:
115
+ case "ESSENTIAL":
116
+ installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["ESSENTIAL"])
132
117
  install_all(installers_data=installers_)
133
- case "essentialsDev":
134
- installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["GITHUB_DEV", "CUSTOM_DEV", "GITHUB_ESSENTIAL", "CUSTOM_ESSENTIAL"])
118
+ case "DEV":
119
+ installers_ = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["DEV", "ESSENTIAL"])
135
120
  install_all(installers_data=installers_)
136
- case "systymPackages":
137
- if system() == "Windows":
138
- options_system = parse_apps_installer_windows(LIBRARY_ROOT.joinpath("setup_windows/apps.ps1").read_text(encoding="utf-8"))
139
- elif system() == "Linux":
140
- options_system_1 = parse_apps_installer_linux(LIBRARY_ROOT.joinpath("setup_linux/apps_dev.sh").read_text(encoding="utf-8"))
141
- options_system_2 = parse_apps_installer_linux(LIBRARY_ROOT.joinpath("setup_linux/apps.sh").read_text(encoding="utf-8"))
142
- options_system = {**options_system_1, **options_system_2}
143
- else:
144
- raise NotImplementedError(f"❌ System {system()} not supported")
145
- program_names = choose_from_options(multi=True, msg="", options=sorted(list(options_system.keys())), header="🚀 CHOOSE DEV APP", fzf=True)
146
- program = ""
147
- for name in program_names:
148
- print(f"""
149
- ┌────────────────────────────────────────────────────
150
- ⚙️ Installing: {name}
151
- └────────────────────────────────────────────────────""")
152
- sub_program = options_system[name]
153
- if sub_program.startswith("#winget"):
154
- sub_program = sub_program[1:]
155
- program += "\n" + sub_program
156
- case "ia":
157
- install_interactively()
158
- case "precheckedPackages":
159
- # from machineconfig.jobs.python.check_installations import precheckedPackages
160
- # ci = precheckedPackages()
161
- # ci.download_safe_apps(name="essentials")
162
- # program = ""
163
- raise NotImplementedError("precheckedPackages is not implemented yet.")
121
+ case "DEV_SYSTEM" | "ESSENTIAL_SYSTEM":
122
+ options_system = get_installers_system_groups()
123
+ from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
124
+ for an_item in options_system:
125
+ if an_item["appName"] == package_group:
126
+ program = an_item["fileNamePattern"][get_normalized_arch()][get_os_name()]
127
+ if program is not None:
128
+ install_terminal_packages(program)
129
+
130
+
131
+ def choose_from_system_package_groups(options_system: dict[str, tuple[str, str]]) -> str:
132
+ from machineconfig.utils.options import choose_from_options
133
+ display_options = []
134
+ for group_name, (description, _) in options_system.items():
135
+ if description:
136
+ display_options.append(f"{group_name:<20} - {description}")
137
+ else:
138
+ display_options.append(group_name)
139
+ program_names = choose_from_options(multi=True, msg="", options=sorted(display_options), header="🚀 CHOOSE DEV APP", fzf=True)
140
+ program = ""
141
+ for display_name in program_names:
142
+ # Extract the actual group name (everything before " - " if present)
143
+ group_name = display_name.split(" - ")[0].strip() if " - " in display_name else display_name.strip()
144
+ console.print(f"\n[bold cyan]⚙️ Installing: [yellow]{group_name}[/yellow][/bold cyan]", style="bold")
145
+ _, sub_program = options_system[group_name] # Extract content from tuple
146
+ if sub_program.startswith("#winget"):
147
+ sub_program = sub_program[1:]
148
+ program += "\n" + sub_program
149
+ return program
150
+
151
+
152
+ def install_terminal_packages(program: str):
153
+ from pathlib import Path
154
+
155
+ if system() == "Windows":
156
+ temp_script_path = Path("C:/Windows/Temp/temp_install_script.ps1")
157
+ lexer = "powershell"
158
+ else:
159
+ temp_script_path = Path("/tmp/temp_install_script.sh")
160
+ lexer = "bash"
161
+ temp_script_path.write_text(program, encoding="utf-8")
162
+ console.print(f"📝 [blue]Temporary script written to:[/blue] [green]{temp_script_path}[/green]")
163
+ from rich.syntax import Syntax
164
+
165
+ console.print(Panel(Syntax(code=program, lexer=lexer), title="📄 Installation Program", subtitle="shell code"), style="bold red")
166
+ console.print("🚀 [bold yellow]Starting installation...[/bold yellow]")
167
+ if system() == "Windows":
168
+ import subprocess
169
+
170
+ subprocess.run(["powershell", "-ExecutionPolicy", "Bypass", "-File", str(temp_script_path)], check=True)
171
+ elif system() == "Linux":
172
+ import subprocess
173
+
174
+ subprocess.run(["bash", str(temp_script_path)], check=True)
175
+ console.print("✅ [bold green]Installation completed.[/bold green]")
176
+ temp_script_path.unlink(missing_ok=True)
177
+
178
+
179
+ def install_clis(clis_names: list[str]):
180
+ from machineconfig.utils.schemas.installer.installer_types import get_normalized_arch, get_os_name
181
+ from machineconfig.utils.installer import get_installers
182
+ from machineconfig.utils.installer_utils.installer_class import Installer
183
+
184
+ total_messages: list[str] = []
185
+ for a_which in clis_names:
186
+ all_installers = get_installers(os=get_os_name(), arch=get_normalized_arch(), which_cats=["ESSENTIAL", "DEV"])
187
+ selected_installer = None
188
+ for installer in all_installers:
189
+ exe_name = installer["appName"]
190
+ app_name = installer["appName"]
191
+ if exe_name == a_which or app_name == a_which:
192
+ selected_installer = installer
193
+ break
194
+ if selected_installer is None:
195
+ _handle_installer_not_found(a_which, all_installers)
196
+ return None
197
+ message = Installer(selected_installer).install_robust(version=None) # finish the task
198
+ total_messages.append(message)
199
+ if total_messages:
200
+ console.print("\n[bold green]📊 Installation Results:[/bold green]")
201
+ for a_message in total_messages:
202
+ console.print(f"[blue]• {a_message}[/blue]")
203
+ return None
164
204
 
165
205
 
166
206
  if __name__ == "__main__":
167
207
  from machineconfig.utils.schemas.installer.installer_types import InstallerData
168
208
  from machineconfig.utils.installer_utils.installer_class import Installer
209
+
169
210
  _ = InstallerData, Installer
170
211
  pass