feat: add chronometer mode
This commit is contained in:
78
src/main.rs
78
src/main.rs
@@ -4,11 +4,11 @@ use std::{
|
|||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
sync::atomic::Ordering,
|
sync::atomic::Ordering,
|
||||||
thread,
|
thread,
|
||||||
time::Duration,
|
time::{self, Duration},
|
||||||
};
|
};
|
||||||
|
|
||||||
use atomic_enum::atomic_enum;
|
use atomic_enum::atomic_enum;
|
||||||
use chrono::Local;
|
use chrono;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use config::{write_default_config, Config};
|
use config::{write_default_config, Config};
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
@@ -46,6 +46,7 @@ struct Cli {
|
|||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum Commands {
|
enum Commands {
|
||||||
Debug {},
|
Debug {},
|
||||||
|
Chrono {},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[atomic_enum]
|
#[atomic_enum]
|
||||||
@@ -53,6 +54,7 @@ enum Commands {
|
|||||||
pub enum AppMode {
|
pub enum AppMode {
|
||||||
Clock = 0,
|
Clock = 0,
|
||||||
Debug,
|
Debug,
|
||||||
|
Chrono,
|
||||||
}
|
}
|
||||||
|
|
||||||
static APP_MODE: AtomicAppMode = AtomicAppMode::new(AppMode::Debug);
|
static APP_MODE: AtomicAppMode = AtomicAppMode::new(AppMode::Debug);
|
||||||
@@ -72,7 +74,8 @@ fn main() -> io::Result<()> {
|
|||||||
Some(Commands::Debug {}) => {
|
Some(Commands::Debug {}) => {
|
||||||
set_app_mode(AppMode::Debug);
|
set_app_mode(AppMode::Debug);
|
||||||
}
|
}
|
||||||
_ => {}
|
Some(Commands::Chrono {}) => set_app_mode(AppMode::Chrono),
|
||||||
|
_ => set_app_mode(AppMode::Clock),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load config
|
// Load config
|
||||||
@@ -118,8 +121,8 @@ fn main() -> io::Result<()> {
|
|||||||
let mut config = config::load_from_file(config_file);
|
let mut config = config::load_from_file(config_file);
|
||||||
let mut stdout = io::stdout();
|
let mut stdout = io::stdout();
|
||||||
|
|
||||||
match &cli.command {
|
match get_app_mode() {
|
||||||
Some(Commands::Debug {}) => {
|
AppMode::Debug => {
|
||||||
print_debug_infos(&mut config)?;
|
print_debug_infos(&mut config)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -130,6 +133,8 @@ fn main() -> io::Result<()> {
|
|||||||
execute!(stdout, terminal::EnterAlternateScreen, cursor::Hide)?;
|
execute!(stdout, terminal::EnterAlternateScreen, cursor::Hide)?;
|
||||||
let _ = terminal::enable_raw_mode()?;
|
let _ = terminal::enable_raw_mode()?;
|
||||||
|
|
||||||
|
let start_time = time::Instant::now();
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
let mut quit = false;
|
let mut quit = false;
|
||||||
while !quit {
|
while !quit {
|
||||||
@@ -153,7 +158,11 @@ fn main() -> io::Result<()> {
|
|||||||
queue!(stdout, terminal::Clear(ClearType::All))?;
|
queue!(stdout, terminal::Clear(ClearType::All))?;
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
render_frame(&config)?;
|
match get_app_mode() {
|
||||||
|
AppMode::Clock => render_clock(&config)?,
|
||||||
|
AppMode::Chrono => render_chrono(&config, &start_time)?,
|
||||||
|
AppMode::Debug => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
config.color.update();
|
config.color.update();
|
||||||
|
|
||||||
@@ -174,31 +183,36 @@ fn main() -> io::Result<()> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_frame(config: &Config) -> io::Result<()> {
|
fn render_clock(config: &Config) -> io::Result<()> {
|
||||||
let (width, height) = terminal::size()?;
|
let color = config.color.get_value();
|
||||||
|
|
||||||
let date_time = Local::now();
|
let date_time = chrono::Local::now();
|
||||||
|
|
||||||
// Display time
|
// Display time
|
||||||
let time = date_time.time().format(&config.time_format).to_string();
|
let time = date_time.time().format(&config.time_format).to_string();
|
||||||
|
draw_time(&time, color)?;
|
||||||
let text_width = draw_time_width(&time);
|
|
||||||
let text_height = 5;
|
|
||||||
let color = config.color.get_value();
|
|
||||||
|
|
||||||
let x = width / 2 - text_width / 2;
|
|
||||||
let y = height / 2 - text_height / 2;
|
|
||||||
draw_time(&time, x, y, color)?;
|
|
||||||
|
|
||||||
// Display date
|
// Display date
|
||||||
let date = date_time
|
let date = date_time
|
||||||
.date_naive()
|
.date_naive()
|
||||||
.format(&config.date_format.to_owned())
|
.format(&config.date_format.to_owned())
|
||||||
.to_string();
|
.to_string();
|
||||||
|
draw_date(&date, color)?;
|
||||||
|
|
||||||
let x = width / 2 - (date.len() as u16) / 2;
|
return Ok(());
|
||||||
let y = height / 2 + text_height / 2 + 2;
|
}
|
||||||
draw_date(&date, x, y, color)?;
|
|
||||||
|
fn render_chrono(config: &Config, start_time: &time::Instant) -> io::Result<()> {
|
||||||
|
let color = config.color.get_value();
|
||||||
|
|
||||||
|
// Display time
|
||||||
|
let seconds = start_time.elapsed().as_secs();
|
||||||
|
let hours = seconds / 3600;
|
||||||
|
let minutes = (seconds % 3600) / 60;
|
||||||
|
let seconds = seconds % 60;
|
||||||
|
|
||||||
|
let elapsed = format!("{:02}:{:02}:{:02}", hours, minutes, seconds);
|
||||||
|
draw_time(&elapsed, color)?;
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -210,14 +224,25 @@ fn draw_time_width(time: &str) -> u16 {
|
|||||||
|
|
||||||
let mut w = 0;
|
let mut w = 0;
|
||||||
for c in time.chars() {
|
for c in time.chars() {
|
||||||
w += if c == ':' { 6 } else { 7 };
|
w += if c == ':' {
|
||||||
|
symbols::SYMBOL_HEIGHT
|
||||||
|
} else {
|
||||||
|
symbols::SYMBOL_WIDTH + 1
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
w -= if time.len() == 1 { 1 } else { 2 };
|
w -= if time.len() == 1 { 1 } else { 2 };
|
||||||
return w;
|
return w.try_into().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_time(time: &str, mut x: u16, y: u16, color: Color) -> io::Result<()> {
|
fn draw_time(time: &str, color: Color) -> io::Result<()> {
|
||||||
|
let (width, height) = terminal::size()?;
|
||||||
|
|
||||||
|
let text_width = draw_time_width(&time);
|
||||||
|
let text_height = 5;
|
||||||
|
|
||||||
|
let mut x = width / 2 - text_width / 2;
|
||||||
|
let y = height / 2 - text_height / 2;
|
||||||
for c in time.chars() {
|
for c in time.chars() {
|
||||||
if c == ':' {
|
if c == ':' {
|
||||||
x -= 1;
|
x -= 1;
|
||||||
@@ -260,9 +285,14 @@ fn draw_time_symbol(symbol: char, x: u16, y: u16, color: Color) -> io::Result<()
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_date(date: &str, x: u16, y: u16, color: Color) -> io::Result<()> {
|
fn draw_date(date: &str, color: Color) -> io::Result<()> {
|
||||||
let mut stdout = io::stdout();
|
let mut stdout = io::stdout();
|
||||||
|
|
||||||
|
let (width, height) = terminal::size()?;
|
||||||
|
|
||||||
|
let x = width / 2 - (date.len() as u16) / 2;
|
||||||
|
let y = height / 2 + symbols::SYMBOL_HEIGHT as u16 / 2 + 2;
|
||||||
|
|
||||||
queue!(
|
queue!(
|
||||||
stdout,
|
stdout,
|
||||||
cursor::MoveTo(x, y),
|
cursor::MoveTo(x, y),
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
pub fn symbol_to_render_data(ch: char) -> [[bool; 6]; 5] {
|
pub const SYMBOL_WIDTH: usize = 6;
|
||||||
|
pub const SYMBOL_HEIGHT: usize = 5;
|
||||||
|
|
||||||
|
pub fn symbol_to_render_data(ch: char) -> [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] {
|
||||||
match ch {
|
match ch {
|
||||||
'1' => ONE,
|
'1' => ONE,
|
||||||
'2' => TWO,
|
'2' => TWO,
|
||||||
@@ -23,7 +26,7 @@ pub fn symbol_to_render_data(ch: char) -> [[bool; 6]; 5] {
|
|||||||
const O: bool = false;
|
const O: bool = false;
|
||||||
const X: bool = true;
|
const X: bool = true;
|
||||||
|
|
||||||
const ONE: [[bool; 6]; 5] = [
|
const ONE: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[O, O, O, O, X, X],
|
[O, O, O, O, X, X],
|
||||||
[O, O, O, O, X, X],
|
[O, O, O, O, X, X],
|
||||||
[O, O, O, O, X, X],
|
[O, O, O, O, X, X],
|
||||||
@@ -31,7 +34,7 @@ const ONE: [[bool; 6]; 5] = [
|
|||||||
[O, O, O, O, X, X],
|
[O, O, O, O, X, X],
|
||||||
];
|
];
|
||||||
|
|
||||||
const TWO: [[bool; 6]; 5] = [
|
const TWO: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
[O, O, O, O, X, X],
|
[O, O, O, O, X, X],
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
@@ -39,7 +42,7 @@ const TWO: [[bool; 6]; 5] = [
|
|||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
];
|
];
|
||||||
|
|
||||||
const THREE: [[bool; 6]; 5] = [
|
const THREE: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
[O, O, O, O, X, X],
|
[O, O, O, O, X, X],
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
@@ -47,7 +50,7 @@ const THREE: [[bool; 6]; 5] = [
|
|||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
];
|
];
|
||||||
|
|
||||||
const FOUR: [[bool; 6]; 5] = [
|
const FOUR: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[X, X, O, O, X, X],
|
[X, X, O, O, X, X],
|
||||||
[X, X, O, O, X, X],
|
[X, X, O, O, X, X],
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
@@ -55,7 +58,7 @@ const FOUR: [[bool; 6]; 5] = [
|
|||||||
[O, O, O, O, X, X],
|
[O, O, O, O, X, X],
|
||||||
];
|
];
|
||||||
|
|
||||||
const FIVE: [[bool; 6]; 5] = [
|
const FIVE: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
[X, X, O, O, O, O],
|
[X, X, O, O, O, O],
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
@@ -63,7 +66,7 @@ const FIVE: [[bool; 6]; 5] = [
|
|||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
];
|
];
|
||||||
|
|
||||||
const SIX: [[bool; 6]; 5] = [
|
const SIX: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
[X, X, O, O, O, O],
|
[X, X, O, O, O, O],
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
@@ -71,7 +74,7 @@ const SIX: [[bool; 6]; 5] = [
|
|||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
];
|
];
|
||||||
|
|
||||||
const SEVEN: [[bool; 6]; 5] = [
|
const SEVEN: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
[O, O, O, O, X, X],
|
[O, O, O, O, X, X],
|
||||||
[O, O, O, O, X, X],
|
[O, O, O, O, X, X],
|
||||||
@@ -79,7 +82,7 @@ const SEVEN: [[bool; 6]; 5] = [
|
|||||||
[O, O, O, O, X, X],
|
[O, O, O, O, X, X],
|
||||||
];
|
];
|
||||||
|
|
||||||
const EIGHT: [[bool; 6]; 5] = [
|
const EIGHT: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
[X, X, O, O, X, X],
|
[X, X, O, O, X, X],
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
@@ -87,7 +90,7 @@ const EIGHT: [[bool; 6]; 5] = [
|
|||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
];
|
];
|
||||||
|
|
||||||
const NINE: [[bool; 6]; 5] = [
|
const NINE: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
[X, X, O, O, X, X],
|
[X, X, O, O, X, X],
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
@@ -95,7 +98,7 @@ const NINE: [[bool; 6]; 5] = [
|
|||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
];
|
];
|
||||||
|
|
||||||
const ZERO: [[bool; 6]; 5] = [
|
const ZERO: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
[X, X, O, O, X, X],
|
[X, X, O, O, X, X],
|
||||||
[X, X, O, O, X, X],
|
[X, X, O, O, X, X],
|
||||||
@@ -103,7 +106,7 @@ const ZERO: [[bool; 6]; 5] = [
|
|||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
];
|
];
|
||||||
|
|
||||||
const DIV: [[bool; 6]; 5] = [
|
const DIV: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[O, O, O, O, O, O],
|
[O, O, O, O, O, O],
|
||||||
[O, O, X, X, O, O],
|
[O, O, X, X, O, O],
|
||||||
[O, O, O, O, O, O],
|
[O, O, O, O, O, O],
|
||||||
@@ -111,7 +114,7 @@ const DIV: [[bool; 6]; 5] = [
|
|||||||
[O, O, O, O, O, O],
|
[O, O, O, O, O, O],
|
||||||
];
|
];
|
||||||
|
|
||||||
const DASH: [[bool; 6]; 5] = [
|
const DASH: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[O, O, O, O, O, O],
|
[O, O, O, O, O, O],
|
||||||
[O, O, O, O, O, O],
|
[O, O, O, O, O, O],
|
||||||
[O, X, X, X, X, O],
|
[O, X, X, X, X, O],
|
||||||
@@ -119,7 +122,7 @@ const DASH: [[bool; 6]; 5] = [
|
|||||||
[O, O, O, O, O, O],
|
[O, O, O, O, O, O],
|
||||||
];
|
];
|
||||||
|
|
||||||
const ERR: [[bool; 6]; 5] = [
|
const ERR: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[X, X, O, O, X, X],
|
[X, X, O, O, X, X],
|
||||||
[O, X, X, X, X, O],
|
[O, X, X, X, X, O],
|
||||||
[O, O, X, X, O, O],
|
[O, O, X, X, O, O],
|
||||||
@@ -127,7 +130,7 @@ const ERR: [[bool; 6]; 5] = [
|
|||||||
[X, X, O, O, X, X],
|
[X, X, O, O, X, X],
|
||||||
];
|
];
|
||||||
|
|
||||||
const SPACE: [[bool; 6]; 5] = [
|
const SPACE: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[O, O, O, O, O, O],
|
[O, O, O, O, O, O],
|
||||||
[O, O, O, O, O, O],
|
[O, O, O, O, O, O],
|
||||||
[O, O, O, O, O, O],
|
[O, O, O, O, O, O],
|
||||||
@@ -135,7 +138,7 @@ const SPACE: [[bool; 6]; 5] = [
|
|||||||
[O, O, O, O, O, O],
|
[O, O, O, O, O, O],
|
||||||
];
|
];
|
||||||
|
|
||||||
const A: [[bool; 6]; 5] = [
|
const A: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
[X, X, O, O, X, X],
|
[X, X, O, O, X, X],
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
@@ -143,7 +146,7 @@ const A: [[bool; 6]; 5] = [
|
|||||||
[X, X, O, O, X, X],
|
[X, X, O, O, X, X],
|
||||||
];
|
];
|
||||||
|
|
||||||
const P: [[bool; 6]; 5] = [
|
const P: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
[X, X, O, O, X, X],
|
[X, X, O, O, X, X],
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
@@ -151,7 +154,7 @@ const P: [[bool; 6]; 5] = [
|
|||||||
[X, X, O, O, O, O],
|
[X, X, O, O, O, O],
|
||||||
];
|
];
|
||||||
|
|
||||||
const M: [[bool; 6]; 5] = [
|
const M: [[bool; SYMBOL_WIDTH]; SYMBOL_HEIGHT] = [
|
||||||
[X, X, X, X, X, X],
|
[X, X, X, X, X, X],
|
||||||
[X, X, O, X, O, X],
|
[X, X, O, X, O, X],
|
||||||
[X, X, O, X, O, X],
|
[X, X, O, X, O, X],
|
||||||
|
|||||||
Reference in New Issue
Block a user