Merge pull request 'basic_functioanllity' (#1) from basic_functioanllity into develop

Reviewed-on: Fabel/Tree-Structurer#1
This commit is contained in:
Falko Victor Habel 2025-01-19 19:05:03 +00:00
commit b01dff4319
8 changed files with 298 additions and 0 deletions

19
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,19 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"C:/Users/Falko/AppData/Local/Programs/Python/Python311/include",
"C:/Users/Falko/AppData/Local/Programs/Python/Python311/Lib/site-packages/pybind11/include"
],
"defines": [],
"windowsSdkVersion": "10.0.19041.0",
"compilerPath": "cl.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "windows-msvc-x64"
}
],
"version": 4
}

72
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,72 @@
{
"files.associations": {
"*.py": "python",
"algorithm": "cpp",
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"cctype": "cpp",
"charconv": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"concepts": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"exception": "cpp",
"filesystem": "cpp",
"format": "cpp",
"forward_list": "cpp",
"functional": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"iterator": "cpp",
"limits": "cpp",
"list": "cpp",
"locale": "cpp",
"memory": "cpp",
"mutex": "cpp",
"new": "cpp",
"optional": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"string": "cpp",
"system_error": "cpp",
"thread": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"utility": "cpp",
"vector": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xlocmes": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xstring": "cpp",
"xtr1common": "cpp",
"xutility": "cpp"
}
}

27
setup.py Normal file
View File

@ -0,0 +1,27 @@
from setuptools import setup, Extension
import platform
extra_compile_args = []
extra_link_args = []
# Set C++17 flag based on the compiler
if platform.system() == "Windows":
extra_compile_args.append('/std:c++17')
else:
extra_compile_args.append('-std=c++17')
tree_structurer_module = Extension(
'tree_structurer._tree_structurer',
sources=['tree_structurer/cpp/bindings.cpp', 'tree_structurer/cpp/tree_structurer.cpp'],
include_dirs=['tree_structurer/cpp'],
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args,
)
setup(
name='tree_structurer',
version='0.0.2',
description='A module for analyzing directory structures',
ext_modules=[tree_structurer_module],
packages=['tree_structurer'],
)

View File

@ -0,0 +1 @@
from tree_structurer._tree_structurer import create_tree_structurer, get_structure

View File

@ -0,0 +1,31 @@
import os
import sys
import argparse
from tree_structurer import create_tree_structurer, get_structure
def main():
parser = argparse.ArgumentParser(description='Display directory structure in a tree-like format')
parser.add_argument('path', nargs='?', default=os.getcwd(),
help='Path to analyze (default: current directory)')
parser.add_argument('-v', '--verbose', action='store_true',
help='Show more detailed output')
args = parser.parse_args()
try:
if args.verbose:
print(f"Analyzing directory: {args.path}")
# Create tree structurer instance
create_tree_structurer()
# Get and print structure
structure = get_structure(args.path)
for line in structure:
print(line)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,72 @@
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "tree_structurer.hpp"
static PyObject* TreeStructurerError;
static TreeStructurer* g_tree_structurer = nullptr;
static PyObject* create_tree_structurer(PyObject* self, PyObject* args) {
if (g_tree_structurer != nullptr) {
delete g_tree_structurer;
}
g_tree_structurer = new TreeStructurer();
Py_RETURN_NONE;
}
static PyObject* get_structure(PyObject* self, PyObject* args) {
const char* path = nullptr;
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);
PyObject* list = PyList_New(structure.size());
for (size_t i = 0; i < structure.size(); i++) {
PyList_SET_ITEM(list, i, PyUnicode_FromString(structure[i].c_str()));
}
return list;
} catch (const std::exception& e) {
PyErr_SetString(TreeStructurerError, e.what());
return NULL;
}
}
static PyMethodDef TreeStructurerMethods[] = {
{"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"},
{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",
-1,
TreeStructurerMethods
};
PyMODINIT_FUNC PyInit__tree_structurer(void) { // Changed function name to match module name
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) {
Py_XDECREF(TreeStructurerError);
Py_CLEAR(TreeStructurerError);
Py_DECREF(m);
return NULL;
}
return m;
}

View File

@ -0,0 +1,60 @@
#include "tree_structurer.hpp"
#include <algorithm>
#include <filesystem>
namespace fs = std::filesystem;
bool TreeStructurer::should_ignore_dir(const std::string& dirname) {
return dirname[0] == '.' ||
dirname.find("build") != std::string::npos ||
dirname == "venv" ||
dirname == "myenv";
}
bool TreeStructurer::should_ignore_file(const std::string& filename) {
return filename[0] == '.' ||
filename.find("build") != std::string::npos;
}
std::string TreeStructurer::create_indent(int level) {
return std::string(4 * level, ' ');
}
std::string TreeStructurer::get_relative_path(const fs::path& path, const fs::path& base) {
const fs::path rel = fs::relative(path, base);
return rel.string();
}
std::vector<std::string> TreeStructurer::get_directory_structure(const std::string& startpath) {
std::vector<std::string> result;
fs::path start = startpath.empty() ? fs::current_path() : fs::path(startpath);
try {
std::vector<fs::path> paths;
for(const auto& entry : fs::recursive_directory_iterator(start)) {
paths.push_back(entry.path());
}
// Sort paths for consistent output
std::sort(paths.begin(), paths.end());
for(const auto& path : paths) {
std::string rel_path = get_relative_path(path, start);
int level = std::count(rel_path.begin(), rel_path.end(), fs::path::preferred_separator);
if(fs::is_directory(path)) {
if(!should_ignore_dir(path.filename().string())) {
result.push_back(create_indent(level) + path.filename().string() + "/");
}
} else {
if(!should_ignore_file(path.filename().string())) {
result.push_back(create_indent(level) + path.filename().string());
}
}
}
} catch (const fs::filesystem_error& e) {
throw std::runtime_error("Failed to access directory: " + std::string(e.what()));
}
return result;
}

View File

@ -0,0 +1,16 @@
#pragma once
#include <string>
#include <vector>
#include <filesystem>
class TreeStructurer {
public:
TreeStructurer() = default;
std::vector<std::string> get_directory_structure(const std::string& startpath = std::filesystem::current_path().string());
private:
bool should_ignore_dir(const std::string& dirname);
bool should_ignore_file(const std::string& filename);
std::string create_indent(int level);
std::string get_relative_path(const std::filesystem::path& path, const std::filesystem::path& base);
};