| """ |
| Interactive template selector for conference presets. |
| |
| Provides a terminal UI for selecting a conference template |
| with information about requirements and rules. |
| """ |
| from typing import Optional |
|
|
| from rich.console import Console |
| from rich.panel import Panel |
| from rich.table import Table |
| from rich.prompt import Prompt |
| from rich.columns import Columns |
| from rich.text import Text |
|
|
| from ..templates.base_template import ( |
| ConferenceTemplate, |
| get_template, |
| get_all_templates, |
| ConferenceField |
| ) |
|
|
|
|
| class TemplateSelector: |
| """Interactive terminal selector for conference templates.""" |
| |
| def __init__(self): |
| self.console = Console() |
| self.templates = get_all_templates() |
| |
| def display_templates(self): |
| """Display all available templates grouped by field.""" |
| self.console.clear() |
| |
| |
| self.console.print(Panel( |
| "[bold blue]🎓 Conference Template Selector[/bold blue]\n" |
| "[dim]Choose a conference template for submission checks[/dim]", |
| border_style="blue" |
| )) |
| self.console.print() |
| |
| |
| fields = { |
| ConferenceField.NLP: ("🗣️ NLP Conferences", []), |
| ConferenceField.CV: ("👁️ Computer Vision Conferences", []), |
| ConferenceField.ML: ("🧠 Machine Learning Conferences", []), |
| } |
| |
| for template in self.templates.values(): |
| fields[template.field][1].append(template) |
| |
| |
| for field_enum, (title, templates) in fields.items(): |
| self.console.print(f"[bold cyan]{title}[/bold cyan]") |
| |
| table = Table(show_header=True, header_style="bold", box=None, padding=(0, 2)) |
| table.add_column("ID", style="yellow", width=10) |
| table.add_column("Conference", width=15) |
| table.add_column("Pages", width=12) |
| table.add_column("Key Requirements", style="dim") |
| |
| for template in templates: |
| pages = f"{template.page_limit_review}→{template.page_limit_camera}" |
| requirements = [] |
| if template.mandatory_sections: |
| requirements.append(f"Required: {', '.join(template.mandatory_sections)}") |
| if template.extra_rules: |
| first_rule = list(template.extra_rules.values())[0] |
| requirements.append(first_rule[:50]) |
| |
| table.add_row( |
| template.short_name, |
| template.name, |
| pages, |
| " | ".join(requirements) if requirements else "Standard format" |
| ) |
| |
| self.console.print(table) |
| self.console.print() |
| |
| def display_template_details(self, template: ConferenceTemplate): |
| """Display detailed information about a template.""" |
| self.console.print() |
| self.console.print(Panel( |
| f"[bold]{template.name}[/bold]", |
| border_style="cyan" |
| )) |
| |
| |
| info = Table(show_header=False, box=None, padding=(0, 2)) |
| info.add_column("Label", style="dim") |
| info.add_column("Value") |
| |
| info.add_row("Style Package", f"[cyan]{template.style_package}[/cyan]") |
| info.add_row("Page Limit (Review)", f"[yellow]{template.page_limit_review}[/yellow] pages") |
| info.add_row("Page Limit (Camera)", f"[green]{template.page_limit_camera}[/green] pages") |
| info.add_row("Double-Blind", "✓ Yes" if template.double_blind else "✗ No") |
| |
| if template.mandatory_sections: |
| info.add_row("Mandatory Sections", ", ".join(template.mandatory_sections)) |
| if template.optional_sections: |
| info.add_row("Optional Sections", ", ".join(template.optional_sections)) |
| |
| self.console.print(info) |
| |
| |
| if template.extra_rules: |
| self.console.print() |
| self.console.print("[bold]Special Requirements:[/bold]") |
| for key, value in template.extra_rules.items(): |
| self.console.print(f" • [dim]{key}:[/dim] {value}") |
| |
| self.console.print() |
| |
| def run(self) -> Optional[ConferenceTemplate]: |
| """Run the interactive selector and return the chosen template.""" |
| while True: |
| self.display_templates() |
| |
| |
| choice = Prompt.ask( |
| "[bold]Enter template ID (or 'q' to quit, 'd <id>' for details)[/bold]", |
| default="q" |
| ) |
| |
| if choice.lower() == 'q': |
| return None |
| |
| |
| if choice.lower().startswith('d '): |
| template_id = choice[2:].strip().lower() |
| template = get_template(template_id) |
| if template: |
| self.display_template_details(template) |
| Prompt.ask("Press Enter to continue") |
| else: |
| self.console.print(f"[red]Unknown template: {template_id}[/red]") |
| Prompt.ask("Press Enter to continue") |
| continue |
| |
| |
| template = get_template(choice) |
| if template: |
| self.console.print(f"[green]✓ Selected: {template.name}[/green]") |
| return template |
| else: |
| self.console.print(f"[red]Unknown template: {choice}[/red]") |
| self.console.print("[dim]Available: " + ", ".join(self.templates.keys()) + "[/dim]") |
| Prompt.ask("Press Enter to continue") |
|
|
|
|
| def launch_template_selector() -> Optional[ConferenceTemplate]: |
| """Launch the template selector and return the chosen template.""" |
| selector = TemplateSelector() |
| return selector.run() |
|
|
|
|
| def list_templates(console: Console = None): |
| """Print a simple list of available templates.""" |
| if console is None: |
| console = Console() |
| |
| console.print("\n[bold]Available Conference Templates:[/bold]\n") |
| |
| templates = get_all_templates() |
| |
| |
| by_field = {} |
| for t in templates.values(): |
| if t.field not in by_field: |
| by_field[t.field] = [] |
| by_field[t.field].append(t) |
| |
| field_names = { |
| ConferenceField.NLP: "NLP", |
| ConferenceField.CV: "Computer Vision", |
| ConferenceField.ML: "Machine Learning", |
| } |
| |
| for field, field_templates in by_field.items(): |
| console.print(f"[cyan]{field_names[field]}:[/cyan]") |
| for t in field_templates: |
| console.print(f" • [yellow]{t.short_name:8}[/yellow] - {t.name} ({t.page_limit_review}/{t.page_limit_camera} pages)") |
| |
| console.print() |
|
|