mirror of
https://git.meli.delivery/meli/meli
synced 2024-10-30 21:20:34 +00:00
parent
0aef7e03a5
commit
2df22c2da9
33
src/bin.rs
33
src/bin.rs
@ -39,7 +39,9 @@ extern crate chan_signal;
|
||||
|
||||
use chan_signal::Signal;
|
||||
|
||||
fn make_input_thread(sx: chan::Sender<ThreadEvent>, rx: chan::Receiver<bool>) -> () {
|
||||
extern crate nix;
|
||||
|
||||
fn make_input_thread(sx: chan::Sender<ThreadEvent>, rx: chan::Receiver<bool>) -> thread::JoinHandle<()> {
|
||||
let stdin = std::io::stdin();
|
||||
thread::Builder::new().name("input-thread".to_string()).spawn(move || {
|
||||
|
||||
@ -49,14 +51,12 @@ fn make_input_thread(sx: chan::Sender<ThreadEvent>, rx: chan::Receiver<bool>) ->
|
||||
},
|
||||
|| {
|
||||
sx.send(ThreadEvent::UIEventType(UIEventType::ChangeMode(UIMode::Fork)));
|
||||
}, rx)}).unwrap();
|
||||
|
||||
|
||||
}, rx)}).unwrap()
|
||||
}
|
||||
fn main() {
|
||||
/* Lock all stdio outs */
|
||||
let _stdout = stdout();
|
||||
let mut _stdout = _stdout.lock();
|
||||
//let _stdout = stdout();
|
||||
//let mut _stdout = _stdout.lock();
|
||||
/*
|
||||
let _stderr = stderr();
|
||||
let mut _stderr = _stderr.lock();
|
||||
@ -75,11 +75,11 @@ fn main() {
|
||||
* stdin, see get_events() for details
|
||||
* */
|
||||
let (tx, rx) = chan::async();
|
||||
/* Get input thread handle to kill it if we need to */
|
||||
make_input_thread(sender.clone(), rx.clone());
|
||||
/* Get input thread handle to join it if we need to */
|
||||
let mut _thread_handler = make_input_thread(sender.clone(), rx.clone());
|
||||
|
||||
/* Create the application State. This is the 'System' part of an ECS architecture */
|
||||
let mut state = State::new(_stdout, sender.clone(), tx );
|
||||
let mut state = State::new(sender.clone(), tx );
|
||||
|
||||
/* Register some reasonably useful interfaces */
|
||||
let menu = Entity {component: Box::new(AccountMenu::new(&state.context.accounts)) };
|
||||
@ -109,6 +109,18 @@ fn main() {
|
||||
chan_select! {
|
||||
receiver.recv() -> r => {
|
||||
match r.unwrap() {
|
||||
ThreadEvent::Input(Key::Ctrl('z')) => {
|
||||
state.to_main_screen();
|
||||
//_thread_handler.join().expect("Couldn't join on the associated thread");
|
||||
let self_pid = nix::unistd::Pid::this();
|
||||
nix::sys::signal::kill(self_pid, nix::sys::signal::Signal::SIGSTOP).unwrap();
|
||||
state.to_alternate_screen();
|
||||
_thread_handler = make_input_thread(sender.clone(), rx.clone());
|
||||
// BUG: thread sends input event after one received key
|
||||
state.update_size();
|
||||
state.render();
|
||||
state.redraw();
|
||||
},
|
||||
ThreadEvent::Input(k) => {
|
||||
match state.mode {
|
||||
UIMode::Normal => {
|
||||
@ -183,10 +195,9 @@ fn main() {
|
||||
},
|
||||
Some(false) => {
|
||||
use std::{thread, time};
|
||||
|
||||
let ten_millis = time::Duration::from_millis(1500);
|
||||
|
||||
thread::sleep(ten_millis);
|
||||
|
||||
continue 'reap;
|
||||
},
|
||||
None => {break 'reap;},
|
||||
|
@ -456,7 +456,7 @@ impl Component for MailListing {
|
||||
context.replies.push_back(UIEvent { id: 0, event_type: UIEventType::ChangeMode(UIMode::Fork) });
|
||||
return;
|
||||
},
|
||||
UIEventType::Input(Key::Esc) | UIEventType::Input(Key::Char('i')) if self.unfocused == true => {
|
||||
UIEventType::Input(Key::Char('i')) if self.unfocused == true => {
|
||||
self.unfocused = false;
|
||||
self.dirty = true;
|
||||
self.view = None;
|
||||
|
@ -167,10 +167,18 @@ impl Component for MailView {
|
||||
|
||||
fn process_event(&mut self, event: &UIEvent, context: &mut Context) {
|
||||
match event.event_type {
|
||||
UIEventType::Input(Key::Esc) => {
|
||||
match self.mode {
|
||||
ViewMode::Url => {
|
||||
self.cmd_buf.clear();
|
||||
return;
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
},
|
||||
UIEventType::Input(Key::Char(c)) if c >= '0' && c <= '9' => { //TODO:this should be an Action
|
||||
match self.mode {
|
||||
ViewMode::Url => { self.cmd_buf.push(c);
|
||||
eprintln!("buf is {}", self.cmd_buf);
|
||||
return; },
|
||||
_ => {},
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ pub struct State<W: Write> {
|
||||
rows: usize,
|
||||
|
||||
grid: CellBuffer,
|
||||
stdout: termion::screen::AlternateScreen<termion::raw::RawTerminal<W>>,
|
||||
stdout: Option<termion::screen::AlternateScreen<termion::raw::RawTerminal<W>>>,
|
||||
child: Option<ForkType>,
|
||||
pub mode: UIMode,
|
||||
sender: Sender<ThreadEvent>,
|
||||
@ -188,16 +188,18 @@ pub struct State<W: Write> {
|
||||
impl<W: Write> Drop for State<W> {
|
||||
fn drop(&mut self) {
|
||||
// When done, restore the defaults to avoid messing with the terminal.
|
||||
write!(self.stdout, "{}{}{}{}", clear::All, style::Reset, cursor::Goto(1, 1), cursor::Show).unwrap();
|
||||
self.stdout.flush().unwrap();
|
||||
write!(self.stdout(), "{}{}{}{}", clear::All, style::Reset, cursor::Goto(1, 1), cursor::Show).unwrap();
|
||||
self.flush();
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> State<W> {
|
||||
pub fn new(stdout: W, sender: Sender<ThreadEvent>, input_thread: chan::Sender<bool>) -> Self {
|
||||
impl State<std::io::Stdout> {
|
||||
pub fn new(sender: Sender<ThreadEvent>, input_thread: chan::Sender<bool>) -> Self {
|
||||
let _stdout = std::io::stdout();
|
||||
_stdout.lock();
|
||||
let settings = Settings::new();
|
||||
let backends = Backends::new();
|
||||
let stdout = AlternateScreen::from(stdout.into_raw_mode().unwrap());
|
||||
let stdout = AlternateScreen::from(_stdout.into_raw_mode().unwrap());
|
||||
|
||||
let termsize = termion::terminal_size().ok();
|
||||
let termcols = termsize.map(|(w,_)| w);
|
||||
@ -210,7 +212,7 @@ impl<W: Write> State<W> {
|
||||
cols: cols,
|
||||
rows: rows,
|
||||
grid: CellBuffer::new(cols, rows, Cell::with_char(' ')),
|
||||
stdout: stdout,
|
||||
stdout: Some(stdout),
|
||||
child: None,
|
||||
mode: UIMode::Normal,
|
||||
sender: sender,
|
||||
@ -228,8 +230,8 @@ impl<W: Write> State<W> {
|
||||
input_thread: input_thread,
|
||||
},
|
||||
};
|
||||
write!(s.stdout, "{}{}{}", cursor::Hide, clear::All, cursor::Goto(1,1)).unwrap();
|
||||
s.stdout.flush().unwrap();
|
||||
write!(s.stdout(), "{}{}{}", cursor::Hide, clear::All, cursor::Goto(1,1)).unwrap();
|
||||
s.flush();
|
||||
for account in &mut s.context.accounts {
|
||||
let sender = s.sender.clone();
|
||||
account.watch(RefreshEventConsumer::new(Box::new(move |r| {
|
||||
@ -239,6 +241,22 @@ impl<W: Write> State<W> {
|
||||
}
|
||||
s
|
||||
}
|
||||
pub fn to_main_screen(&mut self) {
|
||||
write!(self.stdout(), "{}{}", termion::screen::ToMainScreen, cursor::Show).unwrap();
|
||||
self.flush();
|
||||
self.stdout = None;
|
||||
self.context.input_thread.send(false);
|
||||
}
|
||||
pub fn to_alternate_screen(&mut self) {
|
||||
let s = std::io::stdout();
|
||||
s.lock();
|
||||
self.stdout = Some(AlternateScreen::from(s.into_raw_mode().unwrap()));
|
||||
|
||||
write!(self.stdout(), "{}", termion::screen::ToAlternateScreen).unwrap();
|
||||
self.flush();
|
||||
}
|
||||
}
|
||||
impl<W: Write> State<W> {
|
||||
pub fn update_size(&mut self) {
|
||||
let termsize = termion::terminal_size().ok();
|
||||
let termcols = termsize.map(|(w,_)| w);
|
||||
@ -269,27 +287,27 @@ impl<W: Write> State<W> {
|
||||
let bottom_right = bottom_right!(area);
|
||||
|
||||
for y in get_y(upper_left)..=get_y(bottom_right) {
|
||||
write!(self.stdout, "{}", cursor::Goto(get_x(upper_left) as u16 + 1,(y+1) as u16)).unwrap();
|
||||
write!(self.stdout(), "{}", cursor::Goto(get_x(upper_left) as u16 + 1,(y+1) as u16)).unwrap();
|
||||
for x in get_x(upper_left)..=get_x(bottom_right) {
|
||||
let c = self.grid[(x,y)];
|
||||
|
||||
if c.bg() != cells::Color::Default {
|
||||
write!(self.stdout, "{}", termion::color::Bg(c.bg().as_termion())).unwrap();
|
||||
write!(self.stdout(), "{}", termion::color::Bg(c.bg().as_termion())).unwrap();
|
||||
}
|
||||
if c.fg() != cells::Color::Default {
|
||||
write!(self.stdout, "{}", termion::color::Fg(c.fg().as_termion())).unwrap();
|
||||
write!(self.stdout(), "{}", termion::color::Fg(c.fg().as_termion())).unwrap();
|
||||
}
|
||||
write!(self.stdout, "{}",c.ch()).unwrap();
|
||||
write!(self.stdout(), "{}",c.ch()).unwrap();
|
||||
if c.bg() != cells::Color::Default {
|
||||
write!(self.stdout, "{}", termion::color::Bg(termion::color::Reset)).unwrap();
|
||||
write!(self.stdout(), "{}", termion::color::Bg(termion::color::Reset)).unwrap();
|
||||
}
|
||||
if c.fg() != cells::Color::Default {
|
||||
write!(self.stdout, "{}", termion::color::Fg(termion::color::Reset)).unwrap();
|
||||
write!(self.stdout(), "{}", termion::color::Fg(termion::color::Reset)).unwrap();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
self.stdout.flush().unwrap();
|
||||
self.flush();
|
||||
}
|
||||
pub fn render(&mut self) {
|
||||
self.update_size();
|
||||
@ -338,7 +356,7 @@ impl<W: Write> State<W> {
|
||||
UIEventType::Fork(child) => {
|
||||
self.mode = UIMode::Fork;
|
||||
self.child = Some(child);
|
||||
self.stdout.flush().unwrap();
|
||||
self.flush();
|
||||
return;
|
||||
},
|
||||
UIEventType::EditDraft(dir) => {
|
||||
@ -422,10 +440,17 @@ impl<W: Write> State<W> {
|
||||
}
|
||||
Some(false)
|
||||
}
|
||||
fn flush(&mut self) {
|
||||
self.stdout.as_mut().map(|s| s.flush().unwrap());
|
||||
|
||||
}
|
||||
fn stdout(&mut self) -> &mut termion::screen::AlternateScreen<termion::raw::RawTerminal<W>> {
|
||||
self.stdout.as_mut().unwrap()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: Pass Ctrl C etc to the terminal.
|
||||
#[derive(Debug)]
|
||||
pub enum Key {
|
||||
/// Backspace.
|
||||
@ -468,6 +493,7 @@ pub enum Key {
|
||||
Esc,
|
||||
}
|
||||
|
||||
|
||||
impl From<TermionKey> for Key {
|
||||
fn from(k: TermionKey ) -> Self {
|
||||
match k {
|
||||
@ -510,6 +536,8 @@ pub fn get_events(stdin: std::io::Stdin, mut closure: impl FnMut(Key), mut exit:
|
||||
if let Some(true) = val {
|
||||
exit();
|
||||
return;
|
||||
} else if let Some(false) = val {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user