mirror of
https://codeberg.org/vyn/mirai.git
synced 2025-07-01 17:03:19 +00:00
135 lines
3.9 KiB
C++
135 lines
3.9 KiB
C++
/*
|
|
* 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
|
|
*/
|
|
|
|
#ifndef MIRAI_TODOMD_H
|
|
#define MIRAI_TODOMD_H
|
|
|
|
#include "TaskItem.h"
|
|
#include "cpp-utils/debug.h"
|
|
#include "cpp-utils/string.h"
|
|
#include "mirai-core/DateTime.h"
|
|
#include "mirai-core/Day.h"
|
|
#include "mirai-core/Event.h"
|
|
#include <format>
|
|
#include <optional>
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace mirai
|
|
{
|
|
|
|
struct MiraiMarkdownFormatParseResult {
|
|
std::string name;
|
|
std::vector<DayData> days;
|
|
};
|
|
|
|
class TodoMdFormat
|
|
{
|
|
public:
|
|
static std::string
|
|
stringify(const std::string &name, const std::vector<std::unique_ptr<Day>> &days)
|
|
{
|
|
std::string result = "# " + name + "\n\n";
|
|
std::string currentDate = "";
|
|
|
|
for (const auto &day : days) {
|
|
auto &date = day->getDate();
|
|
result += "## " + std::format("{:02d}-{:02d}-{:02d}", date.year, date.month, date.day) +
|
|
"\n\n";
|
|
for (const auto &event : *(day->events())) {
|
|
auto &start = event->getStartTime();
|
|
auto &end = event->getEndTime();
|
|
result += "> " +
|
|
std::format(
|
|
"{:02d}h{:02d}-{:02d}h{:02d} {}", start.hour, start.minute, end.hour,
|
|
end.minute, event->getText()
|
|
) +
|
|
"\n";
|
|
for (const auto &task : *(event->tasks())) {
|
|
result += taskToString(*task) + '\n';
|
|
}
|
|
result += '\n';
|
|
}
|
|
for (const auto &task : *(day->tasks())) {
|
|
result += taskToString(*task) + '\n';
|
|
}
|
|
result += '\n';
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
static MiraiMarkdownFormatParseResult parse(const std::string &content)
|
|
{
|
|
cpputils::debug::Timer readMdFormatDuration;
|
|
std::vector<TaskItem> taskItems;
|
|
std::string line;
|
|
|
|
std::stringstream contentStream(content);
|
|
|
|
if (!std::getline(contentStream, line) || line.substr(0, 2) != "# ") {
|
|
std::cerr << "Couldn't find the task list name" << std::endl;
|
|
}
|
|
|
|
std::string name = line.substr(2);
|
|
std::string currentDateString = "";
|
|
|
|
std::vector<mirai::DayData> daysData;
|
|
mirai::DayData *currentDay = nullptr;
|
|
mirai::EventData *currentEvent = nullptr;
|
|
|
|
cpputils::debug::Timer stringToTaskDuration;
|
|
stringToTaskDuration.reset();
|
|
cpputils::debug::Timer gelinesDuration;
|
|
while (std::getline(contentStream, line)) {
|
|
if (std::string_view{line.data(), 3} == "## ") {
|
|
currentDateString = line.substr(3);
|
|
auto dateOpt = mirai::stringToDate(currentDateString);
|
|
if (!dateOpt.has_value()) {
|
|
throw std::runtime_error("Malformated date");
|
|
}
|
|
daysData.push_back({.date = dateOpt.value()});
|
|
currentDay = &daysData.back();
|
|
} else if (line.starts_with("> ")) {
|
|
auto event = stringToEvent(line, currentDateString);
|
|
if (currentDay) {
|
|
currentDay->events.push_back(event);
|
|
currentEvent = ¤tDay->events.back();
|
|
}
|
|
} else if (line.starts_with("- [ ]") || line.starts_with("- [X]")) {
|
|
stringToTaskDuration.start();
|
|
TaskItemData taskItemData = stringToTask(line, currentDateString);
|
|
stringToTaskDuration.stop();
|
|
if (currentEvent) {
|
|
currentEvent->tasks.push_back(taskItemData);
|
|
} else if (currentDay) {
|
|
currentDay->tasks.push_back(taskItemData);
|
|
}
|
|
} else if (cpputils::string::trim(line) == "") {
|
|
currentEvent = nullptr;
|
|
}
|
|
}
|
|
|
|
gelinesDuration.printTimeElapsed("getlinesDuration");
|
|
stringToTaskDuration.printTimeElapsed("stringToTaskDuration");
|
|
readMdFormatDuration.printTimeElapsed("Reading MD File duration");
|
|
return {.name = name, .days = daysData};
|
|
}
|
|
|
|
static std::string taskToString(const TaskItem &task);
|
|
static TaskItemData stringToTask(const std::string &str, const std::string &date);
|
|
static EventData stringToEvent(const std::string &str, const std::string &date);
|
|
|
|
private:
|
|
static std::string fieldWithSpace(const std::string &field);
|
|
static TaskItem parseLine(const std::string &line);
|
|
static Tags extractTagsFromMetadata(std::string metadata);
|
|
};
|
|
} // namespace mirai
|
|
|
|
#endif
|