summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAkshay <nerdy@peppe.rs>2021-02-21 10:43:32 +0530
committerAkshay <nerdy@peppe.rs>2021-02-21 10:43:32 +0530
commit38d9dfee224ebcd088c0ebecd9e1243994eea409 (patch)
tree1215766f07b1c2eaf68f20aba284e710eb9a24a3
parentad5bf181a176e64c9f70a292cad870e6e8110f09 (diff)
parent53f7a679a0cf7a510de13d67cf370988f71c0d08 (diff)
Merge branch 'cursor' into master
-rw-r--r--flake.nix12
-rw-r--r--src/app/cursor.rs71
-rw-r--r--src/app/impl_self.rs50
-rw-r--r--src/app/impl_view.rs31
-rw-r--r--src/app/message.rs3
-rw-r--r--src/app/mod.rs4
-rw-r--r--src/habit/bit.rs25
-rw-r--r--src/habit/count.rs25
-rw-r--r--src/habit/mod.rs27
-rw-r--r--src/habit/traits.rs46
-rw-r--r--src/keybinds.rs146
-rw-r--r--src/theme.rs6
-rw-r--r--src/utils.rs4
-rw-r--r--src/views.rs46
14 files changed, 382 insertions, 114 deletions
diff --git a/flake.nix b/flake.nix
index db94656..bc0a0e8 100644
--- a/flake.nix
+++ b/flake.nix
@@ -19,6 +19,11 @@
channel = "nightly";
sha256 = "LbKHsCOFXWpg/SEyACfzZuWjKbkXdH6EJKOPSGoO01E="; # set zeros after modifying channel or date
}).rust;
+ rust-src = (mozilla.rustChannelOf {
+ date = "2020-12-23";
+ channel = "nightly";
+ sha256 = "LbKHsCOFXWpg/SEyACfzZuWjKbkXdH6EJKOPSGoO01E="; # set zeros after modifying channel or date
+ }).rust-src;
naersk-lib = naersk.lib."${system}".override {
cargo = rust;
@@ -38,10 +43,15 @@
devShell = pkgs.mkShell {
nativeBuildInputs = [
rust
+ rust-src
+ pkgs.rust-analyzer
pkgs.cargo
- pkgs.cargo
+ pkgs.openssl
pkgs.ncurses
];
+ shellHook = ''
+ export RUST_SRC_PATH="${rust-src}/lib/rustlib/src/rust/library"
+ '';
};
});
}
diff --git a/src/app/cursor.rs b/src/app/cursor.rs
new file mode 100644
index 0000000..f76d591
--- /dev/null
+++ b/src/app/cursor.rs
@@ -0,0 +1,71 @@
+use chrono::{Duration, Local, NaiveDate};
+use cursive::direction::Absolute;
+
+#[derive(Debug, Copy, Clone)]
+pub struct Cursor(pub NaiveDate);
+
+impl std::default::Default for Cursor {
+ fn default() -> Self {
+ Cursor::new()
+ }
+}
+
+impl Cursor {
+ pub fn new() -> Self {
+ Cursor {
+ 0: Local::now().naive_local().date(),
+ }
+ }
+ pub fn small_seek(&mut self, d: Absolute) {
+ let today = Local::now().naive_local().date();
+ let cursor = self.0;
+ match d {
+ Absolute::Right => {
+ // forward by 1 day
+ let next = cursor.succ_opt().unwrap_or(cursor);
+ if next <= today {
+ self.0 = next;
+ }
+ }
+ Absolute::Left => {
+ // backward by 1 day
+ // assumes an infinite past
+ self.0 = cursor.pred_opt().unwrap_or(cursor);
+ }
+ Absolute::Down => {
+ // forward by 1 week
+ let next = cursor.checked_add_signed(Duration::weeks(1)).unwrap();
+ if next <= today {
+ self.0 = next;
+ }
+ }
+ Absolute::Up => {
+ // backward by 1 week
+ // assumes an infinite past
+ let next = cursor.checked_sub_signed(Duration::weeks(1)).unwrap();
+ self.0 = next;
+ }
+ Absolute::None => {}
+ }
+ }
+ fn long_seek(&mut self, offset: Duration) {
+ let cursor = self.0;
+ let today = Local::now().naive_local().date();
+ let next = cursor.checked_add_signed(offset).unwrap_or(cursor);
+
+ if next <= today {
+ self.0 = next;
+ } else {
+ self.0 = today;
+ }
+ }
+ pub fn month_forward(&mut self) {
+ self.long_seek(Duration::weeks(4));
+ }
+ pub fn month_backward(&mut self) {
+ self.long_seek(Duration::weeks(-4));
+ }
+ pub fn reset(&mut self) {
+ self.0 = Local::now().naive_local().date();
+ }
+}
diff --git a/src/app/impl_self.rs b/src/app/impl_self.rs
index 1114d50..d5f93ff 100644
--- a/src/app/impl_self.rs
+++ b/src/app/impl_self.rs
@@ -6,7 +6,7 @@ use std::path::PathBuf;
use std::sync::mpsc::channel;
use std::time::Duration;
-use chrono::Local;
+use chrono::{Local, NaiveDate};
use cursive::direction::Absolute;
use cursive::Vec2;
use notify::{watcher, RecursiveMode, Watcher};
@@ -15,7 +15,7 @@ use crate::command::{Command, CommandLineError};
use crate::habit::{Bit, Count, HabitWrapper, TrackEvent, ViewMode};
use crate::utils::{self, GRID_WIDTH, VIEW_HEIGHT, VIEW_WIDTH};
-use crate::app::{App, MessageKind, StatusLine};
+use crate::app::{App, Cursor, Message, MessageKind, StatusLine};
impl App {
pub fn new() -> Self {
@@ -27,8 +27,8 @@ impl App {
focus: 0,
_file_watcher: watcher,
file_event_recv: rx,
- view_month_offset: 0,
- message: "Type :add <habit-name> <goal> to get started, Ctrl-L to dismiss".into(),
+ cursor: Cursor::new(),
+ message: Message::startup(),
};
}
@@ -53,35 +53,42 @@ impl App {
if self.habits.is_empty() {
return ViewMode::Day;
}
- return self.habits[self.focus].view_mode();
+ return self.habits[self.focus].inner_data_ref().view_mode();
}
pub fn set_mode(&mut self, mode: ViewMode) {
if !self.habits.is_empty() {
- self.habits[self.focus].set_view_mode(mode);
+ self.habits[self.focus]
+ .inner_data_mut_ref()
+ .set_view_mode(mode);
}
}
- pub fn set_view_month_offset(&mut self, offset: u32) {
- self.view_month_offset = offset;
+ pub fn sift_backward(&mut self) {
+ self.cursor.month_backward();
for v in self.habits.iter_mut() {
- v.set_view_month_offset(offset);
+ v.inner_data_mut_ref().cursor.month_backward();
}
}
- pub fn sift_backward(&mut self) {
- self.view_month_offset += 1;
+ pub fn sift_forward(&mut self) {
+ self.cursor.month_forward();
for v in self.habits.iter_mut() {
- v.set_view_month_offset(self.view_month_offset);
+ v.inner_data_mut_ref().cursor.month_forward();
}
}
- pub fn sift_forward(&mut self) {
- if self.view_month_offset > 0 {
- self.view_month_offset -= 1;
- for v in self.habits.iter_mut() {
- v.set_view_month_offset(self.view_month_offset);
- }
+ pub fn reset_cursor(&mut self) {
+ self.cursor.reset();
+ for v in self.habits.iter_mut() {
+ v.inner_data_mut_ref().cursor.reset();
+ }
+ }
+
+ pub fn move_cursor(&mut self, d: Absolute) {
+ self.cursor.small_seek(d);
+ for v in self.habits.iter_mut() {
+ v.inner_data_mut_ref().move_cursor(d);
}
}
@@ -125,11 +132,12 @@ impl App {
let total = self.habits.iter().map(|h| h.goal()).sum::<u32>();
let completed = total - remaining;
- let timestamp = if self.view_month_offset == 0 {
+ let timestamp = if self.cursor.0 == today {
format!("{}", Local::now().naive_local().date().format("%d/%b/%y"),)
} else {
- let months = self.view_month_offset;
- format!("{}", format!("{} months ago", months),)
+ let since = NaiveDate::signed_duration_since(today, self.cursor.0).num_days();
+ let plural = if since == 1 { "" } else { "s" };
+ format!("{} ({} day{} ago)", self.cursor.0, since, plural)
};
StatusLine {
diff --git a/src/app/impl_view.rs b/src/app/impl_view.rs
index 395cac4..c369d8f 100644
--- a/src/app/impl_view.rs
+++ b/src/app/impl_view.rs
@@ -95,11 +95,29 @@ impl View for App {
self.set_focus(Absolute::Down);
return EventResult::Consumed(None);
}
+
+ Event::Char('K') => {
+ self.move_cursor(Absolute::Up);
+ return EventResult::Consumed(None);
+ }
+ Event::Char('H') => {
+ self.move_cursor(Absolute::Left);
+ return EventResult::Consumed(None);
+ }
+ Event::Char('J') => {
+ self.move_cursor(Absolute::Down);
+ return EventResult::Consumed(None);
+ }
+ Event::Char('L') => {
+ self.move_cursor(Absolute::Right);
+ return EventResult::Consumed(None);
+ }
+
Event::Char('v') => {
if self.habits.is_empty() {
return EventResult::Consumed(None);
}
- if self.habits[self.focus].view_mode() == ViewMode::Week {
+ if self.habits[self.focus].inner_data_ref().view_mode() == ViewMode::Week {
self.set_mode(ViewMode::Day)
} else {
self.set_mode(ViewMode::Week)
@@ -108,14 +126,15 @@ impl View for App {
}
Event::Char('V') => {
for habit in self.habits.iter_mut() {
- habit.set_view_mode(ViewMode::Week);
+ habit.inner_data_mut_ref().set_view_mode(ViewMode::Week);
}
return EventResult::Consumed(None);
}
Event::Key(Key::Esc) => {
for habit in self.habits.iter_mut() {
- habit.set_view_mode(ViewMode::Day);
+ habit.inner_data_mut_ref().set_view_mode(ViewMode::Day);
}
+ self.reset_cursor();
return EventResult::Consumed(None);
}
@@ -131,7 +150,7 @@ impl View for App {
return EventResult::Consumed(None);
}
Event::Char('}') => {
- self.set_view_month_offset(0);
+ self.reset_cursor();
return EventResult::Consumed(None);
}
Event::CtrlChar('l') => {
@@ -141,14 +160,12 @@ impl View for App {
}
/* Every keybind that is not caught by App trickles
- * down to the focused habit. We sift back to today
- * before performing any action, "refocusing" the cursor
+ * down to the focused habit.
* */
_ => {
if self.habits.is_empty() {
return EventResult::Ignored;
}
- self.set_view_month_offset(0);
self.habits[self.focus].on_event(e)
}
}
diff --git a/src/app/message.rs b/src/app/message.rs
index 65f0a5c..a1d3d57 100644
--- a/src/app/message.rs
+++ b/src/app/message.rs
@@ -35,6 +35,9 @@ pub struct Message {
}
impl Message {
+ pub fn startup() -> Self {
+ "Type :add <habit-name> <goal> to get started, Ctrl-L to dismiss".into()
+ }
pub fn contents(&self) -> &str {
&self.msg
}
diff --git a/src/app/mod.rs b/src/app/mod.rs
index 2aecb33..726a656 100644
--- a/src/app/mod.rs
+++ b/src/app/mod.rs
@@ -5,11 +5,13 @@ use notify::{DebouncedEvent, RecommendedWatcher};
use crate::habit::HabitWrapper;
+mod cursor;
mod impl_self;
mod impl_view;
mod message;
pub struct StatusLine(String, String);
+pub use cursor::Cursor;
pub use message::{Message, MessageKind};
pub struct App {
@@ -19,7 +21,7 @@ pub struct App {
_file_watcher: RecommendedWatcher,
file_event_recv: Receiver<DebouncedEvent>,
focus: usize,
- view_month_offset: u32,
+ cursor: Cursor,
message: Message,
}
diff --git a/src/habit/bit.rs b/src/habit/bit.rs
index 2bbb0ac..da64ece 100644
--- a/src/habit/bit.rs
+++ b/src/habit/bit.rs
@@ -1,11 +1,12 @@
use std::collections::HashMap;
+use std::default::Default;
use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
use crate::habit::prelude::default_auto;
use crate::habit::traits::Habit;
-use crate::habit::{TrackEvent, ViewMode};
+use crate::habit::{InnerData, TrackEvent};
use crate::CONFIGURATION;
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
@@ -42,10 +43,7 @@ pub struct Bit {
auto: bool,
#[serde(skip)]
- view_month_offset: u32,
-
- #[serde(skip)]
- view_mode: ViewMode,
+ inner_data: InnerData,
}
impl Bit {
@@ -55,8 +53,7 @@ impl Bit {
stats: HashMap::new(),
goal: CustomBool(true),
auto,
- view_month_offset: 0,
- view_mode: ViewMode::Day,
+ inner_data: Default::default(),
};
}
}
@@ -118,17 +115,11 @@ impl Habit for Bit {
}
}
}
- fn set_view_month_offset(&mut self, offset: u32) {
- self.view_month_offset = offset;
- }
- fn view_month_offset(&self) -> u32 {
- self.view_month_offset
- }
- fn set_view_mode(&mut self, mode: ViewMode) {
- self.view_mode = mode;
+ fn inner_data_ref(&self) -> &InnerData {
+ &self.inner_data
}
- fn view_mode(&self) -> ViewMode {
- self.view_mode
+ fn inner_data_mut_ref(&mut self) -> &mut InnerData {
+ &mut self.inner_data
}
fn is_auto(&self) -> bool {
self.auto
diff --git a/src/habit/count.rs b/src/habit/count.rs
index d351758..09fd399 100644
--- a/src/habit/count.rs
+++ b/src/habit/count.rs
@@ -1,11 +1,12 @@
use std::collections::HashMap;
+use std::default::Default;
use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
use crate::habit::prelude::default_auto;
use crate::habit::traits::Habit;
-use crate::habit::{TrackEvent, ViewMode};
+use crate::habit::{InnerData, TrackEvent};
#[derive(Debug, Serialize, Deserialize)]
pub struct Count {
@@ -17,10 +18,7 @@ pub struct Count {
auto: bool,
#[serde(skip)]
- view_month_offset: u32,
-
- #[serde(skip)]
- view_mode: ViewMode,
+ inner_data: InnerData,
}
impl Count {
@@ -30,8 +28,7 @@ impl Count {
stats: HashMap::new(),
goal,
auto,
- view_month_offset: 0,
- view_mode: ViewMode::Day,
+ inner_data: Default::default(),
};
}
}
@@ -95,17 +92,11 @@ impl Habit for Count {
};
}
}
- fn set_view_month_offset(&mut self, offset: u32) {
- self.view_month_offset = offset;
- }
- fn view_month_offset(&self) -> u32 {
- self.view_month_offset
- }
- fn set_view_mode(&mut self, mode: ViewMode) {
- self.view_mode = mode;
+ fn inner_data_ref(&self) -> &InnerData {
+ &self.inner_data
}
- fn view_mode(&self) -> ViewMode {
- self.view_mode
+ fn inner_data_mut_ref(&mut self) -> &mut InnerData {
+ &mut self.inner_data
}
fn is_auto(&self) -> bool {
self.auto
diff --git a/src/habit/mod.rs b/src/habit/mod.rs
index 75e734a..d51abe5 100644
--- a/src/habit/mod.rs
+++ b/src/habit/mod.rs
@@ -1,3 +1,5 @@
+use std::default::Default;
+
mod traits;
pub use traits::{Habit, HabitWrapper};
@@ -9,3 +11,28 @@ pub use bit::Bit;
mod prelude;
pub use prelude::{TrackEvent, ViewMode};
+
+use crate::app::Cursor;
+
+use cursive::direction::Absolute;
+
+#[derive(Debug, Default)]
+pub struct InnerData {
+ pub cursor: Cursor,
+ pub view_mode: ViewMode,
+}
+
+impl InnerData {
+ pub fn move_cursor(&mut self, d: Absolute) {
+ self.cursor.small_seek(d);
+ }
+ pub fn cursor(&self) -> Cursor {
+ self.cursor
+ }
+ pub fn set_view_mode(&mut self, mode: ViewMode) {
+ self.view_mode = mode;
+ }
+ pub fn view_mode(&self) -> ViewMode {
+ self.view_mode
+ }
+}
diff --git a/src/habit/traits.rs b/src/habit/traits.rs
index 74fd00b..24d941d 100644
--- a/src/habit/traits.rs
+++ b/src/habit/traits.rs
@@ -5,47 +5,41 @@ use cursive::{Printer, Vec2};
use typetag;
-use crate::habit::{Bit, Count, TrackEvent, ViewMode};
+use crate::habit::{Bit, Count, InnerData, TrackEvent};
use crate::views::ShadowView;
pub trait Habit {
type HabitType;
- fn set_name(&mut self, name: impl AsRef<str>);
- fn set_goal(&mut self, goal: Self::HabitType);
- fn name(&self) -> String;
fn get_by_date(&self, date: NaiveDate) -> Option<&Self::HabitType>;
+ fn goal(&self) -> u32;
fn insert_entry(&mut self, date: NaiveDate, val: Self::HabitType);
+ fn modify(&mut self, date: NaiveDate, event: TrackEvent);
+ fn name(&self) -> String;
fn reached_goal(&self, date: NaiveDate) -> bool;
fn remaining(&self, date: NaiveDate) -> u32;
- fn goal(&self) -> u32;
- fn modify(&mut self, date: NaiveDate, event: TrackEvent);
-
- fn set_view_month_offset(&mut self, offset: u32);
- fn view_month_offset(&self) -> u32;
+ fn set_goal(&mut self, goal: Self::HabitType);
+ fn set_name(&mut self, name: impl AsRef<str>);
- fn set_view_mode(&mut self, mode: ViewMode);
- fn view_mode(&self) -> ViewMode;
+ fn inner_data_ref(&self) -> &InnerData;
+ fn inner_data_mut_ref(&mut self) -> &mut InnerData;
fn is_auto(&self) -> bool;
}
#[typetag::serde(tag = "type")]
pub trait HabitWrapper: erased_serde::Serialize {
- fn remaining(&self, date: NaiveDate) -> u32;
+ fn draw(&self, printer: &Printer);
fn goal(&self) -> u32;
fn modify(&mut self, date: NaiveDate, event: TrackEvent);
- fn draw(&self, printer: &Printer);
+ fn name(&self) -> String;
fn on_event(&mut self, event: Event) -> EventResult;
+ fn remaining(&self, date: NaiveDate) -> u32;
fn required_size(&mut self, _: Vec2) -> Vec2;
fn take_focus(&mut self, _: Direction) -> bool;
- fn name(&self) -> String;
-
- fn set_view_month_offset(&mut self, offset: u32);
- fn view_month_offset(&self) -> u32;
- fn set_view_mode(&mut self, mode: ViewMode);
- fn view_mode(&self) -> ViewMode;
+ fn inner_data_ref(&self) -> &InnerData;
+ fn inner_data_mut_ref(&mut self) -> &mut InnerData;
fn is_auto(&self) -> bool;
}
@@ -81,17 +75,11 @@ macro_rules! auto_habit_impl {
fn name(&self) -> String {
Habit::name(self)
}
- fn set_view_month_offset(&mut self, offset: u32) {
- Habit::set_view_month_offset(self, offset)
- }
- fn view_month_offset(&self) -> u32 {
- Habit::view_month_offset(self)
- }
- fn set_view_mode(&mut self, mode: ViewMode) {
- Habit::set_view_mode(self, mode)
+ fn inner_data_ref(&self) -> &InnerData {
+ Habit::inner_data_ref(self)
}
- fn view_mode(&self) -> ViewMode {
- Habit::view_mode(self)
+ fn inner_data_mut_ref(&mut self) -> &mut InnerData {
+ Habit::inner_data_mut_ref(self)
}
fn is_auto(&self) -> bool {
Habit::is_auto(self)
diff --git a/src/keybinds.rs b/src/keybinds.rs
new file mode 100644
index 0000000..1b9c234
--- /dev/null
+++ b/src/keybinds.rs
@@ -0,0 +1,146 @@
+use std::convert::From;
+
+use cursive::event::Event as CursiveEvent;
+use serde::ser;
+use serde::{self, Deserialize, Serialize, Serializer};
+
+#[derive(Debug, PartialEq)]
+struct Event(CursiveEvent);
+
+macro_rules! event {
+ ($thing:expr) => {
+ Event { 0: $thing };
+ };
+}
+
+impl<T> From<T> for Event
+where
+ T: AsRef<str>,
+{
+ fn from(key: T) -> Self {
+ let key = key.as_ref();
+ if key.len() == 1 {
+ // single key
+ return event!(CursiveEvent::Char(key.chars().nth(0).unwrap()));
+ } else if (key.starts_with("c-") || key.starts_with("C-")) && key.len() == 3 {
+ // ctrl-key
+ return event!(CursiveEvent::CtrlChar(key.chars().nth(2).unwrap()));
+ } else {
+ panic!(
+ r"Invalid keybind in configuration!
+ (I intend to handle this error gracefully in the near future)"
+ );
+ }
+ }
+}
+
+enum Bind {
+ Char(char),
+ CtrlChar(char),
+ AltChar(char),
+}
+
+impl Serialize for Bind {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ match self {
+ Bind::Char(c) => serializer.serialize_newtype_variant("bind", 0, "regular", &c),
+ Bind::CtrlChar(c) => serializer.serialize_newtype_variant("bind", 0, "ctrl", &c),
+ Bind::AltChar(c) => serializer.serialize_newtype_variant("bind", 0, "alt", &c),
+ }
+ }
+}
+
+impl Deserialize for Bind {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ eprintln!("hell = {:#?}", hell);
+ }
+}
+
+impl From<Bind> for CursiveEvent {
+ fn from(key: Bind) -> Self {
+ match key {
+ Bind::Char(c) => CursiveEvent::Char(c),
+ Bind::CtrlChar(c) => CursiveEvent::Char(c),
+ Bind::AltChar(c) => CursiveEvent::AltChar(c),
+ }
+ }
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct KeyBinds {
+ grid: Movement,
+ cursor: Movement,
+ week_mode: Bind,
+ global_week_mode: Bind,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct Movement {
+ up: Bind,
+ down: Bind,
+ left: Bind,
+ right: Bind,
+}
+
+impl Movement {
+ pub fn new(left: char, down: char, up: char, right: char) -> Self {
+ return Movement {
+ up: Bind::Char(up),
+ down: Bind::Char(down),
+ left: Bind::Char(left),
+ right: Bind::Char(right),
+ };
+ }
+}
+
+impl std::default::Default for KeyBinds {
+ fn default() -> Self {
+ let grid = Movement::new('h', 'j', 'k', 'l');
+ let cursor = Movement::new('H', 'J', 'K', 'L');
+ return KeyBinds {
+ grid,
+ cursor,
+ week_mode: Bind::Char('v'),
+ global_week_mode: Bind::Char('V'),
+ };
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn normal_keybind() {
+ let bind = "X";
+ let expected = CursiveEvent::Char('X');
+ assert_eq!(Event::from(bind), event!(expected));
+ }
+
+ #[test]
+ fn control_keybind() {
+ let bind = "C-x";
+ let expected = CursiveEvent::CtrlChar('x');
+ assert_eq!(Event::from(bind), event!(expected));
+ }
+
+ #[test]
+ fn lower_case_control_keybind() {
+ let bind = "c-x";
+ let expected = CursiveEvent::CtrlChar('x');
+ assert_eq!(Event::from(bind), event!(expected));
+ }
+
+ #[test]
+ #[should_panic]
+ fn very_long_and_wrong_keybind() {
+ let bind = "alksdjfalkjdf";
+ Event::from(bind);
+ }
+}
diff --git a/src/theme.rs b/src/theme.rs
index 1d2cc36..879584c 100644
--- a/src/theme.rs
+++ b/src/theme.rs
@@ -1,4 +1,4 @@
-use cursive::theme::Color::*;
+use cursive::theme::Color::{self, *};
use cursive::theme::PaletteColor::*;
use cursive::theme::{BorderStyle, Palette, Theme};
@@ -24,3 +24,7 @@ pub fn theme_gen() -> Theme {
t.palette = pallete_gen();
return t;
}
+
+pub fn cursor_bg() -> Color {
+ Light(cursive::theme::BaseColor::Black)
+}
diff --git a/src/utils.rs b/src/utils.rs
index 2453aa6..f5a25c8 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -102,12 +102,12 @@ pub fn load_configuration_file() -> AppConfig {
if let Ok(ref mut f) = File::open(&cf) {
let mut j = String::new();
f.read_to_string(&mut j);
- return toml::from_str(&j).unwrap();
+ return toml::from_str(&j).unwrap_or_else(|e| panic!("Invalid config file: `{}`", e));
} else {
if let Ok(dc) = toml::to_string(&AppConfig::default()) {
match OpenOptions::new().create(true).write(true).open(&cf) {
Ok(ref mut file) => file.write(dc.as_bytes()).unwrap(),
- Err(_) => 0,
+ Err(_) => panic!("Unable to write config file to disk!"),
};
}
return Default::default();
diff --git a/src/views.rs b/src/views.rs
index efd1391..b90ce2b 100644
--- a/src/views.rs
+++ b/src/views.rs
@@ -1,13 +1,14 @@
use cursive::direction::Direction;
use cursive::event::{Event, EventResult, Key};
-use cursive::theme::{Effect, Style};
+use cursive::theme::{ColorStyle, Effect, Style};
use cursive::view::View;
use cursive::{Printer, Vec2};
use chrono::prelude::*;
-use chrono::{Duration, Local, NaiveDate};
+use chrono::{Local, NaiveDate};
use crate::habit::{Bit, Count, Habit, TrackEvent, ViewMode};
+use crate::theme::cursor_bg;
use crate::utils::VIEW_WIDTH;
use crate::CONFIGURATION;
@@ -27,24 +28,24 @@ where
T::HabitType: std::fmt::Display,
{
fn draw(&self, printer: &Printer) {
- let now = if self.view_month_offset() == 0 {
- Local::today()
- } else {
- Local::today()
- .checked_sub_signed(Duration::weeks(4 * self.view_month_offset() as i64))
- .unwrap()
- };
+ // let now = if self.view_month_offset() == 0 {
+ // Local::today()
+ // } else {
+ // Local::today()
+ // .checked_sub_signed(Duration::weeks(4 * self.view_month_offset() as i64))
+ // .unwrap()
+ // };
+ let now = self.inner_data_ref().cursor().0;
+ let is_today = now == Local::now().naive_local().date();
let year = now.year();
let month = now.month();
let goal_reached_style = Style::from(CONFIGURATION.reached_color());
- let todo_style = Style::from(CONFIGURATION.todo_color());
let future_style = Style::from(CONFIGURATION.inactive_color());
let strikethrough = Style::from(Effect::Strikethrough);
- let goal_status =
- self.view_month_offset() == 0 && self.reached_goal(Local::now().naive_local().date());
+ let goal_status = is_today && self.reached_goal(Local::now().naive_local().date());
printer.with_style(
Style::merge(&[
@@ -110,11 +111,20 @@ where
let draw_day = |printer: &Printer| {
let mut i = 0;
while let Some(d) = NaiveDate::from_ymd_opt(year, month, i + 1) {
- let day_style;
+ let mut day_style = Style::none();
+ let mut fs = future_style;
+ let grs = ColorStyle::front(CONFIGURATION.reached_color());
+ let ts = ColorStyle::front(CONFIGURATION.todo_color());
+ let cs = ColorStyle::back(cursor_bg());
+
if self.reached_goal(d) {
- day_style = goal_reached_style;
+ day_style = day_style.combine(Style::from(grs));
} else {
- day_style = todo_style;
+ day_style = day_style.combine(Style::from(ts));
+ }
+ if d == now && printer.focused {
+ day_style = day_style.combine(cs);
+ fs = fs.combine(cs);
}
let coords: Vec2 = ((i % 7) * 3, i / 7 + 2).into();
if let Some(c) = self.get_by_date(d) {
@@ -122,7 +132,7 @@ where
p.print(coords, &format!("{:^3}", c));
});
} else {
- printer.with_style(future_style, |p| {
+ printer.with_style(fs, |p| {
p.print(coords, &format!("{:^3}", CONFIGURATION.look.future_chr));
});
}
@@ -130,7 +140,7 @@ where
}
};
- match self.view_mode() {
+ match self.inner_data_ref().view_mode() {
ViewMode::Day => draw_day(printer),
ViewMode::Week => draw_week(printer),
_ => draw_day(printer),
@@ -146,7 +156,7 @@ where
}
fn on_event(&mut self, e: Event) -> EventResult {
- let now = Local::now().naive_local().date();
+ let now = self.inner_data_mut_ref().cursor().0;
if self.is_auto() {
return EventResult::Ignored;
}