diff --git a/project_scaffold_cli/prompts.py b/project_scaffold_cli/prompts.py new file mode 100644 index 0000000..17757aa --- /dev/null +++ b/project_scaffold_cli/prompts.py @@ -0,0 +1,164 @@ +"""Interactive prompts for Project Scaffold CLI.""" + +from typing import Optional, Tuple + +import click + +from .config import Config + + +class ProjectPrompts: + """Interactive prompt collection for project configuration.""" + + LICENSE_CHOICES = ["MIT", "Apache-2.0", "GPL-3.0", "BSD-3-Clause", "None"] + + LANGUAGE_CHOICES = ["python", "nodejs", "go", "rust"] + + CI_CHOICES = ["github", "gitlab", "none"] + + def __init__(self, config: Config): + self.config = config + + def collect_inputs( + self, + project_name: Optional[str], + language: Optional[str], + author: Optional[str], + email: Optional[str], + description: Optional[str], + license: Optional[str], + ci: Optional[str], + template: Optional[str], + ) -> Tuple[ + Optional[str], + Optional[str], + Optional[str], + Optional[str], + Optional[str], + Optional[str], + Optional[str], + Optional[str], + ]: + """Collect all project configuration inputs interactively.""" + project_name = self._prompt_project_name(project_name) + language = self._prompt_language(language) + author = self._prompt_author(author) + email = self._prompt_email(email) + description = self._prompt_description(description) + license = self._prompt_license(license) + ci = self._prompt_ci(ci) + + return (project_name, language, author, email, description, license, ci, template) + + def _prompt_project_name(self, default: Optional[str]) -> Optional[str]: + """Prompt for project name.""" + if default: + return default + + return click.prompt( + "Project name", + type=str, + default=default, + value_proc=lambda x: x.strip() if x else x, + ) + + def _prompt_language(self, default: Optional[str]) -> Optional[str]: + """Prompt for programming language.""" + if default: + return default + + return click.prompt( + "Project language", + type=click.Choice(self.LANGUAGE_CHOICES), + default=self.config.default_language or "python", + ) + + def _prompt_author(self, default: Optional[str]) -> Optional[str]: + """Prompt for author name.""" + if default: + return default + + if self.config.author: + use_default = click.confirm( + f"Use '{self.config.author}' as author?", default=True + ) + if use_default: + return self.config.author + + return click.prompt( + "Author name", + type=str, + default=self.config.author or "Your Name", + ) + + def _prompt_email(self, default: Optional[str]) -> Optional[str]: + """Prompt for author email.""" + if default: + return default + + if self.config.email: + use_default = click.confirm( + f"Use '{self.config.email}' as email?", default=True + ) + if use_default: + return self.config.email + + return click.prompt( + "Author email", + type=str, + default=self.config.email or "your.email@example.com", + ) + + def _prompt_description(self, default: Optional[str]) -> Optional[str]: + """Prompt for project description.""" + if default: + return default + + if self.config.description: + use_default = click.confirm( + f"Use '{self.config.description}' as description?", default=True + ) + if use_default: + return self.config.description + + return click.prompt( + "Project description", + type=str, + default=self.config.description or "A new project", + ) + + def _prompt_license(self, default: Optional[str]) -> Optional[str]: + """Prompt for license type.""" + if default: + return default + + if self.config.license: + use_default = click.confirm( + f"Use '{self.config.license}' as license?", default=True + ) + if use_default: + return self.config.license + + return click.prompt( + "License", + type=click.Choice(self.LICENSE_CHOICES), + default=self.config.license or "MIT", + ) + + def _prompt_ci(self, default: Optional[str]) -> Optional[str]: + """Prompt for CI/CD provider.""" + if default: + return default + + if self.config.default_ci: + use_default = click.confirm( + f"Use '{self.config.default_ci}' for CI/CD?", default=True + ) + if use_default: + return self.config.default_ci + + return click.prompt( + "CI/CD provider", + type=click.Choice(self.CI_CHOICES), + default=self.config.default_ci or "none", + )