From 336350745a777fea24a569f7b84c0947b2bab709 Mon Sep 17 00:00:00 2001 From: Ian Thomas Date: Mon, 2 Mar 2026 14:50:44 +0000 Subject: [PATCH 1/2] Generate sphinx docs from help pages --- .github/workflows/test.yml | 38 +++++++++++++++++ .gitignore | 3 ++ .readthedocs.yaml | 19 +++++++++ README.md | 19 +++++++++ docs/Makefile | 18 ++++++++ docs/conf.py | 20 +++++++++ docs/create_markdown.py | 85 ++++++++++++++++++++++++++++++++++++++ docs/index.md | 17 ++++++++ 8 files changed, 219 insertions(+) create mode 100644 .readthedocs.yaml create mode 100644 docs/Makefile create mode 100644 docs/conf.py create mode 100644 docs/create_markdown.py create mode 100644 docs/index.md diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 78072f4..0edea56 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -98,3 +98,41 @@ jobs: files: coverage.lcov token: ${{ secrets.CODECOV_TOKEN }} verbose: true + + docs: + name: 'Build docs' + runs-on: ubuntu-latest + steps: + - name: Checkout source + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Create micromamba environment + uses: mamba-org/setup-micromamba@main + with: + environment-file: dev-environment.yml + cache-environment: true + + - name: Configure CMake + run: | + cmake -Bbuild -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX + + - name: Build with CMake + working-directory: build + run: cmake --build . --parallel 8 + + - name: Install docs dependencies + run: | + python -m pip install myst-parser sphinx sphinx-book-theme + + - name: Build docs + working-directory: docs + run: | + make html + + - name: Upload built docs + uses: actions/upload-artifact@v6 + with: + name: git2cpp-docs + path: docs/_build/html diff --git a/.gitignore b/.gitignore index 1061b39..8a84302 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ __pycache__/ compile_commands.json serve.log test/test-results/ + +docs/_build/ +docs/created/ diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..d1c84f1 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,19 @@ +version: 2 + +build: + os: ubuntu-24.04 + tools: + python: mambaforge-23.11 + jobs: + post_install: + - cmake -Bbuild -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX + - cd build && make + - pip install myst-parser sphinx sphinx-book-theme + +conda: + environment: dev-environment.yml + +sphinx: + builder: html + configuration: docs/conf.py + fail_on_warning: true diff --git a/README.md b/README.md index b9cc19f..2f8d445 100644 --- a/README.md +++ b/README.md @@ -38,3 +38,22 @@ See the `README.md` in the `wasm` directory for further details. The latest `cockle` and JupyterLite `terminal` deployments using `git2cpp` are available at [https://quantstack.net/git2cpp](https://quantstack.net/git2cpp) + +# Documentation + +The project documentation is generated from the `git2cpp` help pages. To build the documentation +locally first build `git2cpp` as usual as described above, then install the documentation +dependencies: + +```bash +micromamba install myst-parser sphinx sphinx-book-theme +``` + +and build the documentation: + +```bash +cd docs +make html +``` + +The top-level documentation page will be `docs/_build/html/index.html` diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..cadcd23 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,18 @@ +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + python create_markdown.py + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..3bf0cde --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,20 @@ +from datetime import date + +project = "git2cpp" +author = "QuantStack" +copyright = f"2025-{date.today().year}" + +extensions = [ + "myst_parser", +] + +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + +html_static_path = [] +html_theme = "sphinx_book_theme" +html_theme_options = { + "github_url": "https://github.com/QuantStack/git2cpp", + "home_page_in_toc": True, + "show_navbar_depth": 2, +} +html_title = "git2cpp documentation" diff --git a/docs/create_markdown.py b/docs/create_markdown.py new file mode 100644 index 0000000..7cb59fe --- /dev/null +++ b/docs/create_markdown.py @@ -0,0 +1,85 @@ +import os +from pathlib import Path +import re +import subprocess + + +def get_filename(args): + directory = Path("created").joinpath(*args[:-1]) + filename = args[-1] + ".md" + return directory / filename + + +def sanitise_line(line): + # Remove trailing whitespace otherwise the markdown parser can insert an extra \n + line = line.rstrip() + + # Replace angular brackets with HTML equivalents. + line = line.replace(r"&", r"&") + line = line.replace(r"<", r"<") + line = line.replace(r">", r">") + + # If there are whitespace characters at the start of the line, replace the first with an   + # so that it is not discarded by the markdown parser used by the parsed-literal directive. + line = re.sub(r"^\s", r" ", line) + + return line + + +# Process a single subcommand, adding new subcommands found to to_process. +def process(args, to_process): + cmd = args + ["--help"] + cmd_string = " ".join(cmd) + filename = get_filename(args) + filename.parent.mkdir(parents=True, exist_ok=True) + + print(f"Writing '{cmd_string}' to file {filename}") + p = subprocess.run(cmd, capture_output=True, text=True, check=True) + + # Write output markdown file, identifying subcommands at the same time to provide + # links to the subcommand markdown files. + subcommands = [] + with open(filename, "w") as f: + f.write(f"({filename})=\n") # Target for links. + f.write(f"# {' '.join(args)}\n") + f.write("\n") + f.write("```{parsed-literal}\n") + + in_subcommand_section = False + for line in p.stdout.splitlines(): + if in_subcommand_section: + match = re.match(r"^( )([\w\-_]+)(\s+.*)$", line) + if match: + subcommand = match.group(2) + subcommand_filename = get_filename(args + [subcommand]) + line = match.group(1) + f"[{subcommand}]({subcommand_filename})" + match.group(3) + subcommands.append(subcommand) + elif line.startswith("SUBCOMMANDS:"): + in_subcommand_section = True + + f.write(sanitise_line(line) + "\n") + f.write("```\n") + + subcommands.sort() + to_process.extend(args + [subcommand] for subcommand in subcommands) + + if len(subcommands) > 0: + # Hidden table of contents for subcommands of this command/subcommand. + f.write("\n") + f.write("```{toctree}\n") + f.write(":hidden:\n") + for subcommand in subcommands: + f.write(f"{args[-1]}/{subcommand}\n") + f.write("```\n") + + +if __name__ == "__main__": + # Modify the PATH so that git2cpp is found by name, as using a full path will cause the help + # pages to write that full path. + git2cpp_dir = Path(__file__).parent.parent / 'build' + os.environ["PATH"] = f'{git2cpp_dir}{os.pathsep}{os.environ["PATH"]}' + + to_process = [["git2cpp"]] + while len(to_process) > 0: + subcommand = to_process.pop(0) + process(subcommand, to_process) diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..462e7d4 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,17 @@ +# Overview + +`git2cpp` is a C++ wrapper of [libgit2](https://libgit2.org/) to provide a command-line interface +(CLI) to `git` functionality. The intended use is in WebAssembly in-browser terminals (the +[cockle](https://github.com/jupyterlite/cockle) and +[JupyterLite terminal](https://github.com/jupyterlite/terminal) projects) but it can be compiled and +used on any POSIX-compliant system. + +The Help pages here are generated from the `git2cpp` command and subcommands to show the +functionality that is currently supported. If there are features missing that you would like to use, +please create an issue in the [git2cpp github repository](https://github.com/QuantStack/git2cpp). + +```{toctree} +:caption: Help pages +:hidden: +created/git2cpp +``` From 47034e045b2a386a037a4762b9b88c93f3eb558b Mon Sep 17 00:00:00 2001 From: Ian Thomas Date: Mon, 2 Mar 2026 16:14:30 +0000 Subject: [PATCH 2/2] Fix prebuild steps in .readthedocs.yaml --- .readthedocs.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index d1c84f1..e1768e1 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -8,7 +8,9 @@ build: post_install: - cmake -Bbuild -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX - cd build && make - - pip install myst-parser sphinx sphinx-book-theme + - python -m pip install myst-parser sphinx sphinx-book-theme + pre_build: + - cd docs && python create_markdown.py conda: environment: dev-environment.yml