From cb126028cd90ad14b0c13f05ebe0bde1d170eca7 Mon Sep 17 00:00:00 2001 From: Falko Habel Date: Fri, 6 Jun 2025 21:36:08 +0200 Subject: [PATCH] fixed issue in display in terminal --- README.md | 28 ++++----- pyproject.toml | 2 +- setup.py | 2 +- src/prodir/cpp/tree_structurer.cpp | 94 ++++++++++++++++++++++-------- tests/cpp/test_tree_structurer.py | 22 +++---- 5 files changed, 98 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 600afdc..f92a705 100644 --- a/README.md +++ b/README.md @@ -93,20 +93,20 @@ my_project/ ```plaintext Analyzing directory: .\my_project\ -data/ -└── sample_data.csv -docs/ -└── README.md -requirements.txt -setup.py -src/ -├── __init__.py -├── main.py -└── utils.py -tests/ -├── __init__.py -├── test_main.py -└── test_utils.py +├── data/ + └── sample_data.csv +├── docs/ + └── README.md +├── requirements.txt +├── setup.py +├── src/ +│ ├── __init__.py +│ ├── main.py + └── utils.py +└── tests/ +│ ├── __init__.py +│ ├── test_main.py + └── test_utils.py ``` #### Commands diff --git a/pyproject.toml b/pyproject.toml index 6b54f8c..e11cdbc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "prodir" -version = "1.0.2" +version = "1.1.0" description = "A module for analyzing and creating directory structures" scripts = {prodir = "prodir.__main__:main"} dependencies = [] diff --git a/setup.py b/setup.py index 56400ac..82f4586 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ tree_structurer_module = Extension( setup( name='prodir', - version='1.0.2', + version='1.1.0', description='A module for analyzing directory structures', ext_modules=[tree_structurer_module], packages=find_packages(where="src"), diff --git a/src/prodir/cpp/tree_structurer.cpp b/src/prodir/cpp/tree_structurer.cpp index ad33960..dacbf93 100644 --- a/src/prodir/cpp/tree_structurer.cpp +++ b/src/prodir/cpp/tree_structurer.cpp @@ -124,24 +124,24 @@ std::vector TreeStructurer::get_filtered_paths(const fs::path& start) std::vector TreeStructurer::get_directory_structure(const std::string& startpath) { std::vector result; std::string normalized_path = startpath; - if (normalized_path.size() >= 2 && + if (normalized_path.size() >= 2 && (normalized_path.substr(0, 2) == ".\\" || normalized_path.substr(0, 2) == "./")) { normalized_path = normalized_path.substr(2); } fs::path start = normalized_path.empty() ? fs::current_path() : fs::path(normalized_path); - + try { if (!fs::exists(start)) { throw std::runtime_error("Directory does not exist: " + start.string()); } - + if (!fs::is_directory(start)) { throw std::runtime_error("Path is not a directory: " + start.string()); } - + std::vector paths = get_filtered_paths(start); std::vector is_last_per_level; - + // Skip the first path as it's the root for (size_t i = 1; i < paths.size(); ++i) { fs::path relative = fs::relative(paths[i], start); @@ -149,45 +149,93 @@ std::vector TreeStructurer::get_directory_structure(const std::stri for (const auto& comp : relative) { components.push_back(comp.string()); } - + // Calculate the current level size_t level = components.size() - 1; - + // Adjust is_last_per_level vector size while (is_last_per_level.size() <= level) { is_last_per_level.push_back(false); } - - // Determine if this is the last item at its level - bool is_last = (i == paths.size() - 1) || - (i + 1 < paths.size() && - fs::relative(paths[i + 1], start).begin()->string() != components[0]); - - is_last_per_level[level] = is_last; - + // Build the line prefix std::string line; - for (size_t j = 0; j < level; ++j) { - if (j == level - 1) { - line += is_last ? "└── " : "├── "; + for (size_t j = 0; j <= level; ++j) { + if (j == level) { + // This is the connector for the current item + bool is_last_sibling = true; + + // Look ahead to find next sibling at the same level + for (size_t k = i + 1; k < paths.size(); ++k) { + fs::path next_relative = fs::relative(paths[k], start); + std::vector next_components; + for (const auto& comp : next_relative) { + next_components.push_back(comp.string()); + } + + // Check if it's a sibling (same parent, same level) + if (next_components.size() == components.size()) { + bool same_parent = true; + for (size_t l = 0; l < level; ++l) { + if (l >= next_components.size() || components[l] != next_components[l]) { + same_parent = false; + break; + } + } + if (same_parent) { + is_last_sibling = false; + break; + } + } + } + + line += is_last_sibling ? "└── " : "├── "; } else { - line += is_last_per_level[j] ? " " : "│ "; + // This is a vertical line for parent levels + bool needs_vertical_line = false; + + // Check if there are future items that share this ancestor + for (size_t k = i + 1; k < paths.size(); ++k) { + fs::path next_relative = fs::relative(paths[k], start); + std::vector next_components; + for (const auto& comp : next_relative) { + next_components.push_back(comp.string()); + } + + // If next item shares the same path up to level j + if (next_components.size() > j) { + bool shares_ancestor = true; + for (size_t l = 0; l <= j; ++l) { + if (l >= next_components.size() || l >= components.size() || + components[l] != next_components[l]) { + shares_ancestor = false; + break; + } + } + if (shares_ancestor) { + needs_vertical_line = true; + break; + } + } + } + + line += needs_vertical_line ? "│ " : " "; } } - + // Add the file/directory name line += components.back(); if (fs::is_directory(paths[i])) { line += "/"; } - + result.push_back(line); } - + } catch (const fs::filesystem_error& e) { throw std::runtime_error("Failed to access directory: " + std::string(e.what())); } - + return result; } diff --git a/tests/cpp/test_tree_structurer.py b/tests/cpp/test_tree_structurer.py index 86cc519..3b3f287 100644 --- a/tests/cpp/test_tree_structurer.py +++ b/tests/cpp/test_tree_structurer.py @@ -138,17 +138,17 @@ project/ # Define expected structure with proper tree markers expected_structure = [ - "LICENSE", - "README.md", - "config/", - "└── config.yaml", - "pyproject.toml", - "setup.py", - "src/", - "├── __init__.py", - "├── main.py", - "├── module1.py", - "└── module2.py" + "├── LICENSE", + "├── README.md", + "├── config/", + " └── config.yaml", + "├── pyproject.toml", + "├── setup.py", + "└── src/", + "│ ├── __init__.py", + "│ ├── main.py", + "│ ├── module1.py", + " └── module2.py" ] # Get actual structure