Interactive REPL with command history and tab completion.
(api: SerialStudioAPI, args)
| 958 | |
| 959 | |
| 960 | def cmd_interactive(api: SerialStudioAPI, args) -> int: |
| 961 | """Interactive REPL with command history and tab completion.""" |
| 962 | history_file = os.path.expanduser("~/.serial_studio_api_history") |
| 963 | available_commands: list[str] = [] |
| 964 | |
| 965 | if READLINE_AVAILABLE: |
| 966 | try: |
| 967 | readline.read_history_file(history_file) |
| 968 | except FileNotFoundError: |
| 969 | pass |
| 970 | readline.set_history_length(1000) |
| 971 | |
| 972 | response = api.send_command("api.getCommands") |
| 973 | if response and response.get("success"): |
| 974 | available_commands = [ |
| 975 | c.get("name", "") |
| 976 | for c in response.get("result", {}).get("commands", []) |
| 977 | ] |
| 978 | |
| 979 | def completer(text, state): |
| 980 | options = [c for c in available_commands if c.startswith(text)] |
| 981 | return options[state] if state < len(options) else None |
| 982 | |
| 983 | readline.parse_and_bind("tab: complete") |
| 984 | readline.set_completer(completer) |
| 985 | |
| 986 | print(bold("\n==========================================================")) |
| 987 | print(bold(" Serial Studio Interactive Mode (REPL)")) |
| 988 | print(bold("==========================================================\n")) |
| 989 | |
| 990 | print(dim("Features:")) |
| 991 | if READLINE_AVAILABLE: |
| 992 | print(dim(f" - {success(chr(10003))} Command history (up/down arrows)")) |
| 993 | print( |
| 994 | dim( |
| 995 | f" - {success(chr(10003))} Tab completion ({len(available_commands)} commands)" |
| 996 | ) |
| 997 | ) |
| 998 | else: |
| 999 | print(dim(f" - {warning('!')} Install 'readline' for history & completion")) |
| 1000 | print(dim(f" - Type {bold('help')} for built-in commands")) |
| 1001 | print(dim(f" - Type {bold('list')} to see all API commands")) |
| 1002 | print(dim(f" - Type {bold('quit')} to exit\n")) |
| 1003 | |
| 1004 | while True: |
| 1005 | try: |
| 1006 | line = input(info("ss> ")).strip() |
| 1007 | except (EOFError, KeyboardInterrupt): |
| 1008 | print("\n" + dim("Goodbye!")) |
| 1009 | break |
| 1010 | |
| 1011 | if not line: |
| 1012 | continue |
| 1013 | |
| 1014 | if line.lower() in ("quit", "exit", "q"): |
| 1015 | print(dim("Goodbye!")) |
| 1016 | break |
| 1017 |
no test coverage detected