diff --git a/python/sphinx_rust/config.py b/python/sphinx_rust/config.py index 03d8ec4..14636d9 100644 --- a/python/sphinx_rust/config.py +++ b/python/sphinx_rust/config.py @@ -14,6 +14,12 @@ class RustConfig: rust_crates: list[str] rust_doc_formats: dict[str, str] rust_viewcode: bool + rust_root_pages: str + """pages auto generation path, default api/crates, relative to source""" + rust_enable_auto_pages: bool + """if create auto pages, default True""" + rust_keep_files: bool + """if keep files at the end, if False delete all auto generated files""" @classmethod def from_app(cls, app: Sphinx) -> RustConfig: @@ -22,6 +28,9 @@ def from_app(cls, app: Sphinx) -> RustConfig: rust_crates=app.config.rust_crates, rust_doc_formats=app.config.rust_doc_formats, rust_viewcode=app.config.rust_viewcode, + rust_root_pages=app.config.rust_root_pages, + rust_enable_auto_pages=app.config.rust_enable_auto_pages, + rust_keep_files=app.config.rust_keep_files, ) @staticmethod @@ -30,3 +39,6 @@ def add_configs(app: Sphinx) -> None: app.add_config_value("rust_crates", [], "env") app.add_config_value("rust_doc_formats", {}, "env") app.add_config_value("rust_viewcode", True, "env") + app.add_config_value("rust_root_pages", "api/crates", "env") + app.add_config_value("rust_enable_auto_pages", True, "env") + app.add_config_value("rust_keep_files", True, "env") diff --git a/python/sphinx_rust/domain.py b/python/sphinx_rust/domain.py index 79dbb39..d9f685b 100644 --- a/python/sphinx_rust/domain.py +++ b/python/sphinx_rust/domain.py @@ -4,7 +4,7 @@ import os from pathlib import Path import shutil -from typing import TYPE_CHECKING, Literal, TypedDict +from typing import TYPE_CHECKING, Literal, TypedDict, Union from sphinx import addnodes from sphinx.domains import Domain @@ -82,6 +82,7 @@ class RustDomain(Domain): def app_setup(cls, app: Sphinx) -> None: RustConfig.add_configs(app) app.connect("builder-inited", cls.on_builder_inited) + app.connect("build-finished", cls.on_build_finished) app.add_domain(cls) @staticmethod @@ -105,9 +106,37 @@ def on_builder_inited(app: Sphinx) -> None: f"Error analyzing crate: {e!s}", type="rust", subtype="analyze" ) return - create_pages(srcdir, result) + + if config.rust_enable_auto_pages: + create_pages(srcdir / config.rust_root_pages, result) + if config.rust_viewcode: - create_code_pages(result.crate_, srcdir, cache) + create_code_pages(result.crate_, srcdir / config.rust_root_pages, cache) + + @staticmethod + def on_build_finished(app: Sphinx, exception: Union[Exception, None]) -> None: + # if an exception occure, don't delete files + if exception is not None: + return + + config = RustConfig.from_app(app) + + if config.rust_keep_files: + return + + srcdir = Path(str(app.srcdir)) + for crate in config.rust_crates: + cache_path = app.env.rust_cache_path + path = srcdir / str(crate) + # FIXME do not parse again + try: + result = analyze_crate(str(path), str(cache_path)) + except OSError: + continue + + shutil.rmtree( + srcdir / config.rust_root_pages / result.crate_, ignore_errors=True + ) @property def objects(self) -> dict[str, ObjectEntry]: @@ -192,7 +221,7 @@ def get_objects(self) -> list[tuple[str, str, str, str, str, int]]: def create_pages(srcdir: Path, result: AnalysisResult) -> None: """Create the pages for the analyzed crate.""" - root = srcdir.joinpath("api", "crates", result.crate_) + root = srcdir.joinpath(result.crate_) if root.exists(): # TODO only update changed files (so that sphinx knows what to rebuild) shutil.rmtree(root) @@ -244,7 +273,7 @@ def create_code_pages(crate_name: str, srcdir: Path, cache: Path) -> None: for m in load_descendant_modules(str(cache), [crate_name], True) if m.file ]: - code_folder = srcdir.joinpath("api", "crates", crate_name, "code") + code_folder = srcdir.joinpath(crate_name, "code") code_folder.mkdir(exist_ok=True, parents=True) for full_name, file_path in modules: # TODO catch exceptions here, if a relative path cannot be created