|
| 1 | +import contextlib |
| 2 | +import errno |
| 3 | +import os |
| 4 | +import sys |
| 5 | +from pathlib import Path |
| 6 | + |
| 7 | +import typer |
| 8 | + |
| 9 | + |
| 10 | +def list_available_commands(prefix: str = "minimal-pba-cli-") -> list[tuple[str, str]]: |
| 11 | + """List all commands available on the PATH that match an optional prefix.""" |
| 12 | + commands = [] |
| 13 | + |
| 14 | + for path_str in os.getenv("PATH", "").split(os.pathsep): |
| 15 | + path = Path(path_str) |
| 16 | + |
| 17 | + with contextlib.suppress(PermissionError): |
| 18 | + if path.is_dir(): |
| 19 | + for file in path.iterdir(): |
| 20 | + if file.is_dir(): |
| 21 | + continue |
| 22 | + |
| 23 | + if os.access(file, os.X_OK) and file.name.startswith(prefix): |
| 24 | + commands.append((file.name, str(file))) |
| 25 | + return sorted(set(commands)) |
| 26 | + |
| 27 | + |
| 28 | +def create_command_wrapper(cli: typer.Typer, command: str, full_path: str): |
| 29 | + cli_command_name = command.replace("minimal-pba-cli-", "") |
| 30 | + |
| 31 | + def typer_wrapper_command(): |
| 32 | + commands = [command, *sys.argv[2:]] |
| 33 | + command_string = " ".join(commands) |
| 34 | + display = typer.style(command_string, fg=typer.colors.CYAN, bold=True) |
| 35 | + typer.echo(f"Running {display}", err=True) |
| 36 | + |
| 37 | + try: |
| 38 | + os.execlp(command, *commands) |
| 39 | + except OSError as e: |
| 40 | + if e.errno == errno.ENOEXEC: |
| 41 | + typer.secho(f"Command {command} found, but does not specify a handler. Try adding a shebang line to the file.", fg=typer.colors.RED, err=True) |
| 42 | + |
| 43 | + typer_wrapper_command.__doc__ = f"({full_path}): Custom command with unknown options. Try `pba-cli {cli_command_name} -- --help` for more information." |
| 44 | + |
| 45 | + cli.command( |
| 46 | + name=cli_command_name, |
| 47 | + context_settings={"ignore_unknown_options": True, "allow_extra_args": True}, |
| 48 | + )(typer_wrapper_command) |
0 commit comments