Created
November 3, 2025 06:25
-
-
Save Ismael-VC/e860e94d885bc25e3f300ea649d2dfa8 to your computer and use it in GitHub Desktop.
Reflector
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python | |
| import sys | |
| from code import InteractiveConsole | |
| from io import StringIO | |
| from rich.syntax import Syntax | |
| from textual.app import App, ComposeResult, RenderResult | |
| from textual.containers import Container, Horizontal | |
| from textual.widget import Widget | |
| from textual.widgets import Footer, Header, RichLog, TextArea | |
| class Reflector(Widget): | |
| CSS = """ | |
| #input { | |
| padding: 1 2 1 2; | |
| border: none; | |
| } | |
| #output { | |
| padding: 1 2 1 2; | |
| } | |
| #input-container { | |
| border: solid; | |
| height: 0.4fr; | |
| margin: 0 2 1 2; | |
| } | |
| #output-container { | |
| border: solid; | |
| margin: 1 2 1 2; | |
| height: 0.6fr; | |
| } | |
| """ | |
| BINDINGS = [ | |
| ("ctrl+enter,ctrl+r", "eval", "eval"), | |
| ("ctrl+n", "dir", "namespace"), | |
| ("ctrl+l", "clear_output", "clear"), | |
| ("ctrl+u", "clear_input", "clear input"), | |
| ] | |
| def render(self) -> RenderResult: | |
| self.header = Header(id="header", icon="🐍") | |
| self.input = TextArea.code_editor(id="input", language="python") | |
| self.input_container = Container( | |
| self.input, id="input-container", placeholder="^⏎ to evaluate" | |
| ) | |
| self.output = RichLog(id="output", markup=True, highlight=True) | |
| self.output_container = Container(self.output, id="output-container") | |
| self.footer = Footer(id="footer") | |
| yield self.header | |
| yield self.output_container | |
| yield self.input_container | |
| yield self.footer | |
| def on_mount(self) -> None: | |
| self.title = "Reflector" | |
| self.sub_title = self.app.title | |
| self.footer.show_command_palette = False | |
| self.input_container.border_title = "Input" | |
| self.output_container.border_title = "Output" | |
| self.namespace = {"app": self, "__builtins__": __builtins__} | |
| self.repl = InteractiveConsole(locals=self.namespace) | |
| self.input.focus() | |
| def action_dir(self) -> None: | |
| self.action_eval("dir()") | |
| def action_clear_output(self) -> None: | |
| self.output.clear() | |
| def action_clear_input(self) -> None: | |
| self.input.text = "" | |
| def action_eval(self, code="") -> None: | |
| if not code: | |
| code = self.input.text | |
| if not code: | |
| return | |
| split_code = code.split("\n") | |
| self.output.write(Syntax(f">>> {split_code[0]}", "python", indent_guides=True)) | |
| if len(split_code) > 1: | |
| for line in split_code[1:]: | |
| self.output.write(Syntax(f"... {line}", "python", indent_guides=True)) | |
| self.output.write(Syntax("... ", "python", indent_guides=True)) | |
| old_stdout, old_stderr = sys.stdout, sys.stderr | |
| sys.stdout, sys.stderr = StringIO(), StringIO() | |
| self.repl.push(code + "\n") | |
| captured_output = sys.stdout.getvalue().strip() | |
| captured_error = sys.stderr.getvalue().strip() | |
| if captured_output: | |
| self.output.write(Syntax(captured_output, "python", indent_guides=True)) | |
| if captured_error: | |
| self.output.write(Syntax(captured_error, "python", indent_guides=True)) | |
| sys.stdout, sys.stderr = old_stdout, old_stderr | |
| self.input.text = "" | |
| self.input.focus() | |
| class TerminalApp(App): | |
| def compose(self): | |
| yield Reflector() | |
| if __name__ == "__main__": | |
| app = TerminalApp() | |
| app.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment