Initial commit
This commit is contained in:
161
scripts/map_components.py
Normal file
161
scripts/map_components.py
Normal file
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Component mapper for Bubble Tea TUIs.
|
||||
Maps requirements to appropriate components.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
|
||||
from utils.component_matcher import (
|
||||
match_score,
|
||||
find_best_match,
|
||||
get_alternatives,
|
||||
explain_match,
|
||||
rank_components_by_relevance
|
||||
)
|
||||
from utils.validators import DesignValidator
|
||||
|
||||
|
||||
def map_to_components(requirements: Dict, inventory=None) -> Dict:
|
||||
"""
|
||||
Map requirements to Bubble Tea components.
|
||||
|
||||
Args:
|
||||
requirements: Structured requirements from analyze_requirements
|
||||
inventory: Optional inventory object (unused for now)
|
||||
|
||||
Returns:
|
||||
Dictionary with component recommendations
|
||||
|
||||
Example:
|
||||
>>> components = map_to_components(reqs)
|
||||
>>> components['primary_components'][0]['component']
|
||||
'viewport.Model'
|
||||
"""
|
||||
features = requirements.get('features', [])
|
||||
archetype = requirements.get('archetype', 'general')
|
||||
data_types = requirements.get('data_types', [])
|
||||
views = requirements.get('views', 'single')
|
||||
|
||||
# Get ranked components
|
||||
ranked = rank_components_by_relevance(features, min_score=50)
|
||||
|
||||
# Build primary components list
|
||||
primary_components = []
|
||||
for component, score, matching_features in ranked[:5]: # Top 5
|
||||
justification = explain_match(component, ' '.join(matching_features), score)
|
||||
|
||||
primary_components.append({
|
||||
'component': f'{component}.Model',
|
||||
'score': score,
|
||||
'justification': justification,
|
||||
'example_file': f'examples/{component}/main.go',
|
||||
'key_patterns': [f'{component} usage', 'initialization', 'message handling']
|
||||
})
|
||||
|
||||
# Add archetype-specific components
|
||||
archetype_components = _get_archetype_components(archetype)
|
||||
for comp in archetype_components:
|
||||
if not any(c['component'].startswith(comp) for c in primary_components):
|
||||
primary_components.append({
|
||||
'component': f'{comp}.Model',
|
||||
'score': 70,
|
||||
'justification': f'Standard component for {archetype} TUIs',
|
||||
'example_file': f'examples/{comp}/main.go',
|
||||
'key_patterns': [f'{comp} patterns']
|
||||
})
|
||||
|
||||
# Supporting components
|
||||
supporting = _get_supporting_components(features, views)
|
||||
|
||||
# Styling
|
||||
styling = ['lipgloss for layout and styling']
|
||||
if 'highlighting' in features:
|
||||
styling.append('lipgloss for text highlighting')
|
||||
|
||||
# Alternatives
|
||||
alternatives = {}
|
||||
for comp in primary_components[:3]:
|
||||
comp_name = comp['component'].replace('.Model', '')
|
||||
alts = get_alternatives(comp_name)
|
||||
if alts:
|
||||
alternatives[comp['component']] = [f'{alt}.Model' for alt in alts]
|
||||
|
||||
result = {
|
||||
'primary_components': primary_components,
|
||||
'supporting_components': supporting,
|
||||
'styling': styling,
|
||||
'alternatives': alternatives
|
||||
}
|
||||
|
||||
# Validate
|
||||
validator = DesignValidator()
|
||||
validation = validator.validate_component_selection(result, requirements)
|
||||
|
||||
result['validation'] = validation.to_dict()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _get_archetype_components(archetype: str) -> List[str]:
|
||||
"""Get standard components for archetype."""
|
||||
archetype_map = {
|
||||
'file-manager': ['filepicker', 'viewport', 'list'],
|
||||
'installer': ['progress', 'spinner', 'list'],
|
||||
'dashboard': ['tabs', 'viewport', 'table'],
|
||||
'form': ['textinput', 'textarea', 'help'],
|
||||
'viewer': ['viewport', 'paginator', 'textinput'],
|
||||
'chat': ['viewport', 'textarea', 'textinput'],
|
||||
'table-viewer': ['table', 'paginator'],
|
||||
'menu': ['list'],
|
||||
'editor': ['textarea', 'viewport']
|
||||
}
|
||||
return archetype_map.get(archetype, [])
|
||||
|
||||
|
||||
def _get_supporting_components(features: List[str], views: str) -> List[str]:
|
||||
"""Get supporting components based on features."""
|
||||
supporting = []
|
||||
|
||||
if views in ['multi', 'three-pane']:
|
||||
supporting.append('Multiple viewports for multi-pane layout')
|
||||
|
||||
if 'help' not in features:
|
||||
supporting.append('help.Model for keyboard shortcuts')
|
||||
|
||||
if views == 'multi':
|
||||
supporting.append('tabs.Model or state machine for view switching')
|
||||
|
||||
return supporting
|
||||
|
||||
|
||||
def main():
|
||||
"""Test component mapper."""
|
||||
print("Testing Component Mapper\n" + "=" * 50)
|
||||
|
||||
# Mock requirements
|
||||
requirements = {
|
||||
'archetype': 'viewer',
|
||||
'features': ['display', 'search', 'scrolling'],
|
||||
'data_types': ['text'],
|
||||
'views': 'single'
|
||||
}
|
||||
|
||||
print("\n1. Testing map_to_components()...")
|
||||
components = map_to_components(requirements)
|
||||
|
||||
print(f" Primary components: {len(components['primary_components'])}")
|
||||
for comp in components['primary_components'][:3]:
|
||||
print(f" - {comp['component']} (score: {comp['score']})")
|
||||
|
||||
print(f"\n Validation: {components['validation']['summary']}")
|
||||
|
||||
print("\n✅ Tests passed!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user