#[non_exhaustive]pub struct PseudoTerminal<'a, S> { /* private fields */ }Expand description
A widget representing a pseudo-terminal screen.
The PseudoTerminal widget displays the contents of a pseudo-terminal screen,
which is typically populated with text and control sequences from a terminal emulator.
It provides a visual representation of the terminal output within a TUI application.
The contents of the pseudo-terminal screen are represented by a vt100::Screen object.
The vt100 library provides functionality for parsing and processing terminal control sequences
and handling terminal state, allowing the PseudoTerminal widget to accurately render the
terminal output.
§Examples
use ratatui_core::style::{Color, Modifier, Style};
use ratatui_widgets::{block::Block, borders::Borders};
use tui_term::widget::PseudoTerminal;
use vt100::Parser;
let mut parser = vt100::Parser::new(24, 80, 0);
let pseudo_term = PseudoTerminal::new(parser.screen())
.block(Block::default().title("Terminal").borders(Borders::ALL))
.style(
Style::default()
.fg(Color::White)
.bg(Color::Black)
.add_modifier(Modifier::BOLD),
);Implementations§
Source§impl<'a, S: Screen> PseudoTerminal<'a, S>
impl<'a, S: Screen> PseudoTerminal<'a, S>
Sourcepub fn new(screen: &'a S) -> Self
pub fn new(screen: &'a S) -> Self
Creates a new instance of PseudoTerminal.
§Arguments
screen: The reference to theScreen.
§Example
use tui_term::widget::PseudoTerminal;
use vt100::Parser;
let mut parser = vt100::Parser::new(24, 80, 0);
let pseudo_term = PseudoTerminal::new(parser.screen());Examples found in repository?
177fn ui(f: &mut Frame, screen: &Screen) {
178 let chunks = ratatui::layout::Layout::default()
179 .direction(ratatui::layout::Direction::Vertical)
180 .margin(1)
181 .constraints(
182 [
183 ratatui::layout::Constraint::Percentage(100),
184 ratatui::layout::Constraint::Min(1),
185 ]
186 .as_ref(),
187 )
188 .split(f.area());
189 let block = Block::default()
190 .borders(Borders::ALL)
191 .style(Style::default().add_modifier(Modifier::BOLD));
192 let pseudo_term = PseudoTerminal::new(screen).block(block);
193 f.render_widget(pseudo_term, chunks[0]);
194 let explanation = "Press q to exit".to_string();
195 let explanation = Paragraph::new(explanation)
196 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
197 .alignment(Alignment::Center);
198 f.render_widget(explanation, chunks[1]);
199}More examples
180fn ui(f: &mut Frame, screen: &Screen) {
181 let chunks = ratatui::layout::Layout::default()
182 .direction(ratatui::layout::Direction::Vertical)
183 .margin(1)
184 .constraints(
185 [
186 ratatui::layout::Constraint::Percentage(100),
187 ratatui::layout::Constraint::Min(1),
188 ]
189 .as_ref(),
190 )
191 .split(f.area());
192 let block = Block::default()
193 .borders(Borders::ALL)
194 .style(Style::default().add_modifier(Modifier::BOLD));
195 let pseudo_term = PseudoTerminal::new(screen).block(block);
196 f.render_widget(pseudo_term, chunks[0]);
197 let explanation = "Press q to exit".to_string();
198 let explanation = Paragraph::new(explanation)
199 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
200 .alignment(Alignment::Center);
201 f.render_widget(explanation, chunks[1]);
202}60fn ui(f: &mut Frame, screen: &Screen) {
61 let chunks = ratatui::layout::Layout::default()
62 .direction(ratatui::layout::Direction::Vertical)
63 .margin(1)
64 .constraints(
65 [
66 ratatui::layout::Constraint::Percentage(100),
67 ratatui::layout::Constraint::Min(1),
68 ]
69 .as_ref(),
70 )
71 .split(f.area());
72 let title = Line::from("[ Running: ls ]");
73 let block = Block::default()
74 .borders(Borders::ALL)
75 .title(title)
76 .style(Style::default().add_modifier(Modifier::BOLD));
77 let pseudo_term = PseudoTerminal::new(screen)
78 .cursor(tui_term::widget::Cursor::default().visibility(false))
79 .block(block.clone());
80 f.render_widget(pseudo_term, chunks[0]);
81 let explanation = "Press q to exit";
82 let explanation = Paragraph::new(explanation)
83 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
84 .alignment(Alignment::Center);
85 f.render_widget(explanation, chunks[1]);
86}102fn ui(f: &mut Frame, screen: &Screen) {
103 let chunks = ratatui::layout::Layout::default()
104 .direction(ratatui::layout::Direction::Vertical)
105 .margin(1)
106 .constraints(
107 [
108 ratatui::layout::Constraint::Percentage(0),
109 ratatui::layout::Constraint::Percentage(100),
110 ratatui::layout::Constraint::Min(1),
111 ]
112 .as_ref(),
113 )
114 .split(f.area());
115 let title = Line::from("[ Running: top ]");
116 let block = Block::default()
117 .borders(Borders::ALL)
118 .title(title)
119 .style(Style::default().add_modifier(Modifier::BOLD));
120 let pseudo_term = PseudoTerminal::new(screen).block(block);
121 f.render_widget(pseudo_term, chunks[1]);
122 let block = Block::default().borders(Borders::ALL);
123 f.render_widget(block, f.area());
124 let explanation = "Press q to exit".to_string();
125 let explanation = Paragraph::new(explanation)
126 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
127 .alignment(Alignment::Center);
128 f.render_widget(explanation, chunks[2]);
129}86fn ui(f: &mut Frame, screen: &Screen) {
87 let chunks = ratatui::layout::Layout::default()
88 .direction(ratatui::layout::Direction::Vertical)
89 .margin(1)
90 .constraints(
91 [
92 ratatui::layout::Constraint::Percentage(50),
93 ratatui::layout::Constraint::Percentage(50),
94 ratatui::layout::Constraint::Min(1),
95 ]
96 .as_ref(),
97 )
98 .split(f.area());
99 let title = Line::from("[ Running: ls ]");
100 let block = Block::default()
101 .borders(Borders::ALL)
102 .title(title)
103 .style(Style::default().add_modifier(Modifier::BOLD));
104 let pseudo_term = PseudoTerminal::new(screen).block(block.clone());
105 f.render_widget(pseudo_term, chunks[0]);
106 let pseudo_term = PseudoTerminal::new(screen).block(block);
107 f.render_widget(pseudo_term, chunks[1]);
108 let block = Block::default().borders(Borders::ALL);
109 f.render_widget(block, f.area());
110 let explanation = "Press q to exit";
111 let explanation = Paragraph::new(explanation)
112 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
113 .alignment(Alignment::Center);
114 f.render_widget(explanation, chunks[2]);
115}95fn ui(f: &mut Frame, screen: &Screen) {
96 let chunks = ratatui::layout::Layout::default()
97 .direction(ratatui::layout::Direction::Vertical)
98 .margin(1)
99 .constraints(
100 [
101 ratatui::layout::Constraint::Percentage(50),
102 ratatui::layout::Constraint::Percentage(50),
103 ratatui::layout::Constraint::Min(1),
104 ]
105 .as_ref(),
106 )
107 .split(f.area());
108 let title = Line::from("[ Running: ls ]");
109 let block = Block::default()
110 .borders(Borders::ALL)
111 .title(title)
112 .style(Style::default().add_modifier(Modifier::BOLD));
113 let pseudo_term = PseudoTerminal::new(screen).block(block.clone());
114 f.render_widget(pseudo_term, chunks[0]);
115 let pseudo_term = PseudoTerminal::new(screen).block(block);
116 f.render_widget(pseudo_term, chunks[1]);
117 let block = Block::default().borders(Borders::ALL);
118 f.render_widget(block, f.area());
119 let explanation = "Press q to exit";
120 let explanation = Paragraph::new(explanation)
121 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
122 .alignment(Alignment::Center);
123 f.render_widget(explanation, chunks[2]);
124}Sourcepub fn block(self, block: Block<'a>) -> Self
pub fn block(self, block: Block<'a>) -> Self
Sets the block for the PseudoTerminal.
§Arguments
block: TheBlockto set.
§Example
use ratatui_widgets::block::Block;
use tui_term::widget::PseudoTerminal;
use vt100::Parser;
let mut parser = vt100::Parser::new(24, 80, 0);
let block = Block::default();
let pseudo_term = PseudoTerminal::new(parser.screen()).block(block);Examples found in repository?
177fn ui(f: &mut Frame, screen: &Screen) {
178 let chunks = ratatui::layout::Layout::default()
179 .direction(ratatui::layout::Direction::Vertical)
180 .margin(1)
181 .constraints(
182 [
183 ratatui::layout::Constraint::Percentage(100),
184 ratatui::layout::Constraint::Min(1),
185 ]
186 .as_ref(),
187 )
188 .split(f.area());
189 let block = Block::default()
190 .borders(Borders::ALL)
191 .style(Style::default().add_modifier(Modifier::BOLD));
192 let pseudo_term = PseudoTerminal::new(screen).block(block);
193 f.render_widget(pseudo_term, chunks[0]);
194 let explanation = "Press q to exit".to_string();
195 let explanation = Paragraph::new(explanation)
196 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
197 .alignment(Alignment::Center);
198 f.render_widget(explanation, chunks[1]);
199}More examples
180fn ui(f: &mut Frame, screen: &Screen) {
181 let chunks = ratatui::layout::Layout::default()
182 .direction(ratatui::layout::Direction::Vertical)
183 .margin(1)
184 .constraints(
185 [
186 ratatui::layout::Constraint::Percentage(100),
187 ratatui::layout::Constraint::Min(1),
188 ]
189 .as_ref(),
190 )
191 .split(f.area());
192 let block = Block::default()
193 .borders(Borders::ALL)
194 .style(Style::default().add_modifier(Modifier::BOLD));
195 let pseudo_term = PseudoTerminal::new(screen).block(block);
196 f.render_widget(pseudo_term, chunks[0]);
197 let explanation = "Press q to exit".to_string();
198 let explanation = Paragraph::new(explanation)
199 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
200 .alignment(Alignment::Center);
201 f.render_widget(explanation, chunks[1]);
202}60fn ui(f: &mut Frame, screen: &Screen) {
61 let chunks = ratatui::layout::Layout::default()
62 .direction(ratatui::layout::Direction::Vertical)
63 .margin(1)
64 .constraints(
65 [
66 ratatui::layout::Constraint::Percentage(100),
67 ratatui::layout::Constraint::Min(1),
68 ]
69 .as_ref(),
70 )
71 .split(f.area());
72 let title = Line::from("[ Running: ls ]");
73 let block = Block::default()
74 .borders(Borders::ALL)
75 .title(title)
76 .style(Style::default().add_modifier(Modifier::BOLD));
77 let pseudo_term = PseudoTerminal::new(screen)
78 .cursor(tui_term::widget::Cursor::default().visibility(false))
79 .block(block.clone());
80 f.render_widget(pseudo_term, chunks[0]);
81 let explanation = "Press q to exit";
82 let explanation = Paragraph::new(explanation)
83 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
84 .alignment(Alignment::Center);
85 f.render_widget(explanation, chunks[1]);
86}102fn ui(f: &mut Frame, screen: &Screen) {
103 let chunks = ratatui::layout::Layout::default()
104 .direction(ratatui::layout::Direction::Vertical)
105 .margin(1)
106 .constraints(
107 [
108 ratatui::layout::Constraint::Percentage(0),
109 ratatui::layout::Constraint::Percentage(100),
110 ratatui::layout::Constraint::Min(1),
111 ]
112 .as_ref(),
113 )
114 .split(f.area());
115 let title = Line::from("[ Running: top ]");
116 let block = Block::default()
117 .borders(Borders::ALL)
118 .title(title)
119 .style(Style::default().add_modifier(Modifier::BOLD));
120 let pseudo_term = PseudoTerminal::new(screen).block(block);
121 f.render_widget(pseudo_term, chunks[1]);
122 let block = Block::default().borders(Borders::ALL);
123 f.render_widget(block, f.area());
124 let explanation = "Press q to exit".to_string();
125 let explanation = Paragraph::new(explanation)
126 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
127 .alignment(Alignment::Center);
128 f.render_widget(explanation, chunks[2]);
129}86fn ui(f: &mut Frame, screen: &Screen) {
87 let chunks = ratatui::layout::Layout::default()
88 .direction(ratatui::layout::Direction::Vertical)
89 .margin(1)
90 .constraints(
91 [
92 ratatui::layout::Constraint::Percentage(50),
93 ratatui::layout::Constraint::Percentage(50),
94 ratatui::layout::Constraint::Min(1),
95 ]
96 .as_ref(),
97 )
98 .split(f.area());
99 let title = Line::from("[ Running: ls ]");
100 let block = Block::default()
101 .borders(Borders::ALL)
102 .title(title)
103 .style(Style::default().add_modifier(Modifier::BOLD));
104 let pseudo_term = PseudoTerminal::new(screen).block(block.clone());
105 f.render_widget(pseudo_term, chunks[0]);
106 let pseudo_term = PseudoTerminal::new(screen).block(block);
107 f.render_widget(pseudo_term, chunks[1]);
108 let block = Block::default().borders(Borders::ALL);
109 f.render_widget(block, f.area());
110 let explanation = "Press q to exit";
111 let explanation = Paragraph::new(explanation)
112 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
113 .alignment(Alignment::Center);
114 f.render_widget(explanation, chunks[2]);
115}95fn ui(f: &mut Frame, screen: &Screen) {
96 let chunks = ratatui::layout::Layout::default()
97 .direction(ratatui::layout::Direction::Vertical)
98 .margin(1)
99 .constraints(
100 [
101 ratatui::layout::Constraint::Percentage(50),
102 ratatui::layout::Constraint::Percentage(50),
103 ratatui::layout::Constraint::Min(1),
104 ]
105 .as_ref(),
106 )
107 .split(f.area());
108 let title = Line::from("[ Running: ls ]");
109 let block = Block::default()
110 .borders(Borders::ALL)
111 .title(title)
112 .style(Style::default().add_modifier(Modifier::BOLD));
113 let pseudo_term = PseudoTerminal::new(screen).block(block.clone());
114 f.render_widget(pseudo_term, chunks[0]);
115 let pseudo_term = PseudoTerminal::new(screen).block(block);
116 f.render_widget(pseudo_term, chunks[1]);
117 let block = Block::default().borders(Borders::ALL);
118 f.render_widget(block, f.area());
119 let explanation = "Press q to exit";
120 let explanation = Paragraph::new(explanation)
121 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
122 .alignment(Alignment::Center);
123 f.render_widget(explanation, chunks[2]);
124}Sourcepub fn cursor(self, cursor: Cursor) -> Self
pub fn cursor(self, cursor: Cursor) -> Self
Sets the cursor configuration for the PseudoTerminal.
The cursor method allows configuring the appearance of the cursor within the
PseudoTerminal widget.
§Arguments
cursor: TheCursorconfiguration to set.
§Example
use ratatui_core::style::Style;
use tui_term::widget::{Cursor, PseudoTerminal};
let mut parser = vt100::Parser::new(24, 80, 0);
let cursor = Cursor::default().symbol("|").style(Style::default());
let pseudo_term = PseudoTerminal::new(parser.screen()).cursor(cursor);Examples found in repository?
60fn ui(f: &mut Frame, screen: &Screen) {
61 let chunks = ratatui::layout::Layout::default()
62 .direction(ratatui::layout::Direction::Vertical)
63 .margin(1)
64 .constraints(
65 [
66 ratatui::layout::Constraint::Percentage(100),
67 ratatui::layout::Constraint::Min(1),
68 ]
69 .as_ref(),
70 )
71 .split(f.area());
72 let title = Line::from("[ Running: ls ]");
73 let block = Block::default()
74 .borders(Borders::ALL)
75 .title(title)
76 .style(Style::default().add_modifier(Modifier::BOLD));
77 let pseudo_term = PseudoTerminal::new(screen)
78 .cursor(tui_term::widget::Cursor::default().visibility(false))
79 .block(block.clone());
80 f.render_widget(pseudo_term, chunks[0]);
81 let explanation = "Press q to exit";
82 let explanation = Paragraph::new(explanation)
83 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
84 .alignment(Alignment::Center);
85 f.render_widget(explanation, chunks[1]);
86}More examples
44async fn run_smux(terminal: &mut DefaultTerminal) -> io::Result<()> {
45 let mut size = Size {
46 rows: terminal.size()?.height,
47 cols: terminal.size()?.width,
48 };
49
50 let cwd = std::env::current_dir().unwrap();
51 let mut cmd = CommandBuilder::new_default_prog();
52 cmd.cwd(cwd);
53
54 let mut panes: Vec<PtyPane> = Vec::new();
55 let mut active_pane: Option<usize> = None;
56
57 let pane_size = calc_pane_size(size, 1);
58 open_new_pane(&mut panes, &mut active_pane, &cmd, pane_size)?;
59
60 loop {
61 terminal.draw(|f| {
62 let chunks = Layout::default()
63 .direction(Direction::Vertical)
64 .margin(1)
65 .constraints([Constraint::Percentage(100), Constraint::Min(1)].as_ref())
66 .split(f.area());
67
68 let pane_height = if panes.is_empty() {
69 chunks[0].height
70 } else {
71 (chunks[0].height.saturating_sub(1)) / panes.len() as u16
72 };
73
74 for (index, pane) in panes.iter().enumerate() {
75 let block = Block::default()
76 .borders(Borders::ALL)
77 .style(Style::default().add_modifier(Modifier::BOLD));
78 let mut cursor = Cursor::default();
79 let block = if Some(index) == active_pane {
80 block.style(
81 Style::default()
82 .add_modifier(Modifier::BOLD)
83 .fg(Color::LightMagenta),
84 )
85 } else {
86 cursor.hide();
87 block
88 };
89 let parser = pane.parser.read().unwrap();
90 let screen = parser.screen();
91 let pseudo_term = PseudoTerminal::new(screen).block(block).cursor(cursor);
92 let pane_chunk = Rect {
93 x: chunks[0].x,
94 y: chunks[0].y + (index as u16 * pane_height), /* Adjust the y coordinate for
95 * each pane */
96 width: chunks[0].width,
97 height: pane_height, // Use the calculated pane height directly
98 };
99 f.render_widget(pseudo_term, pane_chunk);
100 }
101
102 let explanation =
103 "Ctrl+n to open a new pane | Ctrl+x to close the active pane | Ctrl+q to quit";
104 let explanation = Paragraph::new(explanation)
105 .style(Style::default().add_modifier(Modifier::BOLD | Modifier::REVERSED))
106 .alignment(Alignment::Center);
107 f.render_widget(explanation, chunks[1]);
108 })?;
109
110 if event::poll(Duration::from_millis(10))? {
111 tracing::info!("Terminal Size: {:?}", terminal.size());
112 match event::read()? {
113 Event::Key(key) => match key.code {
114 KeyCode::Char('q') if key.modifiers.contains(KeyModifiers::CONTROL) => {
115 return Ok(());
116 }
117 KeyCode::Char('n') if key.modifiers.contains(KeyModifiers::CONTROL) => {
118 let pane_size = calc_pane_size(size, panes.len() + 1);
119 tracing::info!("Opened new pane with size: {size:?}");
120 resize_all_panes(&mut panes, pane_size);
121 open_new_pane(&mut panes, &mut active_pane, &cmd, pane_size)?;
122 }
123 KeyCode::Char('x') if key.modifiers.contains(KeyModifiers::CONTROL) => {
124 close_active_pane(&mut panes, &mut active_pane).await?;
125 resize_all_panes(&mut panes, pane_size);
126 }
127 KeyCode::Char('k') if key.modifiers.contains(KeyModifiers::CONTROL) => {
128 if let Some(pane) = active_pane {
129 active_pane = Some(pane.saturating_sub(1));
130 }
131 }
132 KeyCode::Char('j') if key.modifiers.contains(KeyModifiers::CONTROL) => {
133 if let Some(pane) = active_pane {
134 if pane < panes.len() - 1 {
135 active_pane = Some(pane.saturating_add(1));
136 }
137 }
138 }
139 _ => {
140 if let Some(index) = active_pane {
141 if handle_pane_key_event(&mut panes[index], &key).await {
142 continue;
143 }
144 }
145 }
146 },
147 Event::Resize(cols, rows) => {
148 tracing::info!("Resized to: rows: {} cols: {}", rows, cols);
149 size.rows = rows;
150 size.cols = cols;
151 let pane_size = calc_pane_size(size, panes.len());
152 resize_all_panes(&mut panes, pane_size);
153 }
154 _ => {}
155 }
156 }
157
158 cleanup_exited_panes(&mut panes, &mut active_pane);
159
160 if panes.is_empty() {
161 return Ok(());
162 }
163 }
164}pub const fn screen(&self) -> &S
Trait Implementations§
Auto Trait Implementations§
impl<'a, S> Freeze for PseudoTerminal<'a, S>
impl<'a, S> RefUnwindSafe for PseudoTerminal<'a, S>where
S: RefUnwindSafe,
impl<'a, S> Send for PseudoTerminal<'a, S>where
S: Sync,
impl<'a, S> Sync for PseudoTerminal<'a, S>where
S: Sync,
impl<'a, S> Unpin for PseudoTerminal<'a, S>
impl<'a, S> UnwindSafe for PseudoTerminal<'a, S>where
S: RefUnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more