fixed display for tree_structurer

This commit is contained in:
Falko Victor Habel 2025-04-22 15:51:32 +02:00
parent 88ac87a0b6
commit 64596eaf46
1 changed files with 51 additions and 125 deletions

View File

@ -123,7 +123,6 @@ std::vector<fs::path> TreeStructurer::get_filtered_paths(const fs::path& start)
std::vector<std::string> TreeStructurer::get_directory_structure(const std::string& startpath) {
std::vector<std::string> result;
// Normalize the input path by removing ./ or .\ prefix if present
std::string normalized_path = startpath;
if (normalized_path.size() >= 2 &&
(normalized_path.substr(0, 2) == ".\\" || normalized_path.substr(0, 2) == "./")) {
@ -140,144 +139,70 @@ std::vector<std::string> TreeStructurer::get_directory_structure(const std::stri
throw std::runtime_error("Path is not a directory: " + start.string());
}
// Start with the root node
std::string root_name = start.filename().string();
result.push_back(root_name + "/");
// First, collect all paths and organize them by their parent directories
std::map<std::string, std::vector<fs::path>> dir_contents;
std::vector<std::string> dir_paths; // To maintain order of directories
// Add root directory
dir_contents["/"] = {};
dir_paths.push_back("/");
// Collect files and directories
for (const auto& entry : fs::recursive_directory_iterator(start)) {
const auto& path = entry.path();
std::string rel_path = get_relative_path(path, start);
// Replace backslashes with forward slashes
std::replace(rel_path.begin(), rel_path.end(), '\\', '/');
// Skip if it should be ignored
bool should_skip = false;
for (const auto& component : path) {
if (should_ignore_dir(component.string())) {
should_skip = true;
break;
}
}
if (should_skip) continue;
// Get all paths and sort them
std::vector<fs::path> paths;
std::map<fs::path, std::vector<fs::path>> dir_contents;
// First, collect all paths
for (const auto& entry : fs::directory_iterator(start)) {
fs::path path = entry.path();
if (entry.is_directory()) {
if (should_ignore_dir(path.filename().string())) {
continue;
}
// Add directory to its parent
std::string parent_path = "/";
size_t last_slash = rel_path.find_last_of('/');
if (last_slash != std::string::npos) {
parent_path = rel_path.substr(0, last_slash);
if (parent_path.empty()) {
parent_path = "/";
if (!should_ignore_dir(path.filename().string())) {
paths.push_back(path);
// Collect contents of this directory
for (const auto& subentry : fs::directory_iterator(path)) {
if (!should_ignore_file(subentry.path().filename().string()) &&
!should_ignore_dir(subentry.path().filename().string())) {
dir_contents[path].push_back(subentry.path());
}
}
}
// Create parent directory entry if it doesn't exist
if (dir_contents.find(parent_path) == dir_contents.end()) {
dir_contents[parent_path] = {};
dir_paths.push_back(parent_path);
}
// Create directory entry
dir_contents[parent_path].push_back(path);
// Create entry for this directory's contents
dir_contents[rel_path] = {};
dir_paths.push_back(rel_path);
} else {
if (should_ignore_file(path.filename().string())) {
continue;
if (!should_ignore_file(path.filename().string())) {
paths.push_back(path);
}
// Add file to its parent
std::string parent_path = "/";
size_t last_slash = rel_path.find_last_of('/');
if (last_slash != std::string::npos) {
parent_path = rel_path.substr(0, last_slash);
if (parent_path.empty()) {
parent_path = "/";
}
}
// Create parent directory entry if it doesn't exist
if (dir_contents.find(parent_path) == dir_contents.end()) {
dir_contents[parent_path] = {};
dir_paths.push_back(parent_path);
}
dir_contents[parent_path].push_back(path);
}
}
// Now create the tree structure
std::function<void(const std::string&, const std::string&, std::vector<bool>&)>
build_tree = [&](const std::string& dir_path, const std::string& prefix, std::vector<bool>& is_last_stack) {
// Sort paths - directories first, then files
std::vector<fs::path>& paths = dir_contents[dir_path];
std::sort(paths.begin(), paths.end(), [](const fs::path& a, const fs::path& b) {
bool a_is_dir = fs::is_directory(a);
bool b_is_dir = fs::is_directory(b);
if (a_is_dir != b_is_dir) {
return a_is_dir > b_is_dir; // Directories before files
}
return a.filename() < b.filename(); // Alphabetical order
});
// Sort paths
std::sort(paths.begin(), paths.end());
for (auto& [dir, contents] : dir_contents) {
std::sort(contents.begin(), contents.end());
}
// Add entries for this directory
for (size_t i = 0; i < paths.size(); ++i) {
const auto& path = paths[i];
bool is_last = (i == paths.size() - 1);
// Add root directory
std::string root_name = start.filename().string();
result.push_back(root_name + "/");
// Build the line prefix
std::string line_prefix = prefix;
if (!prefix.empty()) {
line_prefix += is_last ? "└── " : "├── ";
}
// Process each path
for (size_t i = 0; i < paths.size(); ++i) {
bool is_last = (i == paths.size() - 1);
std::string line = is_last ? "└── " : "├── ";
// Add the file/directory name
std::string name = path.filename().string();
std::string line = line_prefix + name;
std::string name = paths[i].filename().string();
if (fs::is_directory(paths[i])) {
name += "/";
}
line += name;
result.push_back(line);
if (fs::is_directory(path)) {
line += "/";
}
// If it's a directory, process its contents
if (fs::is_directory(paths[i])) {
const auto& contents = dir_contents[paths[i]];
for (size_t j = 0; j < contents.size(); ++j) {
bool is_last_child = (j == contents.size() - 1);
std::string child_line = is_last ? " " : "";
child_line += is_last_child ? "└── " : "├── ";
result.push_back(line);
// If it's a directory, process its contents with updated prefix
if (fs::is_directory(path)) {
std::string rel_path = get_relative_path(path, start);
std::replace(rel_path.begin(), rel_path.end(), '\\', '/');
std::string next_prefix = prefix;
if (!prefix.empty()) {
next_prefix += is_last ? " " : "";
std::string child_name = contents[j].filename().string();
if (fs::is_directory(contents[j])) {
child_name += "/";
}
std::vector<bool> next_is_last_stack = is_last_stack;
next_is_last_stack.push_back(is_last);
build_tree(rel_path, next_prefix, next_is_last_stack);
child_line += child_name;
result.push_back(child_line);
}
}
};
// Start building the tree from the root
std::vector<bool> is_last_stack;
build_tree("/", "", is_last_stack);
}
} catch (const fs::filesystem_error& e) {
throw std::runtime_error("Failed to access directory: " + std::string(e.what()));
@ -286,6 +211,7 @@ std::vector<std::string> TreeStructurer::get_directory_structure(const std::stri
return result;
}
// -----------------------------------------------------------------------------
// Structure Creation from a Tree-like File or String
// -----------------------------------------------------------------------------