added first creation scripts but currently this is not really well working.
Gitea Actions For Tree-Structurer / Explore-Gitea-Actions (push) Has been cancelled
Details
Gitea Actions For Tree-Structurer / Explore-Gitea-Actions (push) Has been cancelled
Details
This commit is contained in:
parent
763083a5cc
commit
1eb338789c
|
@ -18,12 +18,11 @@ static PyObject* get_structure(PyObject* self, PyObject* args) {
|
|||
if (!PyArg_ParseTuple(args, "|s", &path)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (g_tree_structurer == nullptr) {
|
||||
PyErr_SetString(TreeStructurerError, "TreeStructurer not initialized");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
std::string path_str = path ? path : "";
|
||||
std::vector<std::string> structure = g_tree_structurer->get_directory_structure(path_str);
|
||||
|
@ -38,27 +37,77 @@ static PyObject* get_structure(PyObject* self, PyObject* args) {
|
|||
}
|
||||
}
|
||||
|
||||
static PyObject* create_structure_from_file(PyObject* self, PyObject* args) {
|
||||
const char* structure_file = nullptr;
|
||||
const char* target_path = nullptr;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s|s", &structure_file, &target_path)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (g_tree_structurer == nullptr) {
|
||||
PyErr_SetString(TreeStructurerError, "TreeStructurer not initialized");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
try {
|
||||
std::string target_path_str = target_path ? target_path : "";
|
||||
g_tree_structurer->create_structure_from_file(structure_file, target_path_str);
|
||||
Py_RETURN_NONE;
|
||||
} catch (const std::exception& e) {
|
||||
PyErr_SetString(TreeStructurerError, e.what());
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject* create_structure_from_string(PyObject* self, PyObject* args) {
|
||||
const char* structure_str = nullptr;
|
||||
const char* target_path = nullptr;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s|s", &structure_str, &target_path)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (g_tree_structurer == nullptr) {
|
||||
PyErr_SetString(TreeStructurerError, "TreeStructurer not initialized");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
try {
|
||||
std::string target_path_str = target_path ? target_path : "";
|
||||
g_tree_structurer->create_structure_from_string(structure_str, target_path_str);
|
||||
Py_RETURN_NONE;
|
||||
} catch (const std::exception& e) {
|
||||
PyErr_SetString(TreeStructurerError, e.what());
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyMethodDef TreeStructurerMethods[] = {
|
||||
{"create_tree_structurer", create_tree_structurer, METH_NOARGS,
|
||||
{"create_tree_structurer", create_tree_structurer, METH_NOARGS,
|
||||
"Create a new TreeStructurer instance"},
|
||||
{"get_structure", get_structure, METH_VARARGS,
|
||||
"Get the directory structure for the given path"},
|
||||
{"create_structure_from_file", create_structure_from_file, METH_VARARGS,
|
||||
"Create directory structure from a file containing the structure description"},
|
||||
{"create_structure_from_string", create_structure_from_string, METH_VARARGS,
|
||||
"Create directory structure from a string containing the structure description"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
static struct PyModuleDef tree_structurer_module = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_tree_structurer", // Changed module name to match Python import
|
||||
"Module for analyzing directory structures",
|
||||
"Module for analyzing and creating directory structures",
|
||||
-1,
|
||||
TreeStructurerMethods
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC PyInit__tree_structurer(void) { // Changed function name to match module name
|
||||
PyMODINIT_FUNC PyInit__tree_structurer(void) {
|
||||
PyObject* m = PyModule_Create(&tree_structurer_module);
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
TreeStructurerError = PyErr_NewException("tree_structurer.error", NULL, NULL);
|
||||
Py_XINCREF(TreeStructurerError);
|
||||
if (PyModule_AddObject(m, "error", TreeStructurerError) < 0) {
|
||||
|
@ -67,6 +116,6 @@ PyMODINIT_FUNC PyInit__tree_structurer(void) { // Changed function name to matc
|
|||
Py_DECREF(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return m;
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
#include "tree_structurer.hpp"
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
@ -10,22 +13,21 @@ bool TreeStructurer::should_ignore_dir(const std::string& dirname) {
|
|||
".git", ".idea", ".vscode", "__pycache__", "**pycache**"
|
||||
};
|
||||
|
||||
// Check for __main__.py or __init__.py files
|
||||
if (!dirname.empty() && (dirname == "__main__.py" || dirname == "__init__.py")) {
|
||||
return false; // Do not ignore these files
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::find(ignore_list.begin(), ignore_list.end(), dirname) != ignore_list.end()) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!dirname.empty()) {
|
||||
if (dirname[0] == '.' || dirname[0] == '_') {
|
||||
return true;
|
||||
}
|
||||
if (dirname.find("__") == 0 && dirname.find("__", 2) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -37,10 +39,9 @@ bool TreeStructurer::should_ignore_file(const std::string& filename) {
|
|||
".o", ".obj", ".a", ".lib"
|
||||
};
|
||||
|
||||
// Check for __main__.py or __init__.py files
|
||||
if (!filename.empty() && (filename == "__main__.py" || filename == "__init__.py")) {
|
||||
return false; // Do not ignore these files
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!filename.empty() && (filename[0] == '.' || filename[0] == '_')) {
|
||||
return true;
|
||||
|
@ -55,7 +56,6 @@ bool TreeStructurer::should_ignore_file(const std::string& filename) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Add the missing get_relative_path implementation
|
||||
std::string TreeStructurer::get_relative_path(const fs::path& path, const fs::path& base) {
|
||||
fs::path rel = fs::relative(path, base);
|
||||
return rel.string();
|
||||
|
@ -76,7 +76,6 @@ std::vector<fs::path> TreeStructurer::get_filtered_paths(const fs::path& start)
|
|||
|
||||
paths.push_back(start);
|
||||
|
||||
// Check if directory is empty
|
||||
bool is_empty = fs::directory_iterator(start) == fs::directory_iterator();
|
||||
if (is_empty) {
|
||||
throw std::runtime_error("Directory is empty: " + start.string());
|
||||
|
@ -115,7 +114,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 (startpath.substr(0, 2) == ".\\" || startpath.substr(0, 2) == "./") {
|
||||
normalized_path = startpath.substr(2);
|
||||
|
@ -171,4 +169,169 @@ std::vector<std::string> TreeStructurer::get_directory_structure(const std::stri
|
|||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void TreeStructurer::create_structure_from_file(const std::string& filepath, const std::string& target_path) {
|
||||
std::vector<std::string> lines = read_structure_file(filepath);
|
||||
validate_structure(lines);
|
||||
TreeNode root = build_tree_from_lines(lines);
|
||||
create_node(root, target_path);
|
||||
}
|
||||
|
||||
void TreeStructurer::create_structure_from_string(const std::string& structure, const std::string& target_path) {
|
||||
std::istringstream iss(structure);
|
||||
std::vector<std::string> lines;
|
||||
std::string line;
|
||||
|
||||
while (std::getline(iss, line)) {
|
||||
if (!line.empty()) {
|
||||
lines.push_back(line);
|
||||
}
|
||||
}
|
||||
|
||||
validate_structure(lines);
|
||||
TreeNode root = build_tree_from_lines(lines);
|
||||
create_node(root, target_path);
|
||||
}
|
||||
|
||||
void TreeStructurer::validate_structure(const std::vector<std::string>& lines) {
|
||||
if (lines.empty()) {
|
||||
throw std::runtime_error("Empty structure provided");
|
||||
}
|
||||
|
||||
int prev_indent = -1;
|
||||
for (const auto& line : lines) {
|
||||
int current_indent = get_indent_level(line);
|
||||
if (current_indent > prev_indent + 1) {
|
||||
throw std::runtime_error("Invalid indentation level in structure");
|
||||
}
|
||||
prev_indent = current_indent;
|
||||
}
|
||||
}
|
||||
|
||||
TreeStructurer::TreeNode TreeStructurer::build_tree_from_lines(const std::vector<std::string>& lines) {
|
||||
TreeNode root{"root", true, {}};
|
||||
std::vector<TreeNode*> stack{&root};
|
||||
size_t prev_indent = 0;
|
||||
|
||||
for (const auto& line : lines) {
|
||||
size_t current_indent = get_indent_level(line);
|
||||
|
||||
while (current_indent <= prev_indent && stack.size() > 1) {
|
||||
stack.pop_back();
|
||||
prev_indent--;
|
||||
}
|
||||
|
||||
TreeNode new_node = parse_structure_line(line, current_indent);
|
||||
stack.back()->children.push_back(new_node);
|
||||
|
||||
if (!new_node.is_file) {
|
||||
stack.push_back(&(stack.back()->children.back()));
|
||||
}
|
||||
|
||||
prev_indent = current_indent;
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
void TreeStructurer::create_node(const TreeNode& node, const std::filesystem::path& current_path) {
|
||||
std::filesystem::path new_path = current_path / node.name;
|
||||
|
||||
if (node.is_file) {
|
||||
create_file(new_path);
|
||||
} else {
|
||||
create_directory(new_path);
|
||||
for (const auto& child : node.children) {
|
||||
create_node(child, new_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TreeStructurer::create_directory(const std::filesystem::path& path) {
|
||||
if (!std::filesystem::exists(path)) {
|
||||
if (!std::filesystem::create_directory(path)) {
|
||||
throw std::runtime_error("Failed to create directory: " + path.string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TreeStructurer::create_file(const std::filesystem::path& path) {
|
||||
if (!std::filesystem::exists(path)) {
|
||||
std::ofstream file(path);
|
||||
if (!file.is_open()) {
|
||||
throw std::runtime_error("Failed to create file: " + path.string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TreeStructurer::TreeNode TreeStructurer::parse_structure_line(const std::string& line, size_t indent_level) {
|
||||
size_t name_start = 0;
|
||||
for (size_t i = 0; i < line.length(); ++i) {
|
||||
if (line[i] != ' ' &&
|
||||
static_cast<unsigned char>(line[i]) != INDENT_MARKER_PIPE &&
|
||||
static_cast<unsigned char>(line[i]) != INDENT_MARKER_DASH &&
|
||||
static_cast<unsigned char>(line[i]) != INDENT_MARKER_END &&
|
||||
line[i] != '-') {
|
||||
name_start = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string name = line.substr(name_start);
|
||||
|
||||
name.erase(0, name.find_first_not_of(" "));
|
||||
name.erase(name.find_last_not_of(" ") + 1);
|
||||
|
||||
bool is_file = !is_directory_marker(name);
|
||||
|
||||
if (!is_file && name.back() == '/') {
|
||||
name.pop_back();
|
||||
}
|
||||
|
||||
return TreeNode{name, is_file, {}};
|
||||
}
|
||||
|
||||
size_t TreeStructurer::get_indent_level(const std::string& line) {
|
||||
size_t level = 0;
|
||||
for (size_t i = 0; i < line.length(); ++i) {
|
||||
if (line[i] == ' ') {
|
||||
continue;
|
||||
}
|
||||
if (line[i] == '-' ||
|
||||
static_cast<unsigned char>(line[i]) == INDENT_MARKER_PIPE ||
|
||||
static_cast<unsigned char>(line[i]) == INDENT_MARKER_DASH ||
|
||||
static_cast<unsigned char>(line[i]) == INDENT_MARKER_END) {
|
||||
level++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return level / 4;
|
||||
}
|
||||
|
||||
bool TreeStructurer::is_directory_marker(const std::string& line) {
|
||||
return !line.empty() && line.back() == DIRECTORY_MARKER;
|
||||
}
|
||||
|
||||
std::string TreeStructurer::create_indent(size_t level) {
|
||||
return std::string(level * 4, ' ');
|
||||
}
|
||||
|
||||
std::vector<std::string> TreeStructurer::read_structure_file(const std::string& filepath) {
|
||||
std::vector<std::string> lines;
|
||||
std::ifstream file(filepath);
|
||||
|
||||
if (!file.is_open()) {
|
||||
throw std::runtime_error("Failed to open file: " + filepath);
|
||||
}
|
||||
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
if (!line.empty()) {
|
||||
lines.push_back(line);
|
||||
}
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
|
@ -2,16 +2,44 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
class TreeStructurer {
|
||||
public:
|
||||
TreeStructurer() = default;
|
||||
|
||||
std::vector<std::string> get_directory_structure(const std::string& startpath = std::filesystem::current_path().string());
|
||||
|
||||
void create_structure_from_file(const std::string& filepath, const std::string& target_path = std::filesystem::current_path().string());
|
||||
void create_structure_from_string(const std::string& structure, const std::string& target_path = std::filesystem::current_path().string());
|
||||
|
||||
private:
|
||||
struct TreeNode {
|
||||
std::string name;
|
||||
bool is_file;
|
||||
std::vector<TreeNode> children;
|
||||
};
|
||||
|
||||
bool should_ignore_dir(const std::string& dirname);
|
||||
bool should_ignore_file(const std::string& filename);
|
||||
std::string create_indent(int level);
|
||||
std::string create_indent(size_t level);
|
||||
std::string get_relative_path(const std::filesystem::path& path, const std::filesystem::path& base);
|
||||
std::vector<std::filesystem::path> get_filtered_paths(const std::filesystem::path& start);
|
||||
};
|
||||
|
||||
TreeNode parse_structure_line(const std::string& line, size_t indent_level);
|
||||
TreeNode build_tree_from_lines(const std::vector<std::string>& lines);
|
||||
void create_node(const TreeNode& node, const std::filesystem::path& current_path);
|
||||
size_t get_indent_level(const std::string& line);
|
||||
bool is_directory_marker(const std::string& line);
|
||||
void create_directory(const std::filesystem::path& path);
|
||||
void create_file(const std::filesystem::path& path);
|
||||
std::vector<std::string> read_structure_file(const std::string& filepath);
|
||||
void validate_structure(const std::vector<std::string>& lines);
|
||||
|
||||
static const unsigned char DIRECTORY_MARKER = '/';
|
||||
static const unsigned char INDENT_MARKER_PIPE = '|';
|
||||
static const unsigned char INDENT_MARKER_DASH = '+';
|
||||
static const unsigned char INDENT_MARKER_END = '\\';
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue