This commit is contained in:
Dheepak Krishnamurthy 2023-09-25 05:27:20 -04:00
parent 1ec93c0913
commit 0c9b3b03dc
5 changed files with 56 additions and 55 deletions

View file

@ -1,27 +1,38 @@
use color_eyre::eyre::Result; use color_eyre::eyre::Result;
use serde_derive::{Deserialize, Serialize};
use tokio::sync::mpsc; use tokio::sync::mpsc;
use crate::{ use crate::{
command::Command, command::Command,
components::{app::App, Component}, components::{task_report::TaskReport, Component},
config::Config, config::Config,
tui, tui,
}; };
pub struct Runner { #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Mode {
#[default]
TaskReport,
TaskContext,
Calendar,
Error,
}
pub struct App {
pub config: Config, pub config: Config,
pub tick_rate: f64, pub tick_rate: f64,
pub frame_rate: f64, pub frame_rate: f64,
pub components: Vec<Box<dyn Component>>, pub components: Vec<Box<dyn Component>>,
pub should_quit: bool, pub should_quit: bool,
pub should_suspend: bool, pub should_suspend: bool,
pub mode: Mode,
} }
impl Runner { impl App {
pub fn new(tick_rate: f64, frame_rate: f64) -> Result<Self> { pub fn new(tick_rate: f64, frame_rate: f64) -> Result<Self> {
let app = App::new(); let app = TaskReport::new();
let config = Config::new()?; let config = Config::new()?;
let app = app.keybindings(config.keybindings.clone()); let mode = Mode::TaskReport;
Ok(Self { Ok(Self {
tick_rate, tick_rate,
frame_rate, frame_rate,
@ -29,6 +40,7 @@ impl Runner {
should_quit: false, should_quit: false,
should_suspend: false, should_suspend: false,
config, config,
mode,
}) })
} }
@ -44,6 +56,10 @@ impl Runner {
component.register_command_handler(command_tx.clone())?; component.register_command_handler(command_tx.clone())?;
} }
for component in self.components.iter_mut() {
component.register_config_handler(self.config.clone())?;
}
for component in self.components.iter_mut() { for component in self.components.iter_mut() {
component.init()?; component.init()?;
} }
@ -55,14 +71,20 @@ impl Runner {
tui::Event::Tick => command_tx.send(Command::Tick)?, tui::Event::Tick => command_tx.send(Command::Tick)?,
tui::Event::Render => command_tx.send(Command::Render)?, tui::Event::Render => command_tx.send(Command::Render)?,
tui::Event::Resize(x, y) => command_tx.send(Command::Resize(x, y))?, tui::Event::Resize(x, y) => command_tx.send(Command::Resize(x, y))?,
e => { tui::Event::Key(key) => {
let command = if let Some(keymap) = self.config.keybindings.get(&self.mode) {
if let Some(command) = keymap.get(&vec![key]) {
command_tx.send(command.clone())?;
};
};
},
_ => {},
}
for component in self.components.iter_mut() { for component in self.components.iter_mut() {
if let Some(command) = component.handle_events(Some(e.clone()))? { if let Some(command) = component.handle_events(Some(e.clone()))? {
command_tx.send(command)?; command_tx.send(command)?;
} }
} }
},
}
} }
while let Ok(command) = command_rx.try_recv() { while let Ok(command) = command_rx.try_recv() {

View file

@ -5,16 +5,21 @@ use tokio::sync::mpsc::UnboundedSender;
use crate::{ use crate::{
command::Command, command::Command,
config::Config,
tui::{Event, Frame}, tui::{Event, Frame},
}; };
pub mod app; pub mod task_report;
pub trait Component { pub trait Component {
#[allow(unused_variables)] #[allow(unused_variables)]
fn register_command_handler(&mut self, tx: UnboundedSender<Command>) -> Result<()> { fn register_command_handler(&mut self, tx: UnboundedSender<Command>) -> Result<()> {
Ok(()) Ok(())
} }
#[allow(unused_variables)]
fn register_config_handler(&mut self, config: Config) -> Result<()> {
Ok(())
}
fn init(&mut self) -> Result<()> { fn init(&mut self) -> Result<()> {
Ok(()) Ok(())
} }

View file

@ -10,22 +10,15 @@ use tui_input::backend::crossterm::EventHandler;
use uuid::Uuid; use uuid::Uuid;
use super::{Component, Frame}; use super::{Component, Frame};
use crate::{command::Command, config::KeyBindings}; use crate::{
command::Command,
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] config::{Config, KeyBindings},
pub enum Mode { };
#[default]
TaskReport,
TaskContext,
Calendar,
Error,
}
#[derive(Default)] #[derive(Default)]
pub struct App { pub struct TaskReport {
pub mode: Mode, pub config: Config,
pub command_tx: Option<UnboundedSender<Command>>, pub command_tx: Option<UnboundedSender<Command>>,
pub keybindings: KeyBindings,
pub last_export: Option<std::time::SystemTime>, pub last_export: Option<std::time::SystemTime>,
pub report: String, pub report: String,
pub filter: String, pub filter: String,
@ -33,16 +26,11 @@ pub struct App {
pub tasks: Vec<Task>, pub tasks: Vec<Task>,
} }
impl App { impl TaskReport {
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
pub fn keybindings(mut self, keybindings: KeyBindings) -> Self {
self.keybindings = keybindings;
self
}
pub fn refresh(&mut self) -> Result<()> { pub fn refresh(&mut self) -> Result<()> {
self.last_export = Some(std::time::SystemTime::now()); self.last_export = Some(std::time::SystemTime::now());
Ok(()) Ok(())
@ -93,39 +81,25 @@ impl App {
if let Ok(imported) = import(data.as_bytes()) { if let Ok(imported) = import(data.as_bytes()) {
self.tasks = imported; self.tasks = imported;
log::info!("Imported {} tasks", self.tasks.len()); log::info!("Imported {} tasks", self.tasks.len());
if self.mode == Mode::Error {
self.send_command(Command::ShowTaskReport)?; self.send_command(Command::ShowTaskReport)?;
};
// } else {
// self.error = Some(format!("Unable to parse output of `{:?}`:\n`{:?}`", task, data));
// self.mode = Mode::Tasks(Action::Error);
// debug!("Unable to parse output: {:?}", data);
} }
} else { } else {
// self.error = Some(format!("Cannot run `{:?}` - ({}) error:\n{}", &task, output.status, error)); self.send_command(Command::Error(format!("Unable to parse output of `{:?}`:\n`{:?}`", task, data)))?;
} }
Ok(()) Ok(())
} }
} }
impl Component for App { impl Component for TaskReport {
fn register_command_handler(&mut self, tx: UnboundedSender<Command>) -> Result<()> { fn register_command_handler(&mut self, tx: UnboundedSender<Command>) -> Result<()> {
self.command_tx = Some(tx); self.command_tx = Some(tx);
Ok(()) Ok(())
} }
fn handle_key_events(&mut self, key: KeyEvent) -> Result<Option<Command>> { fn register_config_handler(&mut self, config: Config) -> Result<()> {
let command = if let Some(keymap) = self.keybindings.get(&self.mode) { self.config = config;
if let Some(command) = keymap.get(&vec![key]) { Ok(())
command
} else {
return Ok(None);
}
} else {
return Ok(None);
};
Ok(Some(command.clone()))
} }
fn update(&mut self, command: Command) -> Result<Option<Command>> { fn update(&mut self, command: Command) -> Result<Option<Command>> {

View file

@ -7,7 +7,7 @@ use ratatui::style::{Color, Modifier, Style};
use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor}; use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor};
use serde_derive::Deserialize; use serde_derive::Deserialize;
use crate::{command::Command, components::app::Mode}; use crate::{app::Mode, command::Command};
const CONFIG: &'static str = include_str!("../.config/config.json5"); const CONFIG: &'static str = include_str!("../.config/config.json5");

View file

@ -2,11 +2,11 @@
#![allow(unused_imports)] #![allow(unused_imports)]
#![allow(unused_variables)] #![allow(unused_variables)]
pub mod app;
pub mod cli; pub mod cli;
pub mod command; pub mod command;
pub mod components; pub mod components;
pub mod config; pub mod config;
pub mod runner;
pub mod tui; pub mod tui;
pub mod utils; pub mod utils;
@ -15,7 +15,7 @@ use cli::Cli;
use color_eyre::eyre::Result; use color_eyre::eyre::Result;
use crate::{ use crate::{
runner::Runner, app::App,
utils::{initialize_logging, initialize_panic_handler, version}, utils::{initialize_logging, initialize_panic_handler, version},
}; };
@ -25,7 +25,7 @@ async fn tokio_main() -> Result<()> {
initialize_panic_handler()?; initialize_panic_handler()?;
let args = Cli::parse(); let args = Cli::parse();
let mut runner = Runner::new(args.tick_rate, args.frame_rate)?; let mut runner = App::new(args.tick_rate, args.frame_rate)?;
runner.run().await?; runner.run().await?;
Ok(()) Ok(())