freya_terminal/
lib.rs

1//! # Freya Terminal 🖥️
2//!
3//! Terminal emulator integration for Freya applications.
4//!
5//! This crate provides a way to embed interactive terminal emulators in your Freya applications.
6//! It uses PTY (pseudo-terminal) to spawn shell processes and renders VT100-compatible terminal output
7//! with full 256-color support.
8//!
9//! ## Features
10//!
11//! - **PTY Integration**: Spawn and interact with shell processes
12//! - **VT100 Rendering**: Full terminal emulation with cursor, colors, and text attributes
13//! - **256-Color Support**: ANSI 16 colors, 6x6x6 RGB cube, and 24-level grayscale
14//! - **Keyboard Input**: Handle all standard terminal key sequences
15//! - **Auto-resize**: Terminal automatically resizes based on available space
16//!
17//! ## Basic Usage
18//!
19//! ```rust,no_run
20//! use freya::prelude::*;
21//! use freya_terminal::prelude::*;
22//!
23//! fn main() {
24//!     launch(LaunchConfig::new().with_window(WindowConfig::new(app)))
25//! }
26//!
27//! fn app() -> impl IntoElement {
28//!     let mut handle = use_state(|| {
29//!         let mut cmd = CommandBuilder::new("bash");
30//!         cmd.env("TERM", "xterm-256color");
31//!         TerminalHandle::new(TerminalId::new(), cmd, None).ok()
32//!     });
33//!
34//!     let focus = use_focus();
35//!
36//!     rect().expanded().background((30, 30, 30)).child(
37//!         if let Some(handle) = handle.read().clone() {
38//!             rect()
39//!                 .child(
40//!                     Terminal::new(handle.clone())
41//!                         .a11y_id(focus.a11y_id())
42//!                         .on_mouse_down(move |_| focus.request_focus())
43//!                         .on_key_down(move |e: Event<KeyboardEventData>| {
44//!                             if let Some(ch) = e.try_as_str() {
45//!                                 let _ = handle.write(ch.as_bytes());
46//!                             } else {
47//!                                 let _ = handle.write(match &e.key {
48//!                                     Key::Named(NamedKey::Enter) => b"\n",
49//!                                     Key::Named(NamedKey::Backspace) => &[0x7f],
50//!                                     Key::Named(NamedKey::Tab) => b"\t",
51//!                                     Key::Named(NamedKey::ArrowUp) => b"\x1b[A",
52//!                                     Key::Named(NamedKey::ArrowDown) => b"\x1b[B",
53//!                                     Key::Named(NamedKey::ArrowLeft) => b"\x1b[D",
54//!                                     Key::Named(NamedKey::ArrowRight) => b"\x1b[C",
55//!                                     _ => return,
56//!                                 });
57//!                             }
58//!                         }),
59//!                 )
60//!                 .expanded()
61//!                 .into_element()
62//!         } else {
63//!             "Failed to start Terminal.".into_element()
64//!         },
65//!     )
66//! }
67//! ```
68//!
69//! ## Handling Terminal Exit
70//!
71//! You can detect when the terminal/PTY closes using `TerminalHandle::closed`:
72//!
73//! ```rust,ignore
74//! use_future(move || async move {
75//!     terminal_handle.closed().await;
76//!     // Terminal has exited, update UI state
77//! });
78//! ```
79//!
80//! ## Advance usage
81//!
82//! Check the `feature_terminal.rs` example in the repository.
83pub mod buffer;
84pub mod colors;
85pub mod element;
86pub mod handle;
87pub mod parser;
88pub mod pty;
89
90/// Prelude module for convenient imports.
91pub mod prelude {
92    pub use portable_pty::CommandBuilder;
93
94    pub use crate::{
95        buffer::{
96            TerminalBuffer,
97            TerminalSelection,
98        },
99        element::Terminal,
100        handle::{
101            TerminalError,
102            TerminalHandle,
103            TerminalId,
104        },
105        parser::TerminalMouseButton,
106    };
107}