2021-08-11 17:49:58 +02:00
|
|
|
|
2021-09-15 15:24:39 +02:00
|
|
|
extern crate portable_pty;
|
2021-09-03 06:49:18 +02:00
|
|
|
|
2021-08-11 17:56:42 +02:00
|
|
|
mod monstera;
|
2021-09-03 06:49:18 +02:00
|
|
|
mod process;
|
2021-09-15 17:47:40 +02:00
|
|
|
mod pty;
|
2021-09-24 23:31:09 +02:00
|
|
|
mod ascii_box;
|
2021-08-11 17:49:58 +02:00
|
|
|
|
|
|
|
use{
|
|
|
|
std::sync::{Arc, RwLock},
|
|
|
|
cgmath::{Point2, Vector2},
|
2021-06-05 23:30:40 +02:00
|
|
|
termion::event::{Event, Key},
|
|
|
|
nested::{
|
|
|
|
core::{
|
2021-08-11 17:49:58 +02:00
|
|
|
View,
|
2021-06-05 23:30:40 +02:00
|
|
|
ViewPort,
|
2021-09-15 17:47:40 +02:00
|
|
|
InnerViewPort,
|
2021-06-05 23:30:40 +02:00
|
|
|
OuterViewPort,
|
2021-08-11 17:49:58 +02:00
|
|
|
Observer,
|
|
|
|
ObserverExt,
|
2021-09-15 17:47:40 +02:00
|
|
|
ObserverBroadcast,
|
2021-08-11 17:49:58 +02:00
|
|
|
context::{ReprTree, Object, MorphismType, MorphismMode, Context},
|
|
|
|
port::{UpdateTask}},
|
2021-11-07 07:16:33 +01:00
|
|
|
index::{IndexView, IndexArea},
|
2021-09-13 01:52:37 +02:00
|
|
|
grid::{GridWindowIterator},
|
2021-09-03 06:49:18 +02:00
|
|
|
sequence::{SequenceView, SequenceViewExt},
|
2021-08-11 17:49:58 +02:00
|
|
|
vec::{VecBuffer},
|
2021-09-03 06:49:18 +02:00
|
|
|
integer::{RadixProjection, DigitEditor, PosIntEditor},
|
2021-08-11 17:49:58 +02:00
|
|
|
terminal::{
|
|
|
|
Terminal,
|
|
|
|
TerminalStyle,
|
|
|
|
TerminalAtom,
|
|
|
|
TerminalCompositor,
|
|
|
|
TerminalEvent,
|
|
|
|
make_label,
|
|
|
|
TerminalView,
|
|
|
|
TerminalEditor},
|
2021-09-03 06:49:18 +02:00
|
|
|
string_editor::{StringEditor},
|
2021-08-26 08:20:51 +02:00
|
|
|
tree_nav::{TreeNav, TreeNavResult, TreeCursor, TerminalTreeEditor},
|
2021-11-09 02:57:24 +01:00
|
|
|
list::{SExprView, ListCursorMode, ListEditor, ListEditorStyle},
|
|
|
|
projection::ProjectionHelper
|
2021-09-03 06:49:18 +02:00
|
|
|
},
|
|
|
|
crate::{
|
|
|
|
process::ProcessLauncher
|
2021-06-05 23:30:40 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-11-07 07:16:33 +01:00
|
|
|
struct TestView {}
|
|
|
|
|
|
|
|
impl View for TestView {
|
|
|
|
type Msg = IndexArea<Point2<i16>>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IndexView<Point2<i16>> for TestView {
|
|
|
|
type Item = TerminalAtom;
|
|
|
|
|
|
|
|
fn get(&self, pt: &Point2<i16>) -> Option<TerminalAtom> {
|
|
|
|
Some(TerminalAtom::from('.'))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn area(&self) -> IndexArea<Point2<i16>> {
|
|
|
|
IndexArea::Full
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-09 02:57:24 +01:00
|
|
|
struct Plot {
|
|
|
|
limit: usize,
|
|
|
|
data: Arc<dyn SequenceView<Item = usize>>,
|
|
|
|
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
|
|
|
|
proj_helper: ProjectionHelper<(), Self>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl View for Plot {
|
|
|
|
type Msg = IndexArea<Point2<i16>>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IndexView<Point2<i16>> for Plot {
|
|
|
|
type Item = TerminalAtom;
|
|
|
|
|
|
|
|
fn get(&self, pt: &Point2<i16>) -> Option<TerminalAtom> {
|
|
|
|
if pt.y >= 0 {
|
|
|
|
if let Some(cur_val) = self.data.get(&(pt.x as usize)) {
|
|
|
|
if cur_val <= self.limit {
|
|
|
|
if pt.y == (self.limit - cur_val) as i16 {
|
|
|
|
return Some(TerminalAtom::from('*'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if pt.x > 0 {
|
|
|
|
if let Some(prev_val) = self.data.get(&((pt.x-1) as usize)) {
|
|
|
|
if
|
|
|
|
(
|
|
|
|
pt.y > (self.limit - prev_val) as i16 &&
|
|
|
|
pt.y < (self.limit - cur_val) as i16
|
|
|
|
)
|
|
|
|
||
|
|
|
|
(
|
|
|
|
pt.y < (self.limit - prev_val) as i16 &&
|
|
|
|
pt.y > (self.limit - cur_val) as i16
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return Some(TerminalAtom::from('|'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
fn area(&self) -> IndexArea<Point2<i16>> {
|
|
|
|
IndexArea::Range(
|
|
|
|
Point2::new(0,0)
|
|
|
|
..= Point2::new(
|
|
|
|
self.data.len().unwrap_or(0) as i16,
|
|
|
|
self.limit as i16
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Plot {
|
|
|
|
pub fn new(
|
|
|
|
data_port: OuterViewPort<dyn SequenceView<Item = usize>>,
|
|
|
|
out_port: InnerViewPort<dyn TerminalView>
|
|
|
|
) -> Arc<RwLock<Self>> {
|
|
|
|
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
|
|
|
|
let proj = Arc::new(RwLock::new(
|
|
|
|
Plot {
|
|
|
|
data: proj_helper.new_sequence_arg(
|
|
|
|
(),
|
|
|
|
data_port,
|
|
|
|
|s: &mut Self, idx| {
|
|
|
|
let val = s.data.get(idx).unwrap_or(0);
|
|
|
|
|
|
|
|
if val > s.limit {
|
|
|
|
s.limit = val;
|
|
|
|
s.cast.notify(&s.area());
|
|
|
|
} else {
|
|
|
|
s.cast.notify(&IndexArea::Range(
|
|
|
|
Point2::new(*idx as i16, 0)
|
|
|
|
..= Point2::new(*idx as i16, s.limit as i16)
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
),
|
|
|
|
|
|
|
|
limit: 0,
|
|
|
|
cast: out_port.get_broadcast(),
|
|
|
|
proj_helper
|
|
|
|
}
|
|
|
|
));
|
|
|
|
|
|
|
|
proj.write().unwrap().proj_helper.set_proj(&proj);
|
|
|
|
out_port.set_view(Some(proj.clone()));
|
|
|
|
|
|
|
|
proj
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-05 23:30:40 +02:00
|
|
|
#[async_std::main]
|
|
|
|
async fn main() {
|
|
|
|
let term_port = ViewPort::new();
|
|
|
|
let compositor = TerminalCompositor::new(term_port.inner());
|
|
|
|
|
|
|
|
let mut term = Terminal::new(term_port.outer());
|
|
|
|
let term_writer = term.get_writer();
|
|
|
|
|
|
|
|
async_std::task::spawn(
|
|
|
|
async move {
|
2021-08-28 17:01:31 +02:00
|
|
|
let table_port = ViewPort::<dyn nested::grid::GridView<Item = OuterViewPort<dyn TerminalView>>>::new();
|
|
|
|
let mut table_buf = nested::index::buffer::IndexBuffer::new(table_port.inner());
|
|
|
|
|
2021-11-09 02:57:24 +01:00
|
|
|
let magic =
|
|
|
|
make_label("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>")
|
2021-08-28 17:01:31 +02:00
|
|
|
.map_item(
|
|
|
|
|pos, atom|
|
|
|
|
atom.add_style_back(
|
|
|
|
TerminalStyle::fg_color(
|
|
|
|
(5,
|
|
|
|
((80+(pos.x*30)%100) as u8),
|
|
|
|
(55+(pos.x*15)%180) as u8)
|
2021-06-05 23:30:40 +02:00
|
|
|
)
|
2021-08-28 17:01:31 +02:00
|
|
|
)
|
|
|
|
);
|
2021-06-05 23:30:40 +02:00
|
|
|
|
2021-08-11 17:49:58 +02:00
|
|
|
let cur_size_port = ViewPort::new();
|
|
|
|
let mut cur_size = nested::singleton::SingletonBuffer::new(Vector2::new(10, 10), cur_size_port.inner());
|
|
|
|
|
2021-08-16 01:27:35 +02:00
|
|
|
let status_chars_port = ViewPort::new();
|
|
|
|
let mut status_chars = VecBuffer::new(status_chars_port.inner());
|
|
|
|
|
2021-09-24 23:31:09 +02:00
|
|
|
let mut process_list_editor = ListEditor::new(
|
|
|
|
Box::new(|| {
|
|
|
|
Arc::new(RwLock::new(
|
|
|
|
ProcessLauncher::new()
|
|
|
|
))
|
|
|
|
}),
|
|
|
|
ListEditorStyle::VerticalSexpr
|
|
|
|
);
|
|
|
|
|
2021-11-09 02:57:24 +01:00
|
|
|
|
|
|
|
let plist_vec_port = ViewPort::new();
|
|
|
|
let mut plist = VecBuffer::new(plist_vec_port.inner());
|
|
|
|
|
|
|
|
async_std::task::spawn(async move {
|
|
|
|
let (w, h) = termion::terminal_size().unwrap();
|
|
|
|
let mut x : usize = 0;
|
|
|
|
loop {
|
|
|
|
let val =
|
|
|
|
(
|
|
|
|
5.0 + (x as f32 / 3.0).sin() * 5.0 +
|
|
|
|
2.0 + ((7+x) as f32 / 5.0).sin() * 2.0 +
|
|
|
|
2.0 + ((9+x) as f32 / 10.0).cos() * 3.0
|
|
|
|
) as usize;
|
|
|
|
|
|
|
|
if x < w as usize {
|
|
|
|
plist.push(val);
|
|
|
|
} else {
|
|
|
|
*plist.get_mut(x % (w as usize)) = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
x+=1;
|
|
|
|
async_std::task::sleep(std::time::Duration::from_millis(10)).await;
|
|
|
|
|
|
|
|
if x%(w as usize) == 0 {
|
|
|
|
async_std::task::sleep(std::time::Duration::from_secs(3)).await;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
let plot_port = ViewPort::new();
|
|
|
|
let plot = Plot::new(plist_vec_port.outer().to_sequence(), plot_port.inner());
|
|
|
|
|
2021-08-28 17:01:31 +02:00
|
|
|
table_buf.insert_iter(vec![
|
|
|
|
(Point2::new(0, 0), magic.clone()),
|
2021-09-03 06:49:18 +02:00
|
|
|
(Point2::new(0, 1), status_chars_port.outer().to_sequence().to_grid_horizontal()),
|
2021-09-13 01:52:37 +02:00
|
|
|
(Point2::new(0, 2), magic.clone()),
|
2021-11-09 02:57:24 +01:00
|
|
|
(Point2::new(0, 3), process_list_editor.get_term_view()),
|
2021-08-28 17:01:31 +02:00
|
|
|
]);
|
|
|
|
|
2021-11-09 02:57:24 +01:00
|
|
|
let (w, h) = termion::terminal_size().unwrap();
|
|
|
|
|
|
|
|
compositor.write().unwrap().push(
|
|
|
|
plot_port.outer()
|
|
|
|
.map_item(|pt,a| {
|
|
|
|
a.add_style_back(TerminalStyle::fg_color((255 - pt.y as u8 * 8, 100, pt.y as u8 *15)))
|
|
|
|
})
|
|
|
|
.offset(Vector2::new(0,h as i16-20))
|
|
|
|
);
|
|
|
|
|
|
|
|
compositor.write().unwrap().push(
|
|
|
|
monstera::make_monstera()
|
|
|
|
.offset(Vector2::new(w as i16-38, 0)));
|
|
|
|
|
|
|
|
compositor.write().unwrap().push(
|
|
|
|
table_port.outer()
|
|
|
|
.flatten()
|
|
|
|
.offset(Vector2::new(3, 0))
|
|
|
|
);
|
2021-08-28 17:01:31 +02:00
|
|
|
|
2021-09-24 23:31:09 +02:00
|
|
|
process_list_editor.goto(TreeCursor {
|
2021-09-03 06:49:18 +02:00
|
|
|
leaf_mode: ListCursorMode::Insert,
|
|
|
|
tree_addr: vec![ 0 ]
|
|
|
|
});
|
2021-09-15 17:47:40 +02:00
|
|
|
|
2021-11-07 07:16:33 +01:00
|
|
|
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;
|
2021-09-15 17:47:40 +02:00
|
|
|
}
|
|
|
|
}
|
2021-11-07 07:16:33 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
loop {
|
2021-09-15 17:47:40 +02:00
|
|
|
let ev = term.next_event().await;
|
|
|
|
match ev {
|
2021-08-11 17:49:58 +02:00
|
|
|
TerminalEvent::Resize(new_size) => {
|
|
|
|
cur_size.set(new_size);
|
2021-11-07 07:16:33 +01:00
|
|
|
term_port.inner().get_broadcast().notify(&IndexArea::Full);
|
2021-08-11 17:49:58 +02:00
|
|
|
}
|
|
|
|
TerminalEvent::Input(Event::Key(Key::Ctrl('c'))) |
|
|
|
|
TerminalEvent::Input(Event::Key(Key::Ctrl('g'))) |
|
|
|
|
TerminalEvent::Input(Event::Key(Key::Ctrl('d'))) => break,
|
2021-08-15 04:27:09 +02:00
|
|
|
|
|
|
|
TerminalEvent::Input(Event::Key(Key::Left)) => {
|
2021-09-24 23:31:09 +02:00
|
|
|
process_list_editor.pxev();
|
2021-08-15 04:27:09 +02:00
|
|
|
}
|
|
|
|
TerminalEvent::Input(Event::Key(Key::Right)) => {
|
2021-09-24 23:31:09 +02:00
|
|
|
process_list_editor.nexd();
|
2021-08-15 04:27:09 +02:00
|
|
|
}
|
2021-09-15 17:47:40 +02:00
|
|
|
TerminalEvent::Input(Event::Key(Key::Up)) => {
|
2021-09-24 23:31:09 +02:00
|
|
|
if process_list_editor.up() == TreeNavResult::Exit {
|
|
|
|
process_list_editor.dn();
|
|
|
|
process_list_editor.goto_home();
|
2021-09-15 17:47:40 +02:00
|
|
|
}
|
|
|
|
}
|
2021-08-31 02:11:49 +02:00
|
|
|
TerminalEvent::Input(Event::Key(Key::Down)) => {
|
2021-09-24 23:31:09 +02:00
|
|
|
if process_list_editor.dn() == TreeNavResult::Continue {
|
|
|
|
process_list_editor.goto_home();
|
2021-08-31 02:11:49 +02:00
|
|
|
}
|
|
|
|
}
|
2021-08-16 01:27:35 +02:00
|
|
|
TerminalEvent::Input(Event::Key(Key::Home)) => {
|
2021-09-24 23:31:09 +02:00
|
|
|
process_list_editor.goto_home();
|
2021-08-16 01:27:35 +02:00
|
|
|
}
|
|
|
|
TerminalEvent::Input(Event::Key(Key::End)) => {
|
2021-09-24 23:31:09 +02:00
|
|
|
process_list_editor.goto_end();
|
2021-08-16 01:27:35 +02:00
|
|
|
}
|
2021-08-11 17:49:58 +02:00
|
|
|
TerminalEvent::Input(Event::Key(Key::Char('\n'))) => {
|
2021-11-07 08:50:36 +01:00
|
|
|
if let Some(launcher) = process_list_editor.get_item() {
|
|
|
|
launcher.write().unwrap().launch_pty2();
|
|
|
|
}
|
2021-09-03 06:49:18 +02:00
|
|
|
}
|
2021-08-11 17:49:58 +02:00
|
|
|
|
|
|
|
ev => {
|
2021-09-24 23:31:09 +02:00
|
|
|
if process_list_editor.get_cursor().leaf_mode == ListCursorMode::Select {
|
2021-08-26 08:20:51 +02:00
|
|
|
match ev {
|
2021-09-24 23:31:09 +02:00
|
|
|
TerminalEvent::Input(Event::Key(Key::Char('l'))) => { process_list_editor.up(); },
|
|
|
|
TerminalEvent::Input(Event::Key(Key::Char('a'))) => { process_list_editor.dn(); },
|
|
|
|
TerminalEvent::Input(Event::Key(Key::Char('i'))) => { process_list_editor.pxev(); },
|
|
|
|
TerminalEvent::Input(Event::Key(Key::Char('e'))) => { process_list_editor.nexd(); },
|
|
|
|
TerminalEvent::Input(Event::Key(Key::Char('u'))) => { process_list_editor.goto_home(); },
|
|
|
|
TerminalEvent::Input(Event::Key(Key::Char('o'))) => { process_list_editor.goto_end(); },
|
2021-08-26 08:20:51 +02:00
|
|
|
_ => {
|
2021-09-24 23:31:09 +02:00
|
|
|
process_list_editor.handle_terminal_event(&ev);
|
2021-08-26 08:20:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2021-09-24 23:31:09 +02:00
|
|
|
process_list_editor.handle_terminal_event(&ev);
|
2021-08-26 08:20:51 +02:00
|
|
|
}
|
2021-08-11 17:49:58 +02:00
|
|
|
}
|
2021-06-05 23:30:40 +02:00
|
|
|
}
|
2021-08-16 01:27:35 +02:00
|
|
|
|
|
|
|
status_chars.clear();
|
2021-09-24 23:31:09 +02:00
|
|
|
let cur = process_list_editor.get_cursor();
|
2021-08-26 08:20:51 +02:00
|
|
|
|
|
|
|
if cur.tree_addr.len() > 0 {
|
2021-08-23 05:00:57 +02:00
|
|
|
status_chars.push(TerminalAtom::new('@', TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true))));
|
|
|
|
for x in cur.tree_addr {
|
|
|
|
for c in format!("{}", x).chars() {
|
|
|
|
status_chars.push(TerminalAtom::new(c, TerminalStyle::fg_color((0, 100, 20))));
|
2021-08-16 01:27:35 +02:00
|
|
|
}
|
2021-08-23 05:00:57 +02:00
|
|
|
status_chars.push(TerminalAtom::new('.', TerminalStyle::fg_color((120, 80, 80))));
|
|
|
|
}
|
|
|
|
|
|
|
|
status_chars.push(TerminalAtom::new(':', TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true))));
|
|
|
|
for c in
|
|
|
|
match cur.leaf_mode {
|
|
|
|
ListCursorMode::Insert => "INSERT",
|
|
|
|
ListCursorMode::Select => "SELECT",
|
|
|
|
ListCursorMode::Modify => "MODIFY"
|
|
|
|
}.chars()
|
|
|
|
{
|
|
|
|
status_chars.push(TerminalAtom::new(c, TerminalStyle::fg_color((200, 200, 20))));
|
2021-08-16 01:27:35 +02:00
|
|
|
}
|
2021-08-23 05:00:57 +02:00
|
|
|
status_chars.push(TerminalAtom::new(':', TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true))));
|
2021-08-31 02:11:49 +02:00
|
|
|
} else {
|
|
|
|
for c in "Press <DN> to enter".chars() {
|
|
|
|
status_chars.push(TerminalAtom::new(c, TerminalStyle::fg_color((200, 200, 20))));
|
|
|
|
}
|
2021-08-16 01:27:35 +02:00
|
|
|
}
|
2021-06-05 23:30:40 +02:00
|
|
|
}
|
|
|
|
|
2021-11-07 07:16:33 +01:00
|
|
|
drop(term);
|
|
|
|
drop(term_port);
|
2021-06-05 23:30:40 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
term_writer.show().await.expect("output error!");
|
|
|
|
}
|
|
|
|
|