diff options
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | karlc/Cargo.toml | 1 | ||||
-rw-r--r-- | karlc/src/main.rs | 54 | ||||
-rw-r--r-- | karlc/src/pretty.rs | 39 | ||||
-rw-r--r-- | karlcommon/src/protocol.rs | 25 | ||||
-rw-r--r-- | karld/src/condition.rs | 2 | ||||
-rw-r--r-- | karld/src/main.rs | 43 |
7 files changed, 107 insertions, 59 deletions
@@ -55,6 +55,7 @@ dependencies = [ "libc", "num-integer", "num-traits", + "serde", "time", "winapi", ] @@ -178,6 +179,7 @@ checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" name = "karlc" version = "0.1.0" dependencies = [ + "chrono", "clap", "crossbeam-channel", "env_logger", diff --git a/karlc/Cargo.toml b/karlc/Cargo.toml index c49ecfe..f95dee0 100644 --- a/karlc/Cargo.toml +++ b/karlc/Cargo.toml @@ -12,3 +12,4 @@ serde_json = "1.0.81" env_logger = "0.9.0" log = "0.4.17" crossbeam-channel = "0.5.4" +chrono = { version = "0.4.19", features = ["serde"] } diff --git a/karlc/src/main.rs b/karlc/src/main.rs index c69f1b2..9a89de9 100644 --- a/karlc/src/main.rs +++ b/karlc/src/main.rs @@ -1,14 +1,11 @@ pub mod client; -pub mod pretty; - -use std::{os::unix::net::UnixStream, process::exit}; +use chrono::{NaiveDateTime, Utc}; use clap::{Parser, Subcommand}; use client::Client; use karlcommon::{socket_path, version, ClientboundPacket, ServerboundPacket}; use log::{error, info}; - -use crate::pretty::Pretty; +use std::{os::unix::net::UnixStream, process::exit}; /// CLI interface for karld #[derive(Parser)] @@ -22,8 +19,8 @@ struct Args { pub enum Action { /// Show version of the client and daemon Version, - /// List all taskss - ListTasks, + /// List all tasks + List, } fn main() { @@ -54,11 +51,46 @@ fn main() { error!("handshake is not the first packet") } } - Action::ListTasks => { - client.send(ServerboundPacket::Download); - if let ClientboundPacket::DownloadResponse(tasks) = client.receiver.recv().unwrap() { + Action::List => { + client.send(ServerboundPacket::ListTasks); + if let ClientboundPacket::TaskList(tasks) = client.receiver.recv().unwrap() { for t in tasks { - println!("{}", Pretty(t)) + print!( + " +- \x1b[4m\x1b[1mTASK {}\x1b[0m + \x1b[38;2;100;255;100mName:\x1b[0m {} + \x1b[38;2;100;255;100mDescription:\x1b[0m {} + \x1b[38;2;100;255;100mOccurence:\x1b[0m {:?} + \x1b[38;2;100;255;100mNext instances: \x1b[0m", + t.id, t.name, t.description, t.occurence + ); + client.send(ServerboundPacket::ListInstances { + task: t.id, + limit: 5, + range: Some(Utc::now().naive_local().timestamp())..None, + }); + if let ClientboundPacket::InstanceList(instances) = + client.receiver.recv().unwrap() + { + for i in instances { + println!( + "\x1b[19G{} - {}", + i.at.start + .map(|e| format!( + "{}", + NaiveDateTime::from_timestamp(e as i64, 0) + )) + .unwrap_or("...".to_string()), + i.at.end + .map(|e| format!( + "{}", + NaiveDateTime::from_timestamp(e as i64, 0) + )) + .unwrap_or("...".to_string()), + ); + } + } + println!(); } } } diff --git a/karlc/src/pretty.rs b/karlc/src/pretty.rs deleted file mode 100644 index ceb1bde..0000000 --- a/karlc/src/pretty.rs +++ /dev/null @@ -1,39 +0,0 @@ -use std::fmt::Display; - -use karlcommon::{Condition, Task}; - -pub struct Pretty<T>(pub T); - -impl Display for Pretty<Task> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!( - "- \x1b[4m\x1b[1mTASK {}\x1b[0m - \x1b[38;2;100;255;100mName:\x1b[0m {} - \x1b[38;2;100;255;100mDescription:\x1b[0m {} - \x1b[38;2;100;255;100mOccurence:\x1b[0m {}", - self.0.id, - self.0.name, - self.0.description, - Pretty(self.0.occurence.clone()) - )) - } -} - -impl<T> Display for Pretty<Option<T>> -where - T: Clone, - Pretty<T>: Display, -{ - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match &self.0 { - Some(v) => Pretty(v.clone()).fmt(f), - None => Ok(()), - } - } -} - -impl Display for Pretty<Condition> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!("{:?}", self.0)) - } -} diff --git a/karlcommon/src/protocol.rs b/karlcommon/src/protocol.rs index 55dda06..e5bb9f0 100644 --- a/karlcommon/src/protocol.rs +++ b/karlcommon/src/protocol.rs @@ -1,3 +1,4 @@ +use std::ops::Range; use serde::{Deserialize, Serialize}; @@ -6,14 +7,22 @@ use serde::{Deserialize, Serialize}; pub enum ClientboundPacket { Handshake { version: String }, Error(String), - DownloadResponse(Vec<Task>), + TaskList(Vec<Task>), + InstanceList(Vec<Instance>), } #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "type", content = "data", rename_all = "snake_case")] pub enum ServerboundPacket { - Handshake { version: String }, - Download, + Handshake { + version: String, + }, + ListTasks, + ListInstances { + task: u64, + range: Range<Option<i64>>, + limit: usize, + }, UpdateTask(Task), RemoveTask(u64), } @@ -27,14 +36,20 @@ pub struct Task { pub tags: Vec<String>, pub priority: f64, - pub completed: Option<u64>, - pub scheduled: Option<u64>, + pub completed: Option<i64>, + pub scheduled: Option<i64>, pub occurence: Option<Condition>, pub deadline: Option<Condition>, } #[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Instance { + pub of: u64, + pub at: Range<Option<i64>>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum Condition { From(Box<Condition>), diff --git a/karld/src/condition.rs b/karld/src/condition.rs index 5874e7b..a989a25 100644 --- a/karld/src/condition.rs +++ b/karld/src/condition.rs @@ -24,7 +24,7 @@ pub enum Direction { Backward, } -trait ConditionFind { +pub trait ConditionFind { fn find(&self, edge: Edge, dir: Direction, from: NaiveDateTime) -> Option<NaiveDateTime>; } diff --git a/karld/src/main.rs b/karld/src/main.rs index f70b7e7..1bc5798 100644 --- a/karld/src/main.rs +++ b/karld/src/main.rs @@ -1,9 +1,11 @@ pub mod condition; pub mod interface; +use chrono::NaiveDateTime; +use condition::ConditionFind; use crossbeam_channel::Sender; use interface::network_loop; -use karlcommon::{ClientboundPacket, Condition, Property, ServerboundPacket, Task}; +use karlcommon::{ClientboundPacket, Condition, Instance, Property, ServerboundPacket, Task}; use log::{debug, info}; use std::{collections::HashMap, sync::RwLock}; @@ -44,8 +46,8 @@ lazy_static::lazy_static! { pub fn handle_packet(client: u32, packet: ServerboundPacket, responder: Sender<ClientboundPacket>) { match packet { - ServerboundPacket::Download => { - let _ = responder.send(ClientboundPacket::DownloadResponse( + ServerboundPacket::ListTasks => { + let _ = responder.send(ClientboundPacket::TaskList( TASKS.read().unwrap().values().map(|e| e.clone()).collect(), )); } @@ -58,5 +60,40 @@ pub fn handle_packet(client: u32, packet: ServerboundPacket, responder: Sender<C ServerboundPacket::Handshake { version } => { debug!("{client}: version {version}"); } + ServerboundPacket::ListInstances { range, task, limit } => { + let t = match TASKS.read().unwrap().get(&task).cloned() { + Some(t) => t, + None => { + let _ = + responder.send(ClientboundPacket::Error("task does not exist".to_string())); + return; + } + }; + + let mut ocs = vec![]; + if let Some(o) = &t.occurence { + let mut time = NaiveDateTime::from_timestamp(range.start.unwrap_or(0), 0); + let end_time = range.end.map(|e| NaiveDateTime::from_timestamp(e, 0)); + for _ in 0..limit { + let start = o.find(condition::Edge::Start, condition::Direction::Forward, time); + let end = o.find(condition::Edge::End, condition::Direction::Forward, time); + ocs.push(Instance { + of: t.id, + at: start.map(|e| e.timestamp())..end.map(|e| e.timestamp()), + }); + if let Some(s) = end { + if let Some(e) = end_time { + if s > e { + break; + } + } + time = s; + } else { + break; + } + } + } + let _ = responder.send(ClientboundPacket::InstanceList(ocs)); + } } } |