diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 7c6e7e7c69..9f2c0a70c1 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -52,6 +52,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: | @@ -61,7 +65,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 68cb1ac12e..68ab7045bc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,25 +9,25 @@ tmuxp is a session manager for tmux that allows users to save and load tmux sess ## Development Commands ### Testing -- `make test` or `uv run py.test` - Run all tests +- `just test` or `uv run py.test` - Run all tests - `uv run py.test tests/path/to/test.py::TestClass::test_method` - Run a single test - `uv run ptw .` - Continuous test runner with pytest-watcher - `uv run ptw . --now --doctest-modules` - Watch tests including doctests -- `make start` or `make watch_test` - Watch and run tests on file changes +- `just start` or `just watch-test` - Watch and run tests on file changes ### Code Quality -- `make ruff` or `uv run ruff check .` - Run linter +- `just ruff` or `uv run ruff check .` - Run linter - `uv run ruff check . --fix --show-fixes` - Fix linting issues automatically -- `make ruff_format` or `uv run ruff format .` - Format code -- `make mypy` or `uv run mypy` - Run type checking (strict mode enabled) -- `make watch_ruff` - Watch and lint on changes -- `make watch_mypy` - Watch and type check on changes +- `just ruff-format` or `uv run ruff format .` - Format code +- `just mypy` or `uv run mypy` - Run type checking (strict mode enabled) +- `just watch-ruff` - Watch and lint on changes +- `just watch-mypy` - Watch and type check on changes ### Documentation -- `make build_docs` - Build documentation -- `make serve_docs` - Serve docs locally at http://localhost:8013 -- `make dev_docs` - Watch and serve docs with auto-reload -- `make start_docs` - Alternative to dev_docs +- `just build-docs` - Build documentation +- `just serve-docs` - Serve docs locally at http://localhost:8013 +- `just dev-docs` - Watch and serve docs with auto-reload +- `just start-docs` - Alternative to dev_docs ### CLI Commands - `tmuxp load ` - Load a tmux session from config diff --git a/CHANGES b/CHANGES index 9b635f9581..e78555bd46 100644 --- a/CHANGES +++ b/CHANGES @@ -31,6 +31,13 @@ $ pipx install --suffix=@next 'tmuxp' --pip-args '\--pre' --force +### Development + +#### Makefile -> Justfile (#1005) + +- Migrate from `Makefile` to `justfile` for running development tasks +- Update documentation to reference `just` commands + ### Documentation - Migrate docs deployment to AWS OIDC authentication and AWS CLI diff --git a/Makefile b/Makefile deleted file mode 100644 index 9749320440..0000000000 --- a/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -PY_FILES= find . -type f -not -path '*/\.*' | grep -i '.*[.]py$$' 2> /dev/null -TEST_FILES= find . -type f -not -path '*/\.*' | grep -i '.*[.]\(yaml\|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 -SHELL := /bin/bash - -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 ${TEST_FILES} | entr -c $(MAKE) test; else $(MAKE) test entr_warn; fi - -build_docs: - $(MAKE) -C docs html - -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 - -start_docs: - $(MAKE) -C docs start - -design_docs: - $(MAKE) -C docs design - -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: - npx 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 43f55d20d0..0000000000 --- a/docs/Makefile +++ /dev/null @@ -1,189 +0,0 @@ -# Makefile for Sphinx documentation -# -SHELL := /bin/bash -HTTP_PORT = 8031 -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/tmuxp.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/tmuxp.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/tmuxp" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/tmuxp" - @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 0000000000..52b33cbaf3 --- /dev/null +++ b/docs/justfile @@ -0,0 +1,191 @@ +# justfile for tmuxp documentation +# https://just.systems/ + +set shell := ["bash", "-uc"] + +# Configuration +http_port := "8031" +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 0000000000..8aa1838a4a --- /dev/null +++ b/justfile @@ -0,0 +1,142 @@ +# justfile for tmuxp +# https://just.systems/ + +set shell := ["bash", "-uc"] + +# File patterns +py_files := "find . -type f -not -path '*/\\.*' | grep -i '.*[.]py$' 2> /dev/null" +test_files := "find . -type f -not -path '*/\\.*' | grep -i '.*[.]\\(yaml\\|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" + +# 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 + ${{ test_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: + npx 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 "----------------------------------------------------------"