diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 55fb375c5..7444a30c5 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -53,6 +53,10 @@ jobs: if: env.PUBLISH == 'true' run: uv sync --all-extras --dev + - name: Install just + if: env.PUBLISH == 'true' + uses: extractions/setup-just@v2 + - name: Print python versions if: env.PUBLISH == 'true' run: | @@ -62,7 +66,7 @@ jobs: - name: Build documentation if: env.PUBLISH == 'true' run: | - pushd docs; make SPHINXBUILD='uv run sphinx-build' html; popd + cd docs && just html - name: Configure AWS Credentials if: env.PUBLISH == 'true' diff --git a/AGENTS.md b/AGENTS.md index d076e88d1..43d09e9dc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -49,7 +49,7 @@ uv pip install --editable . -G dev ```bash # Run all tests -make test +just test # or directly with pytest uv run pytest @@ -60,7 +60,7 @@ uv run pytest tests/test_pane.py uv run pytest tests/test_pane.py::test_send_keys # Run tests with test watcher -make start +just start # or uv run ptw . @@ -72,12 +72,12 @@ uv run ptw . --now --doctest-modules ```bash # Run ruff for linting -make ruff +just ruff # or directly uv run ruff check . # Format code with ruff -make ruff_format +just ruff-format # or directly uv run ruff format . @@ -85,13 +85,13 @@ uv run ruff format . uv run ruff check . --fix --show-fixes # Run mypy for type checking -make mypy +just mypy # or directly uv run mypy src tests # Watch mode for linting (using entr) -make watch_ruff -make watch_mypy +just watch-ruff +just watch-mypy ``` ### Development Workflow @@ -108,13 +108,13 @@ Follow this workflow for code changes: ```bash # Build documentation -make build_docs +just build-docs # Start documentation server with auto-reload -make start_docs +just start-docs # Update documentation CSS/JS -make design_docs +just design-docs ``` ## Code Architecture diff --git a/CHANGES b/CHANGES index fb4c76516..87946c267 100644 --- a/CHANGES +++ b/CHANGES @@ -32,6 +32,13 @@ $ uvx --from 'libtmux' --prerelease allow python +### Development + +#### Makefile -> Justfile (#617) + +- Migrate from `Makefile` to `justfile` for running development tasks +- Update documentation to reference `just` commands + ### Documentation Move documentation deployment to GitHub OIDC and AWS CLI. diff --git a/Makefile b/Makefile deleted file mode 100644 index d786f7e7b..000000000 --- a/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -PY_FILES= find . -type f -not -path '*/\.*' | grep -i '.*[.]py$$' 2> /dev/null -DOC_FILES= find . -type f -not -path '*/\.*' | grep -i '.*[.]rst\$\|.*[.]md\$\|.*[.]css\$\|.*[.]py\$\|mkdocs\.yml\|CHANGES\|TODO\|.*conf\.py' 2> /dev/null -ALL_FILES= find . -type f -not -path '*/\.*' | grep -i '.*[.]py\$\|.*[.]rst\$\|.*[.]md\$\|.*[.]css\$\|.*[.]py\$\|mkdocs\.yml\|CHANGES\|TODO\|.*conf\.py' 2> /dev/null - - -entr_warn: - @echo "----------------------------------------------------------" - @echo " ! File watching functionality non-operational ! " - @echo " " - @echo "Install entr(1) to automatically run tasks on file change." - @echo "See https://eradman.com/entrproject/ " - @echo "----------------------------------------------------------" - -test: - uv run py.test $(test) - -start: - $(MAKE) test; uv run ptw . - -watch_test: - if command -v entr > /dev/null; then ${ALL_FILES} | entr -c $(MAKE) test; else $(MAKE) test entr_warn; fi - -build_docs: - $(MAKE) -C docs html - -start_docs: - $(MAKE) -C docs design - -design_docs: - $(MAKE) -C docs design - -watch_docs: - if command -v entr > /dev/null; then ${DOC_FILES} | entr -c $(MAKE) build_docs; else $(MAKE) build_docs entr_warn; fi - -serve_docs: - $(MAKE) -C docs serve - -dev_docs: - $(MAKE) -j watch_docs serve_docs - -ruff_format: - uv run ruff format . - -ruff: - uv run ruff check . - -watch_ruff: - if command -v entr > /dev/null; then ${PY_FILES} | entr -c $(MAKE) ruff; else $(MAKE) ruff entr_warn; fi - -mypy: - uv run mypy `${PY_FILES}` - -watch_mypy: - if command -v entr > /dev/null; then ${PY_FILES} | entr -c $(MAKE) mypy; else $(MAKE) mypy entr_warn; fi - -format_markdown: - prettier --parser=markdown -w *.md docs/*.md docs/**/*.md CHANGES - -monkeytype_create: - uv run monkeytype run `uv run which py.test` - -monkeytype_apply: - uv run monkeytype list-modules | xargs -n1 -I{} sh -c 'uv run monkeytype apply {}' diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index 8501c103e..000000000 --- a/docs/Makefile +++ /dev/null @@ -1,188 +0,0 @@ -# Makefile for Sphinx documentation -SHELL := /bin/bash -HTTP_PORT = 8023 -WATCH_FILES= find .. -type f -not -path '*/\.*' | grep -i '.*[.]\(rst\|md\)\$\|.*[.]py\$\|CHANGES\|TODO\|.*conf\.py' 2> /dev/null - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = uv run sphinx-build -PAPER = -BUILDDIR = _build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/libtmux.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/libtmux.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/libtmux" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/libtmux" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -redirects: - $(SPHINXBUILD) -b rediraffewritediff $(ALLSPHINXOPTS) $(BUILDDIR)/redirects - @echo - @echo "Build finished. The redirects are in rediraffe_redirects." - -checkbuild: - rm -rf $(BUILDDIR) - $(SPHINXBUILD) -n -q ./ $(BUILDDIR) - -watch: - if command -v entr > /dev/null; then ${WATCH_FILES} | entr -c $(MAKE) html; else $(MAKE) html; fi - -serve: - @echo '==============================================================' - @echo - @echo 'docs server running at http://localhost:${HTTP_PORT}/' - @echo - @echo '==============================================================' - @$(MAKE) serve_py3 - -serve_py3: - python -m http.server ${HTTP_PORT} --directory _build/html - -dev: - $(MAKE) -j watch serve - -start: - uv run sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) --port ${HTTP_PORT} $(O) - -design: - # This adds additional watch directories (for _static file changes) and disable incremental builds - uv run sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) --port ${HTTP_PORT} --watch "." -a $(O) diff --git a/docs/justfile b/docs/justfile new file mode 100644 index 000000000..857afe7d7 --- /dev/null +++ b/docs/justfile @@ -0,0 +1,191 @@ +# justfile for libtmux documentation +# https://just.systems/ + +set shell := ["bash", "-uc"] + +# Configuration +http_port := "8023" +builddir := "_build" +sphinxopts := "" +sphinxbuild := "uv run sphinx-build" +sourcedir := "." + +# File patterns for watching +watch_files := "find .. -type f -not -path '*/\\.*' | grep -i '.*[.]\\(rst\\|md\\)$\\|.*[.]py$\\|CHANGES\\|TODO\\|.*conf\\.py' 2> /dev/null" + +# Sphinx options +allsphinxopts := "-d " + builddir + "/doctrees " + sphinxopts + " ." + +# List all available commands +default: + @just --list + +# ============================================================================ +# Build targets +# ============================================================================ + +# Build HTML documentation +html: + {{ sphinxbuild }} -b html {{ allsphinxopts }} {{ builddir }}/html + @echo "" + @echo "Build finished. The HTML pages are in {{ builddir }}/html." + +# Clean build directory +clean: + rm -rf {{ builddir }}/* + +# Build directory HTML files +dirhtml: + {{ sphinxbuild }} -b dirhtml {{ allsphinxopts }} {{ builddir }}/dirhtml + @echo "" + @echo "Build finished. The HTML pages are in {{ builddir }}/dirhtml." + +# Build single HTML file +singlehtml: + {{ sphinxbuild }} -b singlehtml {{ allsphinxopts }} {{ builddir }}/singlehtml + @echo "" + @echo "Build finished. The HTML page is in {{ builddir }}/singlehtml." + +# Build EPUB +epub: + {{ sphinxbuild }} -b epub {{ allsphinxopts }} {{ builddir }}/epub + @echo "" + @echo "Build finished. The epub file is in {{ builddir }}/epub." + +# Build LaTeX files +latex: + {{ sphinxbuild }} -b latex {{ allsphinxopts }} {{ builddir }}/latex + @echo "" + @echo "Build finished; the LaTeX files are in {{ builddir }}/latex." + +# Build PDF via LaTeX +latexpdf: + {{ sphinxbuild }} -b latex {{ allsphinxopts }} {{ builddir }}/latex + @echo "Running LaTeX files through pdflatex..." + make -C {{ builddir }}/latex all-pdf + @echo "pdflatex finished; the PDF files are in {{ builddir }}/latex." + +# Build plain text files +text: + {{ sphinxbuild }} -b text {{ allsphinxopts }} {{ builddir }}/text + @echo "" + @echo "Build finished. The text files are in {{ builddir }}/text." + +# Build man pages +man: + {{ sphinxbuild }} -b man {{ allsphinxopts }} {{ builddir }}/man + @echo "" + @echo "Build finished. The manual pages are in {{ builddir }}/man." + +# Build JSON output +json: + {{ sphinxbuild }} -b json {{ allsphinxopts }} {{ builddir }}/json + @echo "" + @echo "Build finished; now you can process the JSON files." + +# Build HTML help files +htmlhelp: + {{ sphinxbuild }} -b htmlhelp {{ allsphinxopts }} {{ builddir }}/htmlhelp + @echo "" + @echo "Build finished; now you can run HTML Help Workshop with the .hhp project file in {{ builddir }}/htmlhelp." + +# Build Qt help files +qthelp: + {{ sphinxbuild }} -b qthelp {{ allsphinxopts }} {{ builddir }}/qthelp + @echo "" + @echo "Build finished; now you can run 'qcollectiongenerator' with the .qhcp project file in {{ builddir }}/qthelp." + +# Build Devhelp files +devhelp: + {{ sphinxbuild }} -b devhelp {{ allsphinxopts }} {{ builddir }}/devhelp + @echo "" + @echo "Build finished." + +# Build Texinfo files +texinfo: + {{ sphinxbuild }} -b texinfo {{ allsphinxopts }} {{ builddir }}/texinfo + @echo "" + @echo "Build finished. The Texinfo files are in {{ builddir }}/texinfo." + +# Build Info files from Texinfo +info: + {{ sphinxbuild }} -b texinfo {{ allsphinxopts }} {{ builddir }}/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C {{ builddir }}/texinfo info + @echo "makeinfo finished; the Info files are in {{ builddir }}/texinfo." + +# Build gettext catalogs +gettext: + {{ sphinxbuild }} -b gettext {{ sphinxopts }} . {{ builddir }}/locale + @echo "" + @echo "Build finished. The message catalogs are in {{ builddir }}/locale." + +# ============================================================================ +# Validation +# ============================================================================ + +# Check all external links +linkcheck: + {{ sphinxbuild }} -b linkcheck {{ allsphinxopts }} {{ builddir }}/linkcheck + @echo "" + @echo "Link check complete; look for any errors in the above output or in {{ builddir }}/linkcheck/output.txt." + +# Run doctests embedded in documentation +doctest: + {{ sphinxbuild }} -b doctest {{ allsphinxopts }} {{ builddir }}/doctest + @echo "Testing of doctests in the sources finished, look at the results in {{ builddir }}/doctest/output.txt." + +# Check build from scratch +checkbuild: + rm -rf {{ builddir }} + {{ sphinxbuild }} -n -q ./ {{ builddir }} + +# Build redirects configuration +redirects: + {{ sphinxbuild }} -b rediraffewritediff {{ allsphinxopts }} {{ builddir }}/redirects + @echo "" + @echo "Build finished. The redirects are in rediraffe_redirects." + +# Show changes overview +changes: + {{ sphinxbuild }} -b changes {{ allsphinxopts }} {{ builddir }}/changes + @echo "" + @echo "The overview file is in {{ builddir }}/changes." + +# ============================================================================ +# Development +# ============================================================================ + +# Watch files and rebuild on change +watch: + #!/usr/bin/env bash + set -euo pipefail + if command -v entr > /dev/null; then + ${{ watch_files }} | entr -c just html + else + just html + fi + +# Serve documentation via Python http.server +serve: + @echo '==============================================================' + @echo '' + @echo 'docs server running at http://localhost:{{ http_port }}/' + @echo '' + @echo '==============================================================' + python -m http.server {{ http_port }} --directory {{ builddir }}/html + +# Watch and serve simultaneously +dev: + #!/usr/bin/env bash + set -euo pipefail + just watch & + just serve + +# Start sphinx-autobuild server +start: + uv run sphinx-autobuild "{{ sourcedir }}" "{{ builddir }}" {{ sphinxopts }} --port {{ http_port }} + +# Design mode: watch static files and disable incremental builds +design: + uv run sphinx-autobuild "{{ sourcedir }}" "{{ builddir }}" {{ sphinxopts }} --port {{ http_port }} --watch "." -a diff --git a/justfile b/justfile new file mode 100644 index 000000000..c4038417d --- /dev/null +++ b/justfile @@ -0,0 +1,142 @@ +# justfile for libtmux +# https://just.systems/ + +set shell := ["bash", "-uc"] + +# File patterns +py_files := "find . -type f -not -path '*/\\.*' | grep -i '.*[.]py$' 2> /dev/null" +doc_files := "find . -type f -not -path '*/\\.*' | grep -i '.*[.]rst$\\|.*[.]md$\\|.*[.]css$\\|.*[.]py$\\|mkdocs\\.yml\\|CHANGES\\|TODO\\|.*conf\\.py' 2> /dev/null" +all_files := "find . -type f -not -path '*/\\.*' | grep -i '.*[.]py$\\|.*[.]rst$\\|.*[.]md$\\|.*[.]css$\\|.*[.]py$\\|mkdocs\\.yml\\|CHANGES\\|TODO\\|.*conf\\.py' 2> /dev/null" + +# List all available commands +default: + @just --list + +# ============================================================================ +# Testing +# ============================================================================ + +# Run tests with pytest +test *args: + uv run py.test {{ args }} + +# Run tests then start continuous testing with pytest-watcher +start: + just test + uv run ptw . + +# Watch files and run tests on change (requires entr) +watch-test: + #!/usr/bin/env bash + set -euo pipefail + if command -v entr > /dev/null; then + ${{ all_files }} | entr -c just test + else + just test + just _entr-warn + fi + +# ============================================================================ +# Documentation +# ============================================================================ + +# Build documentation +build-docs: + just -f docs/justfile html + +# Watch files and rebuild docs on change +watch-docs: + #!/usr/bin/env bash + set -euo pipefail + if command -v entr > /dev/null; then + ${{ doc_files }} | entr -c just build-docs + else + just build-docs + just _entr-warn + fi + +# Serve documentation +serve-docs: + just -f docs/justfile serve + +# Watch and serve docs simultaneously +dev-docs: + #!/usr/bin/env bash + set -euo pipefail + just watch-docs & + just serve-docs + +# Start documentation server with auto-reload +start-docs: + just -f docs/justfile start + +# Start documentation design mode (watches static files) +design-docs: + just -f docs/justfile design + +# ============================================================================ +# Linting & Formatting +# ============================================================================ + +# Format code with ruff +ruff-format: + uv run ruff format . + +# Run ruff linter +ruff: + uv run ruff check . + +# Watch files and run ruff on change +watch-ruff: + #!/usr/bin/env bash + set -euo pipefail + if command -v entr > /dev/null; then + ${{ py_files }} | entr -c just ruff + else + just ruff + just _entr-warn + fi + +# Run mypy type checker +mypy: + uv run mypy $(${{ py_files }}) + +# Watch files and run mypy on change +watch-mypy: + #!/usr/bin/env bash + set -euo pipefail + if command -v entr > /dev/null; then + ${{ py_files }} | entr -c just mypy + else + just mypy + just _entr-warn + fi + +# Format markdown files with prettier +format-markdown: + prettier --parser=markdown -w *.md docs/*.md docs/**/*.md CHANGES + +# ============================================================================ +# Typing +# ============================================================================ + +# Run monkeytype to collect runtime types +monkeytype-create: + uv run monkeytype run $(uv run which py.test) + +# Apply collected monkeytype annotations +monkeytype-apply: + uv run monkeytype list-modules | xargs -n1 -I{} sh -c 'uv run monkeytype apply {}' + +# ============================================================================ +# Private helpers +# ============================================================================ + +[private] +_entr-warn: + @echo "----------------------------------------------------------" + @echo " ! File watching functionality non-operational ! " + @echo " " + @echo "Install entr(1) to automatically run tasks on file change." + @echo "See https://eradman.com/entrproject/ " + @echo "----------------------------------------------------------"