shell: first commander prototype
This commit is contained in:
parent
55eb594521
commit
4e02b41a77
14 changed files with 220 additions and 140 deletions
|
@ -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 {}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 => {
|
||||||
|
*cur_depth = ce.get_cursor().tree_addr.len();
|
||||||
TerminalEditorResult::Continue
|
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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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 {}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -199,6 +215,7 @@ async fn main() {
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
match ev {
|
match ev {
|
||||||
|
|
Loading…
Reference in a new issue