Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
heysarver committed Jul 27, 2024
0 parents commit 90426ed
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
venv
.venv
.env
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# file-enumerator

Copy code in a folder for use with LLMs.

Aims to honor .gitignore and .dockerignore files and ignore all dev and non-text files.

## Requirements
- libmagic

## Usage
With pbcopy on macOS
```bash
$ python file_enumerator.py ~/workspace/path/to/copy | pbcopy
```
81 changes: 81 additions & 0 deletions file_enumerator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# /file_enumerator.py

import os
import argparse
import fnmatch
import magic

def load_ignore_patterns(directory):
ignore_patterns = []
ignore_files = ['.gitignore', '.dockerignore']

for ignore_file in ignore_files:
ignore_path = os.path.join(directory, ignore_file)
if os.path.exists(ignore_path):
with open(ignore_path, 'r') as f:
ignore_patterns.extend(line.strip() for line in f if line.strip() and not line.startswith('#'))

# Add pattern to ignore .git directory
ignore_patterns.append('.git/')

return ignore_patterns

def should_ignore(path, base_path, ignore_patterns):
rel_path = os.path.relpath(path, base_path)

# Ignore .git directory and its contents
if '.git' in rel_path.split(os.sep):
return True

for pattern in ignore_patterns:
if pattern.endswith('/'):
if fnmatch.fnmatch(rel_path + '/', pattern) or fnmatch.fnmatch(os.path.dirname(rel_path) + '/', pattern):
return True
elif fnmatch.fnmatch(rel_path, pattern):
return True
return False

def is_text_file(file_path):
mime = magic.Magic(mime=True)
file_type = mime.from_file(file_path)
return file_type.startswith('text/')

def enumerate_files(directory):
ignore_patterns = load_ignore_patterns(directory)

for root, dirs, files in os.walk(directory):
dirs[:] = [d for d in dirs if not should_ignore(os.path.join(root, d), directory, ignore_patterns)]

for file in files:
file_path = os.path.join(root, file)
if not should_ignore(file_path, directory, ignore_patterns):
if is_text_file(file_path):
relative_path = os.path.relpath(file_path, directory)
print(f"File: {relative_path}")
print("-" * 40)

try:
with open(file_path, 'r', encoding='utf-8') as f:
print(f.read())
except Exception as e:
print(f"Error reading file: {e}")

print("-" * 40)
print("-" * 40)
print()

def main():
parser = argparse.ArgumentParser(description="Directory File Enumerator with Ignore Support")
parser.add_argument("directory", help="Path to the directory to enumerate")
args = parser.parse_args()

directory = os.path.abspath(args.directory)

if not os.path.isdir(directory):
print(f"Error: {directory} is not a valid directory")
return

enumerate_files(directory)

if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
python-magic

0 comments on commit 90426ed

Please sign in to comment.