From d693580a7df0d1fb6bceaf7ce578663c9633d200 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Tue, 28 Oct 2025 23:30:05 +0100 Subject: [PATCH] Support multiple languages in generate-yml CLI command --- src/serena/cli.py | 21 ++++++++++++--------- src/serena/config/serena_config.py | 11 ++++++----- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/serena/cli.py b/src/serena/cli.py index e0b64d85..fb78cd3d 100644 --- a/src/serena/cli.py +++ b/src/serena/cli.py @@ -416,19 +416,22 @@ class ProjectCommands(AutoRegisteringGroup): @staticmethod @click.command("generate-yml", help="Generate a project.yml file.") @click.argument("project_path", type=click.Path(exists=True, file_okay=False), default=os.getcwd()) - @click.option("--language", type=str, default=None, help="Programming language; inferred if not specified.") - def generate_yml(project_path: str, language: str | None = None) -> None: + @click.option( + "--language", type=str, multiple=True, help="Programming language(s); inferred if not specified. Can be passed multiple times." + ) + def generate_yml(project_path: str, language: tuple[str, ...]) -> None: yml_path = os.path.join(project_path, ProjectConfig.rel_path_to_project_yml()) if os.path.exists(yml_path): raise FileExistsError(f"Project file {yml_path} already exists.") - lang_inst = None + languages: list[Language] = [] if language: - try: - lang_inst = Language[language.upper()] - except KeyError: - all_langs = [l.name.lower() for l in Language.iter_all(include_experimental=True)] - raise ValueError(f"Unknown language '{language}'. Supported: {all_langs}") - generated_conf = ProjectConfig.autogenerate(project_root=project_path, project_language=lang_inst) + for lang in language: + try: + languages.append(Language(lang.lower())) + except ValueError: + all_langs = [l.value for l in Language] + raise ValueError(f"Unknown language '{lang}'. Supported: {all_langs}") + generated_conf = ProjectConfig.autogenerate(project_root=project_path, languages=languages if languages else None) print(f"Generated project.yml with languages {generated_conf.languages} at {yml_path}.") @staticmethod diff --git a/src/serena/config/serena_config.py b/src/serena/config/serena_config.py index 930a820b..2f17d058 100644 --- a/src/serena/config/serena_config.py +++ b/src/serena/config/serena_config.py @@ -176,7 +176,7 @@ class ProjectConfig(ToolInclusionDefinition, ToStringMixin): @classmethod def autogenerate( - cls, project_root: str | Path, project_name: str | None = None, project_language: Language | None = None, save_to_disk: bool = True + cls, project_root: str | Path, project_name: str | None = None, languages: list[Language] | None = None, save_to_disk: bool = True ) -> Self: """ Autogenerate a project configuration for a given project root. @@ -184,7 +184,7 @@ class ProjectConfig(ToolInclusionDefinition, ToStringMixin): :param project_root: the path to the project root :param project_name: the name of the project; if None, the name of the project will be the name of the directory containing the project - :param project_language: the programming language of the project; if None, it will be determined automatically + :param languages: the languages of the project; if None, they will be determined automatically :param save_to_disk: whether to save the project configuration to disk :return: the project configuration """ @@ -193,7 +193,7 @@ class ProjectConfig(ToolInclusionDefinition, ToStringMixin): raise FileNotFoundError(f"Project root not found: {project_root}") with LogTime("Project configuration auto-generation", logger=log): project_name = project_name or project_root.name - if project_language is None: + if languages is None: language_composition = determine_programming_language_composition(str(project_root)) if len(language_composition) == 0: raise ValueError( @@ -208,11 +208,12 @@ class ProjectConfig(ToolInclusionDefinition, ToStringMixin): ) # find the language with the highest percentage dominant_language = max(language_composition.keys(), key=lambda lang: language_composition[lang]) + languages_to_use = [dominant_language] else: - dominant_language = project_language.value + languages_to_use = [lang.value for lang in languages] config_with_comments = load_yaml(PROJECT_TEMPLATE_FILE, preserve_comments=True) config_with_comments["project_name"] = project_name - config_with_comments["languages"] = [dominant_language] + config_with_comments["languages"] = languages_to_use if save_to_disk: save_yaml(str(project_root / cls.rel_path_to_project_yml()), config_with_comments, preserve_comments=True) return cls._from_dict(config_with_comments)