lib-nested/shell/src/pty.rs

119 lines
4.1 KiB
Rust
Raw Normal View History

2021-09-15 17:47:40 +02:00
use {
termion::event::{Key, Event},
std::sync::Mutex,
2021-09-15 17:47:40 +02:00
nested::{
core::{InnerViewPort},
singleton::{SingletonView, SingletonBuffer},
terminal::{TerminalView, TerminalEvent, TerminalEditorResult}
2021-09-15 17:47:40 +02:00
}
};
pub use portable_pty::CommandBuilder;
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct PTY {
master: Mutex<Box<dyn portable_pty::MasterPty + Send>>
2021-09-15 17:47:40 +02:00
}
impl PTY {
pub fn new(
cmd: portable_pty::CommandBuilder,
term_port: InnerViewPort<dyn TerminalView>,
status_port: InnerViewPort<dyn SingletonView<Item = Option<portable_pty::ExitStatus>>>
2021-09-15 17:47:40 +02:00
) -> Option<Self> {
// Create a new pty
let mut pair = portable_pty::native_pty_system().openpty(portable_pty::PtySize {
rows: 25,
cols: 120,
2021-09-15 17:47:40 +02:00
// Not all systems support pixel_width, pixel_height,
// but it is good practice to set it to something
// that matches the size of the selected font. That
// is more complex than can be shown here in this
// brief example though!
pixel_width: 0,
pixel_height: 0,
}).unwrap();
if let Ok(mut child) = pair.slave.spawn_command(cmd) {
2021-09-15 17:47:40 +02:00
let mut reader = pair.master.try_clone_reader().unwrap();
async_std::task::spawn_blocking(
move || {
nested::terminal::ansi_parser::read_ansi_from(&mut reader, term_port);
2021-09-15 17:47:40 +02:00
});
async_std::task::spawn_blocking(
move || {
let mut status_buf = SingletonBuffer::new(None, status_port);
if let Ok(status) = child.wait() {
status_buf.set(Some(status));
}
}
);
2021-09-15 17:47:40 +02:00
Some(PTY {
master: Mutex::new(pair.master)
2021-09-15 17:47:40 +02:00
})
} else {
None
}
}
pub fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
2021-09-15 17:47:40 +02:00
match event {
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
self.master.lock().unwrap().write(&[13]).unwrap();
TerminalEditorResult::Continue
},
2021-09-15 17:47:40 +02:00
TerminalEvent::Input(Event::Key(Key::Char(c))) => {
write!(self.master.lock().unwrap(), "{}", c);
TerminalEditorResult::Continue
},
TerminalEvent::Input(Event::Key(Key::Esc)) => {
self.master.lock().unwrap().write(&[0x1b]).unwrap();
TerminalEditorResult::Continue
}
TerminalEvent::Input(Event::Key(Key::Backspace)) => {
self.master.lock().unwrap().write(&[0x8]).unwrap();
TerminalEditorResult::Continue
}
TerminalEvent::Input(Event::Key(Key::F(n))) => {
self.master.lock().unwrap().write(&[
0x1b,
0x0a,
match n {
11 => 133,
12 => 134,
n => 58 + n
}
]).unwrap();
TerminalEditorResult::Continue
}
TerminalEvent::Input(Event::Key(Key::Up)) => {
self.master.lock().unwrap().write(&[0, b'\x1B', b'[', b'A']).unwrap();
TerminalEditorResult::Continue
}
TerminalEvent::Input(Event::Key(Key::Down)) => {
self.master.lock().unwrap().write(&[0, b'\x1B', b'[', b'B']).unwrap();
TerminalEditorResult::Continue
}
TerminalEvent::Input(Event::Key(Key::Right)) => {
self.master.lock().unwrap().write(&[0, b'\x1B', b'[', b'C']).unwrap();
TerminalEditorResult::Continue
}
TerminalEvent::Input(Event::Key(Key::Left)) => {
self.master.lock().unwrap().write(&[0, b'\x1B', b'[', b'D']).unwrap();
TerminalEditorResult::Continue
2021-09-15 17:47:40 +02:00
}
_ => {
TerminalEditorResult::Exit
2021-09-15 17:47:40 +02:00
}
}
}
}