diff --git a/libs/cpp-utils/debug.h b/libs/cpp-utils/debug.h index 238262a..2a21dfd 100644 --- a/libs/cpp-utils/debug.h +++ b/libs/cpp-utils/debug.h @@ -26,18 +26,40 @@ class Timer void start() { startTime = std::chrono::high_resolution_clock::now(); + isRunning = true; + } + + void stop() + { + const auto now = std::chrono::high_resolution_clock::now(); + duration += std::chrono::duration_cast(now - startTime).count(); + isRunning = false; + } + + void reset() + { + duration = 0; + isRunning = false; } void printTimeElapsed(const std::string &message) const { - const auto now = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration_cast(now - startTime); - std::cout << "[Debug - Timer] " << message << ": " << ((double)duration.count() / 1000000) + long durationToShow = duration; + if (isRunning) { + const auto now = std::chrono::high_resolution_clock::now(); + durationToShow += + std::chrono::duration_cast(now - startTime).count(); + } + std::cout << "[Debug - Timer] " << message << ": " << ((double)durationToShow / 1000000) << " seconds" << std::endl; } private: std::chrono::time_point startTime; + + // Timer are always running when created. You can use .reset() after creation. + bool isRunning = true; + long duration; }; } // namespace cpputils::debug diff --git a/src/Backend.cpp b/src/Backend.cpp index a0301b3..577dbea 100644 --- a/src/Backend.cpp +++ b/src/Backend.cpp @@ -89,7 +89,7 @@ void Backend::addTodoFromRawFormat(QString filePath, QString text, QString date) return; } file.value().get().addTask( - mirai::TodoMdFormat::StringToTask(text.toStdString(), date.toStdString()) + mirai::TodoMdFormat::stringToTask(text.toStdString(), date.toStdString()) ); mirai.save(); view.update(); @@ -137,7 +137,7 @@ void Backend::updateTodoFromRawFormat(int todoIndex, QString text, QString date) QMLTaskItem &taskItem = QMLTasks[todoIndex]; taskItem.taskItem->setText(taskItem.taskItem->getText()); *(taskItem.taskItem) = - mirai::TodoMdFormat::StringToTask(text.toStdString(), date.toStdString()); + mirai::TodoMdFormat::stringToTask(text.toStdString(), date.toStdString()); mirai.save(); view.update(); rebuildQMLTasksList(); diff --git a/src/TaskItem.cpp b/src/TaskItem.cpp index 0505d1a..5778545 100644 --- a/src/TaskItem.cpp +++ b/src/TaskItem.cpp @@ -9,7 +9,7 @@ QString QMLTaskItem::getRawFormat() { - return QString::fromStdString(mirai::TodoMdFormat::TaskToString(*taskItem)); + return QString::fromStdString(mirai::TodoMdFormat::taskToString(*taskItem)); } QString QMLTaskItem::getText() diff --git a/src/core/Mirai.cpp b/src/core/Mirai.cpp index 440542d..6f38599 100644 --- a/src/core/Mirai.cpp +++ b/src/core/Mirai.cpp @@ -7,6 +7,7 @@ #include "Mirai.h" #include "TaskItem.h" #include "core/TasksFile.h" +#include "cpp-utils/debug.h" #include "utils.h" #include #include @@ -38,6 +39,7 @@ void Mirai::save() { for (auto &file : files) { if (file->isDirty()) { + file->sortByDate(); TodoMdFormat::writeFile(*file); file->setDirty(false); } @@ -90,6 +92,7 @@ const std::vector &Mirai::getTags() void Mirai::reloadTags() { + cpputils::debug::Timer reloadingTagsDuration; tags.clear(); for (auto &file : files) { for (auto &task : file->getTasks()) { @@ -100,6 +103,7 @@ void Mirai::reloadTags() } } } + reloadingTagsDuration.printTimeElapsed("ReloadingTags"); } } // namespace mirai diff --git a/src/core/TasksFile.cpp b/src/core/TasksFile.cpp index 27737cb..3598182 100644 --- a/src/core/TasksFile.cpp +++ b/src/core/TasksFile.cpp @@ -59,7 +59,6 @@ void TasksFile::addTask(TaskItemData taskItem) { tasks.push_back(std::make_unique(this, taskItem)); setDirty(true); - sortByDate(); } void TasksFile::addTask(std::string text, std::string date) @@ -68,7 +67,6 @@ void TasksFile::addTask(std::string text, std::string date) TaskItem{this, {.text = text, .state = TODO, .date = date == "" ? "No date" : date}} ); tasks.push_back(std::move(newTask)); - sortByDate(); } void TasksFile::removeTask(const TaskItem *taskToRemove) diff --git a/src/core/TasksView.cpp b/src/core/TasksView.cpp index f85f6be..25bf9c4 100644 --- a/src/core/TasksView.cpp +++ b/src/core/TasksView.cpp @@ -57,6 +57,7 @@ void TasksView::update() } else if (!t1->hasDate() && t2->hasDate()) { return false; } + if (t1->getDate() < t2->getDate()) { return true; } else if (t1->getDate() > t2->getDate()) { diff --git a/src/core/TodoMd.cpp b/src/core/TodoMd.cpp index 85de3f6..0e3e614 100644 --- a/src/core/TodoMd.cpp +++ b/src/core/TodoMd.cpp @@ -7,16 +7,19 @@ #include "TodoMd.h" #include "TaskItem.h" #include "core/TasksFile.h" +#include "cpp-utils/debug.h" #include "utils.h" #include #include #include +#include namespace mirai { std::unique_ptr TodoMdFormat::readFile(const std::string &path) { + cpputils::debug::Timer readMdFormatDuration; std::ifstream file(path); if (!file.is_open()) { throw std::runtime_error("todo.txt file not found"); @@ -35,17 +38,26 @@ std::unique_ptr TodoMdFormat::readFile(const std::string &path) TasksFileConstructor{.name = name, .path = path, .tasks = taskItems} ); + cpputils::debug::Timer stringToTaskDuration; + stringToTaskDuration.reset(); + cpputils::debug::Timer gelinesDuration; while (std::getline(file, line)) { - if (line.substr(0, 3) == "## ") { + if (std::string_view{line.data(), 3} == "## ") { currentDate = line.substr(3); - } else if (line.substr(0, 5) == "- [ ]" || line.substr(0, 5) == "- [X]") { - TaskItemData taskItemData = StringToTask(line, currentDate); + } else if (std::string_view{line.data(), 5} == "- [ ]" || std::string_view{line.data(), 5} == "- [X]") { + stringToTaskDuration.start(); + TaskItemData taskItemData = stringToTask(line, currentDate); + stringToTaskDuration.stop(); taskItemData.date = currentDate; tasksFile->addTask(taskItemData); } } + + gelinesDuration.printTimeElapsed("getlinesDuration"); + stringToTaskDuration.printTimeElapsed("stringToTaskDuration"); file.close(); tasksFile->setDirty(false); + readMdFormatDuration.printTimeElapsed("Reading MD File duration of " + path); return tasksFile; } @@ -79,7 +91,7 @@ void TodoMdFormat::writeFile(TasksFile &tasks) currentDate = task->getDate(); file << "\n## " << (task->getDate() != "" ? task->getDate() : "No date") << "\n\n"; } - file << TaskToString(*task) << '\n'; + file << taskToString(*task) << '\n'; } file.close(); } @@ -92,7 +104,7 @@ std::string TodoMdFormat::fieldWithSpace(const std::string &field) return (field + " "); } -TaskItemData TodoMdFormat::StringToTask(const std::string &str, const std::string &date) +TaskItemData TodoMdFormat::stringToTask(const std::string &str, const std::string &date) { std::smatch matches; std::regex regex("- \\[(\\s|X)\\] (([0-9]{2}:[0-9]{2})-([0-9]{2}:[0-9]{2}) > )?(.*?)( -- (.*))?" @@ -122,7 +134,7 @@ TaskItemData TodoMdFormat::StringToTask(const std::string &str, const std::strin return taskItem; } -std::string TodoMdFormat::TaskToString(const TaskItem &task) +std::string TodoMdFormat::taskToString(const TaskItem &task) { std::string str = task.getText(); if (task.getTags().size() > 0) { diff --git a/src/core/TodoMd.h b/src/core/TodoMd.h index 89c76bd..2b7e0e7 100644 --- a/src/core/TodoMd.h +++ b/src/core/TodoMd.h @@ -20,8 +20,8 @@ class TodoMdFormat static std::unique_ptr readFile(const std::string &path); static void writeFile(TasksFile &tasks); - static std::string TaskToString(const TaskItem &task); - static TaskItemData StringToTask(const std::string &str, const std::string &date); + static std::string taskToString(const TaskItem &task); + static TaskItemData stringToTask(const std::string &str, const std::string &date); private: static std::string fieldWithSpace(const std::string &field); diff --git a/src/core/utils.cpp b/src/core/utils.cpp index e4faa71..cc6d595 100644 --- a/src/core/utils.cpp +++ b/src/core/utils.cpp @@ -5,12 +5,34 @@ */ #include "utils.h" +#include namespace mirai { bool isDate(const std::string &dateStr) { - std::regex regex("[0-9]{4}-[0-9]{2}-[0-9]{2}"); - return std::regex_match(dateStr, regex); + // std regex are really slow + /*std::regex regex("[0-9]{4}-[0-9]{2}-[0-9]{2}");*/ + /*return std::regex_match(dateStr, regex);*/ + + // Quick hand made check instead of regex until I rework date to use timestamp or std::chrono + if (dateStr.length() != 10) { + return false; + } + + if (dateStr[4] != '-' || dateStr[7] != '-') { + return false; + } + + for (int i = 0; i < dateStr.length(); ++i) { + if (i == 4 || i == 7) { + // These are the '-' characters + continue; + } + if (!isdigit(dateStr[i])) { + return false; + } + } + return true; } } // namespace mirai diff --git a/tests/test.cpp b/tests/test.cpp index a909ca6..54569be 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -15,7 +15,7 @@ TEST_CASE("Creating task from string") { SECTION("All properties") { - auto task = mirai::TodoMdFormat::StringToTask( + auto task = mirai::TodoMdFormat::stringToTask( "- [X] 08:00-10:00 > This is a test -- #mirai", "2024-04-19" ); REQUIRE(task.date == "2024-04-19"); @@ -29,7 +29,7 @@ TEST_CASE("Creating task from string") SECTION("All properties 2") { - auto task = mirai::TodoMdFormat::StringToTask( + auto task = mirai::TodoMdFormat::stringToTask( "- [ ] 09:00-17:00 > This is another test -- #mirai #feature", "2024-04-20" ); REQUIRE(task.date == "2024-04-20"); @@ -44,7 +44,7 @@ TEST_CASE("Creating task from string") SECTION("Only text") { - auto task = mirai::TodoMdFormat::StringToTask("- [ ] This is another test", ""); + auto task = mirai::TodoMdFormat::stringToTask("- [ ] This is another test", ""); REQUIRE(task.date == ""); REQUIRE(task.tags.size() == 0); REQUIRE(task.text == "This is another test"); @@ -53,7 +53,7 @@ TEST_CASE("Creating task from string") SECTION("Only text with a date") { - auto task = mirai::TodoMdFormat::StringToTask("- [X] This is another test", "2025-02-03"); + auto task = mirai::TodoMdFormat::stringToTask("- [X] This is another test", "2025-02-03"); REQUIRE(task.date == "2025-02-03"); REQUIRE(task.tags.size() == 0); REQUIRE(task.text == "This is another test"); @@ -62,7 +62,7 @@ TEST_CASE("Creating task from string") SECTION("Tags before -- are not tags") { - auto task = mirai::TodoMdFormat::StringToTask( + auto task = mirai::TodoMdFormat::stringToTask( "- [ ] This is another test #ImNotATag -- #ImATag", "" ); REQUIRE(task.date == "");