simple_ls_controller/
simple_ls_controller.rs1use std::io;
2
3use crossterm::event::{self, Event, KeyCode, KeyEventKind};
4use portable_pty::CommandBuilder;
5use ratatui::{
6 layout::Alignment,
7 style::{Modifier, Style},
8 text::Line,
9 widgets::{Block, Borders, Paragraph},
10 DefaultTerminal, Frame,
11};
12use tui_term::{controller::Controller, widget::PseudoTerminal};
13use vt100::Screen;
14
15fn main() -> std::io::Result<()> {
16 let mut terminal = ratatui::init();
17 let result = run_app(&mut terminal);
18 ratatui::restore();
19 result
20}
21
22fn run_app(terminal: &mut DefaultTerminal) -> std::io::Result<()> {
23 let terminal_size = terminal.size()?;
24 let size = Size {
25 rows: terminal_size.height,
26 cols: terminal_size.width,
27 };
28
29 let size = tui_term::controller::Size::new(size.cols - 2, size.rows, 0, 0);
31
32 let mut cmd = CommandBuilder::new("ls");
33 if let Ok(cwd) = std::env::current_dir() {
34 cmd.cwd(cwd);
35 }
36
37 let mut controller = Controller::new(cmd, Some(size));
38 controller.run();
39 let screen = controller.screen();
40
41 run(terminal, screen)
42}
43
44fn run(terminal: &mut DefaultTerminal, screen: Option<vt100::Screen>) -> io::Result<()> {
45 loop {
46 if let Some(ref screen) = screen {
47 terminal.draw(|f| ui(f, &screen))?;
48 }
49
50 if let Event::Key(key) = event::read()? {
51 if key.kind == KeyEventKind::Press {
52 if let KeyCode::Char('q') = key.code {
53 return Ok(());
54 }
55 }
56 }
57 }
58}
59
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}
87
88#[derive(Debug, Clone)]
89struct Size {
90 cols: u16,
91 rows: u16,
92}