lib-nested/shell/src/process.rs

278 lines
8.1 KiB
Rust
Raw Normal View History

2021-09-03 06:49:18 +02:00
use {
2021-11-19 12:19:52 +01:00
crate::pty::{PTYStatus, PTY},
2021-09-03 06:49:18 +02:00
nested::{
2021-11-19 12:19:52 +01:00
core::{OuterViewPort, ViewPort},
2022-06-19 23:13:21 +02:00
list::{ListCursorMode, PTYListEditor},
sequence::{SequenceView, SequenceViewExt, decorator::{SeqDecorStyle, Separate, Wrap}},
2021-11-19 12:19:52 +01:00
singleton::SingletonView,
2022-06-19 23:13:21 +02:00
char_editor::CharEditor,
2021-11-19 12:19:52 +01:00
terminal::{
TerminalAtom, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle,
TerminalView,
},
tree::{TreeCursor, TreeNav, TreeNavResult},
diagnostics::Diagnostics,
Nested
},
2021-11-19 12:19:52 +01:00
std::sync::Arc,
std::sync::RwLock,
termion::event::{Event, Key},
2022-06-19 23:13:21 +02:00
cgmath::Vector2
2021-09-03 06:49:18 +02:00
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
/*
2021-09-03 06:49:18 +02:00
pub struct ProcessArg {
2021-11-19 12:19:52 +01:00
editor:
2022-06-19 23:13:21 +02:00
PTYListEditor<CharEditor>,
2021-09-03 06:49:18 +02:00
}
impl ProcessArg {
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = char>> {
2021-11-19 12:19:52 +01:00
self.editor.get_data_port().map(|char_editor| {
char_editor
.read()
.unwrap()
2022-06-19 23:13:21 +02:00
.get_port()
2021-11-19 12:19:52 +01:00
.get_view()
.unwrap()
.get()
.unwrap()
})
2021-09-03 06:49:18 +02:00
}
}
impl TerminalEditor for ProcessArg {
fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> {
2022-06-19 23:13:21 +02:00
self.editor.get_term_view()
2021-09-03 06:49:18 +02:00
}
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
match event {
2021-11-19 12:19:52 +01:00
TerminalEvent::Input(Event::Key(Key::Char(' ')))
| TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
2021-09-03 06:49:18 +02:00
self.editor.up();
TerminalEditorResult::Exit
}
2021-11-19 12:19:52 +01:00
event => self.editor.handle_terminal_event(event),
2021-09-03 06:49:18 +02:00
}
}
}
impl TreeNav for ProcessArg {
2021-11-19 12:19:52 +01:00
fn get_cursor(&self) -> TreeCursor {
self.editor.get_cursor()
}
2022-06-19 23:13:21 +02:00
fn get_cursor_warp(&self) -> TreeCursor {
self.editor.get_cursor_warp()
}
2021-11-19 12:19:52 +01:00
fn goto(&mut self, cur: TreeCursor) -> TreeNavResult {
self.editor.goto(cur)
}
2022-06-19 23:13:21 +02:00
fn goby(&mut self, dir: Vector2<isize>) -> TreeNavResult {
self.editor.goby(dir)
2021-11-19 12:19:52 +01:00
}
2021-09-03 06:49:18 +02:00
}
2022-10-23 19:29:50 +02:00
impl Diagnostics for ProcessArg {
}
impl Nested for ProcessArg {}
2022-06-19 23:13:21 +02:00
2021-09-03 06:49:18 +02:00
pub struct ProcessLauncher {
2022-06-19 23:13:21 +02:00
cmd_editor: PTYListEditor<ProcessArg>,
pty: Option<crate::pty::PTY>,
2021-11-19 12:19:52 +01:00
_ptybox: Arc<RwLock<crate::ascii_box::AsciiBox>>,
suspended: bool,
pty_port: ViewPort<dyn TerminalView>,
status_port: ViewPort<dyn SingletonView<Item = PTYStatus>>,
comp_port: ViewPort<dyn TerminalView>,
2021-11-19 12:19:52 +01:00
_compositor: Arc<RwLock<nested::terminal::TerminalCompositor>>,
2021-09-03 06:49:18 +02:00
}
impl ProcessLauncher {
pub fn new() -> Self {
let pty_port = ViewPort::new();
let status_port = ViewPort::new();
let comp_port = ViewPort::new();
let box_port = ViewPort::<dyn TerminalView>::new();
let compositor = nested::terminal::TerminalCompositor::new(comp_port.inner());
2022-06-19 23:13:21 +02:00
let cmd_editor = PTYListEditor::new(
2021-11-19 12:19:52 +01:00
Box::new(|| {
Arc::new(RwLock::new(ProcessArg {
2022-06-19 23:13:21 +02:00
editor: PTYListEditor::new(
2021-11-19 12:19:52 +01:00
Box::new(|| Arc::new(RwLock::new(CharEditor::new()))),
2022-06-19 23:13:21 +02:00
SeqDecorStyle::Plain,
2022-10-23 21:28:06 +02:00
'\n',
2022-06-19 23:13:21 +02:00
1
2021-11-19 12:19:52 +01:00
),
}))
}) as Box<dyn Fn() -> Arc<RwLock<ProcessArg>> + Send + Sync>,
2022-06-19 23:13:21 +02:00
SeqDecorStyle::HorizontalSexpr,
2022-10-23 21:28:06 +02:00
' ',
2022-06-19 23:13:21 +02:00
0
);
compositor.write().unwrap().push(
2021-11-19 12:19:52 +01:00
box_port
.outer()
.map_item(|_idx, x| x.add_style_back(TerminalStyle::fg_color((90, 120, 100)))),
);
compositor.write().unwrap().push(
2022-06-19 23:13:21 +02:00
cmd_editor.get_term_view()
);
ProcessLauncher {
cmd_editor,
pty: None,
2021-11-19 12:19:52 +01:00
_ptybox: crate::ascii_box::AsciiBox::new(
cgmath::Vector2::new(0, 0),
pty_port.outer().map_item(|_, a: &TerminalAtom| {
a.add_style_back(TerminalStyle::fg_color((230, 230, 230)))
}),
box_port.inner(),
),
suspended: false,
pty_port,
status_port,
comp_port,
2021-11-19 12:19:52 +01:00
_compositor: compositor,
2021-09-03 06:49:18 +02:00
}
}
pub fn launch_pty(&mut self) {
2021-09-03 06:49:18 +02:00
let mut strings = Vec::new();
let v = self.cmd_editor.get_data_port().get_view().unwrap();
2021-11-19 12:19:52 +01:00
for i in 0..v.len().unwrap_or(0) {
let arg_view = v
.get(&i)
.unwrap()
.read()
.unwrap()
.get_data_port()
.get_view()
.unwrap();
2021-09-03 06:49:18 +02:00
strings.push(arg_view.iter().collect::<String>());
}
if strings.len() > 0 {
// Spawn a shell into the pty
2021-09-15 17:47:40 +02:00
let mut cmd = crate::pty::CommandBuilder::new(strings[0].as_str());
cmd.args(&strings[1..]);
2021-11-18 22:55:32 +01:00
cmd.cwd(".");
self.cmd_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Insert,
2021-11-19 12:19:52 +01:00
tree_addr: vec![],
});
2021-11-19 12:19:52 +01:00
self.pty = PTY::new(
cmd,
cgmath::Vector2::new(120, 40),
self.pty_port.inner(),
self.status_port.inner(),
);
2021-09-03 06:49:18 +02:00
}
}
pub fn is_captured(&self) -> bool {
self.pty.is_some() && !self.suspended
}
2021-09-03 06:49:18 +02:00
}
impl TerminalEditor for ProcessLauncher {
fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> {
self.comp_port.outer()
2021-09-03 06:49:18 +02:00
}
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
// todo: move to observer of status view
2021-11-19 12:19:52 +01:00
if let PTYStatus::Done { status: _ } = self.status_port.outer().get_view().get() {
self.pty = None;
self.suspended = false;
}
2021-09-03 06:49:18 +02:00
match event {
TerminalEvent::Input(Event::Key(Key::Ctrl('c'))) => {
// todo: sigterm instead of kill?
2021-11-19 12:19:52 +01:00
if let Some(pty) = self.pty.as_mut() {
pty.kill();
}
self.pty = None;
self.suspended = false;
self.cmd_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Insert,
2021-11-19 12:19:52 +01:00
tree_addr: vec![],
});
TerminalEditorResult::Exit
2021-11-19 12:19:52 +01:00
}
TerminalEvent::Input(Event::Key(Key::Ctrl('z'))) => {
self.suspended = true;
self.cmd_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Insert,
2021-11-19 12:19:52 +01:00
tree_addr: vec![],
});
2021-09-03 06:49:18 +02:00
TerminalEditorResult::Exit
}
event => {
if let Some(pty) = self.pty.as_mut() {
pty.handle_terminal_event(event);
TerminalEditorResult::Continue
} else {
match event {
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
// launch command
self.launch_pty();
TerminalEditorResult::Continue
}
2021-11-19 12:19:52 +01:00
event => self.cmd_editor.handle_terminal_event(event),
}
}
}
2021-09-03 06:49:18 +02:00
}
2021-11-19 12:19:52 +01:00
}
2021-09-03 06:49:18 +02:00
}
impl TreeNav for ProcessLauncher {
fn get_cursor(&self) -> TreeCursor {
self.cmd_editor.get_cursor()
}
2022-06-19 23:13:21 +02:00
fn get_cursor_warp(&self) -> TreeCursor {
self.cmd_editor.get_cursor_warp()
}
fn goto(&mut self, cur: TreeCursor) -> TreeNavResult {
self.suspended = false;
2021-11-19 12:19:52 +01:00
if let PTYStatus::Done { status: _ } = self.status_port.outer().get_view().get() {
self.pty = None;
}
if self.pty.is_none() {
self.cmd_editor.goto(cur)
} else {
self.cmd_editor.goto(TreeCursor {
leaf_mode: ListCursorMode::Select,
2021-11-19 12:19:52 +01:00
tree_addr: vec![],
});
TreeNavResult::Continue
}
}
2022-06-19 23:13:21 +02:00
fn goby(&mut self, dir: Vector2<isize>) -> TreeNavResult {
self.cmd_editor.goby(dir)
}
2021-09-03 06:49:18 +02:00
}
2022-06-19 23:13:21 +02:00
2022-10-23 19:29:50 +02:00
impl Diagnostics for ProcessLauncher {
}
impl Nested for ProcessLauncher {}
*/