machineconfig 7.39__py3-none-any.whl → 7.46__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/jobs/installer/custom/hx.py +60 -8
- machineconfig/jobs/installer/installer_data.json +51 -0
- machineconfig/jobs/installer/package_groups.py +6 -5
- machineconfig/profile/create_helper.py +53 -17
- machineconfig/profile/create_links_export.py +8 -5
- machineconfig/profile/mapper.toml +5 -0
- machineconfig/scripts/python/croshell.py +4 -4
- machineconfig/scripts/python/env_manager/path_manager_tui.py +1 -1
- machineconfig/scripts/python/explore.py +49 -0
- machineconfig/scripts/python/helpers_devops/cli_config.py +2 -1
- machineconfig/scripts/python/helpers_devops/cli_nw.py +7 -6
- machineconfig/scripts/python/helpers_devops/cli_repos.py +1 -1
- machineconfig/scripts/python/helpers_devops/cli_self.py +3 -3
- machineconfig/scripts/python/helpers_devops/cli_share_file.py +137 -0
- machineconfig/scripts/python/helpers_devops/cli_share_server.py +62 -166
- machineconfig/scripts/python/helpers_devops/cli_utils.py +26 -30
- machineconfig/scripts/python/helpers_repos/cloud_repo_sync.py +1 -1
- machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +1 -1
- machineconfig/scripts/python/helpers_repos/grource.py +1 -1
- machineconfig/scripts/python/utils.py +3 -1
- machineconfig/scripts/windows/mounts/mount_ssh.ps1 +1 -1
- 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/shells/bash/init.sh +4 -3
- machineconfig/settings/shells/pwsh/init.ps1 +4 -3
- machineconfig/settings/shells/zsh/init.sh +17 -12
- machineconfig/settings/yazi/init.lua +36 -0
- machineconfig/settings/yazi/keymap.toml +79 -0
- machineconfig/settings/yazi/shell/yazi_cd.ps1 +9 -0
- machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
- machineconfig/settings/yazi/yazi.toml +13 -0
- machineconfig/setup_linux/web_shortcuts/interactive.sh +10 -10
- machineconfig/setup_windows/apps.ps1 +2 -2
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +10 -10
- machineconfig/utils/ssh.py +1 -1
- {machineconfig-7.39.dist-info → machineconfig-7.46.dist-info}/METADATA +1 -1
- {machineconfig-7.39.dist-info → machineconfig-7.46.dist-info}/RECORD +44 -38
- {machineconfig-7.39.dist-info → machineconfig-7.46.dist-info}/entry_points.txt +1 -0
- {machineconfig-7.39.dist-info → machineconfig-7.46.dist-info}/WHEEL +0 -0
- {machineconfig-7.39.dist-info → machineconfig-7.46.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
# import platform
|
|
3
|
+
# import sys
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def share_file_receive(code_args: Annotated[list[str], typer.Argument(help="Receive code or relay command. Examples: '7121-donor-olympic-bicycle' or '--relay 10.17.62.206:443 7121-donor-olympic-bicycle'")],
|
|
8
|
+
) -> None:
|
|
9
|
+
"""Receive a file using croc with relay server.
|
|
10
|
+
Usage examples:
|
|
11
|
+
devops network receive 7121-donor-olympic-bicycle
|
|
12
|
+
devops network receive -- --relay 10.17.62.206:443 7121-donor-olympic-bicycle
|
|
13
|
+
devops network receive -- croc --relay 10.17.62.206:443 7121-donor-olympic-bicycle
|
|
14
|
+
"""
|
|
15
|
+
from machineconfig.utils.installer_utils.installer import install_if_missing
|
|
16
|
+
install_if_missing(which="croc")
|
|
17
|
+
import platform
|
|
18
|
+
import sys
|
|
19
|
+
|
|
20
|
+
is_windows = platform.system() == "Windows"
|
|
21
|
+
|
|
22
|
+
# If no args passed via typer, try to get them from sys.argv directly
|
|
23
|
+
# This handles the case where -- was used and arguments weren't parsed by typer
|
|
24
|
+
if not code_args or (len(code_args) == 1 and code_args[0] in ['--relay', 'croc']):
|
|
25
|
+
# Find the index of 'rx' or 'receive' in sys.argv and get everything after it
|
|
26
|
+
try:
|
|
27
|
+
for i, arg in enumerate(sys.argv):
|
|
28
|
+
if arg in ['rx', 'receive', 'r'] and i + 1 < len(sys.argv):
|
|
29
|
+
code_args = sys.argv[i + 1:]
|
|
30
|
+
break
|
|
31
|
+
except Exception:
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
# Join all arguments
|
|
35
|
+
input_str = " ".join(code_args)
|
|
36
|
+
tokens = input_str.split()
|
|
37
|
+
|
|
38
|
+
# Parse input to extract relay server and secret code
|
|
39
|
+
relay_server: str | None = None
|
|
40
|
+
secret_code: str | None = None
|
|
41
|
+
|
|
42
|
+
# Remove 'croc' and 'export' from tokens if present
|
|
43
|
+
tokens = [t for t in tokens if t not in ['croc', 'export']]
|
|
44
|
+
|
|
45
|
+
# Look for --relay flag and capture next token
|
|
46
|
+
relay_idx = -1
|
|
47
|
+
for i, token in enumerate(tokens):
|
|
48
|
+
if token == '--relay' and i + 1 < len(tokens):
|
|
49
|
+
relay_server = tokens[i + 1]
|
|
50
|
+
relay_idx = i
|
|
51
|
+
break
|
|
52
|
+
|
|
53
|
+
# Look for CROC_SECRET= prefix in any token
|
|
54
|
+
for token in tokens:
|
|
55
|
+
if token.startswith('CROC_SECRET='):
|
|
56
|
+
secret_code = token.split('=', 1)[1].strip('"').strip("'")
|
|
57
|
+
break
|
|
58
|
+
|
|
59
|
+
# If no secret code found yet, look for tokens with dashes (typical pattern: number-word-word-word)
|
|
60
|
+
# Skip relay server and relay flag
|
|
61
|
+
if not secret_code:
|
|
62
|
+
for i, token in enumerate(tokens):
|
|
63
|
+
if '-' in token and not token.startswith('-') and token != relay_server:
|
|
64
|
+
if relay_idx >= 0 and (i == relay_idx or i == relay_idx + 1):
|
|
65
|
+
continue # Skip relay server parts
|
|
66
|
+
secret_code = token
|
|
67
|
+
break
|
|
68
|
+
|
|
69
|
+
if not secret_code and not relay_server:
|
|
70
|
+
typer.echo(f"❌ Error: Could not parse croc receive code from input: {input_str}", err=True)
|
|
71
|
+
typer.echo("Usage:", err=True)
|
|
72
|
+
typer.echo(" devops network receive 7121-donor-olympic-bicycle", err=True)
|
|
73
|
+
typer.echo(" devops network receive -- --relay 10.17.62.206:443 7121-donor-olympic-bicycle", err=True)
|
|
74
|
+
raise typer.Exit(code=1)
|
|
75
|
+
|
|
76
|
+
# Build the appropriate script for current OS
|
|
77
|
+
if is_windows:
|
|
78
|
+
# Windows PowerShell format: croc --relay server:port secret-code --yes
|
|
79
|
+
relay_arg = f"--relay {relay_server}" if relay_server else ""
|
|
80
|
+
code_arg = f"{secret_code}" if secret_code else ""
|
|
81
|
+
script = f"""croc {relay_arg} {code_arg} --yes""".strip()
|
|
82
|
+
else:
|
|
83
|
+
# Linux/macOS Bash format: CROC_SECRET="secret-code" croc --relay server:port --yes
|
|
84
|
+
relay_arg = f"--relay {relay_server}" if relay_server else ""
|
|
85
|
+
if secret_code:
|
|
86
|
+
script = f"""export CROC_SECRET="{secret_code}"
|
|
87
|
+
croc {relay_arg} --yes""".strip()
|
|
88
|
+
else:
|
|
89
|
+
script = f"""croc {relay_arg} --yes""".strip()
|
|
90
|
+
|
|
91
|
+
from machineconfig.utils.code import exit_then_run_shell_script, print_code
|
|
92
|
+
print_code(code=script, desc="🚀 Receiving file with croc", lexer="bash" if platform.system() != "Windows" else "powershell")
|
|
93
|
+
exit_then_run_shell_script(script=script, strict=False)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def share_file_send(path: Annotated[str, typer.Argument(help="Path to the file or directory to send")],
|
|
97
|
+
zip_folder: Annotated[bool, typer.Option("--zip", help="Zip folder before sending")] = False,
|
|
98
|
+
code: Annotated[str | None, typer.Option("--code", "-c", help="Codephrase used to connect to relay")] = None,
|
|
99
|
+
text: Annotated[str | None, typer.Option("--text", "-t", help="Send some text")] = None,
|
|
100
|
+
qrcode: Annotated[bool, typer.Option("--qrcode", "--qr", help="Show receive code as a qrcode")] = False,
|
|
101
|
+
) -> None:
|
|
102
|
+
"""Send a file using croc with relay server."""
|
|
103
|
+
from machineconfig.utils.installer_utils.installer import install_if_missing
|
|
104
|
+
install_if_missing(which="croc")
|
|
105
|
+
# Get relay server IP from environment or use default
|
|
106
|
+
import socket
|
|
107
|
+
import platform
|
|
108
|
+
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
109
|
+
s.connect(('8.8.8.8',80))
|
|
110
|
+
local_ip_v4 = s.getsockname()[0]
|
|
111
|
+
s.close()
|
|
112
|
+
relay_port = "443"
|
|
113
|
+
is_windows = platform.system() == "Windows"
|
|
114
|
+
|
|
115
|
+
# Build command parts
|
|
116
|
+
relay_arg = f"--relay {local_ip_v4}:{relay_port} --ip {local_ip_v4}:{relay_port}"
|
|
117
|
+
zip_arg = "--zip" if zip_folder else ""
|
|
118
|
+
text_arg = f"--text '{text}'" if text else ""
|
|
119
|
+
qrcode_arg = "--qrcode" if qrcode else ""
|
|
120
|
+
path_arg = f"{path}" if not text else ""
|
|
121
|
+
|
|
122
|
+
if is_windows:
|
|
123
|
+
# Windows PowerShell format
|
|
124
|
+
code_arg = f"--code {code}" if code else ""
|
|
125
|
+
script = f"""croc {relay_arg} send {zip_arg} {code_arg} {qrcode_arg} {text_arg} {path_arg}"""
|
|
126
|
+
else:
|
|
127
|
+
# Linux/macOS Bash format
|
|
128
|
+
if code:
|
|
129
|
+
script = f"""export CROC_SECRET="{code}"
|
|
130
|
+
croc {relay_arg} send {zip_arg} {qrcode_arg} {text_arg} {path_arg}"""
|
|
131
|
+
else:
|
|
132
|
+
script = f"""croc {relay_arg} send {zip_arg} {qrcode_arg} {text_arg} {path_arg}"""
|
|
133
|
+
|
|
134
|
+
typer.echo(f"🚀 Sending file: {path}. Use: devops network receive")
|
|
135
|
+
from machineconfig.utils.code import exit_then_run_shell_script, print_code
|
|
136
|
+
print_code(code=script, desc="🚀 sending file with croc", lexer="bash" if platform.system() != "Windows" else "powershell")
|
|
137
|
+
exit_then_run_shell_script(script=script, strict=False)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
from typing import Optional, Annotated
|
|
3
|
+
from machineconfig.scripts.python.helpers_devops.cli_share_file import share_file_receive, share_file_send
|
|
3
4
|
import typer
|
|
4
5
|
|
|
5
6
|
|
|
@@ -31,202 +32,97 @@ def display_share_url(local_ip_v4: str, port: int, protocol: str = "http") -> No
|
|
|
31
32
|
console.print(panel)
|
|
32
33
|
|
|
33
34
|
|
|
34
|
-
def
|
|
35
|
+
def web_file_explorer(
|
|
35
36
|
path: Annotated[str, typer.Argument(help="Path to the file or directory to share")],
|
|
36
37
|
port: Annotated[Optional[int], typer.Option("--port", "-p", help="Port to run the share server on (default: 8080)")] = None,
|
|
37
38
|
username: Annotated[Optional[str], typer.Option("--username", "-u", help="Username for share access (default: current user)")] = None,
|
|
38
39
|
password: Annotated[Optional[str], typer.Option("--password", "-w", help="Password for share access (default: from ~/dotfiles/creds/passwords/quick_password)")] = None,
|
|
39
|
-
over_internet: Annotated[bool, typer.Option("--over-internet", "-i", help="Expose the share server over the internet using ngrok")] = False
|
|
40
|
+
over_internet: Annotated[bool, typer.Option("--over-internet", "-i", help="Expose the share server over the internet using ngrok")] = False,
|
|
41
|
+
backend: Annotated[str, typer.Option("--backend", "-b", help="Backend to use: filebrowser (default), miniserve, or easy-sharing")] = "filebrowser"
|
|
40
42
|
) -> None:
|
|
41
43
|
from machineconfig.utils.installer_utils.installer import install_if_missing
|
|
42
|
-
|
|
43
|
-
if
|
|
44
|
+
|
|
45
|
+
if backend not in ["filebrowser", "miniserve", "easy-sharing"]:
|
|
46
|
+
typer.echo(f"❌ ERROR: Invalid backend '{backend}'. Must be one of: filebrowser, miniserve, easy-sharing", err=True)
|
|
47
|
+
raise typer.Exit(code=1)
|
|
48
|
+
|
|
49
|
+
install_if_missing(which=backend)
|
|
50
|
+
if over_internet:
|
|
51
|
+
install_if_missing(which="ngrok")
|
|
52
|
+
|
|
44
53
|
if username is None:
|
|
45
54
|
import getpass
|
|
46
55
|
username = getpass.getuser()
|
|
56
|
+
|
|
47
57
|
if password is None:
|
|
48
58
|
pwd_path = Path.home().joinpath("dotfiles/creds/passwords/quick_password")
|
|
49
59
|
if pwd_path.exists():
|
|
50
60
|
password = pwd_path.read_text(encoding="utf-8").strip()
|
|
51
61
|
else:
|
|
52
|
-
# raise ValueError("Password not provided and default password file does not exist.")
|
|
53
62
|
typer.echo(f"⚠️ WARNING: Password not provided and default password file does not exist.\nPath: {pwd_path}\nUsing default password: 'quick_password' (insecure!)", err=True)
|
|
54
|
-
typer.Exit(code=1)
|
|
63
|
+
raise typer.Exit(code=1)
|
|
55
64
|
|
|
56
65
|
if port is None:
|
|
57
|
-
port = 8080
|
|
66
|
+
port = 8080
|
|
58
67
|
|
|
59
68
|
import socket
|
|
60
69
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
61
|
-
s.connect(('8.8.8.8',80))
|
|
70
|
+
s.connect(('8.8.8.8', 80))
|
|
62
71
|
local_ip_v4 = s.getsockname()[0]
|
|
63
72
|
s.close()
|
|
64
73
|
|
|
65
|
-
# Display the flashy share announcement
|
|
66
74
|
protocol = "http"
|
|
67
75
|
display_share_url(local_ip_v4, port, protocol)
|
|
68
|
-
import subprocess
|
|
69
|
-
import time
|
|
70
|
-
# Build ezshare command
|
|
71
|
-
ezshare_cmd = f"""easy-sharing --port {port} --username {username} --password "{password}" {path}"""
|
|
72
|
-
ezshare_process = subprocess.Popen(ezshare_cmd, shell=True)
|
|
73
|
-
processes = [ezshare_process]
|
|
74
|
-
|
|
75
|
-
if over_internet:
|
|
76
|
-
ngrok_process = subprocess.Popen(f"ngrok http {port}", shell=True)
|
|
77
|
-
processes.append(ngrok_process)
|
|
78
|
-
time.sleep(3)
|
|
79
|
-
try:
|
|
80
|
-
import requests
|
|
81
|
-
response = requests.get("http://localhost:4040/api/tunnels")
|
|
82
|
-
data = response.json()
|
|
83
|
-
public_url = data['tunnels'][0]['public_url']
|
|
84
|
-
print(f"🌐 Ngrok tunnel ready: {public_url}")
|
|
85
|
-
except Exception as e:
|
|
86
|
-
print(f"Could not retrieve ngrok URL: {e}")
|
|
87
76
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
except KeyboardInterrupt:
|
|
93
|
-
print("\nTerminating processes...")
|
|
94
|
-
for p in processes:
|
|
95
|
-
p.terminate()
|
|
96
|
-
p.wait()
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def share_file_send(path: Annotated[str, typer.Argument(help="Path to the file or directory to send")],
|
|
100
|
-
zip_folder: Annotated[bool, typer.Option("--zip", help="Zip folder before sending")] = False,
|
|
101
|
-
code: Annotated[str | None, typer.Option("--code", "-c", help="Codephrase used to connect to relay")] = None,
|
|
102
|
-
text: Annotated[str | None, typer.Option("--text", "-t", help="Send some text")] = None,
|
|
103
|
-
qrcode: Annotated[bool, typer.Option("--qrcode", "--qr", help="Show receive code as a qrcode")] = False,
|
|
104
|
-
) -> None:
|
|
105
|
-
"""Send a file using croc with relay server."""
|
|
106
|
-
from machineconfig.utils.installer_utils.installer import install_if_missing
|
|
107
|
-
install_if_missing(which="croc")
|
|
108
|
-
# Get relay server IP from environment or use default
|
|
109
|
-
import socket
|
|
110
|
-
import platform
|
|
111
|
-
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
112
|
-
s.connect(('8.8.8.8',80))
|
|
113
|
-
local_ip_v4 = s.getsockname()[0]
|
|
114
|
-
s.close()
|
|
115
|
-
relay_port = "443"
|
|
116
|
-
is_windows = platform.system() == "Windows"
|
|
117
|
-
|
|
118
|
-
# Build command parts
|
|
119
|
-
relay_arg = f"--relay {local_ip_v4}:{relay_port} --ip {local_ip_v4}:{relay_port}"
|
|
120
|
-
zip_arg = "--zip" if zip_folder else ""
|
|
121
|
-
text_arg = f"--text '{text}'" if text else ""
|
|
122
|
-
qrcode_arg = "--qrcode" if qrcode else ""
|
|
123
|
-
path_arg = f"{path}" if not text else ""
|
|
124
|
-
|
|
125
|
-
if is_windows:
|
|
126
|
-
# Windows PowerShell format
|
|
127
|
-
code_arg = f"--code {code}" if code else ""
|
|
128
|
-
script = f"""croc {relay_arg} send {zip_arg} {code_arg} {qrcode_arg} {text_arg} {path_arg}"""
|
|
129
|
-
else:
|
|
130
|
-
# Linux/macOS Bash format
|
|
131
|
-
if code:
|
|
132
|
-
script = f"""export CROC_SECRET="{code}"
|
|
133
|
-
croc {relay_arg} send {zip_arg} {qrcode_arg} {text_arg} {path_arg}"""
|
|
134
|
-
else:
|
|
135
|
-
script = f"""croc {relay_arg} send {zip_arg} {qrcode_arg} {text_arg} {path_arg}"""
|
|
77
|
+
path_obj = Path(path).resolve()
|
|
78
|
+
if not path_obj.exists():
|
|
79
|
+
typer.echo(f"❌ ERROR: Path does not exist: {path}", err=True)
|
|
80
|
+
raise typer.Exit(code=1)
|
|
136
81
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
def share_file_receive(code_args: Annotated[list[str], typer.Argument(help="Receive code or relay command. Examples: '7121-donor-olympic-bicycle' or '--relay 10.17.62.206:443 7121-donor-olympic-bicycle'")],
|
|
144
|
-
) -> None:
|
|
145
|
-
"""Receive a file using croc with relay server.
|
|
146
|
-
Usage examples:
|
|
147
|
-
devops network receive 7121-donor-olympic-bicycle
|
|
148
|
-
devops network receive -- --relay 10.17.62.206:443 7121-donor-olympic-bicycle
|
|
149
|
-
devops network receive -- croc --relay 10.17.62.206:443 7121-donor-olympic-bicycle
|
|
82
|
+
if backend == "filebrowser":
|
|
83
|
+
db_path = Path.home().joinpath(".config/filebrowser/filebrowser.db")
|
|
84
|
+
db_path.parent.mkdir(parents=True, exist_ok=True)
|
|
85
|
+
command = f"""
|
|
86
|
+
filebrowser users add {username} "{password}" --database {db_path}
|
|
87
|
+
filebrowser --address 0.0.0.0 --port {port} --root "{path_obj}" --database {db_path}
|
|
150
88
|
"""
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
# If no args passed via typer, try to get them from sys.argv directly
|
|
159
|
-
# This handles the case where -- was used and arguments weren't parsed by typer
|
|
160
|
-
if not code_args or (len(code_args) == 1 and code_args[0] in ['--relay', 'croc']):
|
|
161
|
-
# Find the index of 'rx' or 'receive' in sys.argv and get everything after it
|
|
162
|
-
try:
|
|
163
|
-
for i, arg in enumerate(sys.argv):
|
|
164
|
-
if arg in ['rx', 'receive', 'r'] and i + 1 < len(sys.argv):
|
|
165
|
-
code_args = sys.argv[i + 1:]
|
|
166
|
-
break
|
|
167
|
-
except Exception:
|
|
168
|
-
pass
|
|
169
|
-
|
|
170
|
-
# Join all arguments
|
|
171
|
-
input_str = " ".join(code_args)
|
|
172
|
-
tokens = input_str.split()
|
|
173
|
-
|
|
174
|
-
# Parse input to extract relay server and secret code
|
|
175
|
-
relay_server: str | None = None
|
|
176
|
-
secret_code: str | None = None
|
|
177
|
-
|
|
178
|
-
# Remove 'croc' and 'export' from tokens if present
|
|
179
|
-
tokens = [t for t in tokens if t not in ['croc', 'export']]
|
|
180
|
-
|
|
181
|
-
# Look for --relay flag and capture next token
|
|
182
|
-
relay_idx = -1
|
|
183
|
-
for i, token in enumerate(tokens):
|
|
184
|
-
if token == '--relay' and i + 1 < len(tokens):
|
|
185
|
-
relay_server = tokens[i + 1]
|
|
186
|
-
relay_idx = i
|
|
187
|
-
break
|
|
188
|
-
|
|
189
|
-
# Look for CROC_SECRET= prefix in any token
|
|
190
|
-
for token in tokens:
|
|
191
|
-
if token.startswith('CROC_SECRET='):
|
|
192
|
-
secret_code = token.split('=', 1)[1].strip('"').strip("'")
|
|
193
|
-
break
|
|
194
|
-
|
|
195
|
-
# If no secret code found yet, look for tokens with dashes (typical pattern: number-word-word-word)
|
|
196
|
-
# Skip relay server and relay flag
|
|
197
|
-
if not secret_code:
|
|
198
|
-
for i, token in enumerate(tokens):
|
|
199
|
-
if '-' in token and not token.startswith('-') and token != relay_server:
|
|
200
|
-
if relay_idx >= 0 and (i == relay_idx or i == relay_idx + 1):
|
|
201
|
-
continue # Skip relay server parts
|
|
202
|
-
secret_code = token
|
|
203
|
-
break
|
|
204
|
-
|
|
205
|
-
if not secret_code and not relay_server:
|
|
206
|
-
typer.echo(f"❌ Error: Could not parse croc receive code from input: {input_str}", err=True)
|
|
207
|
-
typer.echo("Usage:", err=True)
|
|
208
|
-
typer.echo(" devops network receive 7121-donor-olympic-bicycle", err=True)
|
|
209
|
-
typer.echo(" devops network receive -- --relay 10.17.62.206:443 7121-donor-olympic-bicycle", err=True)
|
|
89
|
+
elif backend == "miniserve":
|
|
90
|
+
command = f"""miniserve --port {port} --interfaces 0.0.0.0 --auth {username}:{password} --upload-files --mkdir --enable-tar --enable-tar-gz --enable-zip --qrcode "{path_obj}" """
|
|
91
|
+
elif backend == "easy-sharing":
|
|
92
|
+
command = f"""easy-sharing --port {port} --username {username} --password "{password}" "{path_obj}" """
|
|
93
|
+
else:
|
|
94
|
+
typer.echo(f"❌ ERROR: Unknown backend '{backend}'", err=True)
|
|
210
95
|
raise typer.Exit(code=1)
|
|
211
96
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
97
|
+
from machineconfig.utils.code import exit_then_run_shell_script
|
|
98
|
+
exit_then_run_shell_script(script=command, strict=False)
|
|
99
|
+
# import subprocess
|
|
100
|
+
# import time
|
|
101
|
+
# server_process: subprocess.Popen[bytes]
|
|
102
|
+
# server_process = subprocess.Popen(command, shell=True)
|
|
103
|
+
# processes = [server_process]
|
|
104
|
+
# if over_internet:
|
|
105
|
+
# ngrok_process = subprocess.Popen(f"ngrok http {port}", shell=True)
|
|
106
|
+
# processes.append(ngrok_process)
|
|
107
|
+
# time.sleep(3)
|
|
108
|
+
# try:
|
|
109
|
+
# import requests
|
|
110
|
+
# response = requests.get("http://localhost:4040/api/tunnels")
|
|
111
|
+
# data = response.json()
|
|
112
|
+
# public_url = data['tunnels'][0]['public_url']
|
|
113
|
+
# print(f"🌐 Ngrok tunnel ready: {public_url}")
|
|
114
|
+
# except Exception as e:
|
|
115
|
+
# print(f"Could not retrieve ngrok URL: {e}")
|
|
226
116
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
117
|
+
# try:
|
|
118
|
+
# while True:
|
|
119
|
+
# print(f"Share server ({backend}) is running. Press Ctrl+C to stop.")
|
|
120
|
+
# time.sleep(2)
|
|
121
|
+
# except KeyboardInterrupt:
|
|
122
|
+
# print("\nTerminating processes...")
|
|
123
|
+
# for p in processes:
|
|
124
|
+
# p.terminate()
|
|
125
|
+
# p.wait()
|
|
230
126
|
|
|
231
127
|
|
|
232
128
|
def get_share_file_app():
|
|
@@ -238,7 +134,7 @@ def get_share_file_app():
|
|
|
238
134
|
return app
|
|
239
135
|
|
|
240
136
|
def main_with_parser():
|
|
241
|
-
typer.run(
|
|
137
|
+
typer.run(web_file_explorer)
|
|
242
138
|
|
|
243
139
|
|
|
244
140
|
if __name__ == "__main__":
|
|
@@ -4,19 +4,6 @@ import typer
|
|
|
4
4
|
from typing import Annotated, Literal, Optional, TypedDict
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
# def copy(path: Annotated[str, typer.Argument(..., help="Path of the file to copy to clipboard")]):
|
|
9
|
-
# def copy_internal(path: str):
|
|
10
|
-
# import pyperclip
|
|
11
|
-
# from pathlib import Path
|
|
12
|
-
# pyperclip.copy(Path(path).read_text(encoding="utf-8"))
|
|
13
|
-
# from machineconfig.utils.meta import lambda_to_python_script
|
|
14
|
-
# from machineconfig.utils.code import exit_then_run_shell_script, get_uv_command_executing_python_script
|
|
15
|
-
# py_script = lambda_to_python_script(lambda: copy_internal(path=str(path)), in_global=True, import_module=False)
|
|
16
|
-
# shell_script, _python_file = get_uv_command_executing_python_script(python_script=py_script, uv_with=["pyperclip"], uv_project_dir=None)
|
|
17
|
-
# exit_then_run_shell_script(shell_script, strict=True)
|
|
18
|
-
|
|
19
|
-
|
|
20
7
|
def download(
|
|
21
8
|
url: Annotated[Optional[str], typer.Argument(..., help="The URL to download the file from.")] = None,
|
|
22
9
|
decompress: Annotated[bool, typer.Option("--decompress", "-d", help="Decompress the file if it's an archive.")] = False,
|
|
@@ -228,23 +215,32 @@ uv add --group plot \
|
|
|
228
215
|
# Type hints for packages
|
|
229
216
|
types-python-dateutil types-pyyaml types-requests types-tqdm \
|
|
230
217
|
types-mysqlclient types-paramiko types-pytz types-sqlalchemy types-toml types-urllib3 \
|
|
218
|
+
|
|
231
219
|
"""
|
|
232
220
|
from machineconfig.utils.code import run_shell_script
|
|
233
221
|
run_shell_script(script)
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
#
|
|
249
|
-
|
|
250
|
-
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def edit(path: Annotated[Optional[str], typer.Argument(..., help="The root directory of the project to edit, or a file path.")] = None) -> None:
|
|
225
|
+
if path is None:
|
|
226
|
+
root_path = Path.cwd()
|
|
227
|
+
print(f"No path provided. Using current working directory: {root_path}")
|
|
228
|
+
else:
|
|
229
|
+
root_path = Path(path).expanduser().resolve()
|
|
230
|
+
print(f"Using provided path: {root_path}")
|
|
231
|
+
from machineconfig.utils.accessories import get_repo_root
|
|
232
|
+
repo_root = get_repo_root(root_path)
|
|
233
|
+
if repo_root is not None and repo_root.joinpath("pyproject.toml").exists():
|
|
234
|
+
code = f"""
|
|
235
|
+
cd {repo_root}
|
|
236
|
+
uv add --dev pylsp-mypy python-lsp-server[all] pyright ruff-lsp # for helix editor.
|
|
237
|
+
source ./.venv/bin/activate
|
|
238
|
+
"""
|
|
239
|
+
else:
|
|
240
|
+
code = ""
|
|
241
|
+
if root_path.is_file():
|
|
242
|
+
code += f"hx {root_path}"
|
|
243
|
+
else:
|
|
244
|
+
code += "hx"
|
|
245
|
+
from machineconfig.utils.code import exit_then_run_shell_script
|
|
246
|
+
exit_then_run_shell_script(code)
|
|
@@ -99,7 +99,7 @@ git pull originEnc master
|
|
|
99
99
|
uv_project_dir = f"""{str(Path.home().joinpath("code/machineconfig"))}"""
|
|
100
100
|
uv_with = None
|
|
101
101
|
else:
|
|
102
|
-
uv_with = ["machineconfig>=7.
|
|
102
|
+
uv_with = ["machineconfig>=7.46"]
|
|
103
103
|
uv_project_dir = None
|
|
104
104
|
|
|
105
105
|
import tempfile
|
|
@@ -8,7 +8,7 @@ def analyze_repo_development(repo_path: Annotated[str, typer.Argument(..., help=
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
count_lines_path = Path(count_lines.__file__)
|
|
10
10
|
# --project $HOME/code/ machineconfig --group plot
|
|
11
|
-
cmd = f"""uv run --python 3.14 --with "machineconfig[plot]>=7.
|
|
11
|
+
cmd = f"""uv run --python 3.14 --with "machineconfig[plot]>=7.46" {count_lines_path} analyze-over-time {repo_path}"""
|
|
12
12
|
from machineconfig.utils.code import run_shell_script
|
|
13
13
|
run_shell_script(cmd)
|
|
14
14
|
|
|
@@ -100,7 +100,7 @@ def install_gource_windows(version: Optional[str] = None) -> None:
|
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
def visualize(
|
|
103
|
-
repo: Annotated[str, typer.Option("--repo", "-r", help="Path to git repository to visualize")] =
|
|
103
|
+
repo: Annotated[str, typer.Option("--repo", "-r", help="Path to git repository to visualize")] = ".",
|
|
104
104
|
output_file: Annotated[Optional[Path], typer.Option("--output", "-o", help="Output video file (e.g., output.mp4). If specified, gource will render to video.")] = None,
|
|
105
105
|
resolution: Annotated[str, typer.Option("--resolution", "-res", help="Video resolution (e.g., 1920x1080, 1280x720)")] = "1920x1080",
|
|
106
106
|
seconds_per_day: Annotated[float, typer.Option("--seconds-per-day", "-spd", help="Speed of simulation (lower = faster)")] = 0.1,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
from machineconfig.scripts.python.helpers_devops.cli_utils import download, merge_pdfs, get_machine_specs, init_project, compress_pdf
|
|
3
|
+
from machineconfig.scripts.python.helpers_devops.cli_utils import download, merge_pdfs, get_machine_specs, init_project, compress_pdf, edit
|
|
4
4
|
import typer
|
|
5
5
|
from typing import Annotated
|
|
6
6
|
|
|
@@ -39,6 +39,8 @@ def get_app() -> typer.Typer:
|
|
|
39
39
|
app.command(name="g", no_args_is_help=False, hidden=True)(get_machine_specs)
|
|
40
40
|
app.command(name="init-project", no_args_is_help=False, help="[i] Initialize a project with a uv virtual environment and install dev packages.")(init_project)
|
|
41
41
|
app.command(name="i", no_args_is_help=False, hidden=True)(init_project)
|
|
42
|
+
app.command(name="edit", no_args_is_help=False, help="[e] Open a file in the default editor.")(edit)
|
|
43
|
+
app.command(name="e", no_args_is_help=False, hidden=True)(edit)
|
|
42
44
|
|
|
43
45
|
app.command(name="pdf-merge", no_args_is_help=True, help="[pm] Merge two PDF files into one.")(merge_pdfs)
|
|
44
46
|
app.command(name="pm", no_args_is_help=True, hidden=True)(merge_pdfs)
|
|
@@ -7,7 +7,7 @@ $user = ''
|
|
|
7
7
|
$sharePath = ''
|
|
8
8
|
$driveLetter = ''
|
|
9
9
|
|
|
10
|
-
uv run --python 3.14 --with "machineconfig>=7.
|
|
10
|
+
uv run --python 3.14 --with "machineconfig>=7.46" python -m machineconfig.scripts.python.mount_ssh
|
|
11
11
|
|
|
12
12
|
net use T: \\sshfs.kr\$user@$host.local
|
|
13
13
|
# this worked: net use T: \\sshfs\alex@alex-p51s-5.local
|
|
@@ -25,3 +25,19 @@ enable = true
|
|
|
25
25
|
max-wrap = 25 # increase value to reduce forced mid-word wrapping
|
|
26
26
|
max-indent-retain = 0
|
|
27
27
|
wrap-indicator = "" # set wrap-indicator to "" to hide it
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# https://yazi-rs.github.io/docs/tips#helix-with-zellij
|
|
31
|
+
# ~/.config/helix/config.toml
|
|
32
|
+
[keys.normal]
|
|
33
|
+
C-y = ":sh zellij run -n Yazi -c -f -x 10%% -y 10%% --width 80%% --height 80%% -- bash ~/.config/helix/yazi-picker.sh open %{buffer_name}"
|
|
34
|
+
|
|
35
|
+
# ~/.config/helix/config.toml
|
|
36
|
+
|
|
37
|
+
# [keys.normal.C-y]
|
|
38
|
+
# Open the file(s) in the current window
|
|
39
|
+
# y = ":sh zellij run -n Yazi -c -f -x 10%% -y 10%% --width 80%% --height 80%% -- bash ~/.config/helix/yazi-picker.sh open %{buffer_name}"
|
|
40
|
+
# Open the file(s) in a vertical split
|
|
41
|
+
# v = ":sh zellij run -n Yazi -c -f -x 10%% -y 10%% --width 80%% --height 80%% -- bash ~/.config/helix/yazi-picker.sh vsplit %{buffer_name}"
|
|
42
|
+
# Open the file(s) in a horizontal split
|
|
43
|
+
# h = ":sh zellij run -n Yazi -c -f -x 10%% -y 10%% --width 80%% --height 80%% -- bash ~/.config/helix/yazi-picker.sh hsplit %{buffer_name}"
|
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
# adopted from https://github.com/helix-editor/helix/wiki/
|
|
1
|
+
# adopted from https://github.com/helix-editor/helix/wiki/Language-Server-Configurations
|
|
2
2
|
# adopted from https://github.com/helix-editor/helix/discussions/6623
|
|
3
|
-
# You will need:
|
|
3
|
+
# You will need: uv add --dev pylsp-mypy python-lsp-server[all] pyright ruff-lsp
|
|
4
4
|
|
|
5
5
|
[[language]]
|
|
6
6
|
name = "python"
|
|
7
|
-
language-servers = [ "pyright", "ruff" ]
|
|
7
|
+
language-servers = ["pylsp", "pyright", "ruff", "pyrefly"]
|
|
8
|
+
|
|
9
|
+
[language-server.pyrefly]
|
|
10
|
+
command = "pyrefly"
|
|
11
|
+
args = [ "lsp" ]
|
|
12
|
+
|
|
13
|
+
[language-server.pylsp.config.pylsp]
|
|
14
|
+
plugins.pylsp_mypy.enabled = true
|
|
15
|
+
plugins.pylsp_mypy.live_mode = true
|
|
16
|
+
|
|
8
17
|
|
|
9
18
|
[language-server.pyright.config.python.analysis]
|
|
10
|
-
typeCheckingMode = "
|
|
19
|
+
typeCheckingMode = "strict"
|
|
11
20
|
|
|
12
21
|
[language-server.ruff]
|
|
13
22
|
command = "ruff-lsp"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
paths=$(yazi "$2" --chooser-file=/dev/stdout | while read -r; do printf "%q " "$REPLY"; done)
|
|
4
|
+
|
|
5
|
+
if [[ -n "$paths" ]]; then
|
|
6
|
+
zellij action toggle-floating-panes
|
|
7
|
+
zellij action write 27 # send <Escape> key
|
|
8
|
+
zellij action write-chars ":$1 $paths"
|
|
9
|
+
zellij action write 13 # send <Enter> key
|
|
10
|
+
else
|
|
11
|
+
zellij action toggle-floating-panes
|
|
12
|
+
fi
|
|
@@ -20,8 +20,9 @@ case "$file" in
|
|
|
20
20
|
echo "x: $x, y: $y, width: $width, height: $height"
|
|
21
21
|
|
|
22
22
|
if [ -n "$x" ]; then
|
|
23
|
-
echo "📐 Dimensions provided by caller, passing to viu"
|
|
24
|
-
viu "$file" -x "$x" -y "$y" -w "$width" -h "$height"
|
|
23
|
+
# echo "📐 Dimensions provided by caller, passing to viu"
|
|
24
|
+
# viu "$file" -x "$x" -y "$y" -w "$width" -h "$height"
|
|
25
|
+
# chafa --fit-width -f sixel "$file"
|
|
25
26
|
echo "✅ Finished viu"
|
|
26
27
|
chafa "$file"
|
|
27
28
|
echo "✅ Finished chafa"
|