|
8 | 8 | from typing import Optional |
9 | 9 |
|
10 | 10 | import typer |
11 | | -from prompt_toolkit import PromptSession |
12 | | -from prompt_toolkit.auto_suggest import AutoSuggestFromHistory |
13 | | -from prompt_toolkit.completion import Completer, Completion |
14 | | -from prompt_toolkit.history import FileHistory |
15 | | -from prompt_toolkit.styles import Style |
16 | 11 | from rich.console import Console |
17 | 12 | from rich.panel import Panel |
18 | 13 | from rich.table import Table |
@@ -334,87 +329,28 @@ def editor_command(file: Optional[str] = None) -> bool: |
334 | 329 | return False |
335 | 330 |
|
336 | 331 | def run_repl(verbose: bool) -> bool: |
337 | | - history = FileHistory(str(HISTORY_FILE)) |
338 | | - session = PromptSession(history=history, auto_suggest=AutoSuggestFromHistory(), style=Style.from_dict({ |
339 | | - 'prompt': prompt_style, |
340 | | - })) |
341 | | - lines = [] |
342 | | - in_config = False |
343 | | - output_lines = [ |
344 | | - Text(f"Hacker Lang REPL v{VERSION} - Enhanced Interactive Mode", style=success_style), |
345 | | - Text("Type 'exit' to quit, 'help' for commands, 'clear' to reset", style=info_style), |
346 | | - Text("Supported: //deps, #libs, @vars, =loops, ?ifs, &bg, >cmds, [config], !comments", style=info_style) |
347 | | - ] |
348 | | - while True: |
349 | | - try: |
350 | | - prompt = "CONFIG> " if in_config else "hacker> " |
351 | | - line = session.prompt(Text(prompt, style=prompt_style)) |
352 | | - if not line.strip(): |
353 | | - continue |
354 | | - if line == "exit": |
355 | | - break |
356 | | - if line == "help": |
357 | | - output_lines.append(Text("REPL Commands:\n- exit: Quit REPL\n- help: This menu\n- clear: Reset session\n- verbose: Toggle verbose", style=header_style)) |
358 | | - elif line == "clear": |
359 | | - lines = [] |
360 | | - in_config = False |
361 | | - output_lines.append(Text("Session cleared!", style=success_style)) |
362 | | - elif line == "verbose": |
363 | | - verbose = not verbose |
364 | | - output_lines.append(Text(f"Verbose mode: {verbose}", style=info_style)) |
365 | | - else: |
366 | | - if line == "[": |
367 | | - in_config = True |
368 | | - elif line == "]": |
369 | | - if not in_config: |
370 | | - output_lines.append(Text("Error: Unmatched ']'", style=error_style)) |
371 | | - in_config = False |
372 | | - lines.append(line) |
373 | | - if not in_config and line and not line.startswith("!"): |
374 | | - parsed = parse_lines(lines, verbose) |
375 | | - if parsed["errors"]: |
376 | | - output_lines.append(Text("REPL Errors:\n" + "\n".join(parsed["errors"]), style=error_style)) |
377 | | - else: |
378 | | - if parsed["libs"]: |
379 | | - output_lines.append(Text(f"Warning: Missing custom libs: {', '.join(parsed['libs'])}", style=warning_style)) |
380 | | - with tempfile.NamedTemporaryFile(mode="w+", suffix=".sh", delete=False) as temp_sh: |
381 | | - temp_sh.write("#!/bin/bash\nset -e\n") |
382 | | - for k, v in parsed["vars"].items(): |
383 | | - temp_sh.write(f'export {k}="{v}"\n') |
384 | | - for dep in parsed["deps"]: |
385 | | - if dep != "sudo": |
386 | | - temp_sh.write(f'command -v {dep} || (sudo apt update && sudo apt install -y {dep})\n') |
387 | | - for inc in parsed["includes"]: |
388 | | - lib_path = LIBS_DIR / inc / "main.hacker" |
389 | | - with open(lib_path, "r") as lib_f: |
390 | | - temp_sh.write(f"# include {inc}\n") |
391 | | - temp_sh.write(lib_f.read()) |
392 | | - temp_sh.write("\n") |
393 | | - for cmd in parsed["cmds"]: |
394 | | - temp_sh.write(f"{cmd}\n") |
395 | | - for bin in parsed["binaries"]: |
396 | | - temp_sh.write(f"{bin}\n") |
397 | | - for plugin in parsed["plugins"]: |
398 | | - temp_sh.write(f"{plugin} &\n") |
399 | | - temp_path = temp_sh.name |
400 | | - os.chmod(temp_path, 0o755) |
401 | | - env = os.environ.copy() |
402 | | - env.update(parsed["vars"]) |
403 | | - result = subprocess.run(["bash", temp_path], env=env, capture_output=True, text=True) |
404 | | - os.remove(temp_path) |
405 | | - out_str = result.stdout + result.stderr |
406 | | - if result.returncode != 0: |
407 | | - output_lines.append(Text("REPL Error:\n" + out_str.strip(), style=error_style)) |
408 | | - elif out_str.strip(): |
409 | | - output_lines.append(Text("REPL Output:\n" + out_str.strip(), style=success_style)) |
410 | | - for out in output_lines: |
411 | | - console.print(out) |
412 | | - output_lines = [] # Clear after print? No, accumulate like viewport |
413 | | - # To simulate viewport, perhaps print all each time, but for simplicity, print incrementally |
414 | | - except KeyboardInterrupt: |
415 | | - break |
416 | | - console.print(Text("REPL session ended.", style=success_style)) |
417 | | - return True |
| 332 | + repl_path = BIN_DIR / "hackerc" / "repl" |
| 333 | + args = [str(repl_path)] |
| 334 | + if verbose: |
| 335 | + args.append("--verbose") |
| 336 | + console.print(Text("Launching REPL...", style=info_style)) |
| 337 | + try: |
| 338 | + result = subprocess.run(args, check=True) |
| 339 | + console.print(Text("REPL session ended.", style=success_style)) |
| 340 | + return result.returncode == 0 |
| 341 | + except Exception as e: |
| 342 | + console.print(Text(f"REPL failed: {e}", style=error_style)) |
| 343 | + return False |
| 344 | + |
| 345 | +def run_help_ui() -> bool: |
| 346 | + help_ui_path = BIN_DIR / "hackerc" / "help-ui" |
| 347 | + console.print(Text("Launching Help UI...", style=info_style)) |
| 348 | + try: |
| 349 | + result = subprocess.run([str(help_ui_path)], check=True) |
| 350 | + return result.returncode == 0 |
| 351 | + except Exception as e: |
| 352 | + console.print(Text(f"Help UI failed: {e}", style=error_style)) |
| 353 | + return False |
418 | 354 |
|
419 | 355 | def version_command() -> bool: |
420 | 356 | console.print(Text(f"Hacker Lang v{VERSION}", style=info_style)) |
@@ -543,13 +479,17 @@ def version(): |
543 | 479 | success = version_command() |
544 | 480 | raise typer.Exit(code=0 if success else 1) |
545 | 481 |
|
546 | | -@app.command() |
547 | | -def help_cmd(): # Renamed to avoid conflict with help |
| 482 | +@app.command(name="help") |
| 483 | +def help_cmd(): |
548 | 484 | ensure_hacker_dir() |
549 | 485 | success = help_command(True) |
550 | 486 | raise typer.Exit(code=0 if success else 1) |
551 | 487 |
|
552 | | -# TODO: help-ui if needed |
| 488 | +@app.command(name="help-ui") |
| 489 | +def help_ui(): |
| 490 | + ensure_hacker_dir() |
| 491 | + success = run_help_ui() |
| 492 | + raise typer.Exit(code=0 if success else 1) |
553 | 493 |
|
554 | 494 | if __name__ == "__main__": |
555 | 495 | ensure_hacker_dir() |
|
0 commit comments