Add templates and MCP server modules
This commit is contained in:
346
src/contextgen/templates/engine.py
Normal file
346
src/contextgen/templates/engine.py
Normal file
@@ -0,0 +1,346 @@
|
||||
"""Template engine using Jinja2 for rendering."""
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from jinja2 import BaseLoader, Environment, FileSystemLoader, TemplateSyntaxError, UndefinedError
|
||||
|
||||
|
||||
class TemplateEngine:
|
||||
"""Jinja2-based template engine for rendering context output."""
|
||||
|
||||
BUILTIN_TEMPLATES = {
|
||||
"minimal": """# Project Context
|
||||
|
||||
## Overview
|
||||
{{ project.name }}
|
||||
|
||||
{{ project.description }}
|
||||
|
||||
## Tech Stack
|
||||
{% for lang, details in analysis.languages.items() %}
|
||||
- {{ lang }}: {{ details.file_count }} files
|
||||
{% endfor %}
|
||||
|
||||
## Key Files
|
||||
{% for file, desc in structure.key_files.items() %}
|
||||
- {{ file }}: {{ desc }}
|
||||
{% endfor %}
|
||||
""",
|
||||
"standard": """# Project Context
|
||||
|
||||
## Overview
|
||||
- **Project**: {{ project.name }}
|
||||
- **Description**: {{ project.description }}
|
||||
- **Primary Language**: {{ analysis.primary_language }}
|
||||
- **Generated**: {{ timestamp }}
|
||||
|
||||
## Tech Stack
|
||||
|
||||
### Languages
|
||||
{% for lang, details in analysis.languages.items() %}
|
||||
- **{{ lang }}**: {{ details.file_count }} files
|
||||
{% endfor %}
|
||||
|
||||
### Frameworks
|
||||
{% if analysis.frameworks %}
|
||||
{% for fw in analysis.frameworks %}
|
||||
- {{ fw.name }} (confidence: {{ (fw.confidence * 100)|round(1) }}%)
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
- No frameworks detected
|
||||
{% endif %}
|
||||
|
||||
### Build Tools
|
||||
{% if analysis.build_tools %}
|
||||
{% for tool in analysis.build_tools %}
|
||||
- {{ tool.name }} (confidence: {{ (tool.confidence * 100)|round(1) }}%)
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
- No build tools detected
|
||||
{% endif %}
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Key Files
|
||||
{% for file, desc in structure.key_files.items() %}
|
||||
- `{{ file }}`: {{ desc }}
|
||||
{% endfor %}
|
||||
|
||||
### Directory Tree
|
||||
```
|
||||
{% for dir, contents in structure.file_tree.directories.items() %}
|
||||
{{ dir }}
|
||||
{% for subdir, subcontents in contents.directories.items() %}
|
||||
{{ subdir }}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
## Coding Conventions
|
||||
|
||||
### Naming Style
|
||||
- **Functions**: {{ conventions.naming.functions.dominant }}
|
||||
- **Classes**: {{ conventions.naming.classes.dominant }}
|
||||
- **Variables**: {{ conventions.naming.variables.dominant }}
|
||||
- **Files**: {{ conventions.naming.files.pattern }}
|
||||
|
||||
### Code Style
|
||||
- **Indentation**: {{ conventions.style.indentation.style }} ({{ conventions.style.indentation.width }} spaces)
|
||||
- **Quote Style**: {{ conventions.style.quote_style.style }}
|
||||
- **Line Endings**: {{ conventions.style.line_endings.style }}
|
||||
|
||||
### Documentation
|
||||
- **Style**: {{ conventions.documentation.style }}
|
||||
- **Coverage**: {{ (conventions.documentation.documentation_coverage.ratio * 100)|round(1) }}%
|
||||
|
||||
## Setup Instructions
|
||||
|
||||
{% if setup.install_commands %}
|
||||
### Installation
|
||||
{% for cmd in setup.install_commands %}
|
||||
```
|
||||
{{ cmd }}
|
||||
```
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if setup.run_commands %}
|
||||
### Running
|
||||
{% for cmd in setup.run_commands %}
|
||||
```
|
||||
{{ cmd }}
|
||||
```
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if setup.test_commands %}
|
||||
### Testing
|
||||
{% for cmd in setup.test_commands %}
|
||||
```
|
||||
{{ cmd }}
|
||||
```
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if setup.environment_variables %}
|
||||
### Environment Variables
|
||||
{% for var in setup.environment_variables %}
|
||||
- `{{ var }}`
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
""",
|
||||
"comprehensive": """# Project Context - Comprehensive Analysis
|
||||
|
||||
## Metadata
|
||||
- **Project Name**: {{ project.name }}
|
||||
- **Description**: {{ project.description }}
|
||||
- **Primary Language**: {{ analysis.primary_language }}
|
||||
- **Total Files**: {{ structure.total_files }}
|
||||
- **Total Directories**: {{ structure.total_dirs }}
|
||||
- **Generated**: {{ timestamp }}
|
||||
|
||||
---
|
||||
|
||||
## 1. Technology Stack
|
||||
|
||||
### 1.1 Languages Detected
|
||||
| Language | Files | Extensions |
|
||||
|----------|-------|------------|
|
||||
{% for lang, details in analysis.languages.items() %}
|
||||
| {{ lang }} | {{ details.file_count }} | {{ details.extensions|join(', ') }} |
|
||||
{% endfor %}
|
||||
|
||||
### 1.2 Frameworks & Libraries
|
||||
{% if analysis.frameworks %}
|
||||
| Framework | Confidence | Indicators |
|
||||
|-----------|------------|------------|
|
||||
{% for fw in analysis.frameworks %}
|
||||
| {{ fw.name }} | {{ (fw.confidence * 100)|round(1) }}% | {{ fw.indicators_found }} |
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
No frameworks detected.
|
||||
{% endif %}
|
||||
|
||||
### 1.3 Build Tools
|
||||
{% if analysis.build_tools %}
|
||||
| Tool | Confidence |
|
||||
|------|------------|
|
||||
{% for tool in analysis.build_tools %}
|
||||
| {{ tool.name }} | {{ (tool.confidence * 100)|round(1) }}% |
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
No build tools detected.
|
||||
{% endif %}
|
||||
|
||||
### 1.4 Full Stack
|
||||
{% if analysis.full_stack %}
|
||||
- **Frontend**: {{ analysis.full_stack.frontend or 'Not detected' }}
|
||||
- **Backend**: {{ analysis.full_stack.backend or 'Not detected' }}
|
||||
{% else %}
|
||||
No clear full stack detected.
|
||||
{% endif %}
|
||||
|
||||
---
|
||||
|
||||
## 2. Project Structure
|
||||
|
||||
### 2.1 Key Files
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
{% for file, desc in structure.key_files.items() %}
|
||||
| `{{ file }}` | {{ desc }} |
|
||||
{% endfor %}
|
||||
|
||||
### 2.2 File Statistics
|
||||
- **Total Files**: {{ structure.total_files }}
|
||||
- **Total Directories**: {{ structure.total_dirs }}
|
||||
|
||||
### 2.3 Directory Tree
|
||||
```
|
||||
{{ project.path }}
|
||||
{% for dir, contents in structure.file_tree.directories.items() %}
|
||||
├── {{ dir }}
|
||||
{% for subdir, subcontents in contents.directories.items() %}
|
||||
│ ├── {{ subdir }}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Coding Conventions
|
||||
|
||||
### 3.1 Naming Conventions
|
||||
| Type | Dominant Style | Examples |
|
||||
|------|----------------|----------|
|
||||
| Functions | {{ conventions.naming.functions.dominant }} | {{ conventions.naming.functions.examples[:3]|join(', ') }} |
|
||||
| Classes | {{ conventions.naming.classes.dominant }} | {{ conventions.naming.classes.examples[:3]|join(', ') }} |
|
||||
| Variables | {{ conventions.naming.variables.dominant }} | {{ conventions.naming.variables.examples[:3]|join(', ') }} |
|
||||
| Constants | {{ conventions.naming.constants.dominant }} | {{ conventions.naming.constants.examples[:3]|join(', ') }} |
|
||||
| Files | {{ conventions.naming.files.pattern }} | {{ conventions.naming.files.examples[:3]|join(', ') }} |
|
||||
|
||||
### 3.2 Code Style
|
||||
| Aspect | Value |
|
||||
|--------|-------|
|
||||
| Indentation | {{ conventions.style.indentation.style }} ({{ conventions.style.indentation.width }} spaces) |
|
||||
| Quote Style | {{ conventions.style.quote_style.style }} |
|
||||
| Line Endings | {{ conventions.style.line_endings.style }} |
|
||||
| Max Line Length | {{ conventions.style.max_line_length.max }} characters |
|
||||
| Trailing Newline | {{ 'Yes' if conventions.style.trailing_newline.has_trailing_newline else 'No' }} |
|
||||
|
||||
### 3.3 Documentation
|
||||
| Aspect | Value |
|
||||
|--------|-------|
|
||||
| Docstring Style | {{ conventions.documentation.style }} |
|
||||
| Coverage | {{ (conventions.documentation.documentation_coverage.ratio * 100)|round(1) }}% |
|
||||
| Comment Style | {{ conventions.documentation.comment_style.dominant }} |
|
||||
|
||||
---
|
||||
|
||||
## 4. Setup Instructions
|
||||
|
||||
### 4.1 Installation
|
||||
{% for cmd in setup.install_commands %}
|
||||
```bash
|
||||
{{ cmd }}
|
||||
```
|
||||
{% endfor %}
|
||||
|
||||
### 4.2 Build
|
||||
{% for cmd in setup.build_commands %}
|
||||
```bash
|
||||
{{ cmd }}
|
||||
```
|
||||
{% endfor %}
|
||||
|
||||
### 4.3 Running
|
||||
{% for cmd in setup.run_commands %}
|
||||
```bash
|
||||
{{ cmd }}
|
||||
```
|
||||
{% endfor %}
|
||||
|
||||
### 4.4 Testing
|
||||
{% for cmd in setup.test_commands %}
|
||||
```bash
|
||||
{{ cmd }}
|
||||
```
|
||||
{% endfor %}
|
||||
|
||||
### 4.5 Environment Variables
|
||||
{% for var in setup.environment_variables %}
|
||||
- `{{ var }}`
|
||||
{% endfor %}
|
||||
|
||||
### 4.6 Notes
|
||||
{% for note in setup.notes %}
|
||||
- {{ note }}
|
||||
{% endfor %}
|
||||
|
||||
---
|
||||
|
||||
## 5. AI Assistant Tips
|
||||
|
||||
When working with this codebase:
|
||||
|
||||
1. **Naming**: The project uses {{ conventions.naming.dominant_style }} naming conventions.
|
||||
2. **Documentation**: Docstrings follow {{ conventions.documentation.style }} style.
|
||||
3. **Setup**: Run `{{ setup.install_commands[0] if setup.install_commands else 'appropriate install command' }}` to get started.
|
||||
4. **Language**: Primary language is {{ analysis.primary_language }}.
|
||||
|
||||
---
|
||||
|
||||
*Generated by Project Context Generator*
|
||||
""",
|
||||
}
|
||||
|
||||
def __init__(self, template_path: Path | None = None):
|
||||
self.template_path = template_path
|
||||
self.env = self._create_environment()
|
||||
|
||||
def _create_environment(self) -> Environment:
|
||||
"""Create Jinja2 environment."""
|
||||
if self.template_path and self.template_path.exists():
|
||||
loader: BaseLoader = FileSystemLoader(str(self.template_path))
|
||||
else:
|
||||
loader = DummyLoader(self.BUILTIN_TEMPLATES)
|
||||
|
||||
return Environment(
|
||||
loader=loader,
|
||||
trim_blocks=True,
|
||||
lstrip_blocks=True,
|
||||
)
|
||||
|
||||
def render(
|
||||
self, template_name: str, context: dict[str, Any]
|
||||
) -> str:
|
||||
"""Render a template with the given context."""
|
||||
try:
|
||||
template = self.env.get_template(template_name)
|
||||
return template.render(**context)
|
||||
except (TemplateSyntaxError, UndefinedError) as e:
|
||||
raise ValueError(f"Template error: {e}")
|
||||
|
||||
def get_available_templates(self) -> list[str]:
|
||||
"""Get list of available templates."""
|
||||
return list(self.BUILTIN_TEMPLATES.keys())
|
||||
|
||||
def list_templates(self) -> list[str]:
|
||||
"""List all available template names."""
|
||||
return self.get_available_templates()
|
||||
|
||||
|
||||
class DummyLoader(BaseLoader):
|
||||
"""Dummy loader for builtin templates."""
|
||||
|
||||
def __init__(self, templates: dict[str, str]):
|
||||
self.templates = templates
|
||||
|
||||
def get_source(self, environment: Environment, template: str) -> tuple[str, str, None]:
|
||||
if template in self.templates:
|
||||
return self.templates[template], template, None
|
||||
raise FileNotFoundError(f"Template {template} not found")
|
||||
|
||||
def list_templates(self) -> list[str]:
|
||||
return list(self.templates.keys())
|
||||
Reference in New Issue
Block a user