Initial Commit
This commit is contained in:
7
CMakeLists.txt
Normal file
7
CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.24)
|
||||
project(todo)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_executable(todo main.cpp colors.h json.h)
|
101
colors.h
Normal file
101
colors.h
Normal file
@@ -0,0 +1,101 @@
|
||||
// Console Color Codes
|
||||
|
||||
#define RESET_ALL "\033[0m"
|
||||
#define BOLD "\033[1m"
|
||||
#define DIM "\033[2m"
|
||||
#define STANDOUT "\033[3m"
|
||||
#define UNDERSCORE "\033[4m"
|
||||
#define BLINK "\033[5m"
|
||||
#define INVERT "\033[7m"
|
||||
#define HIDDEN "\033[8m"
|
||||
#define SAVE_SCREEN "\033[?47h"
|
||||
#define RESTORE_SCREEN "\033[?47l"
|
||||
#define BG_BLACK "\033[40m"
|
||||
#define BG_DARK_GRAY "\033[1;40m"
|
||||
#define BG_RED "\033[41m"
|
||||
#define BG_LIGHT_RED "\033[1;41m"
|
||||
#define BG_GREEN "\033[42m"
|
||||
#define BG_LIGHT_GREEN "\033[1;42m"
|
||||
#define BG_BROWN "\033[43m"
|
||||
#define BG_YELLOW "\033[1;43m"
|
||||
#define BG_BLUE "\033[44m"
|
||||
#define BG_LIGHT_BLUE "\033[1;44m"
|
||||
#define BG_MAGENTA "\033[45m"
|
||||
#define BG_LIGHT_PURPLE "\033[1;45m"
|
||||
#define BG_CYAN "\033[46m"
|
||||
#define BG_LIGHT_CYAN "\033[1;46m"
|
||||
#define BG_LIGHT_GRAY "\033[47m"
|
||||
#define BG_WHITE "\033[1;47m"
|
||||
#define BG_DEFAULT "\033[48m"
|
||||
#define FG_BLACK "\033[30m"
|
||||
#define FG_DARK_GRAY "\033[1;30m"
|
||||
#define FG_RED "\033[31m"
|
||||
#define FG_LIGHT_RED "\033[1;31m"
|
||||
#define FG_GREEN "\033[32m"
|
||||
#define FG_LIGHT_GREEN "\033[1;32m"
|
||||
#define FG_BROWN "\033[33m"
|
||||
#define FG_YELLOW "\033[1;33m"
|
||||
#define FG_BLUE "\033[34m"
|
||||
#define FG_LIGHT_BLUE "\033[1;34m"
|
||||
#define FG_MAGENTA "\033[35m"
|
||||
#define FG_LIGHT_PURPLE "\033[1;35m"
|
||||
#define FG_CYAN "\033[36m"
|
||||
#define FG_LIGHT_CYAN "\033[1;36m"
|
||||
#define FG_LIGHT_GRAY "\033[37m"
|
||||
#define FG_WHITE "\033[1;37m"
|
||||
#define FG_DEFAULT "\033[38m"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void fg_color_test(const char* bg)
|
||||
{
|
||||
std::cout << bg;
|
||||
std::cout << FG_BLACK << "Sample Text";
|
||||
std::cout << FG_DARK_GRAY << "Sample Text";
|
||||
std::cout << FG_RED << "Sample Text";
|
||||
std::cout << FG_LIGHT_RED << "Sample Text";
|
||||
std::cout << FG_GREEN << "Sample Text";
|
||||
std::cout << FG_LIGHT_GREEN << "Sample Text";
|
||||
std::cout << FG_BROWN << "Sample Text";
|
||||
std::cout << FG_YELLOW << "Sample Text";
|
||||
std::cout << FG_BLUE << "Sample Text";
|
||||
std::cout << FG_LIGHT_BLUE << "Sample Text";
|
||||
std::cout << FG_MAGENTA << "Sample Text";
|
||||
std::cout << FG_LIGHT_PURPLE << "Sample Text";
|
||||
std::cout << FG_CYAN << "Sample Text";
|
||||
std::cout << FG_LIGHT_CYAN << "Sample Text";
|
||||
std::cout << FG_WHITE << "Sample Text";
|
||||
std::cout << FG_LIGHT_GRAY << "Sample Text";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void bg_color_test()
|
||||
{
|
||||
fg_color_test(BG_BLACK);
|
||||
fg_color_test(BG_DARK_GRAY);
|
||||
fg_color_test(BG_RED);
|
||||
fg_color_test(BG_LIGHT_RED);
|
||||
fg_color_test(BG_GREEN);
|
||||
fg_color_test(BG_LIGHT_GREEN);
|
||||
fg_color_test(BG_BROWN);
|
||||
fg_color_test(BG_YELLOW);
|
||||
fg_color_test(BG_BLUE);
|
||||
fg_color_test(BG_LIGHT_BLUE);
|
||||
fg_color_test(BG_MAGENTA);
|
||||
fg_color_test(BG_LIGHT_PURPLE);
|
||||
fg_color_test(BG_CYAN);
|
||||
fg_color_test(BG_LIGHT_CYAN);
|
||||
fg_color_test(BG_WHITE);
|
||||
fg_color_test(BG_LIGHT_GRAY);
|
||||
std::cout << BG_DEFAULT << std::endl;
|
||||
}
|
||||
|
||||
void color_test()
|
||||
{
|
||||
bg_color_test();
|
||||
std::cout << RESET_ALL;
|
||||
std::cout << BOLD;
|
||||
bg_color_test();
|
||||
std::cout << RESET_ALL << std::endl;
|
||||
}
|
165
main.cpp
Normal file
165
main.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/// To Do List Program
|
||||
// Copyright Conarium Software 2023
|
||||
// @auth J. O'Leary
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "colors.h"
|
||||
#include "json.h"
|
||||
|
||||
using std::chrono_literals::operator""h;
|
||||
using string = std::string;
|
||||
using timestamp = std::chrono::time_point<std::chrono::system_clock>;
|
||||
string timestamp_to_string(const timestamp time)
|
||||
{
|
||||
auto in_time_t = std::chrono::system_clock::to_time_t(time);
|
||||
std::stringstream ss;
|
||||
ss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %H:%M:%S");
|
||||
return ss.str();
|
||||
}
|
||||
const timestamp string_to_timestamp(std::string time_str)
|
||||
{
|
||||
std::tm tm = {};
|
||||
strptime(time_str.c_str(), "%Y-%m-%d %H:%M:%S", &tm);
|
||||
// The -1h is a lazy hack to hotfix timezones incrementing the hour
|
||||
return std::chrono::system_clock::from_time_t(std::mktime(&tm))-1h;
|
||||
}
|
||||
timestamp get_current_timestamp() {
|
||||
return std::chrono::system_clock::now();
|
||||
}
|
||||
string get_current_timestamp_str() {
|
||||
return timestamp_to_string(get_current_timestamp());
|
||||
}
|
||||
int get_timestamp_age(const std::string timestamp)
|
||||
{
|
||||
auto tp = string_to_timestamp(timestamp);
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
const auto difference = std::chrono::duration_cast<std::chrono::days>(now-tp).count();
|
||||
return difference;
|
||||
}
|
||||
bool matches(const std::string needle, std::vector<std::string> haystack)
|
||||
{
|
||||
return std::find(haystack.begin(), haystack.end(), needle) != haystack.end();
|
||||
}
|
||||
void show_help()
|
||||
{
|
||||
std::cout << "To Do List Program by Conarium Software" << std::endl;
|
||||
}
|
||||
|
||||
std::string rebuild_args_to_sentence(std::vector<std::string> args)
|
||||
{
|
||||
std::string sentence;
|
||||
for(int i = 0; i < args.size(); i++) {
|
||||
sentence += args[i];
|
||||
if (i < args.size()-1) // Append a space between each token, without appending to the final token's end
|
||||
sentence += " ";
|
||||
}
|
||||
return sentence;
|
||||
}
|
||||
#define FILENAME ".todo.txt"
|
||||
#define MAGENTA_LIMIT 21
|
||||
#define RED_LIMIT 14
|
||||
#define YELLOW_LIMIT 7
|
||||
#define GREEN_LIMIT 1
|
||||
|
||||
void output_line(const char* colorcode, std::string timestamp, std::string age, std::string text)
|
||||
{
|
||||
std::cout << BOLD << colorcode << "[" << timestamp << "] [" << age << "] "<< FG_WHITE << text << std::endl;
|
||||
}
|
||||
void output_list(std::string file_path)
|
||||
{
|
||||
// Find, Parse, Output the todo list
|
||||
std::ifstream file(file_path);
|
||||
|
||||
// is the file empty?
|
||||
if (file.peek() == std::ifstream::traits_type::eof())
|
||||
{
|
||||
std::cout << "No tasks on the TODO list!" << std::endl;
|
||||
return;
|
||||
}
|
||||
// Read each line from the file and parse it into a TODO.
|
||||
std::string str;
|
||||
while (std::getline(file, str)) {
|
||||
// Parses 1 line of the file (str) as a json object; (NOT the entire file!)
|
||||
// Grab relevant strings; timestamp, text, tag
|
||||
nlohmann::json token = nlohmann::json::parse(str);
|
||||
std::string timestamp = token["timestamp"].get<std::string>();
|
||||
std::string text = token["text"].get<std::string>();
|
||||
std::string ag = token["tag"].get<std::string>();
|
||||
// Calculate age (in days) of the TODO
|
||||
int age = get_timestamp_age(timestamp);
|
||||
// TODO: Make timeline configurable.
|
||||
// Create timestamp string
|
||||
std::string days_counter = std::to_string(age) + " days ago";
|
||||
|
||||
if (age > MAGENTA_LIMIT) { output_line(FG_MAGENTA, timestamp, days_counter, text); }
|
||||
else if (age > RED_LIMIT) { output_line(FG_RED, timestamp, days_counter, text); }
|
||||
else if (age > YELLOW_LIMIT) { output_line(FG_YELLOW, timestamp, days_counter, text); }
|
||||
else if (age > GREEN_LIMIT) { output_line(FG_GREEN, timestamp, days_counter, text); }
|
||||
else { output_line(FG_BLUE, timestamp, days_counter, text); }
|
||||
}
|
||||
file.close();
|
||||
std::cout << RESET_ALL;
|
||||
}
|
||||
|
||||
void append_to_list(std::string file_id, std::string current_timestamp, std::string content){
|
||||
nlohmann::json token = {
|
||||
{"text", content},
|
||||
{"timestamp", current_timestamp},
|
||||
{"tag", ""},
|
||||
};
|
||||
std::ofstream file(file_id, std::ios_base::app);
|
||||
file << token.dump() << std::endl;
|
||||
file.close();
|
||||
std::cout << "Added to TODO list!" << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
// System Variables
|
||||
std::string current_timestamp = get_current_timestamp_str();
|
||||
std::string home_dir = getenv("HOME");
|
||||
std::string file_id = home_dir + "/" + FILENAME;
|
||||
|
||||
std::vector<std::string> args_list(argv + 1, argv + argc);
|
||||
|
||||
// Check for option flags to parse out. (--<flag>)
|
||||
// Flags are removed from args_list at this point.
|
||||
// Runs in reverse so we can remove vector elements safely.
|
||||
for(int i = args_list.size()- 1; i >= 0 ; i--) {
|
||||
if (matches(args_list[i], {"--version", "-v", "--v"})) {
|
||||
args_list.erase(args_list.begin() + i);
|
||||
std::cout << "Version 1.1" << std::endl;
|
||||
return 0; // Certain Flags cause the program to terminate.
|
||||
}
|
||||
if (matches(args_list[i], {"--help", "-h", "--h"})) {
|
||||
args_list.erase(args_list.begin() + i);
|
||||
show_help();
|
||||
return 0; // Certain Flags cause the program to terminate.
|
||||
}
|
||||
if (matches(args_list[i], {"--here"})) {
|
||||
args_list.erase(args_list.begin() + i);
|
||||
|
||||
file_id = FILENAME;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Run the program with cherry-picked args_list
|
||||
if (args_list.size() < 1) {
|
||||
output_list(file_id);
|
||||
} else {
|
||||
std::string item = rebuild_args_to_sentence(args_list);
|
||||
append_to_list(file_id, get_current_timestamp_str(), item);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user