2024-04-13 11:52:42 +02:00
|
|
|
/*
|
2024-04-10 16:53:18 +02:00
|
|
|
* Mirai. Copyright (C) 2024 Vyn
|
|
|
|
* This file is licensed under version 3 of the GNU General Public License (GPL-3.0-only)
|
|
|
|
* The license can be found in the LICENSE file or at https://www.gnu.org/licenses/gpl-3.0.txt
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "TodoMd.h"
|
2024-04-11 11:42:13 +02:00
|
|
|
#include "TaskItem.h"
|
2024-04-30 18:18:54 +02:00
|
|
|
#include "cpp-utils/debug.h"
|
2024-04-14 14:11:41 +02:00
|
|
|
#include "utils.h"
|
2024-08-16 21:35:12 +02:00
|
|
|
#include <charconv>
|
2024-04-14 14:11:41 +02:00
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
|
|
|
#include <memory>
|
2024-08-16 21:35:12 +02:00
|
|
|
#include <ranges>
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <string>
|
2024-04-30 18:18:54 +02:00
|
|
|
#include <string_view>
|
2024-04-10 16:53:18 +02:00
|
|
|
|
2024-04-13 11:52:42 +02:00
|
|
|
namespace mirai
|
|
|
|
{
|
2024-04-10 16:53:18 +02:00
|
|
|
|
2024-04-13 11:52:42 +02:00
|
|
|
Tags TodoMdFormat::extractTagsFromMetadata(std::string metadata)
|
|
|
|
{
|
|
|
|
Tags tags;
|
2024-04-11 11:42:13 +02:00
|
|
|
|
2024-04-21 09:43:56 +02:00
|
|
|
std::regex regex("(#([a-zA-Z0-1]+))");
|
2024-04-13 11:52:42 +02:00
|
|
|
std::smatch matches;
|
2024-04-11 11:42:13 +02:00
|
|
|
|
2024-04-13 11:52:42 +02:00
|
|
|
while (std::regex_search(metadata, matches, regex)) {
|
2024-04-21 09:43:56 +02:00
|
|
|
if (!vectorUtils::contains(tags, matches[2].str())) {
|
|
|
|
tags.push_back(matches[2]);
|
2024-04-11 11:42:13 +02:00
|
|
|
}
|
2024-04-13 11:52:42 +02:00
|
|
|
metadata = matches.suffix();
|
2024-04-11 11:42:13 +02:00
|
|
|
}
|
2024-04-13 11:52:42 +02:00
|
|
|
return tags;
|
|
|
|
}
|
2024-04-11 11:42:13 +02:00
|
|
|
|
2024-04-13 11:52:42 +02:00
|
|
|
std::string TodoMdFormat::fieldWithSpace(const std::string &field)
|
|
|
|
{
|
2024-04-14 14:11:41 +02:00
|
|
|
if (field.length() == 0) {
|
2024-04-13 11:52:42 +02:00
|
|
|
return "";
|
2024-04-14 14:11:41 +02:00
|
|
|
}
|
2024-04-13 11:52:42 +02:00
|
|
|
return (field + " ");
|
|
|
|
}
|
2024-04-11 11:42:13 +02:00
|
|
|
|
2024-04-30 18:18:54 +02:00
|
|
|
TaskItemData TodoMdFormat::stringToTask(const std::string &str, const std::string &date)
|
2024-04-13 11:52:42 +02:00
|
|
|
{
|
|
|
|
std::smatch matches;
|
2024-04-14 14:11:41 +02:00
|
|
|
std::regex regex("- \\[(\\s|X)\\] (([0-9]{2}:[0-9]{2})-([0-9]{2}:[0-9]{2}) > )?(.*?)( -- (.*))?"
|
|
|
|
);
|
2024-04-13 11:52:42 +02:00
|
|
|
std::regex_match(str, matches, regex);
|
|
|
|
|
|
|
|
/*std::cout << "line " << str << std::endl;*/
|
|
|
|
/*std::cout << "M 0 " << matches[0] << std::endl;*/
|
|
|
|
/*std::cout << "M 1 " << matches[1] << std::endl;*/
|
|
|
|
/*std::cout << "M 2 " << matches[2] << std::endl;*/
|
|
|
|
/*std::cout << "M 3 " << matches[3] << std::endl;*/
|
|
|
|
/*std::cout << "M 4 " << matches[4] << std::endl;*/
|
|
|
|
/*std::cout << "M 5 " << matches[5] << std::endl;*/
|
|
|
|
/*std::cout << "M 6 " << matches[6] << std::endl;*/
|
|
|
|
/*std::cout << "M 7 " << matches[7] << std::endl;*/
|
|
|
|
|
|
|
|
std::string text = stringUtils::trim(matches[5]);
|
|
|
|
|
2024-04-14 14:11:41 +02:00
|
|
|
TaskItemData taskItem{
|
|
|
|
.text = text,
|
|
|
|
.state = str.substr(0, 5) == "- [X]" ? DONE : TODO,
|
|
|
|
.tags = extractTagsFromMetadata(matches[7])
|
|
|
|
};
|
2024-04-13 11:52:42 +02:00
|
|
|
return taskItem;
|
|
|
|
}
|
|
|
|
|
2024-08-16 21:35:12 +02:00
|
|
|
Time stringToTime(const std::string &str)
|
|
|
|
{
|
|
|
|
if (str.length() != 5) {
|
|
|
|
throw std::runtime_error("Str time length must be 5 (got '" + str + "')");
|
|
|
|
}
|
|
|
|
if (str[2] != 'h') {
|
|
|
|
throw std::runtime_error("Malformated time range");
|
|
|
|
}
|
|
|
|
Time time{};
|
|
|
|
std::from_chars(str.data(), str.data() + 2, time.hour);
|
|
|
|
std::from_chars(str.data() + 3, str.data() + 5, time.minute);
|
|
|
|
|
|
|
|
return time;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventData TodoMdFormat::stringToEvent(const std::string &str, const std::string &dateString)
|
|
|
|
{
|
|
|
|
std::smatch matches;
|
|
|
|
std::regex regex("> (([0-9]{2}h[0-9]{2})-([0-9]{2}h[0-9]{2}) )(.*?)( -- (.*))?");
|
|
|
|
std::regex_match(str, matches, regex);
|
|
|
|
|
|
|
|
/*std::cout << "line " << str << std::endl;*/
|
|
|
|
/*std::cout << "M 0 " << matches[0] << std::endl;*/
|
|
|
|
/*std::cout << "M 1 " << matches[1] << std::endl;*/
|
|
|
|
/*std::cout << "M 2 " << matches[2] << std::endl;*/
|
|
|
|
/*std::cout << "M 3 " << matches[3] << std::endl;*/
|
|
|
|
/*std::cout << "M 4 " << matches[4] << std::endl;*/
|
|
|
|
/*std::cout << "M 5 " << matches[5] << std::endl;*/
|
|
|
|
/*std::cout << "M 6 " << matches[6] << std::endl;*/
|
|
|
|
|
|
|
|
std::string text = stringUtils::trim(matches[4]);
|
|
|
|
|
|
|
|
auto date = stringToDate(dateString);
|
|
|
|
|
|
|
|
if (!date.has_value()) {
|
|
|
|
throw std::runtime_error("Malformated date");
|
|
|
|
}
|
|
|
|
|
|
|
|
EventData eventData{
|
|
|
|
.description = text,
|
|
|
|
.date = date.value(),
|
|
|
|
.startTime = stringToTime(matches[2]),
|
|
|
|
.endTime = stringToTime(matches[3]),
|
|
|
|
.tags = extractTagsFromMetadata(matches[6])
|
|
|
|
};
|
|
|
|
return eventData;
|
|
|
|
}
|
|
|
|
|
2024-04-30 18:18:54 +02:00
|
|
|
std::string TodoMdFormat::taskToString(const TaskItem &task)
|
2024-04-13 11:52:42 +02:00
|
|
|
{
|
|
|
|
std::string str = task.getText();
|
|
|
|
if (task.getTags().size() > 0) {
|
|
|
|
str += " --";
|
|
|
|
for (const std::string &tag : task.getTags()) {
|
2024-04-21 09:43:56 +02:00
|
|
|
str += " #" + tag;
|
2024-04-11 11:42:13 +02:00
|
|
|
}
|
|
|
|
}
|
2024-04-13 11:52:42 +02:00
|
|
|
str = (task.getState() == DONE ? "- [X] " : "- [ ] ") + str;
|
|
|
|
return str;
|
2024-04-10 16:53:18 +02:00
|
|
|
}
|
2024-04-13 11:52:42 +02:00
|
|
|
} // namespace mirai
|