working now
parent
b248d9ef91
commit
e2b278e8bd
|
@ -12,7 +12,9 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <optional>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <unordered_set>
|
||||||
#include <blt/compatibility.h>
|
#include <blt/compatibility.h>
|
||||||
|
|
||||||
namespace blt::string
|
namespace blt::string
|
||||||
|
@ -120,6 +122,29 @@ namespace blt::string
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline std::optional<std::vector<size_t>> containsAll(const std::string& string, const std::unordered_set<char>& search)
|
||||||
|
{
|
||||||
|
std::vector<size_t> pos;
|
||||||
|
for (size_t i = 0; i < string.length(); i++)
|
||||||
|
{
|
||||||
|
if (BLT_CONTAINS(search, string[i]))
|
||||||
|
pos.push_back(i);
|
||||||
|
}
|
||||||
|
if (!pos.empty())
|
||||||
|
return pos;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t contains(const std::string& string, const std::unordered_set<char>& search)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < string.length(); i++)
|
||||||
|
{
|
||||||
|
if (BLT_CONTAINS(search, string[i]))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline BLT_CPP20_CONSTEXPR bool contains(const std::string& string, const char search)
|
static inline BLT_CPP20_CONSTEXPR bool contains(const std::string& string, const char search)
|
||||||
{
|
{
|
||||||
#if __cplusplus >= 202002L
|
#if __cplusplus >= 202002L
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* See LICENSE file for license detail
|
* See LICENSE file for license detail
|
||||||
*/
|
*/
|
||||||
#include <blt/std/format.h>
|
#include <blt/std/format.h>
|
||||||
|
#include <blt/std/string.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "blt/std/logging.h"
|
#include "blt/std/logging.h"
|
||||||
#include "blt/std/assert.h"
|
#include "blt/std/assert.h"
|
||||||
|
@ -169,6 +170,7 @@ std::vector<std::string> blt::string::TreeFormatter::construct()
|
||||||
// construct a stack of the highest node -> the lowest node.
|
// construct a stack of the highest node -> the lowest node.
|
||||||
level_data currentLevel;
|
level_data currentLevel;
|
||||||
currentLevel.depth = 0;
|
currentLevel.depth = 0;
|
||||||
|
size_t maxLineLength = 0;
|
||||||
while (!bfs.empty())
|
while (!bfs.empty())
|
||||||
{
|
{
|
||||||
auto n = bfs.front();
|
auto n = bfs.front();
|
||||||
|
@ -182,6 +184,15 @@ std::vector<std::string> blt::string::TreeFormatter::construct()
|
||||||
{
|
{
|
||||||
auto box = generateBox(n.node);
|
auto box = generateBox(n.node);
|
||||||
currentLevel.max_horizontal_length = std::max(currentLevel.max_horizontal_length, box[0].size());
|
currentLevel.max_horizontal_length = std::max(currentLevel.max_horizontal_length, box[0].size());
|
||||||
|
std::string replacement = "-";
|
||||||
|
// UGLY TODO: fix this
|
||||||
|
if (n.node->left != nullptr)
|
||||||
|
replacement = "$";
|
||||||
|
else if (n.node->right != nullptr)
|
||||||
|
replacement = "#";
|
||||||
|
if (replacement[0] == '$' && n.node->right != nullptr)
|
||||||
|
replacement = "@";
|
||||||
|
blt::string::replaceAll(box.front(), "%", replacement);
|
||||||
n.box = std::move(box);
|
n.box = std::move(box);
|
||||||
}
|
}
|
||||||
currentLevel.level.push_back(n);
|
currentLevel.level.push_back(n);
|
||||||
|
@ -204,6 +215,7 @@ std::vector<std::string> blt::string::TreeFormatter::construct()
|
||||||
size_t lineLength = 0;
|
size_t lineLength = 0;
|
||||||
const size_t lineHeight = format.verticalPadding * 2 + 3;
|
const size_t lineHeight = format.verticalPadding * 2 + 3;
|
||||||
//std::cout << levels.size() << "\n";
|
//std::cout << levels.size() << "\n";
|
||||||
|
const size_t verticalSpacing = format.verticalSpacing % 2 == 0 ? format.verticalSpacing + 1 : format.verticalSpacing;
|
||||||
while (!levels.empty())
|
while (!levels.empty())
|
||||||
{
|
{
|
||||||
std::vector<std::string> currentLines;
|
std::vector<std::string> currentLines;
|
||||||
|
@ -238,57 +250,79 @@ std::vector<std::string> blt::string::TreeFormatter::construct()
|
||||||
{
|
{
|
||||||
lineLength = std::max(lineLength, v.length());
|
lineLength = std::max(lineLength, v.length());
|
||||||
lines.push_back(createPadding(padLength) + v);
|
lines.push_back(createPadding(padLength) + v);
|
||||||
|
maxLineLength = std::max(maxLineLength, lines.back().length());
|
||||||
}
|
}
|
||||||
levels.pop();
|
levels.pop();
|
||||||
//if (!levels.empty())
|
if (!levels.empty())
|
||||||
// for (int i = 0; i < format.verticalSpacing; i++)
|
for (size_t i = 0; i < verticalSpacing; i++)
|
||||||
// lines.emplace_back("&");
|
lines.emplace_back(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = 1;
|
for (auto& line : lines)
|
||||||
size_t startLine = 0;
|
if (line.length() < maxLineLength)
|
||||||
size_t endLine = 0;
|
line += createPadding(maxLineLength - line.length());
|
||||||
while (index < lines.size() - 1)
|
|
||||||
{
|
|
||||||
auto& line = lines[index];
|
|
||||||
size_t beginMarkerIndex = 0;
|
|
||||||
size_t endMarkerIndex = 0;
|
|
||||||
startLine = index++;
|
|
||||||
beginMarkerIndex = line.find('%');
|
|
||||||
if (beginMarkerIndex != std::string::npos)
|
|
||||||
{
|
|
||||||
// find endLine we need to connect with
|
|
||||||
while (index < lines.size())
|
|
||||||
{
|
|
||||||
auto& line2 = lines[index];
|
|
||||||
endMarkerIndex = line2.find('%');
|
|
||||||
if (endMarkerIndex != std::string::npos)
|
|
||||||
{
|
|
||||||
endLine = index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (beginMarkerIndex == std::string::npos || endMarkerIndex == std::string::npos)
|
|
||||||
break;
|
|
||||||
|
|
||||||
BLT_TRACE(std::abs(static_cast<std::int64_t>(endMarkerIndex) - static_cast<std::int64_t>(beginMarkerIndex)));
|
|
||||||
auto connector = createPadding(std::abs(static_cast<std::int64_t>(endMarkerIndex) - static_cast<std::int64_t>(beginMarkerIndex)), '-');
|
|
||||||
auto frontPad = createPadding(std::min(beginMarkerIndex, endMarkerIndex));
|
|
||||||
lines.insert(lines.begin() + static_cast<std::int64_t>(startLine) + 1, frontPad += connector);
|
|
||||||
index++;
|
|
||||||
|
|
||||||
beginMarkerIndex = line.find('%', beginMarkerIndex + 1);
|
|
||||||
endMarkerIndex = line.find('%', endMarkerIndex + 1);
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::reverse(lines.begin(), lines.end());
|
std::reverse(lines.begin(), lines.end());
|
||||||
|
|
||||||
|
size_t index = 1;
|
||||||
|
while (index < lines.size())
|
||||||
|
{
|
||||||
|
if (auto poses = blt::string::containsAll(lines[index], std::unordered_set{'$', '#', '@'}))
|
||||||
|
{
|
||||||
|
const auto& nextLine = lines[index + verticalSpacing + 1];
|
||||||
|
auto poses2 = blt::string::containsAll(nextLine, std::unordered_set{'%'}).value();
|
||||||
|
size_t consume = 0;
|
||||||
|
for (auto p : poses.value())
|
||||||
|
{
|
||||||
|
char type = lines[index][p];
|
||||||
|
for (size_t n = 0; n < verticalSpacing / 2; n++)
|
||||||
|
lines[index + n + 1][p] = '|';
|
||||||
|
lines[index + (verticalSpacing / 2) + 1][p] = '+';
|
||||||
|
auto start = index + (verticalSpacing / 2) + 1;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case '@':
|
||||||
|
for (size_t i = poses2[consume] + 1; i < poses2[consume + 1]; i++)
|
||||||
|
lines[start][i] = '-';
|
||||||
|
lines[start][poses2[consume]] = '+';
|
||||||
|
lines[start][poses2[consume + 1]] = '+';
|
||||||
|
for (size_t n = 0; n < verticalSpacing / 2; n++)
|
||||||
|
{
|
||||||
|
lines[start + n + 1][poses2[consume]] = '|';
|
||||||
|
lines[start + n + 1][poses2[consume + 1]] = '|';
|
||||||
|
}
|
||||||
|
consume += 2;
|
||||||
|
break;
|
||||||
|
case '$':
|
||||||
|
for (size_t i = poses2[consume] + 1; i < p; i++)
|
||||||
|
lines[start][i] = '-';
|
||||||
|
lines[start][poses2[consume]] = '+';
|
||||||
|
lines[start][p] = '+';
|
||||||
|
for (size_t n = 0; n < verticalSpacing / 2; n++)
|
||||||
|
lines[start + n + 1][poses2[consume]] = '|';
|
||||||
|
consume++;
|
||||||
|
break;
|
||||||
|
case '#':
|
||||||
|
for (size_t i = p; i < poses2[consume]; i++)
|
||||||
|
lines[start][i] = '-';
|
||||||
|
lines[start][poses2[consume]] = '+';
|
||||||
|
lines[start][p] = '+';
|
||||||
|
for (size_t n = 0; n < verticalSpacing / 2; n++)
|
||||||
|
lines[start + n + 1][poses2[consume]] = '|';
|
||||||
|
consume++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blt::string::replaceAll(lines[index], "%", "+");
|
||||||
|
blt::string::replaceAll(lines[index], "#", "+");
|
||||||
|
blt::string::replaceAll(lines[index], "@", "+");
|
||||||
|
blt::string::replaceAll(lines[index], "$", "+");
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
blt::string::replaceAll(lines.front(), "%", "-");
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue