shell: first commander prototype

This commit is contained in:
Michael Sippel 2022-08-12 18:57:40 +02:00
parent 55eb594521
commit 4e02b41a77
14 changed files with 220 additions and 140 deletions

View file

@ -30,6 +30,10 @@ impl CharEditor {
pub fn get_port(&self) -> OuterViewPort<dyn SingletonView<Item = Option<char>>> { pub fn get_port(&self) -> OuterViewPort<dyn SingletonView<Item = Option<char>>> {
self.data.get_port() self.data.get_port()
} }
pub fn get(&self) -> char {
self.get_port().get_view().unwrap().get().unwrap_or('?')
}
} }
impl TreeNav for CharEditor {} impl TreeNav for CharEditor {}

View file

@ -3,22 +3,23 @@ use {
}; };
pub fn bg_style_from_depth(depth: usize) -> TerminalStyle { pub fn bg_style_from_depth(depth: usize) -> TerminalStyle {
if depth == 0 { match depth {
TerminalStyle::default() 0 => TerminalStyle::default(),
} else { 1 => TerminalStyle::bg_color((20,20,20)),
TerminalStyle::bg_color(( 2 => TerminalStyle::default(),
(30.0 / ( 0.90*depth as f64 )) as u8, 3 => TerminalStyle::default(),
(30.0 / ( 0.93*depth as f64 )) as u8, 4 => TerminalStyle::default(),
(50.0 / ( 0.95*depth as f64 )) as u8 5 => TerminalStyle::default(),
)) _ => TerminalStyle::bg_color((80,80,80))
} }
} }
pub fn fg_style_from_depth(depth: usize) -> TerminalStyle { pub fn fg_style_from_depth(depth: usize) -> TerminalStyle {
match depth % 3 { match depth % 3 {
0 => TerminalStyle::fg_color((200, 200, 80)), 0 => TerminalStyle::fg_color((200, 200, 80)),
1 => TerminalStyle::fg_color((80, 200, 200)), 1 => TerminalStyle::fg_color((80, 200, 200)).add(TerminalStyle::bold(true)),
2 => TerminalStyle::fg_color((150, 150, 200)), 2 => TerminalStyle::fg_color((80, 80, 200)),
3 => TerminalStyle::fg_color((200, 80, 200)),
_ => TerminalStyle::default() _ => TerminalStyle::default()
} }
} }

View file

@ -87,7 +87,7 @@ impl PosIntEditor {
PosIntEditor { PosIntEditor {
radix, radix,
digits_editor: PTYListEditor::new( digits_editor: PTYListEditor::new(
Box::new(move || Arc::new(RwLock::new(DigitEditor::new(radix)))), Box::new(move || Arc::new(RwLock::new(DigitEditor::new(radix)))) as Box<dyn Fn() -> Arc<RwLock<DigitEditor>> + Send + Sync>,
SeqDecorStyle::Hex, SeqDecorStyle::Hex,
0 0
), ),
@ -136,7 +136,6 @@ impl TreeNav for PosIntEditor {
fn goby(&mut self, cur: Vector2<isize>) -> TreeNavResult { fn goby(&mut self, cur: Vector2<isize>) -> TreeNavResult {
self.digits_editor.goby(cur) self.digits_editor.goby(cur)
} }
} }
impl TerminalEditor for PosIntEditor { impl TerminalEditor for PosIntEditor {

View file

@ -36,11 +36,11 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static
impl<ItemEditor> ListEditor<ItemEditor> impl<ItemEditor> ListEditor<ItemEditor>
where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static
{ {
pub fn new(make_item_editor: impl Into<Box<dyn Fn() -> Arc<RwLock<ItemEditor>> + Send + Sync>>, depth: usize) -> Self { pub fn new(make_item_editor: impl Fn() -> Arc<RwLock<ItemEditor>> + Send + Sync + 'static, depth: usize) -> Self {
ListEditor { ListEditor {
cursor: SingletonBuffer::new(ListCursor::default()), cursor: SingletonBuffer::new(ListCursor::default()),
data: VecBuffer::<Arc<RwLock<ItemEditor>>>::new(), data: VecBuffer::<Arc<RwLock<ItemEditor>>>::new(),
make_item_editor: make_item_editor.into(), make_item_editor: Box::new(make_item_editor),
depth, depth,
cur_dist: Arc::new(RwLock::new(0)), cur_dist: Arc::new(RwLock::new(0)),
} }

View file

@ -133,6 +133,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static
if direction.y < 0 { if direction.y < 0 {
// up // up
self.cursor.set(ListCursor::none());
TreeNavResult::Exit TreeNavResult::Exit
} else if direction.y > 0 { } else if direction.y > 0 {
// dn // dn

View file

@ -36,7 +36,7 @@ impl<ItemEditor> PTYListEditor<ItemEditor>
where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static
{ {
pub fn new( pub fn new(
make_item_editor: Box<dyn Fn() -> Arc<RwLock<ItemEditor>> + Send + Sync>, make_item_editor: impl Fn() -> Arc<RwLock<ItemEditor>> + Send + Sync + 'static,
style: SeqDecorStyle, style: SeqDecorStyle,
depth: usize depth: usize
) -> Self { ) -> Self {
@ -49,6 +49,20 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static
} }
} }
pub fn from_editor(
editor: ListEditor<ItemEditor>,
style: SeqDecorStyle,
depth: usize
) -> Self {
let port = ViewPort::new();
PTYListEditor {
editor,
style,
depth,
port
}
}
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = Arc<RwLock<ItemEditor>>>> { pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = Arc<RwLock<ItemEditor>>>> {
self.editor.get_data_port() self.editor.get_data_port()
} }
@ -206,3 +220,15 @@ impl<ItemEditor> TerminalTreeEditor for PTYListEditor<ItemEditor>
where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static
{} {}
use crate::{
char_editor::CharEditor,
sequence::SequenceViewExt
};
impl PTYListEditor<CharEditor> {
pub fn get_string(&self) -> String {
self.get_data_port().map(|ce| ce.read().unwrap().get()).get_view().unwrap().iter().collect::<String>()
}
}

View file

@ -46,7 +46,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static
editor.read().unwrap().get_term_view().map_item(move |_pt, atom| { editor.read().unwrap().get_term_view().map_item(move |_pt, atom| {
let cur_depth = e.read().unwrap().get_cursor().tree_addr.len(); let cur_depth = e.read().unwrap().get_cursor().tree_addr.len();
atom.add_style_back(bg_style_from_depth(cur_depth)) atom.add_style_back(bg_style_from_depth(cur_depth))
.add_style_back(fg_style_from_depth(d+cur_depth)) .add_style_back(fg_style_from_depth(d))
}) })
} }
} }

View file

@ -76,13 +76,13 @@ pub fn make_editor(ctx: Arc<RwLock<Context>>, t: &TypeLadder, depth: usize) -> A
} else if t[0] == c.type_term_from_str("( List RGB )").unwrap() { } else if t[0] == c.type_term_from_str("( List RGB )").unwrap() {
Arc::new(RwLock::new( Arc::new(RwLock::new(
PTYListEditor::<dyn TerminalTreeEditor + Send +Sync>::new( PTYListEditor::<dyn TerminalTreeEditor + Send +Sync>::new(
Box::new({ {
let d = depth+1; let d = depth+1;
let ctx = ctx.clone(); let ctx = ctx.clone();
move || { Box::new(move || {
make_editor(ctx.clone(), &vec![ ctx.read().unwrap().type_term_from_str("( RGB )").unwrap() ], d) make_editor(ctx.clone(), &vec![ ctx.read().unwrap().type_term_from_str("( RGB )").unwrap() ], d)
} })
}), },
SeqDecorStyle::VerticalSexpr, SeqDecorStyle::VerticalSexpr,
depth depth
) )
@ -97,7 +97,7 @@ pub fn make_editor(ctx: Arc<RwLock<Context>>, t: &TypeLadder, depth: usize) -> A
.with_n(Point2::new(2, 2), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] ) .with_n(Point2::new(2, 2), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] )
.with_t(Point2::new(1, 3), "b: ") .with_t(Point2::new(1, 3), "b: ")
.with_n(Point2::new(2, 3), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] ) .with_n(Point2::new(2, 3), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] )
.with_t(Point2::new(0, 4), " }") .with_t(Point2::new(0, 4), "}")
)) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>> )) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} else if t[0] == c.type_term_from_str("( Vec3i )").unwrap() { } else if t[0] == c.type_term_from_str("( Vec3i )").unwrap() {
@ -109,7 +109,7 @@ pub fn make_editor(ctx: Arc<RwLock<Context>>, t: &TypeLadder, depth: usize) -> A
.with_n(Point2::new(2, 2), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] ) .with_n(Point2::new(2, 2), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] )
.with_t(Point2::new(1, 3), "z: ") .with_t(Point2::new(1, 3), "z: ")
.with_n(Point2::new(2, 3), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] ) .with_n(Point2::new(2, 3), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] )
.with_t(Point2::new(0, 4), " }") .with_t(Point2::new(0, 4), "}")
)) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>> )) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} else if t[0] == c.type_term_from_str("( Json )").unwrap() { } else if t[0] == c.type_term_from_str("( Json )").unwrap() {
@ -147,14 +147,13 @@ pub fn make_editor(ctx: Arc<RwLock<Context>>, t: &TypeLadder, depth: usize) -> A
} else { // else: term } else { // else: term
Arc::new(RwLock::new( Arc::new(RwLock::new(
PTYListEditor::new( PTYListEditor::new(
Box::new(|| { || {
Arc::new(RwLock::new(CharEditor::new())) Arc::new(RwLock::new(CharEditor::new()))
}), },
SeqDecorStyle::DoubleQuote, SeqDecorStyle::DoubleQuote,
depth depth
) )
)) ))
} }
} }

View file

@ -119,10 +119,11 @@ impl TerminalEditor for ProductEditor {
match event { match event {
TerminalEvent::Input(Event::Key(Key::Backspace)) => { TerminalEvent::Input(Event::Key(Key::Backspace)) => {
*editor = None; *editor = None;
*cur_depth -= 1; *cur_depth = 1;
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
_ => { _ => {
*cur_depth = ce.get_cursor().tree_addr.len();
drop(ce); drop(ce);
match self.nexd() { match self.nexd() {
TreeNavResult::Continue => TerminalEditorResult::Continue, TreeNavResult::Continue => TerminalEditorResult::Continue,
@ -130,15 +131,17 @@ impl TerminalEditor for ProductEditor {
} }
} }
}, },
TerminalEditorResult::Continue => TerminalEditorResult::Continue => {
TerminalEditorResult::Continue *cur_depth = ce.get_cursor().tree_addr.len();
TerminalEditorResult::Continue
}
} }
} else { } else {
let e = make_editor(self.ctx.clone(), t, self.depth+1); let e = make_editor(self.ctx.clone(), t, self.depth+1);
*editor = Some(e.clone()); *editor = Some(e.clone());
e.write().unwrap().dn(); e.write().unwrap().dn();
let x = e.write().unwrap().handle_terminal_event(event); let x = e.write().unwrap().handle_terminal_event(event);
*cur_depth = self.get_cursor().tree_addr.len()+1; *cur_depth = e.write().unwrap().get_cursor().tree_addr.len();
x x
} }
} else { } else {

View file

@ -66,9 +66,15 @@ impl TreeNav for ProductEditor {
self.cursor = Some(crate::modulo(c.tree_addr.remove(0), self.n_indices.len() as isize)); self.cursor = Some(crate::modulo(c.tree_addr.remove(0), self.n_indices.len() as isize));
if let Some(mut element) = self.get_cur_segment_mut() { if let Some(mut element) = self.get_cur_segment_mut() {
if let Some(ProductEditorSegment::N{ t: _t, editor, cur_depth }) = element.deref_mut() { if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() {
if let Some(e) = editor { if let Some(e) = editor {
e.write().unwrap().goto(c.clone()); e.write().unwrap().goto(c.clone());
} else if c.tree_addr.len() > 0 {
// create editor
let e = make_editor(self.ctx.clone(), t, self.depth+1);
*editor = Some(e.clone());
let mut e = e.write().unwrap();
e.goto(c.clone());
} }
*cur_depth = c.tree_addr.len(); *cur_depth = c.tree_addr.len();
} }
@ -111,7 +117,7 @@ impl TreeNav for ProductEditor {
if let Some(e) = editor { if let Some(e) = editor {
let mut e = e.write().unwrap(); let mut e = e.write().unwrap();
e.goby(direction); e.goby(direction);
*cur_depth = e.get_cursor().tree_addr.len(); *cur_depth = e.get_cursor().tree_addr.len() + 1;
} else { } else {
// create editor // create editor
let e = make_editor(self.ctx.clone(), t, self.depth+1); let e = make_editor(self.ctx.clone(), t, self.depth+1);
@ -133,6 +139,12 @@ impl TreeNav for ProductEditor {
self.cursor = None; self.cursor = None;
TreeNavResult::Exit TreeNavResult::Exit
} else { } else {
if let Some(mut element) = self.get_cur_segment_mut() {
if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() {
*cur_depth = 0;
}
}
// horizontal // horizontal
if (cur.tree_addr[0]+direction.x >= 0) && if (cur.tree_addr[0]+direction.x >= 0) &&
(cur.tree_addr[0]+direction.x < self.n_indices.len() as isize) (cur.tree_addr[0]+direction.x < self.n_indices.len() as isize)
@ -142,6 +154,7 @@ impl TreeNav for ProductEditor {
*cur_depth = 0; *cur_depth = 0;
} }
} }
self.cursor = Some(cur.tree_addr[0] + direction.x); self.cursor = Some(cur.tree_addr[0] + direction.x);
if let Some(mut element) = self.get_cur_segment_mut() { if let Some(mut element) = self.get_cur_segment_mut() {
if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() { if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() {
@ -165,21 +178,31 @@ impl TreeNav for ProductEditor {
//\\//\\//\\//\\ //\\//\\//\\//\\
match ce.goby(direction) { match ce.goby(direction) {
TreeNavResult::Exit => { TreeNavResult::Exit => {
*cur_depth = 0; *cur_depth = 1;
drop(ce); drop(ce);
drop(e); drop(e);
if direction.y < 0 { if direction.y < 0 {
if depth <= (1-direction.y) as usize { if depth <= (1-direction.y) as usize {
// up // up
TreeNavResult::Exit *cur_depth = 1;
TreeNavResult::Continue
} else { } else {
panic!("unplausible direction.y on exit");
TreeNavResult::Continue TreeNavResult::Continue
} }
} else if direction.y > 0 { } else if direction.y > 0 {
// dn // dn
*cur_depth = depth + direction.y as usize;
TreeNavResult::Continue TreeNavResult::Continue
} else if direction.y == 0 { } else if direction.y == 0 {
// horizontal // horizontal
if direction.x != 0 {
*cur_depth = 0;
}
if (cur.tree_addr[0]+direction.x >= 0) && if (cur.tree_addr[0]+direction.x >= 0) &&
(cur.tree_addr[0]+direction.x < self.n_indices.len() as isize) (cur.tree_addr[0]+direction.x < self.n_indices.len() as isize)
{ {
@ -205,9 +228,7 @@ impl TreeNav for ProductEditor {
} }
} }
TreeNavResult::Continue => { TreeNavResult::Continue => {
if direction.y > 0 { *cur_depth = (depth as isize + direction.y - 1) as usize;
*cur_depth = depth + direction.y as usize - 1;
}
TreeNavResult::Continue TreeNavResult::Continue
} }
} }

View file

@ -37,16 +37,20 @@ impl ProductEditorSegment {
ProductEditorSegment::N { t: _, editor: Some(e), cur_depth } => ProductEditorSegment::N { t: _, editor: Some(e), cur_depth } =>
e.read().unwrap() e.read().unwrap()
.get_term_view() .get_term_view()
.map_item({ let cur_depth = *cur_depth;//e.read().unwrap().get_cursor().tree_addr.len()+1; .map_item({
move |i, x| x let e = e.clone();
move |i, x| {
let cur_depth = e.read().unwrap().get_cursor().tree_addr.len();
x
.add_style_back(fg_style_from_depth(cur_depth))//fg_color((250,210,0))) .add_style_back(fg_style_from_depth(cur_depth))//fg_color((250,210,0)))
.add_style_back(bg_style_from_depth(cur_depth)) .add_style_back(bg_style_from_depth(cur_depth))
}
}), }),
ProductEditorSegment::N{ t, editor: None, cur_depth } => ProductEditorSegment::N{ t, editor: None, cur_depth } =>
make_label(&ctx.read().unwrap().type_term_to_str(&t[0])) make_label(&ctx.read().unwrap().type_term_to_str(&t[0]))
.map_item({ .map_item({
let cur_depth = *cur_depth; let cur_depth = 0;
move |i, x| x move |i, x| x
.add_style_back(TerminalStyle::fg_color((130,90,40))) .add_style_back(TerminalStyle::fg_color((130,90,40)))
.add_style_back(bg_style_from_depth(cur_depth)) .add_style_back(bg_style_from_depth(cur_depth))

View file

@ -24,6 +24,7 @@ use {
}, },
}; };
#[derive(PartialEq, Eq)]
pub enum TerminalEvent { pub enum TerminalEvent {
Resize(Vector2<i16>), Resize(Vector2<i16>),
Input(termion::event::Event), Input(termion::event::Event),

View file

@ -3,81 +3,107 @@ use {
sync::{Arc, RwLock}, sync::{Arc, RwLock},
collections::HashMap collections::HashMap
}, },
cgmath::{Point2}, cgmath::{Vector2, Point2},
termion::event::{Event, Key}, termion::event::{Event, Key},
nested::{ nested::{
list::{sexpr::ListDecoration, ListEditor, ListEditorStyle}, vec::VecBuffer,
core::TypeTerm, list::{ListEditor, PTYListEditor},
sequence::decorator::{Separate, Wrap, SeqDecorStyle},
core::{TypeTerm, Context},
core::{OuterViewPort, ViewPort}, core::{OuterViewPort, ViewPort},
index::{IndexArea, IndexView}, index::{IndexArea, IndexView},
string_editor::StringEditor, char_editor::CharEditor,
vec::VecBuffer,
terminal::{ terminal::{
TerminalAtom, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView, make_label TerminalAtom, TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView, make_label
}, },
tree_nav::{TreeCursor, TreeNav, TreeNavResult}, tree_nav::{TreeCursor, TreeNav, TreeNavResult, TerminalTreeEditor},
make_editor::make_editor,
product::ProductEditor
} }
}; };
trait Action { trait Action {
fn make_editor(&self) -> fn make_editor(&self, ctx: Arc<RwLock<Context>>) -> Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>;
(Arc<RwLock<dyn TerminalEditor + Send + Sync>>,
Arc<RwLock<dyn TreeNav + Send + Sync>>);
} }
pub struct ActCd {} pub struct ActCd {}
impl Action for ActCd { impl Action for ActCd {
fn make_editor(&self) -> fn make_editor(&self, ctx: Arc<RwLock<Context>>) -> Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>> {
(Arc<RwLock<dyn TerminalEditor + Send + Sync>>, make_editor(
Arc<RwLock<dyn TreeNav + Send + Sync>>) ctx.clone(),
{ &vec![ctx.read().unwrap().type_term_from_str("( Path )").unwrap()],
let ed = 1
Arc::new(RwLock::new(ListEditor::new( )
Box::new(|| {
Arc::new(RwLock::new(StringEditor::new()))
}) as Box<dyn Fn() -> Arc<RwLock<StringEditor>> + Send + Sync>,
ListEditorStyle::HorizontalSexpr,
)));
//Arc::new(RwLock::new(StringEditor::new()));
(ed.clone() as Arc<RwLock<dyn TerminalEditor + Send + Sync>>, ed as Arc<RwLock<dyn TreeNav + Send + Sync>>)
} }
} }
pub struct ActEcho {}
impl Action for ActEcho {
fn make_editor(&self, ctx: Arc<RwLock<Context>>) -> Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>> {
make_editor(
ctx.clone(),
&vec![ctx.read().unwrap().type_term_from_str("( String )").unwrap()],
2
)
}
}
pub struct ActCp {}
impl Action for ActCp {
fn make_editor(&self, ctx: Arc<RwLock<Context>>) -> Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>> {
let depth = 1;
Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone())
.with_t(Point2::new(0, 0), "Source ")
.with_n(Point2::new(1, 0), vec![ ctx.read().unwrap().type_term_from_str("( Path )").unwrap() ] )
.with_t(Point2::new(0, 1), "Destination ")
.with_n(Point2::new(1, 1), vec![ ctx.read().unwrap().type_term_from_str("( Path )").unwrap() ] )
.with_t(Point2::new(0, 2), "Options ")
.with_n(Point2::new(1, 2), vec![ ctx.read().unwrap().type_term_from_str("( List String )").unwrap() ] )
)) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
}
}
pub struct Commander { pub struct Commander {
ctx: Arc<RwLock<Context>>,
cmds: HashMap<String, Arc<dyn Action + Send + Sync>>, cmds: HashMap<String, Arc<dyn Action + Send + Sync>>,
symbol_editor: StringEditor, symbol_editor: PTYListEditor<CharEditor>,
cmd_editor: Option<( cmd_editor: Option<Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>>,
Arc<RwLock<dyn TerminalEditor + Send + Sync>>,
Arc<RwLock<dyn TreeNav + Send + Sync>>
)>,
view_elements: VecBuffer<OuterViewPort<dyn TerminalView>>, view_elements: VecBuffer<OuterViewPort<dyn TerminalView>>,
out_port: OuterViewPort<dyn TerminalView>, out_port: OuterViewPort<dyn TerminalView>,
} }
impl Commander { impl Commander {
pub fn new() -> Self { pub fn new(ctx: Arc<RwLock<Context>>) -> Self {
let port = ViewPort::new(); let port = ViewPort::new();
let mut view_elements = VecBuffer::new(port.inner()); let mut view_elements = VecBuffer::with_port(port.inner());
let symbol_editor = StringEditor::new();
view_elements.push(symbol_editor.get_plain_editor_view()); let symbol_editor = PTYListEditor::new(
|| {
Arc::new(RwLock::new(CharEditor::new()))
},
SeqDecorStyle::Plain,
0
);
view_elements.push(symbol_editor.get_term_view());
let mut cmds = HashMap::new(); let mut cmds = HashMap::new();
cmds.insert("cd".into(), Arc::new(ActCd{}) as Arc<dyn Action + Send + Sync>); cmds.insert("cd".into(), Arc::new(ActCd{}) as Arc<dyn Action + Send + Sync>);
cmds.insert("echo".into(), Arc::new(ActCd{}) as Arc<dyn Action + Send + Sync>); cmds.insert("echo".into(), Arc::new(ActEcho{}) as Arc<dyn Action + Send + Sync>);
cmds.insert("ls".into(), Arc::new(ActCd{}) as Arc<dyn Action + Send + Sync>); cmds.insert("ls".into(), Arc::new(ActCd{}) as Arc<dyn Action + Send + Sync>);
cmds.insert("cp".into(), Arc::new(ActCp{}) as Arc<dyn Action + Send + Sync>);
let mut c = Commander { let mut c = Commander {
ctx,
cmds, cmds,
symbol_editor, symbol_editor,
cmd_editor: None, cmd_editor: None,
view_elements, view_elements,
out_port: port.outer() out_port: port.outer()
.to_sequence() .to_sequence()
.separate(make_label(" "))
.to_grid_horizontal() .to_grid_horizontal()
.flatten() .flatten()
}; };
@ -96,11 +122,11 @@ impl TerminalEditor for Commander {
match event { match event {
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => { TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
// run // run
cmd_editor.1.write().unwrap().up(); cmd_editor.write().unwrap().goto(TreeCursor::none());
TerminalEditorResult::Exit TerminalEditorResult::Exit
} }
event => { event => {
cmd_editor.0.write().unwrap().handle_terminal_event(event) cmd_editor.write().unwrap().handle_terminal_event(event)
} }
} }
} else { } else {
@ -110,14 +136,19 @@ impl TerminalEditor for Commander {
let symbol = self.symbol_editor.get_string(); let symbol = self.symbol_editor.get_string();
if let Some(action) = self.cmds.get(&symbol) { if let Some(action) = self.cmds.get(&symbol) {
let editor = action.make_editor(); let editor = action.make_editor(self.ctx.clone());
self.symbol_editor.up(); self.symbol_editor.up();
self.view_elements.push(make_label(" ")); self.view_elements.push(editor.read().unwrap().get_term_view());
self.view_elements.push(editor.0.read().unwrap().get_term_view());
editor.1.write().unwrap().goto_home(); editor.write().unwrap().qpxev();
self.cmd_editor = Some(editor); self.cmd_editor = Some(editor);
if *event == TerminalEvent::Input(Event::Key(Key::Char('\n'))) {
return self.handle_terminal_event(event);
}
} else {
// undefined command
} }
TerminalEditorResult::Continue TerminalEditorResult::Continue
@ -134,61 +165,34 @@ impl TerminalEditor for Commander {
impl TreeNav for Commander { impl TreeNav for Commander {
fn get_cursor(&self) -> TreeCursor { fn get_cursor(&self) -> TreeCursor {
if let Some(cmd_editor) = self.cmd_editor.as_ref() { if let Some(cmd_editor) = self.cmd_editor.as_ref() {
cmd_editor.1.write().unwrap().get_cursor() cmd_editor.write().unwrap().get_cursor()
} else { } else {
self.symbol_editor.get_cursor() self.symbol_editor.get_cursor()
} }
} }
fn get_cursor_warp(&self) -> TreeCursor {
if let Some(cmd_editor) = self.cmd_editor.as_ref() {
cmd_editor.write().unwrap().get_cursor_warp()
} else {
self.symbol_editor.get_cursor_warp()
}
}
fn goby(&mut self, dir: Vector2<isize>) -> TreeNavResult {
if let Some(cmd_editor) = self.cmd_editor.as_ref() {
cmd_editor.write().unwrap().goby(dir)
} else {
self.symbol_editor.goby(dir)
}
}
fn goto(&mut self, cur: TreeCursor) -> TreeNavResult { fn goto(&mut self, cur: TreeCursor) -> TreeNavResult {
if let Some(cmd_editor) = self.cmd_editor.as_ref() { if let Some(cmd_editor) = self.cmd_editor.as_ref() {
cmd_editor.1.write().unwrap().goto(cur) cmd_editor.write().unwrap().goto(cur)
} else { } else {
self.symbol_editor.goto(cur) self.symbol_editor.goto(cur)
} }
} }
fn goto_home(&mut self) -> TreeNavResult {
if let Some(cmd_editor) = self.cmd_editor.as_ref() {
cmd_editor.1.write().unwrap().goto_home()
} else {
self.symbol_editor.goto_home()
}
}
fn goto_end(&mut self) -> TreeNavResult {
if let Some(cmd_editor) = self.cmd_editor.as_ref() {
cmd_editor.1.write().unwrap().goto_end()
} else {
self.symbol_editor.goto_end()
}
}
fn pxev(&mut self) -> TreeNavResult {
if let Some(cmd_editor) = self.cmd_editor.as_ref() {
cmd_editor.1.write().unwrap().pxev()
} else {
self.symbol_editor.pxev()
}
}
fn nexd(&mut self) -> TreeNavResult {
if let Some(cmd_editor) = self.cmd_editor.as_ref() {
cmd_editor.1.write().unwrap().nexd()
} else {
self.symbol_editor.nexd()
}
}
fn up(&mut self) -> TreeNavResult {
if let Some(cmd_editor) = self.cmd_editor.as_ref() {
cmd_editor.1.write().unwrap().up()
} else {
self.symbol_editor.up()
}
}
fn dn(&mut self) -> TreeNavResult {
if let Some(cmd_editor) = self.cmd_editor.as_ref() {
cmd_editor.1.write().unwrap().dn()
} else {
self.symbol_editor.dn()
}
}
} }
impl TerminalTreeEditor for Commander {}

View file

@ -4,14 +4,17 @@ mod ascii_box;
mod monstera; mod monstera;
mod process; mod process;
mod pty; mod pty;
mod command;
mod plot; mod plot;
use { use {
crate::process::ProcessLauncher, crate::{
process::ProcessLauncher,
command::Commander
},
cgmath::{Point2, Vector2}, cgmath::{Point2, Vector2},
nested::{ nested::{
core::{port::UpdateTask, Observer, OuterViewPort, ViewPort}, core::{port::UpdateTask, Observer, OuterViewPort, ViewPort, Context, TypeTerm},
index::IndexArea, index::IndexArea,
list::{ListCursorMode, PTYListEditor}, list::{ListCursorMode, PTYListEditor},
sequence::{decorator::{SeqDecorStyle}}, sequence::{decorator::{SeqDecorStyle}},
@ -34,9 +37,28 @@ async fn main() {
let mut term = Terminal::new(term_port.outer()); let mut term = Terminal::new(term_port.outer());
let term_writer = term.get_writer(); let term_writer = term.get_writer();
// Update Loop //
let tp = term_port.clone();
async_std::task::spawn(async move {
loop {
tp.update();
async_std::task::sleep(std::time::Duration::from_millis(20)).await;
}
});
async_std::task::spawn(async move { async_std::task::spawn(async move {
let mut table = nested::index::buffer::IndexBuffer::new(); let mut table = nested::index::buffer::IndexBuffer::new();
// Type Context //
let mut ctx = Arc::new(RwLock::new(Context::new()));
for tn in vec![
"MachineWord", "MachineInt", "MachineSyllab", "Bits",
"Vec", "Stream", "Json",
"Sequence", "AsciiString", "UTF-8-String", "Char", "String",
"PosInt", "Digit", "LittleEndian", "BigEndian",
"DiffStream", "", "List", "Path", "Term", "RGB", "Vec3i"
] { ctx.write().unwrap().add_typename(tn.into()); }
let magic = let magic =
make_label("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>").map_item(|pos, atom| { make_label("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>").map_item(|pos, atom| {
atom.add_style_back(TerminalStyle::fg_color(( atom.add_style_back(TerminalStyle::fg_color((
@ -50,7 +72,7 @@ async fn main() {
let mut status_chars = VecBuffer::new(); let mut status_chars = VecBuffer::new();
let mut process_list_editor = PTYListEditor::new( let mut process_list_editor = PTYListEditor::new(
Box::new(|| Arc::new(RwLock::new(ProcessLauncher::new()))), Box::new({let ctx = ctx.clone(); move || Arc::new(RwLock::new(Commander::new(ctx.clone())))}),
SeqDecorStyle::VerticalSexpr, SeqDecorStyle::VerticalSexpr,
0 0
); );
@ -93,7 +115,8 @@ async fn main() {
status_chars.get_port().to_sequence().to_grid_horizontal(), status_chars.get_port().to_sequence().to_grid_horizontal(),
), ),
(Point2::new(0, 2), magic.clone()), (Point2::new(0, 2), magic.clone()),
(Point2::new(0, 3), process_list_editor.get_term_view()),
(Point2::new(0, 4), process_list_editor.get_term_view()),
]); ]);
let (w, h) = termion::terminal_size().unwrap(); let (w, h) = termion::terminal_size().unwrap();
@ -125,14 +148,6 @@ async fn main() {
tree_addr: vec![0], tree_addr: vec![0],
}); });
let tp = term_port.clone();
async_std::task::spawn(async move {
loop {
tp.update();
async_std::task::sleep(std::time::Duration::from_millis(10)).await;
}
});
loop { loop {
status_chars.clear(); status_chars.clear();
let cur = process_list_editor.get_cursor(); let cur = process_list_editor.get_cursor();
@ -191,6 +206,7 @@ async fn main() {
if let Some(process_editor) = process_list_editor.get_item() { if let Some(process_editor) = process_list_editor.get_item() {
let mut pe = process_editor.write().unwrap(); let mut pe = process_editor.write().unwrap();
/*
if pe.is_captured() { if pe.is_captured() {
if let TerminalEditorResult::Exit = pe.handle_terminal_event(&ev) { if let TerminalEditorResult::Exit = pe.handle_terminal_event(&ev) {
drop(pe); drop(pe);
@ -198,7 +214,8 @@ async fn main() {
process_list_editor.nexd(); process_list_editor.nexd();
} }
continue; continue;
} }
*/
} }
match ev { match ev {