diff options
Diffstat (limited to 'src/rttt/text.hpp')
-rw-r--r-- | src/rttt/text.hpp | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/rttt/text.hpp b/src/rttt/text.hpp new file mode 100644 index 0000000..fb59b55 --- /dev/null +++ b/src/rttt/text.hpp @@ -0,0 +1,101 @@ +#pragma once + +#include <string> +#include <vector> + +#include "rttt.hpp" + +namespace rttt { +namespace text { +// TODO: should work with constexpr, but might need newer g++/clang++ +inline std::vector<std::string> split(std::string_view strv, + std::string_view delims = " ", + size_t no_pieces = 0) { + std::vector<std::string> output; + size_t first = 0; + + while (first < strv.size()) { + const auto second = strv.find_first_of(delims, first); + + if (first != second) + output.emplace_back(strv.substr(first, second - first)); + + if (second == std::string_view::npos) { + break; + } else if (no_pieces > 0 && output.size() >= no_pieces - 1) { + output.emplace_back(strv.substr(second + 1, strv.size())); + break; + } + + first = second + 1; + } + + return output; +} + +std::vector<std::string> wrap_single_line(const std::string &line, + size_t width) { + std::vector<std::string> output; + + // Check for carriage return. Would be nice if this was not explicitely needed + if (line.empty() || line == "\n") { + output.push_back(""); + return output; + } + + std::istringstream str(line); + std::ostringstream new_line; + + std::string word; + // Length of the new_line + size_t s = 0; + while (!str.eof()) { + str >> word; + if (s + word.size() + 1 >= width) { + // Break long words (when there is enough white space left) + if (word.size() >= std::min(std::size_t{20}, width) && width > s + 7) { + auto n = width - s - 2; + std::string w1 = " " + word.substr(0, n) + "-"; + std::string w2 = word.substr(n, word.size()); + new_line << w1; + word = w2; + } + output.push_back(new_line.str()); + new_line = std::ostringstream(); + s = 0; + } else if (new_line.tellp() != 0) { + new_line << " "; + ++s; + } + new_line << word; + s += word.size(); + word.clear(); + } + output.push_back(new_line.str()); + return output; +} + +std::vector<std::string> wrap(std::string_view text, size_t width) { + auto lines = rttt::text::split(text, "\n"); + std::vector<std::string> output; + output.reserve(lines.size()); + + for (auto &line : lines) { + auto v = wrap_single_line(line, width); + output.insert(output.end(), v.begin(), v.end()); + } + return output; +} + +inline std::string time_since_string(uint64_t t) { + auto delta = rttt::current_time() - t; + if (delta < 60) + return std::to_string(delta) + " seconds"; + if (delta < 3600) + return std::to_string(delta / 60) + " minutes"; + if (delta < 24 * 3600) + return std::to_string(delta / 3600) + " hours"; + return std::to_string(delta / 24 / 3600) + " days"; +} +} // namespace text +} // namespace rttt |