mirror of
https://gitlab.com/fabinfra/fabaccess/sute.git
synced 2025-03-12 14:41:52 +01:00
Event handling~
This commit is contained in:
parent
97bc38e74a
commit
02c310aa67
48
src/app.rs
48
src/app.rs
@ -1,10 +1,14 @@
|
|||||||
|
use std::mem;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll, Waker};
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
|
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
|
use futures::ready;
|
||||||
use futures_signals::signal::{Mutable, Signal, MutableSignalCloned, MutableLockMut};
|
use futures_signals::signal::{Mutable, Signal, MutableSignalCloned, MutableLockMut};
|
||||||
|
|
||||||
|
use termion::event::Key;
|
||||||
|
|
||||||
use crate::input::Inputs;
|
use crate::input::Inputs;
|
||||||
use crate::schema::API;
|
use crate::schema::API;
|
||||||
|
|
||||||
@ -32,7 +36,6 @@ pub struct Sute<'a, S> {
|
|||||||
// change the state.
|
// change the state.
|
||||||
|
|
||||||
state: SuteState<'a>,
|
state: SuteState<'a>,
|
||||||
modified: bool,
|
|
||||||
|
|
||||||
signal: S,
|
signal: S,
|
||||||
inputs: Inputs,
|
inputs: Inputs,
|
||||||
@ -47,7 +50,6 @@ impl<'a, S: Unpin> Sute<'a, S> {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
state: state,
|
state: state,
|
||||||
modified: false,
|
|
||||||
|
|
||||||
signal: s,
|
signal: s,
|
||||||
inputs: inputs,
|
inputs: inputs,
|
||||||
@ -66,31 +68,51 @@ impl<'a, S: Unpin> Sute<'a, S> {
|
|||||||
|
|
||||||
fn handle_resize(&mut self, new_size: (u16,u16)) {
|
fn handle_resize(&mut self, new_size: (u16,u16)) {
|
||||||
self.state.size = new_size;
|
self.state.size = new_size;
|
||||||
self.modified = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_state(&self) -> SuteState<'a> {
|
pub fn get_state(&self) -> SuteState<'a> {
|
||||||
self.state.clone()
|
self.state.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_key(&mut self, key: Key) {
|
||||||
|
match key {
|
||||||
|
Key::Char('\n') => {
|
||||||
|
let cmd = mem::replace(&mut self.state.cmd_line, String::new());
|
||||||
|
self.run_cmd(cmd);
|
||||||
|
},
|
||||||
|
Key::Char(c) => {
|
||||||
|
self.state.cmd_line.push(c);
|
||||||
|
},
|
||||||
|
Key::Backspace => {
|
||||||
|
self.state.cmd_line.pop();
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S: Signal<Item=(u16,u16)> + Unpin> Signal for Sute<'a, S> {
|
impl<'a, S: Signal<Item=(u16,u16)> + Unpin> Signal for Sute<'a, S> {
|
||||||
type Item = SuteState<'a>;
|
type Item = SuteState<'a>;
|
||||||
fn poll_change(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
fn poll_change(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||||
match Pin::new(&mut self.inputs).poll_next(cx) {
|
let mut dirty = false;
|
||||||
Poll::Ready(Some(line)) => self.run_cmd(line),
|
|
||||||
|
if let Poll::Ready(Some(size)) = Pin::new(&mut self.signal).poll_change(cx) {
|
||||||
|
dirty = true;
|
||||||
|
self.handle_resize(size);
|
||||||
|
}
|
||||||
|
match ready!(Pin::new(&mut self.inputs).poll_next(cx)) {
|
||||||
|
Some(key) => {
|
||||||
|
dirty = true;
|
||||||
|
self.handle_key(key);
|
||||||
|
},
|
||||||
// If the input closes stop the program
|
// If the input closes stop the program
|
||||||
Poll::Ready(None) => {
|
None => {
|
||||||
self.state.running = false;
|
self.state.running = false;
|
||||||
return Poll::Ready(None);
|
return Poll::Ready(None);
|
||||||
},
|
},
|
||||||
Poll::Pending => { },
|
|
||||||
}
|
|
||||||
if let Poll::Ready(Some(size)) = Pin::new(&mut self.signal).poll_change(cx) {
|
|
||||||
self.handle_resize(size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.modified {
|
if dirty {
|
||||||
Poll::Ready(Some(self.get_state()))
|
Poll::Ready(Some(self.get_state()))
|
||||||
} else {
|
} else {
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
@ -125,6 +147,7 @@ pub struct SuteState<'a> {
|
|||||||
pub server: Option<&'a str>,
|
pub server: Option<&'a str>,
|
||||||
pub log: Arc<LogDrain<'a>>,
|
pub log: Arc<LogDrain<'a>>,
|
||||||
pub cmd_line: String,
|
pub cmd_line: String,
|
||||||
|
pub tick_c: char,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SuteState<'a> {
|
impl<'a> SuteState<'a> {
|
||||||
@ -137,6 +160,7 @@ impl<'a> SuteState<'a> {
|
|||||||
server: None,
|
server: None,
|
||||||
log: log,
|
log: log,
|
||||||
cmd_line: String::new(),
|
cmd_line: String::new(),
|
||||||
|
tick_c: '|',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
33
src/input.rs
33
src/input.rs
@ -13,7 +13,6 @@ use futures::SinkExt;
|
|||||||
pub struct Inputs {
|
pub struct Inputs {
|
||||||
rx: mpsc::Receiver<Key>,
|
rx: mpsc::Receiver<Key>,
|
||||||
hndl: thread::JoinHandle<()>,
|
hndl: thread::JoinHandle<()>,
|
||||||
cmd_line: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Inputs {
|
impl Inputs {
|
||||||
@ -32,42 +31,14 @@ impl Inputs {
|
|||||||
Self {
|
Self {
|
||||||
rx: rx,
|
rx: rx,
|
||||||
hndl: hndl,
|
hndl: hndl,
|
||||||
cmd_line: String::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_line(&self) -> &str {
|
|
||||||
self.cmd_line.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle_key(&mut self, key: Key) -> Option<String> {
|
|
||||||
match key {
|
|
||||||
Key::Char('\n') => Some(mem::replace(&mut self.cmd_line, String::new())),
|
|
||||||
Key::Char(c) => {
|
|
||||||
self.cmd_line.push(c);
|
|
||||||
None
|
|
||||||
},
|
|
||||||
Key::Backspace => {
|
|
||||||
self.cmd_line.pop();
|
|
||||||
None
|
|
||||||
},
|
|
||||||
_ => None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stream for Inputs {
|
impl Stream for Inputs {
|
||||||
type Item = String;
|
type Item = Key;
|
||||||
|
|
||||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||||
if let Some(key) = ready!(Pin::new(&mut self.rx).poll_next(cx)) {
|
Pin::new(&mut self.rx).poll_next(cx)
|
||||||
if let Some(line) = self.handle_key(key) {
|
|
||||||
Poll::Ready(Some(line))
|
|
||||||
} else {
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
src/main.rs
10
src/main.rs
@ -79,6 +79,8 @@ fn main() -> Result<(), io::Error> {
|
|||||||
let mut terminal = Terminal::new(backend)?;
|
let mut terminal = Terminal::new(backend)?;
|
||||||
terminal.hide_cursor()?;
|
terminal.hide_cursor()?;
|
||||||
|
|
||||||
|
let mut tick_c = '|';
|
||||||
|
|
||||||
// Refresh the screen once by resizing the terminal
|
// Refresh the screen once by resizing the terminal
|
||||||
if let Ok((x,y)) = termion::terminal_size() {
|
if let Ok((x,y)) = termion::terminal_size() {
|
||||||
terminal.resize(tui::layout::Rect::new(0, 0, x,y)).unwrap();
|
terminal.resize(tui::layout::Rect::new(0, 0, x,y)).unwrap();
|
||||||
@ -90,6 +92,14 @@ fn main() -> Result<(), io::Error> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tick_c = match tick_c {
|
||||||
|
'\\' => '|',
|
||||||
|
'|' => '/',
|
||||||
|
'/' => '-',
|
||||||
|
'-' => '\\',
|
||||||
|
_ => '|',
|
||||||
|
};
|
||||||
|
state.tick_c = tick_c;
|
||||||
terminal.draw(|f| ui::draw_ui(f, &mut state))?;
|
terminal.draw(|f| ui::draw_ui(f, &mut state))?;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -31,14 +31,12 @@ fn draw_header<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk:
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn draw_main<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) {
|
fn draw_main<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) {
|
||||||
let chunk = Layout::default()
|
// let chunk = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
// .direction(Direction::Horizontal)
|
||||||
.constraints([Constraint::Percentage(20), Constraint::Percentage(80)].as_ref())
|
// .constraints([Constraint::Percentage(20), Constraint::Percentage(80)].as_ref())
|
||||||
.split(layout_chunk);
|
// .split(layout_chunk);
|
||||||
|
|
||||||
f.render_widget(Paragraph::new(app.server.unwrap_or("Not connected")), chunk[0]);
|
draw_logs(f, app, layout_chunk)
|
||||||
|
|
||||||
draw_logs(f, app, chunk[1])
|
|
||||||
}
|
}
|
||||||
fn draw_logs<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) {
|
fn draw_logs<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) {
|
||||||
// TODO: Just use a signal.
|
// TODO: Just use a signal.
|
||||||
@ -53,5 +51,7 @@ fn draw_command_line<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_c
|
|||||||
let inner_rect = block.inner(layout_chunk);
|
let inner_rect = block.inner(layout_chunk);
|
||||||
|
|
||||||
f.render_widget(block, layout_chunk);
|
f.render_widget(block, layout_chunk);
|
||||||
f.render_widget(Paragraph::new(app.cmd_line.as_ref()), inner_rect);
|
|
||||||
|
let cmdline = format!("{} > {}", app.tick_c, app.cmd_line);
|
||||||
|
f.render_widget(Paragraph::new(&cmdline[..]), inner_rect);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user