// demos_terminal.cpp — demos del modulo terminal_panel (issue 0132). // // Demo 1: One-shot — spawn bash que ejecuta "echo hello; date; ls /tmp | head" // con auto-close cuando el proceso termina. Muestra el scrollback. // Demo 2: Interactivo — bash -i (Linux) / cmd.exe (Windows) con input box. // Demo 3: Readonly — tail simulado de un archivo de log. #include "demos.h" #include "demo.h" #include "viz/terminal_panel/terminal_panel.h" #include "imgui.h" #include #include namespace gallery { // --------------------------------------------------------------------------- // Demo 1: One-shot con auto-close // --------------------------------------------------------------------------- void demo_terminal_oneshot() { demo_header("terminal_panel", "v1.0.0", "Emulador TTY embebible. Demo 1: one-shot — spawn bash, ejecuta comandos, auto-close."); static fn_term::TerminalPanel s_term; static bool s_started = false; if (!s_started) { ImGui::TextUnformatted("Pulsa 'Run' para lanzar el one-shot."); if (ImGui::Button("Run")) { if (!s_term.is_open()) { s_term.shell = "/bin/bash"; s_term.scrollback_lines = 200; s_term.readonly = true; // solo output, sin input fn_term::open(s_term); fn_term::send(s_term, "echo hello; date; ls /tmp | head -5; exit 0\n"); s_started = true; } } return; } fn_term::render(s_term); if (s_term.process_exited.load() && s_term.is_open()) { ImGui::SameLine(); ImGui::TextDisabled("[done — exit %d]", s_term.exit_code); } if (ImGui::Button("Reset demo")) { if (s_term.is_open()) fn_term::close(s_term); s_started = false; } code_block( "fn_term::TerminalPanel term;\n" "term.shell = \"/bin/bash\";\n" "term.readonly = true;\n" "fn_term::open(term);\n" "fn_term::send(term, \"echo hello; date; exit 0\\n\");\n" "// En cada frame ImGui:\n" "fn_term::render(term);\n" "if (term.process_exited.load()) fn_term::close(term);" ); } // --------------------------------------------------------------------------- // Demo 2: Interactivo // --------------------------------------------------------------------------- void demo_terminal_interactive() { demo_header("terminal_panel", "v1.0.0", "Demo 2: terminal interactivo — bash -i (Linux) / cmd.exe (Windows)."); static fn_term::TerminalPanel s_term; if (!s_term.is_open()) { if (ImGui::Button("Open shell")) { #ifdef _WIN32 s_term.shell = "cmd.exe"; #else s_term.shell = "/bin/bash"; #endif s_term.scrollback_lines = 1000; s_term.readonly = false; fn_term::open(s_term); } return; } fn_term::render(s_term); if (ImGui::Button("Close shell")) { fn_term::close(s_term); } } // --------------------------------------------------------------------------- // Demo 3: Readonly tail // --------------------------------------------------------------------------- void demo_terminal_readonly() { demo_header("terminal_panel", "v1.0.0", "Demo 3: readonly — tail de /tmp/fn_gallery_test.log (creado al abrir)."); static fn_term::TerminalPanel s_term; static bool s_log_created = false; // Crear el archivo de log de prueba si no existe. if (!s_log_created) { if (ImGui::Button("Start tail")) { // Escribir unas líneas de muestra al log. FILE* f = fopen("/tmp/fn_gallery_test.log", "w"); if (f) { for (int i = 0; i < 5; i++) fprintf(f, "[sample] log line %d\n", i); fclose(f); } s_term.shell = "/bin/bash"; s_term.readonly = true; s_term.scrollback_lines = 500; fn_term::open(s_term); fn_term::send(s_term, "tail -f /tmp/fn_gallery_test.log\n"); s_log_created = true; } return; } fn_term::render(s_term); ImGui::Separator(); if (ImGui::Button("Append line")) { FILE* f = fopen("/tmp/fn_gallery_test.log", "a"); if (f) { static int s_count = 0; fprintf(f, "[appended] line %d\n", s_count++); fclose(f); } } ImGui::SameLine(); if (ImGui::Button("Stop")) { if (s_term.is_open()) fn_term::close(s_term); s_log_created = false; } code_block( "fn_term::TerminalPanel term;\n" "term.shell = \"/bin/bash\";\n" "term.readonly = true; // sin input box\n" "fn_term::open(term);\n" "fn_term::send(term, \"tail -f /tmp/agent.log\\n\");\n" "// En cada frame:\n" "fn_term::render(term);" ); } // --------------------------------------------------------------------------- // Entry point unificado (llamado desde main.cpp via demos.h) // --------------------------------------------------------------------------- void demo_terminal() { static int s_tab = 0; if (ImGui::BeginTabBar("##term_tabs")) { if (ImGui::BeginTabItem("One-shot")) { s_tab = 0; ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Interactive")) { s_tab = 1; ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Readonly tail")) { s_tab = 2; ImGui::EndTabItem(); } ImGui::EndTabBar(); } switch (s_tab) { case 0: demo_terminal_oneshot(); break; case 1: demo_terminal_interactive(); break; case 2: demo_terminal_readonly(); break; } } } // namespace gallery