|
38 | 38 | import shutil |
39 | 39 | import json |
40 | 40 | import ast |
| 41 | +import argparse |
41 | 42 | import subprocess |
42 | 43 | import re |
43 | 44 | import threading |
@@ -195,6 +196,69 @@ def parse_startup_file_argument(argv: Optional[List[str]] = None) -> Optional[st |
195 | 196 |
|
196 | 197 | return None |
197 | 198 |
|
| 199 | + |
| 200 | +def parse_cli_args(argv: Optional[List[str]] = None) -> argparse.Namespace: |
| 201 | + """Parse CLI arguments for GUI and headless modes.""" |
| 202 | + parser = argparse.ArgumentParser( |
| 203 | + prog="PythonBox", |
| 204 | + description="Python Code Architect — Editor und Linter", |
| 205 | + add_help=False, |
| 206 | + ) |
| 207 | + parser.add_argument("--open", metavar="DATEI", help="Datei im Editor öffnen") |
| 208 | + parser.add_argument("--lint", metavar="DATEI", help="Datei headless linten (kein GUI)") |
| 209 | + parser.add_argument("file", nargs="?", default=None, help="Datei im Editor öffnen") |
| 210 | + parser.add_argument("-h", "--help", action="help", default=argparse.SUPPRESS, |
| 211 | + help="Diese Hilfe anzeigen") |
| 212 | + |
| 213 | + args = parser.parse_args(sys.argv[1:] if argv is None else argv) |
| 214 | + if args.open is None and args.file: |
| 215 | + args.open = args.file |
| 216 | + return args |
| 217 | + |
| 218 | + |
| 219 | +def run_lint_cli(file_path: str) -> int: |
| 220 | + """Run linter on a file in headless mode and print results to stdout.""" |
| 221 | + path = Path(file_path) |
| 222 | + if not path.is_file(): |
| 223 | + print(f"Fehler: Datei nicht gefunden: {file_path}", file=sys.stderr) |
| 224 | + return 2 |
| 225 | + |
| 226 | + try: |
| 227 | + code = path.read_text(encoding="utf-8") |
| 228 | + except UnicodeDecodeError: |
| 229 | + try: |
| 230 | + code = path.read_text(encoding="latin-1") |
| 231 | + except Exception as exc: |
| 232 | + print(f"Fehler: Datei nicht lesbar: {exc}", file=sys.stderr) |
| 233 | + return 2 |
| 234 | + |
| 235 | + runner = LinterRunner() |
| 236 | + results = runner.run_linter(code, str(path)) |
| 237 | + |
| 238 | + results.sort(key=lambda r: (r.get("line", 0), r.get("column", 0))) |
| 239 | + |
| 240 | + errors = 0 |
| 241 | + warnings = 0 |
| 242 | + for r in results: |
| 243 | + severity = r.get("severity", "warning") |
| 244 | + if severity == "error": |
| 245 | + errors += 1 |
| 246 | + else: |
| 247 | + warnings += 1 |
| 248 | + line = r.get("line", 0) |
| 249 | + col = r.get("column", 0) |
| 250 | + code_id = r.get("code", "?") |
| 251 | + msg = r.get("message", "").strip() |
| 252 | + print(f"{path}:{line}:{col}: {code_id} {msg}") |
| 253 | + |
| 254 | + if results: |
| 255 | + print(f"\n{errors} Fehler, {warnings} Warnungen") |
| 256 | + return 1 |
| 257 | + else: |
| 258 | + print(f"{path}: Keine Findings") |
| 259 | + return 0 |
| 260 | + |
| 261 | + |
198 | 262 | # ============================================================================ |
199 | 263 | # MODERN UI THEME |
200 | 264 | # ============================================================================ |
@@ -4068,20 +4132,25 @@ def run_external_tool(self, path): |
4068 | 4132 | # ============================================================================ |
4069 | 4133 |
|
4070 | 4134 | def main(argv: Optional[List[str]] = None): |
| 4135 | + args = parse_cli_args(argv) |
| 4136 | + |
| 4137 | + if args.lint: |
| 4138 | + sys.exit(run_lint_cli(args.lint)) |
| 4139 | + |
4071 | 4140 | cli_args = list(sys.argv[1:] if argv is None else argv) |
4072 | | - startup_file = parse_startup_file_argument(cli_args) |
| 4141 | + startup_file = args.open |
4073 | 4142 | app = QApplication([sys.argv[0], *cli_args]) |
4074 | 4143 | icon_path = Path(__file__).with_name("PythonBox.ico") |
4075 | 4144 | icon = QIcon(str(icon_path)) if icon_path.exists() else QIcon() |
4076 | 4145 | if not icon.isNull(): |
4077 | 4146 | app.setWindowIcon(icon) |
4078 | 4147 | set_dark_theme(app) |
4079 | | - |
| 4148 | + |
4080 | 4149 | window = PythonArchitect(startup_file=startup_file) |
4081 | 4150 | if not icon.isNull(): |
4082 | 4151 | window.setWindowIcon(icon) |
4083 | 4152 | window.show() |
4084 | | - |
| 4153 | + |
4085 | 4154 | sys.exit(app.exec()) |
4086 | 4155 |
|
4087 | 4156 |
|
|
0 commit comments