From b232bebed572a20ec227d64776eb42deeb683b6e Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Fri, 12 Feb 2021 02:54:19 -0600 Subject: [PATCH] Osuation --- src/app.rs | 29 ---------------------- src/config.rs | 25 ------------------- src/event.rs | 1 - src/mailapp.rs | 21 ---------------- src/main.rs | 62 ++++++++-------------------------------------- src/panorama.rs | 37 ---------------------------- src/ui.rs | 65 +++++++++++++++++++++---------------------------- 7 files changed, 38 insertions(+), 202 deletions(-) delete mode 100644 src/app.rs delete mode 100644 src/config.rs delete mode 100644 src/event.rs delete mode 100644 src/mailapp.rs delete mode 100644 src/panorama.rs diff --git a/src/app.rs b/src/app.rs deleted file mode 100644 index c4c830c..0000000 --- a/src/app.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::ops::Deref; - -use crate::config::ConfigWatcher; - -#[async_trait] -pub trait AnyApp { - fn say_hello(&self) { - debug!("hello from app"); - } -} - -/// An App is usually associated with a particular separate service or piece of functionality. -pub struct App { - inner: A, - // config_watcher: ConfigWatcher, -} - -impl App { - pub fn new(app: A) -> Self { - App { inner: app } - } -} - -/// The interface that anything that wants to become an App must implement -pub trait AppI: Sized { - type Config; -} - -impl AnyApp for App {} diff --git a/src/config.rs b/src/config.rs deleted file mode 100644 index 3b78872..0000000 --- a/src/config.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::marker::PhantomData; -use std::sync::mpsc::channel; -use std::time::Duration; - -use anyhow::Result; -use notify::{DebouncedEvent, RecursiveMode, Watcher}; -use xdg::BaseDirectories; - -pub struct ConfigWatcher { - _ty: PhantomData, -} - -pub fn watch_config() -> Result<()> { - let (tx, rx) = channel(); - - let xdg = BaseDirectories::new()?; - let config_home = xdg.get_config_home(); - let mut watcher = notify::watcher(tx, Duration::from_secs(5))?; - watcher.watch(config_home, RecursiveMode::Recursive)?; - - loop { - let evt = rx.recv()?; - } - Ok(()) -} diff --git a/src/event.rs b/src/event.rs deleted file mode 100644 index 7c470eb..0000000 --- a/src/event.rs +++ /dev/null @@ -1 +0,0 @@ -pub enum Event {} diff --git a/src/mailapp.rs b/src/mailapp.rs deleted file mode 100644 index 34ede36..0000000 --- a/src/mailapp.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::collections::HashMap; - -use lettre::SmtpClient; -use anyhow::Result; - -use crate::app::AppI; - -pub struct MailApp { - client: SmtpClient, -} - -impl AppI for MailApp { - type Config = (); -} - -impl MailApp { - pub fn new(domain: impl AsRef) -> Result { - let client = SmtpClient::new_simple(domain.as_ref())?; - Ok(MailApp { client }) - } -} diff --git a/src/main.rs b/src/main.rs index 53fe21b..b083063 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,65 +1,23 @@ #[macro_use] -extern crate async_trait; -#[macro_use] -extern crate cfg_if; -#[macro_use] extern crate crossterm; -#[macro_use] -extern crate log; -#[macro_use] -extern crate pin_project; -mod app; -mod config; -mod event; -mod mailapp; -mod panorama; mod ui; -use std::io; -use std::sync::mpsc::channel; -use std::thread; - use anyhow::Result; -use tokio::runtime::Runtime; +use lettre::SmtpClient; +use tokio::sync::oneshot; -use crate::panorama::Panorama; -use crate::config::watch_config; -use crate::ui::Ui; +type ExitSender = oneshot::Sender<()>; -fn main() -> Result<()> { - fern::Dispatch::new() - .format(|out, message, record| { - out.finish(format_args!( - "{}[{}][{}] {}", - chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), - record.target(), - record.level(), - message - )) - }) - .level(log::LevelFilter::Debug) - .chain(fern::log_file("output.log")?) - .apply()?; +#[tokio::main] +async fn main() -> Result<()> { + SmtpClient::new_simple(""); - let runtime = Runtime::new()?; - thread::spawn(move || { - let panorama = Panorama::new().unwrap(); - runtime.block_on(panorama.run()); - }); + let (exit_tx, exit_rx) = oneshot::channel::<()>(); - let stdout = io::stdout(); - let (evts_tx, evts_rx) = channel(); - - // spawn a thread for listening to configuration changes - thread::spawn(move || { - watch_config(); - }); - info!("poggers"); - - // run the ui on the main thread - let ui = Ui::init(stdout, evts_rx)?; - ui.run()?; + let stdout = std::io::stdout(); + tokio::spawn(ui::run_ui(stdout, exit_tx)); + exit_rx.await?; Ok(()) } diff --git a/src/panorama.rs b/src/panorama.rs deleted file mode 100644 index 90c64a5..0000000 --- a/src/panorama.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::any::{Any, TypeId}; -use std::collections::HashMap; - -use anyhow::Result; - -use crate::mailapp::MailApp; -use crate::app::{AnyApp, App}; - -pub struct Panorama { - apps: Vec>, -} - -impl Panorama { - pub fn new() -> Result { - let mut apps = Vec::new(); - - let mail = MailApp::new("mzhang.io")?; - let mail = Box::new(App::new(mail)) as Box; - apps.push(mail); - - Ok(Panorama { - apps, - }) - } - - pub async fn run(&self) -> Result<()> { - debug!("starting all apps..."); - - loop { - self.apps.iter().map(|app| { - app.say_hello(); - }); - } - - Ok(()) - } -} diff --git a/src/ui.rs b/src/ui.rs index d7f63be..a955ff5 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,60 +1,51 @@ use std::io::Write; -use std::sync::mpsc::Receiver; +use std::time::Duration; use anyhow::Result; +use chrono::Local; use crossterm::{ - event, - terminal::{self, EnterAlternateScreen}, + cursor, + event::{self, Event, KeyCode, KeyEvent}, + style, terminal, }; +use tokio::time; -use crate::event::Event; +use crate::ExitSender; -pub struct Ui { - screen: S, - evts: Receiver, -} +const FRAME: Duration = Duration::from_millis(16); -impl Ui { - pub fn init(mut screen: S, evts: Receiver) -> Result { - execute!(screen, EnterAlternateScreen)?; - terminal::enable_raw_mode()?; +pub async fn run_ui(mut w: impl Write, exit: ExitSender) -> Result<()> { + execute!(w, cursor::Hide, terminal::EnterAlternateScreen)?; + terminal::enable_raw_mode()?; - Ok(Ui { screen, evts }) - } + loop { + execute!(w, cursor::MoveTo(0, 0))?; - pub fn run(mut self) -> Result<()> { - use crossterm::event::{Event, KeyCode, KeyEvent}; + let now = Local::now(); + println!("shiet {}", now); - loop { - // check for new events - use std::sync::mpsc::TryRecvError; - match self.evts.try_recv() { - Ok(evt) => {} - Err(TryRecvError::Empty) => {} // skip - Err(TryRecvError::Disconnected) => todo!("impossible?"), - } + // approx 60fps + time::sleep(FRAME).await; - // read events from the terminal + if event::poll(FRAME)? { match event::read()? { Event::Key(KeyEvent { code: KeyCode::Char('q'), .. - }) => { - break; - } + }) => break, _ => {} } } - - Ok(()) } -} -impl Drop for Ui { - fn drop(&mut self) { - use crossterm::{cursor::Show, style::ResetColor, terminal::LeaveAlternateScreen}; + execute!( + w, + style::ResetColor, + cursor::Show, + terminal::LeaveAlternateScreen + )?; + terminal::disable_raw_mode()?; - execute!(self.screen, ResetColor, Show, LeaveAlternateScreen,).unwrap(); - terminal::disable_raw_mode().unwrap(); - } + exit.send(()).expect("fake news?"); + Ok(()) }