shell: first ProcessLauncher with PTY
This commit is contained in:
parent
bd1572c632
commit
cee6e02a04
5 changed files with 261 additions and 214 deletions
|
@ -77,5 +77,10 @@ where Key: Clone + Hash + Eq + Send + Sync + 'static,
|
|||
self.insert(key, item);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, key: Key) {
|
||||
self.data.write().unwrap().remove(&key);
|
||||
self.cast.notify(&key);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,10 +43,6 @@ impl TerminalEditor for CharEditor {
|
|||
} else {
|
||||
"".to_string()
|
||||
})
|
||||
.map_item(
|
||||
|_idx, atom|
|
||||
atom.add_style_back(TerminalStyle::fg_color((120, 200, 10)))
|
||||
)
|
||||
}
|
||||
|
||||
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
|
||||
|
@ -114,6 +110,10 @@ impl TerminalEditor for StringEditor {
|
|||
.decorate("\"", "\"", "", 1)
|
||||
.to_grid_horizontal()
|
||||
.flatten()
|
||||
.map_item(
|
||||
|_idx, atom|
|
||||
atom.add_style_back(TerminalStyle::fg_color((120, 200, 10)))
|
||||
)
|
||||
}
|
||||
|
||||
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
|
||||
|
|
|
@ -7,6 +7,9 @@ edition = "2018"
|
|||
nested = { path = "../nested" }
|
||||
cgmath = "*"
|
||||
termion = "*"
|
||||
bincode = "*"
|
||||
libc = "0.2.*"
|
||||
tty = { git = "https://github.com/stemjail/tty-rs.git" }
|
||||
|
||||
[dependencies.async-std]
|
||||
version = "1.9.0"
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
|
||||
extern crate tty;
|
||||
|
||||
mod monstera;
|
||||
mod process;
|
||||
|
||||
use{
|
||||
std::sync::{Arc, RwLock},
|
||||
|
@ -15,9 +18,9 @@ use{
|
|||
context::{ReprTree, Object, MorphismType, MorphismMode, Context},
|
||||
port::{UpdateTask}},
|
||||
index::{IndexView},
|
||||
sequence::{SequenceView},
|
||||
sequence::{SequenceView, SequenceViewExt},
|
||||
vec::{VecBuffer},
|
||||
integer::{RadixProjection, DigitEditor},
|
||||
integer::{RadixProjection, DigitEditor, PosIntEditor},
|
||||
terminal::{
|
||||
Terminal,
|
||||
TerminalStyle,
|
||||
|
@ -27,60 +30,17 @@ use{
|
|||
make_label,
|
||||
TerminalView,
|
||||
TerminalEditor},
|
||||
string_editor::{CharEditor},
|
||||
string_editor::{StringEditor},
|
||||
tree_nav::{TreeNav, TreeNavResult, TreeCursor, TerminalTreeEditor},
|
||||
list::{SExprView, ListCursorMode, ListEditor, ListEditorStyle}
|
||||
},
|
||||
crate::{
|
||||
process::ProcessLauncher
|
||||
}
|
||||
};
|
||||
|
||||
struct GridFill<T: Send + Sync + Clone>(T);
|
||||
impl<T: Send + Sync + Clone> View for GridFill<T> {
|
||||
type Msg = Point2<i16>;
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + Clone> IndexView<Point2<i16>> for GridFill<T> {
|
||||
type Item = T;
|
||||
|
||||
fn area(&self) -> Option<Vec<Point2<i16>>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn get(&self, _: &Point2<i16>) -> Option<T> {
|
||||
Some(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_std::main]
|
||||
async fn main() {
|
||||
/* todo:
|
||||
|
||||
open::
|
||||
>0:
|
||||
( Path )
|
||||
( Sequence ( Sequence UnicodeChar ) )
|
||||
( Sequence UnicodeChar )
|
||||
<1:
|
||||
( FileDescriptor )
|
||||
( MachineInt )
|
||||
|
||||
read::
|
||||
>0:
|
||||
( FileDescriptor )
|
||||
( MachineInt )
|
||||
<1:
|
||||
( Sequence MachineSyllab )
|
||||
( Vec MachineSyllab )
|
||||
|
||||
write::
|
||||
>0
|
||||
( FileDescriptor )
|
||||
( MachineInt )
|
||||
>1:
|
||||
( Sequence MachineSyllab )
|
||||
( Vec MachineSyllab )
|
||||
|
||||
*/
|
||||
|
||||
let term_port = ViewPort::new();
|
||||
let compositor = TerminalCompositor::new(term_port.inner());
|
||||
|
||||
|
@ -107,83 +67,27 @@ write::
|
|||
let cur_size_port = ViewPort::new();
|
||||
let mut cur_size = nested::singleton::SingletonBuffer::new(Vector2::new(10, 10), cur_size_port.inner());
|
||||
|
||||
// TypeEditor
|
||||
let make_char_editor = || {
|
||||
std::sync::Arc::new(std::sync::RwLock::new(CharEditor::new()))
|
||||
};
|
||||
let make_subsub_editor = move || {
|
||||
std::sync::Arc::new(std::sync::RwLock::new(ListEditor::new(make_char_editor.clone(), ListEditorStyle::String)))
|
||||
};
|
||||
let make_sub_editor = move || {
|
||||
std::sync::Arc::new(std::sync::RwLock::new(ListEditor::new(make_subsub_editor.clone(), ListEditorStyle::HorizontalSexpr)))
|
||||
};
|
||||
|
||||
let mut te = ListEditor::new(make_sub_editor.clone(), ListEditorStyle::VerticalSexpr);
|
||||
|
||||
te.goto(
|
||||
TreeCursor {
|
||||
leaf_mode: ListCursorMode::Insert,
|
||||
tree_addr: vec![ 0 ]
|
||||
}
|
||||
);
|
||||
|
||||
let mut p = te.get_data_port().map(|sub_editor| sub_editor.read().unwrap().get_data_port());
|
||||
|
||||
let status_chars_port = ViewPort::new();
|
||||
let mut status_chars = VecBuffer::new(status_chars_port.inner());
|
||||
|
||||
let help_port = ViewPort::<dyn nested::grid::GridView<Item = OuterViewPort<dyn TerminalView>>>::new();
|
||||
let mut help_buf = nested::index::buffer::IndexBuffer::<Point2<i16>, OuterViewPort<dyn TerminalView>>::new(help_port.inner());
|
||||
|
||||
let table_style = TerminalStyle::fg_color((120, 100, 80));
|
||||
let desc_style = TerminalStyle::italic(true);
|
||||
help_buf.insert_iter(vec![
|
||||
(Point2::new(0, 0), make_label("CTRL+{c,d,g}").map_item(|_idx, atom| atom.add_style_back(TerminalStyle::bold(true)))),
|
||||
(Point2::new(1, 0), make_label(" | ").map_item(move |_idx, atom| atom.add_style_back(table_style))),
|
||||
(Point2::new(2, 0), make_label("quit").map_item(move |_idx, atom| atom.add_style_back(desc_style))),
|
||||
|
||||
(Point2::new(0, 1), make_label("↞ ← ↑ ↓ → ↠").map_item(|_idx, atom| atom.add_style_back(TerminalStyle::bold(true)))),
|
||||
(Point2::new(1, 1), make_label(" | ").map_item(move |_idx, atom| atom.add_style_back(table_style))),
|
||||
(Point2::new(2, 1), make_label("move cursor").map_item(move |_idx, atom| atom.add_style_back(desc_style))),
|
||||
|
||||
(Point2::new(0, 3), make_label("<DEL> (Select)").map_item(|_idx, atom| atom.add_style_back(TerminalStyle::bold(true)))),
|
||||
(Point2::new(1, 3), make_label(" | ").map_item(move |_idx, atom| atom.add_style_back(table_style))),
|
||||
(Point2::new(2, 3), make_label("delete item at cursor position").map_item(move |_idx, atom| atom.add_style_back(desc_style))),
|
||||
|
||||
(Point2::new(0, 4), make_label("<DEL> (Insert)").map_item(|_idx, atom| atom.add_style_back(TerminalStyle::bold(true)))),
|
||||
(Point2::new(1, 4), make_label(" | ").map_item(move |_idx, atom| atom.add_style_back(table_style))),
|
||||
(Point2::new(2, 4), make_label("delete item right to cursor").map_item(move |_idx, atom| atom.add_style_back(desc_style))),
|
||||
|
||||
(Point2::new(0, 5), make_label("<BACKSPACE> (Insert)").map_item(|_idx, atom| atom.add_style_back(TerminalStyle::bold(true)))),
|
||||
(Point2::new(1, 5), make_label(" | ").map_item(move |_idx, atom| atom.add_style_back(table_style))),
|
||||
(Point2::new(2, 5), make_label("delete item left to cursor").map_item(move |_idx, atom| atom.add_style_back(desc_style))),
|
||||
|
||||
(Point2::new(0, 6), make_label("<TAB>").map_item(|_idx, atom| atom.add_style_back(TerminalStyle::bold(true)))),
|
||||
(Point2::new(1, 6), make_label(" | ").map_item(move |_idx, atom| atom.add_style_back(table_style))),
|
||||
(Point2::new(2, 6), make_label("toggle cursor mode (insert / select)").map_item(move |_idx, atom| atom.add_style_back(desc_style))),
|
||||
]);
|
||||
|
||||
let help_head = make_label("─────────────────────┬─────────────────────").map_item(move |_idx, atom| atom.add_style_back(table_style));
|
||||
|
||||
table_buf.insert_iter(vec![
|
||||
(Point2::new(0, 0), magic.clone()),
|
||||
(Point2::new(0, 2), status_chars_port.outer().to_sequence().to_grid_horizontal()),
|
||||
(Point2::new(0, 3), te.get_term_view()),
|
||||
(Point2::new(0, 4), make_label(" ")),
|
||||
(Point2::new(0, 5), help_head),
|
||||
(Point2::new(0, 6), help_port.outer().flatten()),
|
||||
(Point2::new(0, 7), magic.clone()),
|
||||
(Point2::new(0, 1), status_chars_port.outer().to_sequence().to_grid_horizontal()),
|
||||
]);
|
||||
|
||||
compositor.write().unwrap().push(monstera::make_monstera());
|
||||
compositor.write().unwrap().push(table_port.outer().flatten().offset(Vector2::new(40, 2)));
|
||||
|
||||
/*
|
||||
te.get_data_port()
|
||||
.map(
|
||||
|item_editor| item_editor.read().unwrap().get_data_port()
|
||||
)
|
||||
*/
|
||||
let mut y = 2;
|
||||
|
||||
let mut process_launcher = ProcessLauncher::new();
|
||||
table_buf.insert(Point2::new(0, y), process_launcher.get_term_view());
|
||||
|
||||
process_launcher.goto(TreeCursor {
|
||||
leaf_mode: ListCursorMode::Insert,
|
||||
tree_addr: vec![ 0 ]
|
||||
});
|
||||
|
||||
loop {
|
||||
term_port.update();
|
||||
match term.next_event().await {
|
||||
|
@ -200,122 +104,60 @@ write::
|
|||
TerminalEvent::Input(Event::Key(Key::Ctrl('d'))) => break,
|
||||
|
||||
TerminalEvent::Input(Event::Key(Key::Left)) => {
|
||||
if te.pxev() == TreeNavResult::Exit {
|
||||
te.goto_home();
|
||||
}
|
||||
process_launcher.pxev();
|
||||
}
|
||||
TerminalEvent::Input(Event::Key(Key::Right)) => {
|
||||
if te.nexd() == TreeNavResult::Exit {
|
||||
te.goto_end();
|
||||
}
|
||||
process_launcher.nexd();
|
||||
}
|
||||
TerminalEvent::Input(Event::Key(Key::Up)) => { te.up(); }
|
||||
TerminalEvent::Input(Event::Key(Key::Up)) => { process_launcher.up(); }
|
||||
TerminalEvent::Input(Event::Key(Key::Down)) => {
|
||||
if te.dn() == TreeNavResult::Continue {
|
||||
te.goto_home();
|
||||
if process_launcher.dn() == TreeNavResult::Continue {
|
||||
process_launcher.goto_home();
|
||||
}
|
||||
}
|
||||
TerminalEvent::Input(Event::Key(Key::Home)) => {
|
||||
if te.goto_home() == TreeNavResult::Exit {
|
||||
te.goto_home();
|
||||
}
|
||||
process_launcher.goto_home();
|
||||
}
|
||||
TerminalEvent::Input(Event::Key(Key::End)) => {
|
||||
if te.goto_end() == TreeNavResult::Exit {
|
||||
te.goto_end();
|
||||
}
|
||||
process_launcher.goto_end();
|
||||
}
|
||||
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
|
||||
let output_view = process_launcher.launch();
|
||||
|
||||
y += 1;
|
||||
table_buf.insert(Point2::new(0, y), output_view);
|
||||
|
||||
process_launcher = ProcessLauncher::new();
|
||||
process_launcher.goto(TreeCursor {
|
||||
leaf_mode: ListCursorMode::Insert,
|
||||
tree_addr: vec![ 0 ]
|
||||
});
|
||||
|
||||
y += 1;
|
||||
table_buf.insert(Point2::new(0, y), process_launcher.get_term_view());
|
||||
}
|
||||
|
||||
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
|
||||
/*
|
||||
let mut strings = Vec::new();
|
||||
|
||||
let v = p.get_view().unwrap();
|
||||
for i in 0 .. v.len().unwrap_or(0) {
|
||||
strings.push(
|
||||
v
|
||||
.get(&i).unwrap()
|
||||
.get_view().unwrap()
|
||||
.read().unwrap()
|
||||
.iter().collect::<String>()
|
||||
);
|
||||
}
|
||||
|
||||
if strings.len() == 0 { continue; }
|
||||
|
||||
if let Ok(output) =
|
||||
std::process::Command::new(strings[0].as_str())
|
||||
.args(&strings[1..])
|
||||
.output()
|
||||
{
|
||||
// take output and update terminal view
|
||||
let mut line_port = ViewPort::new();
|
||||
let mut line = VecBuffer::new(line_port.inner());
|
||||
for byte in output.stdout {
|
||||
match byte {
|
||||
b'\n' => {
|
||||
compositor.write().unwrap().push(
|
||||
line_port.outer()
|
||||
.to_sequence()
|
||||
.map(|c| TerminalAtom::new(*c, TerminalStyle::fg_color((130,90,90))))
|
||||
.to_grid_horizontal()
|
||||
.offset(Vector2::new(45, y))
|
||||
);
|
||||
y += 1;
|
||||
line_port = ViewPort::new();
|
||||
line = VecBuffer::new(line_port.inner());
|
||||
}
|
||||
byte => {
|
||||
line.push(byte as char);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
compositor.write().unwrap().push(
|
||||
make_label("Command not found")
|
||||
.map_item(|idx, a| a.add_style_back(TerminalStyle::fg_color((200,0,0))))
|
||||
.offset(Vector2::new(45, y))
|
||||
);
|
||||
y+=1;
|
||||
}
|
||||
|
||||
te.up();
|
||||
te.goto_home();
|
||||
te = ListEditor::new(make_sub_editor.clone());
|
||||
|
||||
compositor.write().unwrap().push(magic.offset(Vector2::new(40, y)));
|
||||
y += 1;
|
||||
compositor.write().unwrap().push(
|
||||
te
|
||||
.horizontal_sexpr_view()
|
||||
.offset(Vector2::new(40, y))
|
||||
);
|
||||
y += 1;
|
||||
|
||||
p = te.get_data_port().map(|string_editor| string_editor.read().unwrap().get_data_port());
|
||||
*/
|
||||
},
|
||||
ev => {
|
||||
if te.get_cursor().leaf_mode == ListCursorMode::Select {
|
||||
if process_launcher.get_cursor().leaf_mode == ListCursorMode::Select {
|
||||
match ev {
|
||||
TerminalEvent::Input(Event::Key(Key::Char('l'))) => { te.up(); },
|
||||
TerminalEvent::Input(Event::Key(Key::Char('a'))) => { te.dn(); },
|
||||
TerminalEvent::Input(Event::Key(Key::Char('i'))) => { te.pxev(); },
|
||||
TerminalEvent::Input(Event::Key(Key::Char('e'))) => { te.nexd(); },
|
||||
TerminalEvent::Input(Event::Key(Key::Char('u'))) => { te.goto_home(); },
|
||||
TerminalEvent::Input(Event::Key(Key::Char('o'))) => { te.goto_end(); },
|
||||
TerminalEvent::Input(Event::Key(Key::Char('l'))) => { process_launcher.up(); },
|
||||
TerminalEvent::Input(Event::Key(Key::Char('a'))) => { process_launcher.dn(); },
|
||||
TerminalEvent::Input(Event::Key(Key::Char('i'))) => { process_launcher.pxev(); },
|
||||
TerminalEvent::Input(Event::Key(Key::Char('e'))) => { process_launcher.nexd(); },
|
||||
TerminalEvent::Input(Event::Key(Key::Char('u'))) => { process_launcher.goto_home(); },
|
||||
TerminalEvent::Input(Event::Key(Key::Char('o'))) => { process_launcher.goto_end(); },
|
||||
_ => {
|
||||
te.handle_terminal_event(&ev);
|
||||
process_launcher.handle_terminal_event(&ev);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
te.handle_terminal_event(&ev);
|
||||
process_launcher.handle_terminal_event(&ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status_chars.clear();
|
||||
let cur = te.get_cursor();
|
||||
let cur = process_launcher.get_cursor();
|
||||
|
||||
if cur.tree_addr.len() > 0 {
|
||||
status_chars.push(TerminalAtom::new('@', TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true))));
|
||||
|
|
197
shell/src/process.rs
Normal file
197
shell/src/process.rs
Normal file
|
@ -0,0 +1,197 @@
|
|||
use {
|
||||
std::{
|
||||
sync::Arc,
|
||||
process::Command,
|
||||
os::unix::io::{FromRawFd, AsRawFd},
|
||||
},
|
||||
std::sync::RwLock,
|
||||
tty::{FileDesc, TtyServer},
|
||||
termion::event::{Key, Event},
|
||||
cgmath::Point2,
|
||||
nested::{
|
||||
core::{ViewPort, OuterViewPort, Observer},
|
||||
singleton::{SingletonView, SingletonBuffer},
|
||||
sequence::{SequenceView, SequenceViewExt},
|
||||
index::buffer::IndexBuffer,
|
||||
vec::VecBuffer,
|
||||
terminal::{TerminalAtom, TerminalStyle, TerminalView, TerminalEvent, TerminalEditor, TerminalEditorResult, make_label},
|
||||
tree_nav::{TreeNav, TreeNavResult, TerminalTreeEditor, TreeCursor},
|
||||
list::{ListEditor, ListEditorStyle, sexpr::ListDecoration},
|
||||
string_editor::CharEditor,
|
||||
}
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub struct ProcessArg {
|
||||
editor: ListEditor< CharEditor,
|
||||
Box<dyn Fn() -> Arc<RwLock<CharEditor>> + Send + Sync + 'static> >
|
||||
}
|
||||
|
||||
impl ProcessArg {
|
||||
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = char>> {
|
||||
self.editor.get_data_port()
|
||||
.map(
|
||||
|char_editor| char_editor.read().unwrap().get_data_port().get_view().unwrap().get().unwrap()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl TerminalEditor for ProcessArg {
|
||||
fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> {
|
||||
self.editor
|
||||
.get_seg_seq_view()
|
||||
.to_grid_horizontal()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
|
||||
match event {
|
||||
TerminalEvent::Input(Event::Key(Key::Char(' '))) |
|
||||
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
|
||||
self.editor.up();
|
||||
TerminalEditorResult::Exit
|
||||
}
|
||||
|
||||
event => self.editor.handle_terminal_event(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TreeNav for ProcessArg {
|
||||
fn get_cursor(&self) -> TreeCursor { self.editor.get_cursor() }
|
||||
fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { self.editor.goto(cur) }
|
||||
fn goto_home(&mut self) -> TreeNavResult { self.editor.goto_home() }
|
||||
fn goto_end(&mut self) -> TreeNavResult { self.editor.goto_end() }
|
||||
fn pxev(&mut self) -> TreeNavResult { self.editor.pxev() }
|
||||
fn nexd(&mut self) -> TreeNavResult { self.editor.nexd() }
|
||||
fn up(&mut self) -> TreeNavResult { self.editor.up() }
|
||||
fn dn(&mut self) -> TreeNavResult { self.editor.dn() }
|
||||
}
|
||||
|
||||
pub struct ProcessLauncher {
|
||||
editor: ListEditor< ProcessArg,
|
||||
Box<dyn Fn() -> Arc<RwLock<ProcessArg>> + Send + Sync + 'static> >
|
||||
}
|
||||
|
||||
impl ProcessLauncher {
|
||||
pub fn new() -> Self {
|
||||
ProcessLauncher {
|
||||
editor: ListEditor::new(
|
||||
Box::new(
|
||||
|| {
|
||||
Arc::new(RwLock::new(ProcessArg {
|
||||
editor: ListEditor::new(
|
||||
Box::new(
|
||||
|| {
|
||||
Arc::new(RwLock::new(CharEditor::new()))
|
||||
}
|
||||
),
|
||||
ListEditorStyle::Plain)
|
||||
}))
|
||||
}
|
||||
),
|
||||
ListEditorStyle::Plain
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn launch(&mut self) -> OuterViewPort<dyn TerminalView> {
|
||||
self.up();
|
||||
self.up();
|
||||
|
||||
let mut strings = Vec::new();
|
||||
|
||||
let v = self.editor.get_data_port().get_view().unwrap();
|
||||
for i in 0 .. v.len().unwrap_or(0) {
|
||||
let arg_view = v.get(&i).unwrap().read().unwrap().get_data_port().get_view().unwrap();
|
||||
strings.push(arg_view.iter().collect::<String>());
|
||||
}
|
||||
|
||||
if strings.len() > 0 {
|
||||
let stdin = FileDesc::new(libc::STDIN_FILENO, false);
|
||||
let mut server = match TtyServer::new(Some(&stdin)) {
|
||||
Ok(s) => s,
|
||||
Err(e) => { return make_label(&format!("Error TTY server: {}", e)); },
|
||||
};
|
||||
|
||||
let mut cmd = std::process::Command::new(strings[0].as_str());
|
||||
cmd.args(&strings[1..]).stdin(std::process::Stdio::null());
|
||||
|
||||
let process = match server.spawn(cmd) {
|
||||
Ok(p) => p,
|
||||
Err(e) => { return make_label(&format!("Failed to execute process: {}", e));},
|
||||
};
|
||||
|
||||
if let Ok(mut term_view_proc) = std::process::Command::new("./target/release/ansi_parser")
|
||||
.stdin(unsafe{ std::process::Stdio::from_raw_fd(server.get_master().as_raw_fd()) })
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.stderr(std::process::Stdio::null())
|
||||
.spawn()
|
||||
{
|
||||
let mut term_view_bin = term_view_proc.stdout.unwrap();
|
||||
/*
|
||||
//let mut term_view_bin = async_std::io::BufReader::new(unsafe { async_std::fs::File::from_raw_fd( term_view_proc.stdout.unwrap().as_raw_fd() ) } );
|
||||
//let mut tv_stream = async_bincode::AsyncBincodeReader::<_, (Point2<i16>, Option<TerminalAtom>)>::from(term_view_bin);
|
||||
|
||||
async_std::task::spawn(
|
||||
async move {
|
||||
*/
|
||||
|
||||
let output_view_port = ViewPort::new();
|
||||
let mut output_buf = IndexBuffer::new(output_view_port.inner());
|
||||
|
||||
while let Ok((pos, atom)) = bincode::deserialize_from(&mut term_view_bin) {
|
||||
if let Some(a) = atom {
|
||||
output_buf.insert(pos, a);
|
||||
} else {
|
||||
output_buf.remove(pos);
|
||||
}
|
||||
}
|
||||
// });
|
||||
output_view_port.outer()
|
||||
} else {
|
||||
make_label("Failed to spawn ansi parser process")
|
||||
.map_item(|idx, a| a.add_style_back(TerminalStyle::fg_color((200,0,0))))
|
||||
}
|
||||
} else {
|
||||
make_label("no command")
|
||||
.map_item(|idx, a| a.add_style_back(TerminalStyle::fg_color((200,0,0))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TerminalEditor for ProcessLauncher {
|
||||
fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> {
|
||||
self.editor
|
||||
.get_seg_seq_view()
|
||||
.decorate("$(", ")", " ", 0)
|
||||
.to_grid_horizontal()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
|
||||
match event {
|
||||
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
|
||||
// launch command
|
||||
self.editor.up();
|
||||
self.editor.up();
|
||||
TerminalEditorResult::Exit
|
||||
}
|
||||
|
||||
event => self.editor.handle_terminal_event(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TreeNav for ProcessLauncher {
|
||||
fn get_cursor(&self) -> TreeCursor { self.editor.get_cursor() }
|
||||
fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { self.editor.goto(cur) }
|
||||
fn goto_home(&mut self) -> TreeNavResult { self.editor.goto_home() }
|
||||
fn goto_end(&mut self) -> TreeNavResult { self.editor.goto_end() }
|
||||
fn pxev(&mut self) -> TreeNavResult { self.editor.pxev() }
|
||||
fn nexd(&mut self) -> TreeNavResult { self.editor.nexd() }
|
||||
fn up(&mut self) -> TreeNavResult { self.editor.up() }
|
||||
fn dn(&mut self) -> TreeNavResult { self.editor.dn() }
|
||||
}
|
||||
|
Loading…
Reference in a new issue