Initial commit: gitignore-generator v0.1.0
Some checks failed
CI / test (push) Failing after 11s

This commit is contained in:
2026-02-01 03:31:34 +00:00
parent 8924aca7c4
commit 0e5873b6cc

243
src/generator.py Normal file
View File

@@ -0,0 +1,243 @@
"""Gitignore generation from templates."""
import os
from pathlib import Path
from typing import Dict, List, Optional, Set
class GitignoreGenerator:
"""Generate .gitignore content from templates."""
TEMPLATE_MAP: Dict[str, str] = {
"python": "languages/python.gitignore",
"javascript": "languages/javascript.gitignore",
"typescript": "languages/typescript.gitignore",
"java": "languages/java.gitignore",
"go": "languages/go.gitignore",
"rust": "languages/rust.gitignore",
"dotnet": "languages/dotnet.gitignore",
"php": "languages/php.gitignore",
"ruby": "languages/ruby.gitignore",
"django": "frameworks/django.gitignore",
"flask": "frameworks/flask.gitignore",
"react": "frameworks/react.gitignore",
"vue": "frameworks/vue.gitignore",
"angular": "frameworks/angular.gitignore",
"rails": "frameworks/rails.gitignore",
"laravel": "frameworks/laravel.gitignore",
"spring": "frameworks/spring.gitignore",
"vscode": "ide/vscode.gitignore",
"jetbrains": "ide/jetbrains.gitignore",
"visualstudiocode": "ide/visualstudiocode.gitignore",
"linux": "os/linux.gitignore",
"macos": "os/macos.gitignore",
"windows": "os/windows.gitignore",
"docker": "tools/docker.gitignore",
"gradle": "tools/gradle.gitignore",
"maven": "tools/maven.gitignore",
"jupyter": "tools/jupyter.gitignore",
"terraform": "tools/terraform.gitignore",
}
def __init__(self, config: Optional["Config"] = None) -> None:
"""Initialize generator with optional configuration."""
self.template_dir = Path(__file__).parent / "templates"
self.selected_templates: Set[str] = set()
self.config = config
def add_template(self, template_type: str) -> None:
"""Add a template type to include."""
if template_type in self.TEMPLATE_MAP:
self.selected_templates.add(template_type)
def remove_template(self, template_type: str) -> None:
"""Remove a template type from selection."""
self.selected_templates.discard(template_type)
def get_template_path(self, template_type: str) -> Optional[Path]:
"""Get the path to a template file."""
template_rel = self.TEMPLATE_MAP.get(template_type)
if template_rel:
template_path = self.template_dir / template_rel
if template_path.exists():
return template_path
return None
def load_template(self, template_type: str) -> str:
"""Load template content."""
template_path = self.get_template_path(template_type)
if template_path:
try:
with open(template_path, "r") as f:
return f.read()
except OSError:
return ""
return ""
def load_template_lines(self, template_type: str) -> List[str]:
"""Load template content as list of lines."""
content = self.load_template(template_type)
lines = content.split("\n")
while lines and not lines[-1]:
lines.pop()
while lines and not lines[0]:
lines.pop(0)
return lines
def deduplicate_entries(
self, entries: List[str], comments: List[str] = None
) -> List[str]:
"""Remove duplicate entries while preserving order."""
seen: Set[str] = set()
unique_entries: List[str] = []
for entry in entries:
normalized = entry.strip().lower()
if normalized and normalized not in seen:
seen.add(normalized)
unique_entries.append(entry)
if comments:
unique_comments = []
seen_comments = set()
for comment in comments:
if comment not in seen_comments:
seen_comments.add(comment)
unique_comments.append(comment)
return unique_comments + unique_entries
return unique_entries
def generate(self) -> str:
"""Generate combined .gitignore content."""
all_entries: List[str] = []
all_comments: List[str] = []
used_categories: Set[str] = set()
template_order = [
"language",
"framework",
"ide",
"os",
"tools",
]
category_map = {
"python": "language",
"javascript": "language",
"typescript": "language",
"java": "language",
"go": "language",
"rust": "language",
"dotnet": "language",
"php": "language",
"ruby": "language",
"django": "framework",
"flask": "framework",
"react": "framework",
"vue": "framework",
"angular": "framework",
"rails": "framework",
"laravel": "framework",
"spring": "framework",
"vscode": "ide",
"jetbrains": "ide",
"visualstudiocode": "ide",
"linux": "os",
"macos": "os",
"windows": "os",
"docker": "tools",
"gradle": "tools",
"maven": "tools",
"jupyter": "tools",
"terraform": "tools",
}
for template_type in sorted(self.selected_templates):
template_path = self.get_template_path(template_type)
if template_path:
try:
category = category_map.get(template_type, "other")
header = f"# {template_type.upper()}"
if header not in all_comments:
all_comments.append(header)
lines = self.load_template_lines(template_type)
all_entries.extend(lines)
except OSError:
pass
if not all_entries:
return ""
combined = self.deduplicate_entries(all_entries, all_comments)
result = "\n".join(combined)
if result and not result.endswith("\n"):
result += "\n"
return result
def generate_for_types(
self, types: List[str], deduplicate: bool = True
) -> str:
"""Generate .gitignore for specific types."""
self.selected_templates = set()
for t in types:
self.add_template(t)
return self.generate()
def get_available_templates(self) -> List[str]:
"""Get list of available template types."""
available = []
for template_type, template_rel in self.TEMPLATE_MAP.items():
template_path = self.template_dir / template_rel
if template_path.exists():
available.append(template_type)
return sorted(available)
def validate_template_type(self, template_type: str) -> bool:
"""Validate if a template type is valid."""
return template_type in self.TEMPLATE_MAP
def get_template_categories(self) -> Dict[str, List[str]]:
"""Get templates organized by category."""
categories: Dict[str, List[str]] = {
"language": [],
"framework": [],
"ide": [],
"os": [],
"tools": [],
}
category_map = {
"python": "language",
"javascript": "language",
"typescript": "language",
"java": "language",
"go": "language",
"rust": "language",
"dotnet": "language",
"php": "language",
"ruby": "language",
"django": "framework",
"flask": "framework",
"react": "framework",
"vue": "framework",
"angular": "framework",
"rails": "framework",
"laravel": "framework",
"spring": "framework",
"vscode": "ide",
"jetbrains": "ide",
"visualstudiocode": "ide",
"linux": "os",
"macos": "os",
"windows": "os",
"docker": "tools",
"gradle": "tools",
"maven": "tools",
"jupyter": "tools",
"terraform": "tools",
}
for template_type in self.TEMPLATE_MAP:
category = category_map.get(template_type, "other")
if category in categories:
categories[category].append(template_type)
return categories