Refactored clock code.

This commit is contained in:
shy 2021-04-12 08:26:26 +02:00
parent 557358a4c0
commit 5eef3dd811
5 changed files with 296 additions and 275 deletions

View file

@ -1,9 +1,11 @@
pub mod font;
use std::time;
use std::io::Write;
use termion::{color, cursor, style};
use termion::raw::RawTerminal;
use crate::consts::COLOR;
use crate::consts::digits::*;
use crate::Config;
use crate::layout::{Layout, Position};
pub struct Clock {
@ -13,10 +15,11 @@ pub struct Clock {
pub paused: bool,
paused_at: Option<time::Instant>,
pub color_index: Option<usize>,
font: font::Font,
}
impl Clock {
pub fn new() -> Clock {
pub fn new(config: &Config) -> Clock {
Clock {
start: time::Instant::now(),
elapsed: 0,
@ -24,6 +27,10 @@ impl Clock {
paused: false,
paused_at: None,
color_index: None,
font: match config.plain {
false => font::NORMAL,
true => font::PLAIN,
},
}
}
@ -81,13 +88,14 @@ impl Clock {
&mut self,
mut stdout: &mut RawTerminal<W>,
layout: &Layout,
) {
) -> Result<(), std::io::Error>
{
// Setup style and color if appropriate.
if self.paused {
write!(stdout, "{}", style::Faint).unwrap();
write!(stdout, "{}", style::Faint)?;
}
if let Some(c) = self.color_index {
write!(stdout, "{}", color::Fg(COLOR[c])).unwrap();
write!(stdout, "{}", color::Fg(COLOR[c]))?;
}
// Draw hours if necessary.
@ -96,14 +104,12 @@ impl Clock {
self.draw_digit_pair(
&mut stdout,
self.elapsed / 3600,
&layout.clock_hr,
layout.plain);
&layout.clock_hr)?;
// Draw colon.
self.draw_colon(
&mut stdout,
&layout.clock_colon1,
layout.plain);
&layout.clock_colon1)?;
}
// Draw days.
@ -119,8 +125,7 @@ impl Clock {
layout.clock_days.col,
layout.clock_days.line,
),
day_count)
.unwrap();
day_count)?;
}
}
@ -129,33 +134,30 @@ impl Clock {
self.draw_digit_pair(
&mut stdout,
(self.elapsed % 3600) / 60,
&layout.clock_min,
layout.plain);
&layout.clock_min)?;
}
// Draw colon if necessary.
if layout.force_redraw {
self.draw_colon(
&mut stdout,
&layout.clock_colon0,
layout.plain);
&layout.clock_colon0)?;
}
// Draw seconds.
self.draw_digit_pair(
&mut stdout,
self.elapsed % 60,
&layout.clock_sec,
layout.plain);
&layout.clock_sec)?;
// Reset color and style.
if self.paused || self.color_index != None {
write!(stdout,
"{}{}",
style::NoFaint,
color::Fg(color::Reset))
.unwrap();
color::Fg(color::Reset))?;
}
Ok(())
}
fn draw_digit_pair<W: Write>(
@ -163,37 +165,35 @@ impl Clock {
stdout: &mut RawTerminal<W>,
value: u32,
pos: &Position,
plain: bool,
) {
let digits = if plain { DIGITS_PLAIN } else { DIGITS };
for l in 0..DIGIT_HEIGHT {
) -> Result<(), std::io::Error>
{
for l in 0..self.font.height {
write!(stdout,
"{}{} {}",
cursor::Goto(pos.col, pos.line + l),
// First digit.
digits[(value / 10) as usize][l as usize],
self.font.digits[(value / 10) as usize][l as usize],
// Second digit.
digits[(value % 10) as usize][l as usize])
.unwrap();
self.font.digits[(value % 10) as usize][l as usize]
)?;
}
Ok(())
}
fn draw_colon<W: Write>(
&self,
stdout: &mut RawTerminal<W>,
pos: &Position,
plain: bool,
) {
let dot = if plain {'█'} else {'■'};
) -> Result<(), std::io::Error>
{
write!(stdout,
"{}{}{}{}",
cursor::Goto(pos.col, pos.line + 1),
dot,
self.font.dot,
cursor::Goto(pos.col, pos.line + 3),
dot)
.unwrap();
self.font.dot,
)?;
Ok(())
}
}

243
src/clock/font.rs Normal file
View file

@ -0,0 +1,243 @@
pub const DIGIT_HEIGHT: u16 = 5;
pub const DIGIT_WIDTH: u16 = 5;
pub struct Font {
pub height: u16,
pub width: u16,
pub dot: char,
pub digits: [[&'static str; DIGIT_HEIGHT as usize]; 10],
}
pub const NORMAL: Font = Font {
height: DIGIT_HEIGHT,
width: 5,
dot: '',
digits: [[
// 0
"█▀▀▀█",
"█ █",
"█ █",
"█ █",
"█▄▄▄█",
], [
// 1
" ▀█ ",
"",
"",
"",
""
], [
// 2
"▀▀▀▀█",
"",
"█▀▀▀▀",
"",
"█▄▄▄▄"
], [
// 3
"▀▀▀▀█",
"",
" ▀▀▀█",
"",
"▄▄▄▄█"
], [
// 4
"",
"█ █ ",
"▀▀▀█▀",
"",
""
], [
// 5
"█▀▀▀▀",
"",
"▀▀▀▀█",
"",
"▄▄▄▄█"
], [
// 6
"",
"",
"█▀▀▀█",
"█ █",
"█▄▄▄█"
], [
// 7
"▀▀▀▀█",
"",
"",
"",
"",
], [
// 8
"█▀▀▀█",
"█ █",
"█▀▀▀█",
"█ █",
"█▄▄▄█"
], [
// 9
"█▀▀▀█",
"█ █",
"▀▀▀▀█",
"",
""
]],
};
pub const PLAIN: Font = Font {
height: DIGIT_HEIGHT,
width: 5,
dot: '',
digits: [[
// 0
"█████",
"█ █",
"█ █",
"█ █",
"█████"
], [
// 1
" ██ ",
"",
"",
"",
""
], [
// 2
"█████",
"",
"█████",
"",
"█████"
], [
// 3
"█████",
"",
" ████",
"",
"█████"
], [
// 4
"",
"█ █ ",
"█████",
"",
""
], [
// 5
"█████",
"",
"█████",
"",
"█████"
], [
// 6
"",
"",
"█████",
"█ █",
"█████"
], [
// 7
"█████",
"",
"",
"",
""
], [
// 8
"█████",
"█ █",
"█████",
"█ █",
"█████"
], [
// 9
"█████",
"█ █",
"█████",
"",
""
]],
};
/*
pub const FANCE: Font = Font {
height: DIGIT_HEIGHT,
width: 5,
dot: '',
digits: [[
// 0
"█▀▀▀█",
"█ █",
"▀ ▀",
"🮐 🮐",
"🮐🮏🮏🮏🮐",
], [
// 1
" ▀█ ",
"",
"",
" 🮐 ",
" 🮐 "
], [
// 2
"▀▀▀▀█",
"",
"▀▀▀▀▀",
"🮐 ",
"🮐🮏🮏🮏🮏"
], [
// 3
"▀▀▀▀█",
"",
" ▀▀▀▀",
" 🮐",
"🮏🮏🮏🮏🮐"
], [
// 4
"",
"█ █ ",
"▀▀▀▀▀",
" 🮐 ",
" 🮐 "
], [
// 5
"█▀▀▀▀",
"",
"▀▀▀▀▀",
" 🮐",
"🮏🮏🮏🮏🮐"
], [
// 6
"",
"",
"▀▀▀▀▀",
"🮐 🮐",
"🮐🮏🮏🮏🮐"
], [
// 7
"▀▀▀▀█",
"",
"",
" 🮐 ",
" 🮐 ",
], [
// 8
"█▀▀▀█",
"█ █",
"▀▀▀▀▀",
"🮐 🮐",
"🮐🮏🮏🮏🮐"
], [
// 9
"█▀▀▀█",
"█ █",
"▀▀▀▀▀",
" 🮐",
" 🮐"
]],
};
*/

View file

@ -9,7 +9,7 @@ pub const COLOR: [&dyn termion::color::Color; 6] = [
];
// Maximum length of labels.
pub const LABEL_SIZE_LIMIT: usize = 48;
pub const LABEL_SIZE_LIMIT: usize = 42;
pub mod ui {
pub const NAME: &str = env!("CARGO_PKG_NAME");
@ -40,229 +40,3 @@ SIGNALS: <SIGUSR1> Reset clock.
"Format: HH:MM:SS/LABEL [ENTER] Accept [ESC] Cancel [CTR-C] Quit";
}
pub mod digits {
pub const DIGIT_HEIGHT: u16 = 5;
pub const DIGIT_WIDTH: u16 = 5;
pub const DIGITS: [[&str; DIGIT_HEIGHT as usize]; 10] = [
[
// 0
"█▀▀▀█",
"█ █",
"█ █",
"█ █",
"█▄▄▄█",
], [
// 1
" ▀█ ",
"",
"",
"",
""
], [
// 2
"▀▀▀▀█",
"",
"█▀▀▀▀",
"",
"█▄▄▄▄"
], [
// 3
"▀▀▀▀█",
"",
" ▀▀▀█",
"",
"▄▄▄▄█"
], [
// 4
"",
"█ █ ",
"▀▀▀█▀",
"",
""
], [
// 5
"█▀▀▀▀",
"",
"▀▀▀▀█",
"",
"▄▄▄▄█"
], [
// 6
"",
"",
"█▀▀▀█",
"█ █",
"█▄▄▄█"
], [
// 7
"▀▀▀▀█",
"",
"",
"",
"",
], [
// 8
"█▀▀▀█",
"█ █",
"█▀▀▀█",
"█ █",
"█▄▄▄█"
], [
// 9
"█▀▀▀█",
"█ █",
"▀▀▀▀█",
"",
""
]
];
pub const _DIGITS_FANCY: [[&str; DIGIT_HEIGHT as usize]; 10] = [
[
// 0
"█▀▀▀█",
"█ █",
"▀ ▀",
"🮐 🮐",
"🮐🮏🮏🮏🮐",
], [
// 1
" ▀█ ",
"",
"",
" 🮐 ",
" 🮐 "
], [
// 2
"▀▀▀▀█",
"",
"▀▀▀▀▀",
"🮐 ",
"🮐🮏🮏🮏🮏"
], [
// 3
"▀▀▀▀█",
"",
" ▀▀▀▀",
" 🮐",
"🮏🮏🮏🮏🮐"
], [
// 4
"",
"█ █ ",
"▀▀▀▀▀",
" 🮐 ",
" 🮐 "
], [
// 5
"█▀▀▀▀",
"",
"▀▀▀▀▀",
" 🮐",
"🮏🮏🮏🮏🮐"
], [
// 6
"",
"",
"▀▀▀▀▀",
"🮐 🮐",
"🮐🮏🮏🮏🮐"
], [
// 7
"▀▀▀▀█",
"",
"",
" 🮐 ",
" 🮐 ",
], [
// 8
"█▀▀▀█",
"█ █",
"▀▀▀▀▀",
"🮐 🮐",
"🮐🮏🮏🮏🮐"
], [
// 9
"█▀▀▀█",
"█ █",
"▀▀▀▀▀",
" 🮐",
" 🮐"
]
];
pub const DIGITS_PLAIN: [[&str; DIGIT_HEIGHT as usize]; 10] = [
[
// 0
"█████",
"█ █",
"█ █",
"█ █",
"█████"
], [
// 1
" ██ ",
"",
"",
"",
""
], [
// 2
"█████",
"",
"█████",
"",
"█████"
], [
// 3
"█████",
"",
" ████",
"",
"█████"
], [
// 4
"",
"█ █ ",
"█████",
"",
""
], [
// 5
"█████",
"",
"█████",
"",
"█████"
], [
// 6
"",
"",
"█████",
"█ █",
"█████"
], [
// 7
"█████",
"",
"",
"",
""
], [
// 8
"█████",
"█ █",
"█████",
"█ █",
"█████"
], [
// 9
"█████",
"█ █",
"█████",
"",
""
]
];
}

View file

@ -1,7 +1,7 @@
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use crate::Config;
use crate::consts::digits::*;
use crate::clock::font::*;
// If screen size falls below these values we skip computation of new
// positions.

View file

@ -45,7 +45,7 @@ pub fn run(
layout.force_recalc = sigwinch;
// Initialise roster_width.
layout.set_roster_width(alarm_roster.width());
let mut clock = Clock::new();
let mut clock = Clock::new(&config);
let mut countdown = Countdown::new();
let mut buffer = Buffer::new();
@ -182,7 +182,7 @@ pub fn run(
buffer.draw(&mut stdout, &mut layout)?;
}
clock.draw(&mut stdout, &layout);
clock.draw(&mut stdout, &layout)?;
// Display countdown.
if countdown.value > 0 {
@ -392,33 +392,37 @@ impl Config {
// for process::Command::new().
fn parse_to_command(input: &str) -> Vec<String> {
let mut command: Vec<String> = Vec::new();
let mut buffer: String = String::new();
let mut segment: String = String::new();
let mut quoted = false;
let mut escaped = false;
for byte in input.chars() {
match byte {
for c in input.chars() {
match c {
'\\' if !escaped => {
// Next char is escaped.
// Next char is escaped. (If not escaped itself.)
escaped = true;
continue;
},
' ' if escaped || quoted => { &buffer.push(' '); },
// Keep spaces when escaped or quoted.
' ' if escaped || quoted => { &segment.push(' '); },
// Otherwise end the current segment.
' ' => {
if !&buffer.is_empty() {
command.push(buffer.clone());
&buffer.clear();
if !&segment.is_empty() {
command.push(segment.clone());
&segment.clear();
}
},
// Quotation marks toggle quote.
'"' | '\'' if !escaped => quoted = !quoted,
// Carry everything else. Escape if found escaped.
_ => {
if escaped { &buffer.push('\\'); }
&buffer.push(byte);
if escaped { &segment.push('\\'); }
&segment.push(c);
},
}
escaped = false;
}
command.push(buffer);
command.push(segment);
command.shrink_to_fit();
command
}