Add helper lib for strings and vectors

This commit is contained in:
Vyn 2024-04-12 20:58:13 +02:00
parent 6ef9740db9
commit 2bb7fcfcc6
10 changed files with 168 additions and 123 deletions

View file

@ -7,6 +7,7 @@ set(CMAKE_CXX_STANDARD 20)
find_package(Qt6 6.6 REQUIRED COMPONENTS Quick) find_package(Qt6 6.6 REQUIRED COMPONENTS Quick)
include_directories(src) include_directories(src)
include_directories(libs)
qt_standard_project_setup(REQUIRES 6.6) qt_standard_project_setup(REQUIRES 6.6)

27
libs/cpp-utils/string.h Normal file
View file

@ -0,0 +1,27 @@
/*
* 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 CPP_UTILS_STRING_H
#define CPP_UTILS_STRING_H
#include <algorithm>
#include <string>
namespace cpputils::string {
inline std::string trim(std::string str) {
str.erase(str.begin(), std::ranges::find_if(str, [](unsigned char ch) {
return !std::isspace(ch);
}));
str.erase(std::ranges::find_if(str.rbegin(), str.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), str.end());
return str;
}
}
#endif

44
libs/cpp-utils/vector.h Normal file
View file

@ -0,0 +1,44 @@
/*
* 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 CPP_UTILS_VECTOR_H
#define CPP_UTILS_VECTOR_H
#include <algorithm>
#include <functional>
#include <optional>
#include <vector>
#include <concepts>
namespace cpputils::vector {
template <typename C, typename T>
concept AnyIterable =
std::same_as<typename C::value_type, T> &&
requires (C c) {
{ c.begin() } -> std::forward_iterator;
{ c.end() } -> std::forward_iterator;
{ const_cast<const C&>(c).begin() } -> std::forward_iterator;
{ const_cast<const C&>(c).end() } -> std::forward_iterator;
};
template<typename T>
bool contains(const std::vector<T>& vec, const T& value) {
return std::ranges::find(vec, value) != vec.end();
}
template<typename T>
bool containsAll(const std::vector<T>& vec, const AnyIterable<T> auto vec2) {
for (auto& elem : vec) {
if (!contains(vec2, elem)) {
return false;
}
}
return true;
}
}
#endif

View file

@ -6,7 +6,7 @@
#include "Mirai.h" #include "Mirai.h"
#include "TaskItem.h" #include "TaskItem.h"
#include <algorithm> #include "cpp-utils/vector.h"
namespace mirai { namespace mirai {
@ -16,7 +16,7 @@ namespace mirai {
tags.clear(); tags.clear();
for (auto& task : (*files)[0].getTasks()) { for (auto& task : (*files)[0].getTasks()) {
for (auto& tag : task->getTags()) { for (auto& tag : task->getTags()) {
if (std::find(tags.begin(), tags.end(), tag) == tags.end()) { if (vectorUtils::contains(tags, tag)) {
tags.push_back(tag); tags.push_back(tag);
} }
} }

View file

@ -6,7 +6,7 @@
#include "TaskItem.h" #include "TaskItem.h"
#include <algorithm> #include "cpp-utils/vector.h"
namespace mirai { namespace mirai {
@ -36,6 +36,6 @@ namespace mirai {
bool TaskItem::hasTag(const std::string& tag) const { bool TaskItem::hasTag(const std::string& tag) const {
return std::find(tags.begin(), tags.end(), tag) != tags.end(); return vectorUtils::contains(tags, tag);
} }
} }

View file

@ -5,6 +5,9 @@
*/ */
#include "TasksView.h" #include "TasksView.h"
#include "cpp-utils/vector.h"
#include <algorithm>
#include <string>
namespace mirai { namespace mirai {
@ -23,10 +26,10 @@ namespace mirai {
tasksToShow.clear(); tasksToShow.clear();
for (auto& file : *files) { for (auto& file : *files) {
for (auto& task : file.getTasks()) { for (auto& task : file.getTasks()) {
if (tagsFilter.size() != 0 std::function<bool(const std::string&)> f = [&](const std::string& tag) {
&& std::find_if(tagsFilter.begin(), tagsFilter.end(), [&](const std::string& tag) {
return task->hasTag(tag); return task->hasTag(tag);
}) == tagsFilter.end()) };
if (tagsFilter.size() > 0 && !vectorUtils::containsAll(tagsFilter, task->getTags()))
continue; continue;
tasksToShow.push_back(task.get()); tasksToShow.push_back(task.get());
} }

View file

@ -6,6 +6,7 @@
#include "TodoMd.h" #include "TodoMd.h"
#include "TaskItem.h" #include "TaskItem.h"
#include "cpp-utils/vector.h"
namespace mirai { namespace mirai {
@ -50,7 +51,7 @@ namespace mirai {
while (std::regex_search(metadata, matches, regex)) while (std::regex_search(metadata, matches, regex))
{ {
if (std::find(tags.begin(), tags.end(), matches[0]) == tags.end()) { if (!vectorUtils::contains(tags, matches[0].str())) {
tags.push_back(matches[0]); tags.push_back(matches[0]);
} }
metadata = matches.suffix(); metadata = matches.suffix();
@ -97,8 +98,7 @@ namespace mirai {
/*std::cout << "M 6 " << matches[6] << std::endl;*/ /*std::cout << "M 6 " << matches[6] << std::endl;*/
/*std::cout << "M 7 " << matches[7] << std::endl;*/ /*std::cout << "M 7 " << matches[7] << std::endl;*/
std::string text = matches[5]; std::string text = stringUtils::trim(matches[5]);
trim(text);
TaskItem taskItem = { TaskItem taskItem = {
.text = text, .text = text,

View file

@ -7,89 +7,89 @@
#ifndef MIRAI_TODOTXT_H #ifndef MIRAI_TODOTXT_H
#define MIRAI_TODOTXT_H #define MIRAI_TODOTXT_H
#include "TaskItem.h" /*#include "TaskItem.h"*/
#include "utils.h" /*#include "utils.h"*/
#include <fstream> /*#include <fstream>*/
#include <iostream> /*#include <iostream>*/
#include <iterator> /*#include <iterator>*/
#include <memory> /*#include <memory>*/
#include <regex> /*#include <regex>*/
#include <stdexcept> /*#include <stdexcept>*/
#include <string> /*#include <string>*/
#include <vector> /*#include <vector>*/
namespace mirai { /*namespace mirai {*/
class TodoTxtFormat { /*class TodoTxtFormat {*/
public: /*public:*/
static TaskList readFile() { /*static TaskList readFile() {*/
std::ifstream file("../newqml/todo.txt"); /*std::ifstream file("../newqml/todo.txt");*/
if (!file.is_open()) { /*if (!file.is_open()) {*/
throw std::runtime_error("todo.txt file not found"); /*throw std::runtime_error("todo.txt file not found");*/
} /*}*/
std::vector<TaskItem> taskItems; /*std::vector<TaskItem> taskItems;*/
std::string line; /*std::string line;*/
while (std::getline(file, line)) { /*while (std::getline(file, line)) {*/
auto taskItem = parseLine(line); /*auto taskItem = parseLine(line);*/
taskItems.push_back(taskItem); /*taskItems.push_back(taskItem);*/
} /*}*/
file.close(); /*file.close();*/
TaskList tasks({ /*TaskList tasks({*/
.tasks = taskItems /*.tasks = taskItems*/
}); /*});*/
return tasks; /*return tasks;*/
} /*}*/
static void writeFile(TaskList& tasks) { /*static void writeFile(TaskList& tasks) {*/
std::ofstream file("../newqml/todo.txt"); /*std::ofstream file("../newqml/todo.txt");*/
if (!file.is_open()) { /*if (!file.is_open()) {*/
throw std::runtime_error("can't create todo.txt"); /*throw std::runtime_error("can't create todo.txt");*/
} /*}*/
for (const auto& task : tasks.getTasks()) { /*for (const auto& task : tasks.getTasks()) {*/
file << fieldWithSpace(task->state == DONE ? "x" : task->priority); /*file << fieldWithSpace(task->state == DONE ? "x" : task->priority);*/
file << fieldWithSpace(task->state == DONE ? task->getDate() : ""); /*file << fieldWithSpace(task->state == DONE ? task->getDate() : "");*/
file << fieldWithSpace(task->getCreationDate()); /*file << fieldWithSpace(task->getCreationDate());*/
file << task->getText() << '\n'; /*file << task->getText() << '\n';*/
} /*}*/
file.close(); /*file.close();*/
} /*}*/
private: /*private:*/
static std::string fieldWithSpace(const std::string& field) { /*static std::string fieldWithSpace(const std::string& field) {*/
if (field.length() == 0) /*if (field.length() == 0)*/
return ""; /*return "";*/
return (field + " "); /*return (field + " ");*/
} /*}*/
static TaskItem parseLine(const std::string& line) { /*static TaskItem parseLine(const std::string& line) {*/
std::smatch matches; /*std::smatch matches;*/
std::regex regex("(^x )?(\\([A-Z]\\) )?([0-9]{4}-[0-9]{2}-[0-9]{2} )?([0-9]{4}-[0-9]{2}-[0-9]{2} )?(.*)"); /*std::regex regex("(^x )?(\\([A-Z]\\) )?([0-9]{4}-[0-9]{2}-[0-9]{2} )?([0-9]{4}-[0-9]{2}-[0-9]{2} )?(.*)");*/
std::regex_match(line, matches, regex); /*std::regex_match(line, matches, regex);*/
for (size_t i = 0; i < matches.size(); ++i) { /*for (size_t i = 0; i < matches.size(); ++i) {*/
std::ssub_match sub_match = matches[i]; /*std::ssub_match sub_match = matches[i];*/
std::string piece = sub_match.str(); /*std::string piece = sub_match.str();*/
} /*}*/
const TaskItemState taskState = trim_copy(matches[1].str()) == "x" ? DONE : TODO; /*const TaskItemState taskState = trim_copy(matches[1].str()) == "x" ? DONE : TODO;*/
const std::string priority = trim_copy(matches[2].str()); /*const std::string priority = trim_copy(matches[2].str());*/
const std::string firstDate = trim_copy(matches[3].str()); /*const std::string firstDate = trim_copy(matches[3].str());*/
const std::string secondDate = trim_copy(matches[4].str()); /*const std::string secondDate = trim_copy(matches[4].str());*/
const std::string text = trim_copy(matches[5].str()); /*const std::string text = trim_copy(matches[5].str());*/
const std::string date = taskState == DONE ? firstDate : ""; /*const std::string date = taskState == DONE ? firstDate : "";*/
return { /*return {*/
.text = text, /*.text = text,*/
.state = taskState, /*.state = taskState,*/
.date = date, /*.date = date,*/
}; /*};*/
} /*}*/
}; /*};*/
} /*}*/
#endif #endif

View file

@ -6,39 +6,9 @@
#include "utils.h" #include "utils.h"
void ltrim(std::string& s) { namespace mirai {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { bool isDate(const std::string& dateStr) {
return !std::isspace(ch); std::regex regex("[0-9]{4}-[0-9]{2}-[0-9]{2}");
})); return std::regex_match(dateStr, regex);
} }
void rtrim(std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
void trim(std::string& s) {
rtrim(s);
ltrim(s);
}
std::string ltrim_copy(std::string s) {
ltrim(s);
return s;
}
std::string rtrim_copy(std::string s) {
rtrim(s);
return s;
}
std::string trim_copy(std::string s) {
trim(s);
return s;
}
bool isDate(const std::string& dateStr) {
std::regex regex("[0-9]{4}-[0-9]{2}-[0-9]{2}");
return std::regex_match(dateStr, regex);
} }

View file

@ -11,15 +11,15 @@
#include <cctype> #include <cctype>
#include <locale> #include <locale>
#include <regex> #include <regex>
#include <cpp-utils/string.h>
#include <cpp-utils/vector.h>
void ltrim(std::string& s); namespace mirai {
void rtrim(std::string& s); namespace stringUtils = cpputils::string;
void trim(std::string& s); namespace vectorUtils = cpputils::vector;
std::string ltrim_copy(std::string s); bool isDate(const std::string& dateStr);
std::string rtrim_copy(std::string s); }
std::string trim_copy(std::string s);
bool isDate(const std::string& dateStr);
#endif #endif