docs: Added some code documentation

This commit is contained in:
Alexey 2026-05-08 12:33:56 +03:00
commit 4c2ddde26f
5 changed files with 70 additions and 20 deletions

View file

@ -2,10 +2,13 @@ use std::{collections::HashMap, hash::{DefaultHasher, Hash, Hasher}};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use slint::Color; use slint::Color;
/// Enum that is either an color or an alias
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
#[serde(untagged)] #[serde(untagged)]
pub enum ConfigColor { pub enum ConfigColor {
/// ARGB color
Raw(u32), Raw(u32),
/// Alias to a color defined in [Colors::aliases]
Alias(String), Alias(String),
} }
@ -15,11 +18,16 @@ impl Default for ConfigColor {
} }
} }
/// Struct used for events colors
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
#[serde(default)] #[serde(default)]
pub struct EventColor { pub struct EventColor {
/// Base color of the event
pub background: ConfigColor, pub background: ConfigColor,
/// Color of the text inside the event
/// If none, color defaults to [Colors::text]
pub text: Option<ConfigColor>, pub text: Option<ConfigColor>,
/// How often this color will be chosen for the event
pub priority: u64, pub priority: u64,
} }
@ -33,16 +41,23 @@ impl Default for EventColor {
} }
} }
/// Colors used by Aliveline
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
#[serde(default)] #[serde(default)]
pub struct Colors { pub struct Colors {
/// Maps aliases to actual colors
pub aliases: HashMap<String, u32>, pub aliases: HashMap<String, u32>,
/// Color behind the timeline
pub background: ConfigColor, pub background: ConfigColor,
/// Color of the timeline itself
pub timeline: ConfigColor, pub timeline: ConfigColor,
/// Color of the text on the timeline background
pub text: ConfigColor, pub text: ConfigColor,
/// Color used to replace ill-defined aliases
/// If it is ill-defined itself, uses black color
pub fallback: ConfigColor, pub fallback: ConfigColor,
/// List of event colors
/// Colors are chosen pseudorandomly by their priority
pub events: Vec<EventColor>, pub events: Vec<EventColor>,
} }
@ -58,22 +73,30 @@ fn argb(value: u32) -> Color {
} }
impl Colors { impl Colors {
/// Get [Colors::fallback] or the default color if it is also ill-defined
#[inline(always)] #[inline(always)]
pub fn fallback_color(&self) -> Color { pub fn fallback_color(&self) -> Color {
self.try_get_color(&self.fallback).unwrap_or_default() self.try_get_color(&self.fallback).unwrap_or_default()
} }
/// Try to get actual color from [ConfigColor].
/// Returns None if it is [ConfigColor::Alias] and alias was not found in [Colors::aliases]
#[inline(always)]
pub fn try_get_color(&self, color: &ConfigColor) -> Option<Color> { pub fn try_get_color(&self, color: &ConfigColor) -> Option<Color> {
match color { match color {
ConfigColor::Raw(color) => Some(argb(*color)), ConfigColor::Raw(color) => Some(argb(*color)),
ConfigColor::Alias(alias) => self.aliases.get(alias).map(|c| argb(*c)), ConfigColor::Alias(alias) => self.aliases.get(alias).map(|c| argb(*c)),
} }
} }
/// Get either the color or fallback color
#[inline(always)]
pub fn get_color(&self, color: &ConfigColor) -> Color { pub fn get_color(&self, color: &ConfigColor) -> Color {
self.try_get_color(color).unwrap_or_else(|| self.fallback_color()) self.try_get_color(color).unwrap_or_else(|| self.fallback_color())
} }
/// Compute hash and choose a color for the given event string
/// This way same strings will get same colors but it still feels randomly
pub fn event_color_for(&self, text: &str) -> &EventColor { pub fn event_color_for(&self, text: &str) -> &EventColor {
let priority_sum: u64 = self.events.iter().map(|e| e.priority).sum(); let priority_sum: u64 = self.events.iter().map(|e| e.priority).sum();

View file

@ -13,15 +13,15 @@ pub(super) struct DefaultConfig {
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct DefaultColors { pub(super) struct DefaultColors {
pub aliases: HashMap<String, u32>, pub(super) aliases: HashMap<String, u32>,
pub background: ConfigColor, pub(super) background: ConfigColor,
pub timeline: ConfigColor, pub(super) timeline: ConfigColor,
pub text: ConfigColor, pub(super) text: ConfigColor,
pub fallback: ConfigColor, pub(super) fallback: ConfigColor,
pub events: Vec<EventColor>, pub(super) events: Vec<EventColor>,
} }
impl From<DefaultColors> for Colors { impl From<DefaultColors> for Colors {
@ -38,8 +38,8 @@ impl From<DefaultColors> for Colors {
} }
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct DefaultPaths { pub(super) struct DefaultPaths {
pub logs: PathBuf, pub(super) logs: PathBuf,
} }
impl From<DefaultPaths> for Paths { impl From<DefaultPaths> for Paths {

View file

@ -2,12 +2,16 @@ use std::path::PathBuf;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use color::Colors; use color::Colors;
/// Color-related structs and methods
pub mod color; pub mod color;
// Not very optimal, but needed to avoid recursion in Config::default
mod default; mod default;
/// Paths which are used by Aliveline
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
#[serde(default)] #[serde(default)]
pub struct Paths { pub struct Paths {
/// Path to logs folder
pub logs: PathBuf, pub logs: PathBuf,
} }
@ -17,17 +21,21 @@ impl Default for Paths {
} }
} }
/// Configuration struct
#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq, Debug)] #[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq, Debug)]
#[serde(default)] #[serde(default)]
pub struct Config { pub struct Config {
/// directory, where config is located /// Directory, where config is located
#[serde(skip)] #[serde(skip)]
pub conf_path: PathBuf, pub conf_path: PathBuf,
/// Config colors
pub colors: Colors, pub colors: Colors,
/// Config paths
pub paths: Paths, pub paths: Paths,
} }
impl Config { impl Config {
/// Get the default config and make it think it is in the given [PathBuf]
pub fn new(conf_path: PathBuf) -> Self { pub fn new(conf_path: PathBuf) -> Self {
let conf_dir: PathBuf = conf_path.parent().unwrap().into(); let conf_dir: PathBuf = conf_path.parent().unwrap().into();
Config { Config {
@ -36,6 +44,7 @@ impl Config {
} }
} }
// replace fields that are not filled from deserializing
fn replace_missing_fields(&mut self) { fn replace_missing_fields(&mut self) {
let default = Config::default(); let default = Config::default();
@ -43,7 +52,8 @@ impl Config {
self.colors.events = default.colors.events; self.colors.events = default.colors.events;
} }
} }
/// Try to load [Config] from given [PathBuf]
pub fn load(path: PathBuf) -> Option<Self> { pub fn load(path: PathBuf) -> Option<Self> {
if let Ok(toml_string) = std::fs::read_to_string(path.clone()) { if let Ok(toml_string) = std::fs::read_to_string(path.clone()) {
if let Ok(mut conf) = toml::from_str::<Config>(&toml_string) { if let Ok(mut conf) = toml::from_str::<Config>(&toml_string) {

View file

@ -1,7 +1,9 @@
use config::Config; use config::Config;
use std::path::PathBuf; use std::path::PathBuf;
/// Configuration module
pub mod config; pub mod config;
/// Event tracking module
pub mod log; pub mod log;
fn try_config_path(var: &'static str, path: &[&'static str]) -> Option<Config> { fn try_config_path(var: &'static str, path: &[&'static str]) -> Option<Config> {

View file

@ -6,17 +6,22 @@ use serde::{Deserialize, Serialize};
use toml::value::{Date, Time}; use toml::value::{Date, Time};
use crate::config::Config; use crate::config::Config;
/// Contains all activity tracked in one day
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct Log { pub struct Log {
/// Logging date, should match its filename
pub date: Date, pub date: Date,
/// Recorded events
pub events: Vec<Event>, pub events: Vec<Event>,
} }
impl Log { impl Log {
/// Construct new empty log for given date
pub fn new(date: Date) -> Self { pub fn new(date: Date) -> Self {
Log { date, events: Vec::new() } Log { date, events: Vec::new() }
} }
/// Load log from [Paths::logs](crate::config::Paths::logs) or get empty log
pub fn load_from(config: &Config, date: Date) -> Self { pub fn load_from(config: &Config, date: Date) -> Self {
let path = Log::get_filepath(&date, config); let path = Log::get_filepath(&date, config);
if let Ok(log_string) = std::fs::read_to_string(path) { if let Ok(log_string) = std::fs::read_to_string(path) {
@ -25,7 +30,8 @@ impl Log {
Log::new(date) Log::new(date)
} }
} }
/// Save log in [Paths::logs](crate::config::Paths::logs)
pub fn save(&self, config: &Config) -> std::io::Result<()> { pub fn save(&self, config: &Config) -> std::io::Result<()> {
Log::try_create_log_dir(config)?; Log::try_create_log_dir(config)?;
let path = Log::get_filepath(&self.date, config); let path = Log::get_filepath(&self.date, config);
@ -36,7 +42,8 @@ impl Log {
} }
} }
} }
// get filepath based on log date
fn get_filepath(date: &Date, config: &Config) -> PathBuf { fn get_filepath(date: &Date, config: &Config) -> PathBuf {
let mut path = Log::get_log_dir(&config); let mut path = Log::get_log_dir(&config);
let filename = format!("{}-{}-{}", date.day, date.month, date.year); let filename = format!("{}-{}-{}", date.day, date.month, date.year);
@ -44,7 +51,8 @@ impl Log {
path.set_extension("toml"); path.set_extension("toml");
path path
} }
// get logging directory based on relativeness in the config
fn get_log_dir(config: &Config) -> PathBuf { fn get_log_dir(config: &Config) -> PathBuf {
if config.paths.logs.is_relative() { if config.paths.logs.is_relative() {
let mut path = config.conf_path.clone(); let mut path = config.conf_path.clone();
@ -54,7 +62,8 @@ impl Log {
return config.paths.logs.clone(); return config.paths.logs.clone();
} }
} }
// create logging directory if it does not exist
fn try_create_log_dir(config: &Config) -> std::io::Result<()> { fn try_create_log_dir(config: &Config) -> std::io::Result<()> {
let path = Log::get_log_dir(config); let path = Log::get_log_dir(config);
if !std::fs::exists(&path)? { if !std::fs::exists(&path)? {
@ -64,15 +73,21 @@ impl Log {
} }
} }
/// Single event with duration and a name
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
pub struct Event { pub struct Event {
/// Event name string
pub name: String, pub name: String,
/// When the event began
pub start: Time, pub start: Time,
/// When the event finished (if it is)
pub end: Time, pub end: Time,
/// Is the event finished or it continues
pub finished: bool, pub finished: bool,
} }
impl Event { impl Event {
/// Construct new event from time seconds
pub fn new(name: String, start: i32, end: i32, finished: bool) -> Self { pub fn new(name: String, start: i32, end: i32, finished: bool) -> Self {
let start = Time { let start = Time {
hour: (start / 3600) as u8, hour: (start / 3600) as u8,