Compare commits

...

5 Commits

23 changed files with 259 additions and 147 deletions

2
.gitignore vendored

@ -55,7 +55,7 @@ bld/
[Bb]uild/
[Oo]bj/
[Ll]og/
cmake-build-debug
cmake-build-debug*
# Visual Studio 2015 cache/options directory
.vs/

@ -7,7 +7,11 @@ COPY . ./
RUN mkdir build && cd build && ../cbuildrel
FROM alpine:latest as run
RUN apk add libstdc++
COPY --from=build /kc/build/kc /kc/kc
RUN mkdir /kc/log
WORKDIR /kc

@ -14,7 +14,6 @@
task/current_tasks.cpp
net/ntfy.cpp
net/http.cpp
# image/img.cpp
)
FetchContent_Declare(
@ -27,7 +26,27 @@ FetchContent_MakeAvailable(Boost)
find_package(OpenSSL REQUIRED)
include_directories(${OPENSSL_INCLUDE_DIR})
#find_package( OpenCV REQUIRED )
#include_directories( ${OpenCV_INCLUDE_DIRS} )
if(OPENCV)
add_compile_definitions(WITH_OPENCV)
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
target_sources(kc PRIVATE image/img.cpp)
endif()
target_link_libraries(kc PRIVATE Boost::program_options Boost::log Boost::date_time Boost::filesystem Boost::system Boost::thread Boost::log_setup Boost::chrono Boost::atomic Boost::asio Boost::beast Boost::json Boost::algorithm ${OPENSSL_LIBRARIES} ${OpenCV_LIBS})
target_link_libraries(kc PRIVATE
Boost::program_options
Boost::log
Boost::date_time
Boost::filesystem
Boost::system
Boost::thread
Boost::log_setup
Boost::chrono
Boost::atomic
Boost::asio
Boost::beast
Boost::json
Boost::algorithm
${OPENSSL_LIBRARIES}
${OpenCV_LIBS}
)

@ -5,12 +5,16 @@
#include "config.hpp"
#include "logging.hpp"
#if __cpp_lib_execution //checking to see if the <execution> header is there
#include <execution>
#endif
namespace kc {
AppContext::AppContext(): config_loaded(false) {
}
void AppContext::load_config(int argc, const char *argv[])
void AppContext::load_config(const int argc, const char *argv[])
{
config = init_config(argc, argv);
config_loaded = true;
@ -22,17 +26,31 @@ void AppContext::load_and_parse_cache() {
void AppContext::load_and_parse_cache(ParseOperations operations)
{
if (!config->contains("path")) {
print_and_log_error("No paths provided");
return;
}
const auto env_paths = (*config)["path"].as<std::vector<std::string>>();
for (const auto& env_path : env_paths) {
#ifdef __cpp_lib_execution
std::mutex m;
std::for_each(std::execution::par, env_paths.begin(), env_paths.end(), [this, &operations, &m](const std::string &env_path)
#else
std::ranges::for_each(env_paths, [this, &operations](const std::string &env_path)
#endif
{
print_and_log("Loading knowledge base from " + env_path);
auto file_cache = std::make_shared<kc::FileContextCache>();
const auto file_cache = std::make_shared<kc::FileContextCache>();
file_cache->load(env_path);
file_cache->parse_all(operations);
#ifdef __cpp_lib_execution
std::lock_guard<std::mutex> lock{m};
#endif
file_caches.push_back(file_cache);
}
});
}
std::string AppContext::command() const {
@ -40,10 +58,7 @@ std::string AppContext::command() const {
{
return (*config)["command"].as<std::string>();
}
else
{
return "";
}
return "";
}
}

@ -7,6 +7,7 @@
#include <boost/program_options.hpp>
#include "const.hpp"
#include "logging.hpp"
po::options_description get_current_tasks_options() {
po::options_description options("Current Tasks");
@ -15,6 +16,7 @@ po::options_description get_current_tasks_options() {
(CONFIG_HOST.c_str(), po::value<std::string>(), "ntfy hostname")
(CONFIG_TOPIC.c_str(), po::value<std::string>(), "ntfy topic name")
(CONFIG_TITLE.c_str(), po::value<std::string>(), "title for notifications")
(CONFIG_TAGS.c_str(), po::value<std::vector<std::string>>(), "tags to add to notification")
;
return options;
@ -28,6 +30,7 @@ std::shared_ptr<po::variables_map> init_config(int argc, const char *argv[])
("help,h", "produce help message")
("path,p", po::value<std::vector<std::string>>(), "set root path of knowledge base")
("config", po::value<std::string>()->default_value("kc.ini"), "config file location")
("logpath", po::value<std::string>()->default_value("."), "log folder location")
;
po::options_description hidden_general("Hidden");
@ -75,10 +78,10 @@ std::shared_ptr<po::variables_map> init_config(int argc, const char *argv[])
if (vm->contains("config"))
{
auto config_path = (*vm)["config"].as<std::string>();
BOOST_LOG_TRIVIAL(info) << "Attempting file config load for " << config_path;
// BOOST_LOG_TRIVIAL(info) << "Attempting file config load for " << config_path;
if (std::ifstream ifs{config_path.c_str()}) {
BOOST_LOG_TRIVIAL(info) << "File opened, loading...";
// BOOST_LOG_TRIVIAL(info) << "File opened, loading...";
po::store(po::parse_config_file(ifs, config_file_options), *vm);
}
}
@ -88,9 +91,7 @@ std::shared_ptr<po::variables_map> init_config(int argc, const char *argv[])
if (vm->count("command") == 1)
{
auto command = (*vm)["command"].as<std::string>();
if (command == CMD_CURRENT_TASKS) {
if (auto command = (*vm)["command"].as<std::string>(); command == CMD_CURRENT_TASKS) {
std::cout << visible_general << std::endl << current_tasks_options;
}
}
@ -107,7 +108,7 @@ std::shared_ptr<po::variables_map> init_config(int argc, const char *argv[])
}
catch (const po::error &ex)
{
BOOST_LOG_TRIVIAL(error) << ex.what();
std::cout << ex.what() << std::endl;
return nullptr;
}

@ -10,7 +10,6 @@ static const std::string CMD_VALIDATE_TASKS = "validate";
static const std::string CMD_IMG_TASKS = "img";
static const std::string CMD_PRINT_TASKS = "print";
static const std::string CMD_CURRENT_TASKS = "current";
static const std::string CMD_NET_TASKS = "net";
///////////////
@ -21,6 +20,7 @@ static const std::string CONFIG_NOTIFY = "notify";
static const std::string CONFIG_HOST = "host";
static const std::string CONFIG_TOPIC = "topic";
static const std::string CONFIG_TITLE = "title";
static const std::string CONFIG_TAGS = "tag";
///////////////

@ -15,16 +15,21 @@ bool FileEntry::content_loaded() const
return loaded;
}
std::string FileEntry::load_content()
std::vector<std::string> FileEntry::load_content()
{
std::ifstream ifs(file_entry.path());
file_content.assign( (std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()) );
for (std::string line; std::getline(ifs, line);)
{
file_content.emplace_back(line);
}
loaded = true;
return file_content;
}
std::string FileEntry::get_content() const
std::vector<std::string> FileEntry::get_content() const
{
return file_content;
}

@ -18,13 +18,13 @@ class FileEntry {
fs::path relative_path;
[[nodiscard]] bool content_loaded() const;
std::string load_content();
[[nodiscard]] std::string get_content() const;
std::vector<std::string> load_content();
[[nodiscard]] std::vector<std::string> get_content() const;
void clear_content();
private:
std::string file_content;
std::vector<std::string> file_content;
bool loaded;
};

@ -5,12 +5,11 @@
static const std::string exclusions[] = {".git", ".obsidian"};
std::vector<std::shared_ptr<kc::FileEntry>> kc::walk_dir(const std::string dir)
std::vector<std::shared_ptr<kc::FileEntry>> kc::walk_dir(const std::string &dir)
{
auto matched = std::vector<std::shared_ptr<kc::FileEntry>>();
const auto base_path = fs::path(dir);
for (auto const& dir_entry : fs::recursive_directory_iterator(base_path))
for (const auto base_path = fs::path(dir); auto const& dir_entry : fs::recursive_directory_iterator(base_path))
{
if (dir_entry.is_directory()) continue;

@ -11,6 +11,6 @@ namespace fs = std::filesystem;
namespace kc {
std::vector<std::shared_ptr<kc::FileEntry>> walk_dir(std::string dir);
std::vector<std::shared_ptr<kc::FileEntry>> walk_dir(const std::string &dir);
}

@ -1,18 +1,22 @@
#include "logging.hpp"
#include <filesystem>
namespace logging = boost::log;
namespace src = boost::log::sources;
namespace sinks = boost::log::sinks;
namespace keywords = boost::log::keywords;
namespace fs = std::filesystem;
void init_logging()
void init_logging(const std::string &log_path)
{
logging::register_simple_formatter_factory<logging::trivial::severity_level, char>("Severity");
auto log_file = std::string(fs::path(log_path) / fs::path("kc_%N.log"));
logging::add_file_log
(
keywords::file_name = "kc_%N.log",
keywords::file_name = log_file,
keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0),
keywords::format = "[%TimeStamp%] [%ThreadID%] [%Severity%] %Message%",
keywords::open_mode = std::ios::app

@ -9,7 +9,7 @@
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/console.hpp>
void init_logging();
void init_logging(const std::string &log_path);
inline void print_and_log(std::string log_line)
{

@ -3,78 +3,84 @@
#include <iostream>
#include <fstream>
#include <memory>
#include <regex>
#include "const.hpp"
#include "logging.hpp"
#include "config.hpp"
#include "appcontext.hpp"
#include "fs/fs.hpp"
#include "net/http.hpp"
#include "net/ntfy.hpp"
#include "parse/FileContextCache.hpp"
#include "print/print.hpp"
#include "task/current_tasks.hpp"
#include "valid/link.hpp"
//#include "image/img.hpp"
#ifdef WITH_OPENCV
#include "image/img.hpp"
#endif
void run_validate(const kc::AppContext &app_context);
void run_img(const kc::AppContext &app_context);
void run_print(const kc::AppContext &app_context);
int run_current_tasks(const kc::AppContext &app_context);
void run_test_net(const kc::AppContext &app_context);
int main(int argc, const char *argv[]) {
init_logging();
BOOST_LOG_TRIVIAL(info) << "================================";
BOOST_LOG_TRIVIAL(info) << " kc";
BOOST_LOG_TRIVIAL(info) << "================================";
BOOST_LOG_TRIVIAL(info) << "Starting up....";
kc::AppContext app_context;
app_context.load_config(argc, argv);
if(app_context.config)
{
const auto command = app_context.command();
if (!command.empty())
{
if (command == CMD_VALIDATE_TASKS)
{
app_context.load_and_parse_cache(kc::LINKS);
run_validate(app_context);
}
else if (command == CMD_IMG_TASKS)
{
app_context.load_and_parse_cache(kc::IMAGES);
run_img(app_context);
}
else if (command == CMD_PRINT_TASKS)
{
app_context.load_and_parse_cache();
run_print(app_context);
}
else if (command == CMD_CURRENT_TASKS)
{
app_context.load_and_parse_cache(kc::TASKS);
return run_current_tasks(app_context);
}
else if (command == CMD_NET_TASKS)
{
// app_context.load_and_parse_cache(kc::TASKS);
run_test_net(app_context);
}
}
else
{
print_and_log_error("Command not found, exiting");
return 1;
}
init_logging((*app_context.config)["logpath"].as<std::string>());
return 0;
try {
BOOST_LOG_TRIVIAL(info) << "================================";
BOOST_LOG_TRIVIAL(info) << " kc";
BOOST_LOG_TRIVIAL(info) << "================================";
BOOST_LOG_TRIVIAL(info) << "Starting up....";
#ifdef __cpp_lib_execution
BOOST_LOG_TRIVIAL(debug) << "Compiled with parallel loops";
#else
BOOST_LOG_TRIVIAL(debug) << "Compiled WITHOUT parallel loops";
#endif
if(app_context.config)
{
if (const auto command = app_context.command(); !command.empty())
{
if (command == CMD_VALIDATE_TASKS)
{
app_context.load_and_parse_cache(kc::LINKS);
run_validate(app_context);
}
#ifdef WITH_OPENCV
else if (command == CMD_IMG_TASKS)
{
app_context.load_and_parse_cache(kc::IMAGES);
run_img(app_context);
}
#endif
else if (command == CMD_PRINT_TASKS)
{
app_context.load_and_parse_cache();
run_print(app_context);
}
else if (command == CMD_CURRENT_TASKS)
{
app_context.load_and_parse_cache(kc::TASKS);
return run_current_tasks(app_context);
}
}
else
{
print_and_log_error("Command not found, exiting");
return 1;
}
return 0;
}
}
catch (const std::exception &e) {
print_and_log_error(std::format("Exception occurred - {}", e.what()));
}
return 1;
@ -91,11 +97,14 @@ void run_validate(const kc::AppContext &app_context)
void run_img(const kc::AppContext &app_context)
{
#ifdef WITH_OPENCV
BOOST_LOG_TRIVIAL(info) << "Running \"Image Processing\" command";
for(const auto& file_cache : app_context.file_caches) {
BOOST_LOG_TRIVIAL(info) << "Image processing in " << file_cache->get_root_path();
// kc::image_proc(file_cache->get());
kc::image_proc(file_cache->get());
}
#endif
}
void run_print(const kc::AppContext &app_context)
@ -110,10 +119,4 @@ int run_current_tasks(const kc::AppContext &app_context)
{
BOOST_LOG_TRIVIAL(info) << "Running \"Current Tasks\" command";
return kc::current_tasks(app_context);
}
void run_test_net(const kc::AppContext &app_context)
{
kc::notify("ntfy.sheep-ghoul.ts.net",
kc::Notification("todo", "next test!"));
}

@ -2,6 +2,7 @@
#include <boost/beast/version.hpp>
#include <boost/log/trivial.hpp>
#include <utility>
// https://www.boost.org/doc/libs/1_87_0/libs/beast/example/http/client/sync-ssl/http_client_sync_ssl.cpp
@ -38,11 +39,11 @@ void shutdown_stream(const std::shared_ptr<ssl::stream<beast::tcp_stream>> &stre
}
void request(http::verb method, const std::string &host, std::string target, std::string body, std::unique_ptr<std::unordered_map<std::string, std::string>> headers) {
request(method, host, target, 443, body, std::move(headers));
request(std::move(method), std::move(host), std::move(target), 443, std::move(body), std::move(headers));
}
void request(http::verb method, const std::string &host, std::string target, std::string body) {
request(method, host, target, 443, body, nullptr);
request(std::move(method), std::move(host), std::move(target), 443, std::move(body), nullptr);
}
void request(http::verb method, const std::string &host, std::string target, int port, std::string body, std::unique_ptr<std::unordered_map<std::string, std::string>> headers) {
@ -89,8 +90,8 @@ void request(http::verb method, const std::string &host, std::string target, int
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
if (headers) {
for (auto const &kv : *headers) {
req.set(kv.first, kv.second);
for (const auto &[fst, snd] : *headers) {
req.set(fst, snd);
}
}

@ -4,7 +4,7 @@
namespace kc {
constexpr std::string get_urgency_string(NotificationUrgency u){
constexpr std::string get_urgency_string(const NotificationUrgency u){
switch(u){
case NotificationUrgency::MAX:
return "max";
@ -20,7 +20,7 @@ constexpr std::string get_urgency_string(NotificationUrgency u){
return "default";
}
void notify(std::string host, Notification notification)
void notify(const std::string &host, const Notification &notification)
{
request(
http::verb::post,

@ -58,6 +58,6 @@ private:
NotificationUrgency priority;
};
void notify(std::string host, Notification notification);
void notify(const std::string &host, const Notification &notification);
}

@ -1,11 +1,15 @@
#include "FileContext.hpp"
#include "../logging.hpp"
namespace kc {
FileContext::FileContext(std::shared_ptr<kc::FileEntry> entry)
: file_entry(std::move(entry)), links_parsed(false) {
}
constexpr int MAX_LINE_LENGTH = 3000;
void FileContext::parse()
{
if (!file_entry->content_loaded())
@ -24,7 +28,7 @@ void FileContext::parse()
parse_tasks();
}
void FileContext::parse(ParseOperations operations)
void FileContext::parse(const ParseOperations operations)
{
if (!file_entry->content_loaded())
{
@ -53,50 +57,86 @@ void FileContext::parse(ParseOperations operations)
}
void FileContext::parse_links() {
std::regex link_regex(MD_MD_LINK_REGEX);
std::string file_content = file_entry->get_content();
std::smatch link_match;
while(std::regex_search(file_content, link_match, link_regex)) {
const std::regex link_regex(MD_MD_LINK_REGEX, std::regex::optimize);
const auto file_content = file_entry->get_content();
links.emplace_back(link_match.str());
file_content = link_match.suffix();
for (const auto& line : file_content) {
if (line.length() < MAX_LINE_LENGTH) {
std::string line_content = line;
std::smatch link_match;
while(std::regex_search(line_content, link_match, link_regex)) {
links.emplace_back(link_match.str());
line_content = link_match.suffix();
}
}
else {
BOOST_LOG_TRIVIAL(error) << "Skipping line because too long: " << line;
}
}
}
void FileContext::parse_images() {
std::regex image_regex(MD_IMAGE_LINK_REGEX);
std::string file_content = file_entry->get_content();
std::smatch image_match;
while(std::regex_search(file_content, image_match, image_regex)) {
const std::regex image_regex(MD_IMAGE_LINK_REGEX, std::regex::optimize);
const auto file_content = file_entry->get_content();
images.emplace_back(image_match.str());
file_content = image_match.suffix();
for (const auto& line : file_content) {
if (line.length() < MAX_LINE_LENGTH) {
std::string line_content = line;
std::smatch image_match;
while(std::regex_search(line_content, image_match, image_regex)) {
images.emplace_back(image_match.str());
line_content = image_match.suffix();
}
}
else {
BOOST_LOG_TRIVIAL(error) << "Skipping line because too long: " << line;
}
}
}
void FileContext::parse_tags() {
#if __APPLE__
std::regex tag_regex(MD_TAG_REGEX, std::regex::multiline);
std::regex tag_regex(MD_TAG_REGEX, std::regex::multiline | std::regex::optimize);
#else
std::regex tag_regex(MD_TAG_REGEX);
std::regex tag_regex(MD_TAG_REGEX, std::regex::optimize);
#endif
std::string file_content = file_entry->get_content();
std::smatch tag_match;
while(std::regex_search(file_content, tag_match, tag_regex)) {
const auto file_content = file_entry->get_content();
tags.push_back(tag_match.str().substr(1));
file_content = tag_match.suffix();
for (const auto& line : file_content) {
if (line.length() < MAX_LINE_LENGTH) {
std::string line_content = line;
std::smatch tag_match;
while(std::regex_search(line_content, tag_match, tag_regex)) {
tags.push_back(tag_match.str().substr(1));
line_content = tag_match.suffix();
}
}
else {
BOOST_LOG_TRIVIAL(error) << "Skipping line because too long: " << line;
}
}
}
void FileContext::parse_tasks() {
std::regex task_regex(TASK_REGEX);
std::string file_content = file_entry->get_content();
std::smatch task_match;
while(std::regex_search(file_content, task_match, task_regex)) {
const std::regex task_regex(TASK_REGEX, std::regex::optimize);
const auto file_content = file_entry->get_content();
tasks.emplace_back(task_match[2], task_match[1], task_match[3]);
file_content = task_match.suffix();
for (const auto& line : file_content) {
if (line.length() < MAX_LINE_LENGTH) {
std::string line_content = line;
std::smatch task_match;
while(std::regex_search(line_content, task_match, task_regex)) {
tasks.emplace_back(task_match[2], task_match[1], task_match[3]);
line_content = task_match.suffix();
}
}
else {
BOOST_LOG_TRIVIAL(error) << "Skipping line because too long: " << line;
}
}
}
@ -105,4 +145,4 @@ std::filesystem::path FileContext::abs_path(const kc::Link &link) const {
return file_entry->file_entry.path().parent_path() / fs::path(link.link);
}
}
}

@ -40,7 +40,7 @@ class FileContext {
void parse();
void parse(ParseOperations operations);
std::filesystem::path abs_path(const kc::Link &link) const;
[[nodiscard]] std::filesystem::path abs_path(const kc::Link &link) const;
private:

@ -1,7 +1,10 @@
#include "FileContextCache.hpp"
#include <algorithm>
#if __cpp_lib_execution //checking to see if the <execution> header is there
#include <execution>
#endif
#include "../fs/fs.hpp"
#include "../logging.hpp"
@ -36,12 +39,12 @@ void FileContextCache::parse_all()
void FileContextCache::parse_all(ParseOperations operations) {
tag_map.clear();
#if __APPLE__
std::for_each(file_contexts.begin(), file_contexts.end(), [this, &operations](std::shared_ptr<kc::FileContext> &context)
#ifdef __cpp_lib_execution
std::mutex m;
std::for_each(std::execution::par, file_contexts.begin(), file_contexts.end(), [this, &operations, &m](std::shared_ptr<kc::FileContext> &context)
#else
std::for_each(std::execution::par_unseq, file_contexts.begin(), file_contexts.end(), [this, &operations](std::shared_ptr<kc::FileContext> &context)
std::ranges::for_each(file_contexts, [this, &operations](const std::shared_ptr<kc::FileContext> &context)
#endif
{
if (context->file_entry->relative_path.extension() == ".md")
{
@ -49,6 +52,9 @@ void FileContextCache::parse_all(ParseOperations operations) {
if (!context->tags.empty())
{
#ifdef __cpp_lib_execution
std::lock_guard<std::mutex> lock{m};
#endif
for (const auto& tag : context->tags)
{
tag_map[tag].push_back(context->file_entry);

@ -12,7 +12,7 @@ namespace kc {
void print_file(const std::vector<std::shared_ptr<kc::FileContext>> &contexts)
{
auto date = day_clock::local_day();
const auto date = day_clock::local_day();
for (const auto &entry : contexts) {

@ -19,7 +19,7 @@ std::string get_notification_content(const std::vector<Task>& tasks) {
int current_tasks(const kc::AppContext &app_context)
{
auto date = day_clock::local_day();
const auto date = day_clock::local_day();
std::vector<Task> tasks;
for(const auto& file_cache : app_context.file_caches) {
@ -33,7 +33,7 @@ int current_tasks(const kc::AppContext &app_context)
}
}
std::ranges::sort(tasks, [](Task a, Task b)
std::ranges::sort(tasks, [](const Task &a, const Task &b)
{
return a.get_due_date() < b.get_due_date();
});
@ -42,7 +42,9 @@ int current_tasks(const kc::AppContext &app_context)
std::cout << task.get_content() << " (" << task.get_due_date() << ")" << std::endl;
}
if (app_context.config->contains(CONFIG_NOTIFY)) {
if (!tasks.empty() && app_context.config->contains(CONFIG_NOTIFY)) {
print_and_log(std::format("Sending notification for {} tasks", tasks.size()));
if (!app_context.config->contains(CONFIG_HOST)) {
print_and_log_error("No NTFY host provided");
return 1;
@ -52,14 +54,27 @@ int current_tasks(const kc::AppContext &app_context)
return 1;
}
auto host_name = (*app_context.config)[CONFIG_HOST].as<std::string>();
auto topic_name = (*app_context.config)[CONFIG_TOPIC].as<std::string>();
const auto host_name = (*app_context.config)[CONFIG_HOST].as<std::string>();
const auto topic_name = (*app_context.config)[CONFIG_TOPIC].as<std::string>();
auto payload = get_notification_content(tasks);
const auto payload = get_notification_content(tasks);
auto notif = kc::Notification(topic_name, payload);
kc::notify(host_name, notif);
if (app_context.config->contains(CONFIG_TAGS)) {
for (auto const& tag : (*app_context.config)[CONFIG_TAGS].as<std::vector<std::string>>()) {
BOOST_LOG_TRIVIAL(info) << "Tagging notification with " << tag;
notif.add_tag(tag);
}
}
try{
// kc::notify(host_name, notif);
print_and_log("Notification sent");
}
catch (const std::exception &e) {
print_and_log_error(std::format("Exception occurred while sending notification - {}", e.what()));
}
}
return 0;

@ -2,7 +2,7 @@
namespace kc {
constexpr TaskState get_task_state(char c){
constexpr TaskState get_task_state(const char c){
switch(c){
case ' ':
return TaskState::NOT_STARTED;
@ -17,7 +17,7 @@ constexpr TaskState get_task_state(char c){
return TaskState::UNKNOWN;
}
constexpr char get_task_state(TaskState c){
constexpr char get_task_state(const TaskState c){
switch(c){
case TaskState::NOT_STARTED:
return ' ';
@ -32,29 +32,29 @@ constexpr char get_task_state(TaskState c){
return '?';
}
bool is_current(Task task) {
bool is_current(const Task &task) {
return is_current(task, day_clock::local_day());
}
bool is_current(Task task, date current_date) {
bool is_current(const Task &task, const date current_date) {
return task.get_due_date() <= current_date
&& (task.get_state() == TaskState::NOT_STARTED || task.get_state() == TaskState::IN_PROGRESS);
}
Task::Task(const std::string &task_content, TaskState state, const std::string &due_date_str)
Task::Task(const std::string &task_content, const TaskState state, const std::string &due_date_str)
: task_content(task_content), state(state), due_date(from_simple_string(due_date_str)) {
}
Task::Task(const std::string &task_content, std::string state, const std::string &due_date_str)
Task::Task(const std::string &task_content, const std::string &state, const std::string &due_date_str)
: task_content(task_content), state(get_task_state(state[0])), due_date(from_simple_string(due_date_str)) {
}
Task::Task(const std::string &task_content, TaskState state, const date &due_date_str)
Task::Task(const std::string &task_content, const TaskState state, const date &due_date_str)
: task_content(task_content), state(state), due_date(due_date_str) {
}
Task::Task(const std::string &task_content, TaskState state)
Task::Task(const std::string &task_content, const TaskState state)
: task_content(task_content), state(state) {
}

@ -17,7 +17,7 @@ class Task {
public:
explicit Task(const std::string &task_content, TaskState state, const std::string &due_date_str);
explicit Task(const std::string &task_content, std::string state, const std::string &due_date_str);
explicit Task(const std::string &task_content, const std::string &state, const std::string &due_date_str);
explicit Task(const std::string &task_content, TaskState state, const date &due_date_str);
explicit Task(const std::string &task_content, TaskState state);
explicit Task(const std::string &task_content);
@ -33,7 +33,7 @@ class Task {
TaskState state;
};
bool is_current(Task task);
bool is_current(Task task, date current_date);
bool is_current(const Task &task);
bool is_current(const Task &task, date current_date);
}