Calendar: Implement basic reading feature

This commit contains a lot of different changes.
Starting from some refacting of user input code,
coloring, and adding a basic reading feature to
the program.
This commit is contained in:
osamu-kj 2023-05-13 15:58:02 +02:00
parent f810759f12
commit ad50383d03
6 changed files with 203 additions and 49 deletions

View File

@ -30,9 +30,11 @@ For example: `vis school.cal`
This will open the default view mode (month) and display the current month's calendar. From there, you can use the following commands to navigate and edit the calendar: This will open the default view mode (month) and display the current month's calendar. From there, you can use the following commands to navigate and edit the calendar:
- `h/j/k/l` - Move 1 day left/down/up/right - `h/j/k/l` - Move 1 day left/down/up/right
- `u/o` - Move 1 month left/right - `u/o` - Move 1 month left/right
- `gg` - Go to the beginning of the month - `g` - Go to the beginning of the month
- `G` - Go to the end of the month - `G` - Go to the end of the month
- `i` - Enter insert mode for the active day. - `i` - Enter insert mode for selected day.
- `x` - Delete event from selected day.
- `w` - Write changes to file (i.e. save)
- `q` - Quit and save the calendar - `q` - Quit and save the calendar
# Todos # Todos

View File

@ -11,6 +11,13 @@ calendar_information::calendar_information() {
current_month_days = Calendar::get_days_in_month(current_month, current_year); current_month_days = Calendar::get_days_in_month(current_month, current_year);
} }
calendar_information::calendar_information(int cday, int cmonth, int cyear) {
current_day = cday;
current_month = cmonth;
current_year = cyear;
current_month_days = Calendar::get_days_in_month(current_month, current_year);
}
int Calendar::get_days_in_month(int month, int year) { int Calendar::get_days_in_month(int month, int year) {
tm date = {0}; tm date = {0};
date.tm_year = year - 1900; date.tm_year = year - 1900;
@ -45,7 +52,12 @@ calendar_information Calendar::get_info() {
return this->info; return this->info;
} }
calendar_information Calendar::get_current_date() {
return this->current_date;
}
Calendar::Calendar(calendar_information *preinfo) { Calendar::Calendar(calendar_information *preinfo) {
this->current_date = calendar_information();
this->info = *preinfo; this->info = *preinfo;
if (preinfo != nullptr) if (preinfo != nullptr)
@ -53,3 +65,25 @@ Calendar::Calendar(calendar_information *preinfo) {
this->info = calendar_information(); this->info = calendar_information();
} }
// https://stackoverflow.com/questions/6054016/c-program-to-find-day-of-week-given-date
int get_weekday(calendar_information *date_info) {
if (date_info == nullptr)
return 0;
int d = date_info->current_day;
int m = date_info->current_month;
int y = date_info->current_year;
return (d += m < 3 ? y-- : y - 2, 23*m/9 + d + 4 + y/4- y/100 + y/400)%7;
}
int datecmp(calendar_information *one, calendar_information *two) {
if (one->current_day != two->current_day) return 0;
if (one->current_month != two->current_month) return 0;
if (one->current_month_days != two->current_month_days) return 0;
if (one->current_year != two->current_year) return 0;
return 1;
}

View File

@ -10,6 +10,7 @@ struct calendar_information {
int current_year; int current_year;
calendar_information(); calendar_information();
calendar_information(int cday, int cmonth, int cyear);
}; };
const bool operator<(const calendar_information& first, const calendar_information& second) { const bool operator<(const calendar_information& first, const calendar_information& second) {
@ -23,11 +24,17 @@ class Calendar {
void set_day(int day); void set_day(int day);
void set_month(int month); void set_month(int month);
void set_year(int year); void set_year(int year);
calendar_information get_info();
calendar_information get_info();
calendar_information get_current_date();
Calendar(calendar_information *preinfo = nullptr); Calendar(calendar_information *preinfo = nullptr);
private: private:
calendar_information info; calendar_information info; // mutable date that can be changed
calendar_information current_date; // current date
}; };
int get_weekday(calendar_information *date_info = nullptr);
int datecmp(calendar_information *one, calendar_information *two);
#endif #endif

View File

@ -1,7 +1,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string>
#include <string.h> #include <string.h>
#include <ncurses.h> #include <ncurses.h>
#include <signal.h> #include <signal.h>
#include <regex>
#include "engine.hpp" #include "engine.hpp"
Engine::Engine(int padding, calendar_view_mode view_mode) { Engine::Engine(int padding, calendar_view_mode view_mode) {
@ -60,12 +62,20 @@ void Engine::ui_month_draw(WINDOW *win) {
if (this->events_map.count(tmp_date) > 0) if (this->events_map.count(tmp_date) > 0)
wattron(win, COLOR_PAIR(2)); wattron(win, COLOR_PAIR(2));
calendar_information current_date = this->calendar->get_current_date();
if (datecmp(&current_date, &tmp_date))
wattron(win, COLOR_PAIR(3));
if (this->active_cell == i) if (this->active_cell == i)
wattron(win, COLOR_PAIR(1)); wattron(win, COLOR_PAIR(1));
mvwprintw(win, y_location, x_location, "D%d", i+1); std::string weekday_prefix = weekday_prefixes[get_weekday(&tmp_date)];
// mvwprintw(win, y_location, x_location, "D%d", i+1);
mvwprintw(win, y_location, x_location, "%s[%d]", weekday_prefix.c_str(), i+1);
wattroff(win, COLOR_PAIR(1)); wattroff(win, COLOR_PAIR(1));
wattroff(win, COLOR_PAIR(2)); wattroff(win, COLOR_PAIR(2));
wattroff(win, COLOR_PAIR(3));
} }
} }
@ -81,7 +91,6 @@ void Engine::ui_top_draw(WINDOW *win) {
if (VIS_COLORING) wattron(win, COLOR_PAIR(1)); if (VIS_COLORING) wattron(win, COLOR_PAIR(1));
mvwprintw(win, 1, 1, "Vi Scheduler"); mvwprintw(win, 1, 1, "Vi Scheduler");
mvwprintw(win, 2, 1, "@0xdeadbeer");
if (VIS_COLORING) wattroff(win, COLOR_PAIR(1)); if (VIS_COLORING) wattroff(win, COLOR_PAIR(1));
} }
@ -97,12 +106,24 @@ void Engine::ui_bottom_draw(WINDOW *win) {
if (VIS_COLORING) wattroff(win, COLOR_PAIR(1)); if (VIS_COLORING) wattroff(win, COLOR_PAIR(1));
} }
void Engine::input_handle_month(WINDOW *win) { void Engine::input_handle(WINDOW *win) {
char key = getch(); char key = getch();
calendar_information date_info = this->calendar->get_info(); if (this->input_handle_universal(win, key))
return;
int day, month, res; if (this->view_mode == MONTH_VIEW)
this->input_handle_month(win, key);
else if (this->view_mode == WEEK_VIEW)
this->input_handle_week(win, key);
else if (this->view_mode == MONTHS_VIEW)
this->input_handle_months(win, key);
// fuc.
}
bool Engine::input_handle_universal(WINDOW *win, char key) {
int day;
switch (key) { switch (key) {
case 'h': case 'h':
if (this->calendar->get_info().current_day <= 1) break; if (this->calendar->get_info().current_day <= 1) break;
@ -128,32 +149,14 @@ void Engine::input_handle_month(WINDOW *win) {
this->active_cell += 7; this->active_cell += 7;
break; break;
case 'k':
if (this->calendar->get_info().current_day-7 < 1) break; if (this->calendar->get_info().current_day-7 < 1) break;
case 'k':
day = this->calendar->get_info().current_day; day = this->calendar->get_info().current_day;
this->calendar->set_day(day-7); this->calendar->set_day(day-7);
this->active_cell -= 7; this->active_cell -= 7;
break; break;
case 'u':
if (this->calendar->get_info().current_month <= 1) break;
month = this->calendar->get_info().current_month;
this->calendar->set_month(--month);
this->calendar->set_day(1);
this->active_cell = 0;
break;
case 'o':
if (this->calendar->get_info().current_month >= 12) break;
month = this->calendar->get_info().current_month;
this->calendar->set_month(++month);
this->calendar->set_day(1);
this->active_cell = 0;
break;
case 'i': { // TODO: Break down this monstrocity of a case case 'i': { // TODO: Break down this monstrocity of a case
endwin(); endwin();
int vipe_out[2], vipe_in[2]; int vipe_out[2], vipe_in[2];
@ -200,6 +203,44 @@ void Engine::input_handle_month(WINDOW *win) {
this->events_map.erase(date_info); this->events_map.erase(date_info);
break; break;
} }
case 'w':
break;
case 'q':
endwin();
exit(EXIT_SUCCESS);
break;
default:
return false;
break;
}
return true;
}
void Engine::input_handle_month(WINDOW *win, char key) {
calendar_information date_info = this->calendar->get_info();
int month;
switch (key) {
case 'u':
if (this->calendar->get_info().current_month <= 1) break;
month = this->calendar->get_info().current_month;
this->calendar->set_month(--month);
this->calendar->set_day(1);
this->active_cell = 0;
break;
case 'o':
if (this->calendar->get_info().current_month >= 12) break;
month = this->calendar->get_info().current_month;
this->calendar->set_month(++month);
this->calendar->set_day(1);
this->active_cell = 0;
break;
case 'g': case 'g':
this->calendar->set_day(1); this->calendar->set_day(1);
this->active_cell = 0; this->active_cell = 0;
@ -208,17 +249,55 @@ void Engine::input_handle_month(WINDOW *win) {
this->calendar->set_day(this->calendar->get_info().current_month_days); this->calendar->set_day(this->calendar->get_info().current_month_days);
this->active_cell = this->calendar->get_info().current_month_days-1; this->active_cell = this->calendar->get_info().current_month_days-1;
break; break;
case 't':
this->view_mode = WEEK_VIEW;
wclear(win);
break;
} }
} }
void Engine::input_handle_week(WINDOW *win) { void Engine::input_handle_week(WINDOW *win, char key) {
// TODO // TODO
} }
void Engine::input_handle_months(WINDOW *win) { void Engine::input_handle_months(WINDOW *win, char key) {
// TODO // TODO
} }
calendar_information Engine::parse_date(std::string date) {
char *token = strtok((char *) date.c_str(), ".");
std::vector<int> tokens;
while (token != NULL) {
tokens.push_back(std::stoi(token));
token = strtok(NULL, ".");
}
return calendar_information(tokens[0], tokens[1], tokens[2]);
}
void Engine::parse_line(std::string line) {
char *token = strtok((char *) line.c_str(), " ");
std::vector<std::string> tokens;
while (token != NULL) {
tokens.push_back(token);
token = strtok(NULL, " ");
}
if (tokens.size() != 2)
return;
calendar_information event_date = this->parse_date(tokens[0]);
this->events_map[event_date] = tokens[1];
}
void Engine::open_calendar(char *filename) {
this->calendar_file.open(filename, std::ios::in | std::ios::out);
// If the file does not exist,
// we'll create and reopen it later ('write' shortcut)
if (this->calendar_file.fail())
return;
std::string line;
while (std::getline(this->calendar_file, line)) {
this->parse_line(line);
}
}

View File

@ -2,6 +2,7 @@
#define ENGINE_HPP #define ENGINE_HPP
#include <iostream> #include <iostream>
#include <fstream>
#include <ncurses.h> #include <ncurses.h>
#include <vector> #include <vector>
// #include <unordered_map> // #include <unordered_map>
@ -20,6 +21,16 @@ enum calendar_view_mode {
MONTHS_VIEW MONTHS_VIEW
}; };
std::string weekday_prefixes[] = {
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
};
std::string calendar_view_mode_str[] = { std::string calendar_view_mode_str[] = {
"MONTH_VIEW", "MONTH_VIEW",
"WEEK_VIEW", "WEEK_VIEW",
@ -30,7 +41,7 @@ std::string calendar_view_mode_str[] = {
// description: use for drawing the TUI and interact with the cells // description: use for drawing the TUI and interact with the cells
class Engine { class Engine {
public: public:
Engine(int padding = 10, calendar_view_mode view_mode = MONTH_VIEW); Engine(int padding, calendar_view_mode view_mode);
~Engine(); ~Engine();
void ui_draw(WINDOW *win); void ui_draw(WINDOW *win);
@ -40,9 +51,15 @@ class Engine {
void ui_bottom_draw(WINDOW *win); void ui_bottom_draw(WINDOW *win);
void ui_top_draw(WINDOW *win); void ui_top_draw(WINDOW *win);
void input_handle_month(WINDOW *win); void input_handle(WINDOW* win);
void input_handle_week(WINDOW *win); bool input_handle_universal(WINDOW *win, char key);
void input_handle_months(WINDOW *win); void input_handle_month(WINDOW *win, char key);
void input_handle_week(WINDOW *win, char key);
void input_handle_months(WINDOW *win, char key);
calendar_information parse_date(std::string date);
void parse_line(std::string line);
void open_calendar(char *filename);
Calendar *calendar; Calendar *calendar;
// std::unordered_map<calendar_information, std::string> events_map; // std::unordered_map<calendar_information, std::string> events_map;
@ -54,7 +71,7 @@ class Engine {
private: private:
std::vector<engine_child> cells_table; std::vector<engine_child> cells_table;
std::fstream calendar_file;
}; };
#endif #endif

View File

@ -6,7 +6,7 @@
#include "engine/engine.hpp" #include "engine/engine.hpp"
#include "global/global.hpp" #include "global/global.hpp"
Engine engine = Engine(10, MONTH_VIEW); Engine engine(10, MONTH_VIEW);
WINDOW *main_win; WINDOW *main_win;
void sig_winch(int sig) { void sig_winch(int sig) {
@ -31,7 +31,25 @@ void signals() {
signal(SIGWINCH, sig_winch); signal(SIGWINCH, sig_winch);
} }
int main() { void print_help() {
}
bool check_args(int argc, char **argv) {
if (argc != 2) {
print_help();
return false;
}
engine.open_calendar(argv[1]);
return true;
}
int main(int argc, char **argv) {
if (!check_args(argc, argv))
return EXIT_FAILURE;
initscr(); initscr();
refresh(); refresh();
@ -49,6 +67,7 @@ int main() {
init_pair(0, COLOR_WHITE, COLOR_BLACK); init_pair(0, COLOR_WHITE, COLOR_BLACK);
init_pair(1, COLOR_BLACK, COLOR_WHITE); init_pair(1, COLOR_BLACK, COLOR_WHITE);
init_pair(2, COLOR_BLACK, COLOR_RED); init_pair(2, COLOR_BLACK, COLOR_RED);
init_pair(3, COLOR_BLACK, COLOR_GREEN);
} }
// handle required signals // handle required signals
@ -57,14 +76,10 @@ int main() {
for (;;) { for (;;) {
engine.ui_draw(main_win); engine.ui_draw(main_win);
if (engine.view_mode == MONTH_VIEW) engine.input_handle(main_win);
engine.input_handle_month(main_win);
if (engine.view_mode == WEEK_VIEW)
engine.input_handle_week(main_win);
else if (engine.view_mode == MONTHS_VIEW)
engine.input_handle_months(main_win);
} }
endwin(); endwin();
return 0; return 0;