Skip to content

Commit

Permalink
✨ Add consolidation functionality and markdown generator (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
OLILHR authored Jul 30, 2024
1 parent 12d9e13 commit 3789acf
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 0 deletions.
45 changes: 45 additions & 0 deletions .alloyignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.bmp
.eps
.gif
.jpeg
.jpg
.pdf
.png
.svg
.tiff

.env
.env.*

__init.py__
.coverage
.dockerignore
.eslintrc.json
.gitattributes
.gitignore
.gitmodules
.nvmrc
.pre-commit-config.yaml
.prettierignore
.prettierrc
.stylelintignore
.stylelintrc.json
Dockerfile
docker-compose.yml
package-lock.json
package.json
pyproject.toml
requirements.in
requirements.txt
tox.ini

.docs/
.github/
.tox/
.vscode/
dev_requirements/
node_modules/
requirements/

LICENSE
README.md
73 changes: 73 additions & 0 deletions alloy/collector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import logging
import os

_logger = logging.getLogger(__name__)


def read_alloyignore(project_root):
"""
Excludes all files, extensions and directories specified in .alloyignore.
"""
alloyignore = os.path.join(project_root, ".alloyignore")

if not os.path.exists(alloyignore):
return lambda _: False

ignore_list = []
with open(alloyignore, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if line and not line.startswith("#"):
ignore_list.append(line) # ignore comments in .alloyignore

def exclude_files(file_path):
for pattern in ignore_list:
if pattern.startswith("/"): # covers absolute paths from the root
if file_path.startswith(pattern[1:]):
return True
elif pattern.endswith("/"): # ignores certain directories
if any(part == pattern[:-1] for part in file_path.split(os.sep)):
return True
elif pattern.startswith("*."): # ignores certain file extensions
if file_path.endswith(pattern[1:]):
return True
elif pattern.endswith("*"): # ignores certain files with depending on their prefixes
if os.path.basename(file_path).startswith(pattern[:-1]):
return True
elif pattern in file_path or pattern == os.path.basename(file_path):
return True
return False

return exclude_files


def consolidate(path):
"""
Consolidates the content of all files from a given directory into a single markdown file.
"""
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
exclude_files = read_alloyignore(project_root)
codebase = ""

for root, dirs, files in os.walk(path):
dirs[:] = [d for d in dirs if not exclude_files(os.path.relpath(str(os.path.join(root, d)), path))]

for file in files:
file_path = os.path.join(root, file)
relative_path = os.path.relpath(str(file_path), path)

if exclude_files(relative_path):
continue

_, file_extension = os.path.splitext(file)

try:
with open(file_path, "r", encoding="utf-8") as p:
content = p.read().rstrip()
except UnicodeDecodeError as e:
_logger.error(str(e))
continue

codebase += f"\n#### {relative_path}\n\n```{file_extension[1:]}\n{content}\n```\n"

return codebase
32 changes: 32 additions & 0 deletions alloy/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import logging
import os

import click

from alloy.collector import consolidate

GLOBAL_LOG_LEVEL = logging.INFO
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")

_logger = logging.getLogger(__name__)
_logger.setLevel(GLOBAL_LOG_LEVEL)


@click.command()
@click.argument("path", type=click.Path(exists=True))
def main(path):
"""
Generates a consolidated markdown file.
"""
markdown_content = consolidate(path)
project_root = os.path.dirname(os.path.abspath(__file__))
output_file = os.path.join(project_root, "../codebase.md")

with open(output_file, "w", encoding="utf-8") as f:
f.write(markdown_content)

_logger.info("Markdown file generated at %s", output_file)


if __name__ == "__main__":
main() # pylint: disable=no-value-for-parameter

0 comments on commit 3789acf

Please sign in to comment.