zig-codeblocks
Advanced tools
| # This file is autogenerated by maturin v1.8.3 | ||
| # To update, run | ||
| # | ||
| # maturin generate-ci --pytest github | ||
| # | ||
| name: Release | ||
| on: | ||
| push: | ||
| tags: | ||
| - '*' | ||
| workflow_dispatch: | ||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
| jobs: | ||
| linux: | ||
| runs-on: ${{ matrix.platform.runner }} | ||
| strategy: | ||
| matrix: | ||
| platform: | ||
| - runner: ubuntu-22.04 | ||
| target: x86_64 | ||
| - runner: ubuntu-22.04 | ||
| target: aarch64 | ||
| - runner: ubuntu-22.04 | ||
| target: armv7 | ||
| - runner: ubuntu-22.04 | ||
| target: s390x | ||
| - runner: ubuntu-22.04 | ||
| target: ppc64le | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: 3.x | ||
| - name: Build wheels | ||
| uses: PyO3/maturin-action@v1 | ||
| with: | ||
| target: ${{ matrix.platform.target }} | ||
| args: --release --out dist | ||
| sccache: false | ||
| manylinux: 2_28 | ||
| - name: Build free-threaded wheels | ||
| uses: PyO3/maturin-action@v1 | ||
| with: | ||
| target: ${{ matrix.platform.target }} | ||
| args: --release --out dist -i python3.13t | ||
| sccache: false | ||
| manylinux: 2_28 | ||
| - name: Upload wheels | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: wheels-linux-${{ matrix.platform.target }} | ||
| path: dist | ||
| - name: pytest | ||
| if: ${{ startsWith(matrix.platform.target, 'x86_64') }} | ||
| shell: bash | ||
| run: | | ||
| set -e | ||
| python3 -m venv .venv | ||
| source .venv/bin/activate | ||
| pip install zig-codeblocks --find-links dist --force-reinstall | ||
| pip install pytest | ||
| pytest | ||
| - name: pytest | ||
| if: ${{ !startsWith(matrix.platform.target, 'x86') && matrix.platform.target != 'ppc64' }} | ||
| uses: uraimo/run-on-arch-action@v2 | ||
| with: | ||
| arch: ${{ matrix.platform.target }} | ||
| distro: ubuntu22.04 | ||
| githubToken: ${{ github.token }} | ||
| install: | | ||
| apt-get update | ||
| apt-get install -y --no-install-recommends python3 python3-pip | ||
| pip3 install -U pip pytest | ||
| run: | | ||
| set -e | ||
| pip3 install zig-codeblocks --find-links dist --force-reinstall | ||
| pytest | ||
| musllinux: | ||
| runs-on: ${{ matrix.platform.runner }} | ||
| strategy: | ||
| matrix: | ||
| platform: | ||
| - runner: ubuntu-22.04 | ||
| target: x86_64 | ||
| - runner: ubuntu-22.04 | ||
| target: x86 | ||
| - runner: ubuntu-22.04 | ||
| target: aarch64 | ||
| - runner: ubuntu-22.04 | ||
| target: armv7 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: 3.x | ||
| - name: Build wheels | ||
| uses: PyO3/maturin-action@v1 | ||
| with: | ||
| target: ${{ matrix.platform.target }} | ||
| args: --release --out dist | ||
| sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} | ||
| manylinux: musllinux_1_2 | ||
| - name: Build free-threaded wheels | ||
| uses: PyO3/maturin-action@v1 | ||
| with: | ||
| target: ${{ matrix.platform.target }} | ||
| args: --release --out dist -i python3.13t | ||
| sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} | ||
| manylinux: musllinux_1_2 | ||
| - name: Upload wheels | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: wheels-musllinux-${{ matrix.platform.target }} | ||
| path: dist | ||
| - name: pytest | ||
| if: ${{ startsWith(matrix.platform.target, 'x86_64') }} | ||
| uses: addnab/docker-run-action@v3 | ||
| with: | ||
| image: alpine:latest | ||
| options: -v ${{ github.workspace }}:/io -w /io | ||
| run: | | ||
| set -e | ||
| apk add py3-pip py3-virtualenv | ||
| python3 -m virtualenv .venv | ||
| source .venv/bin/activate | ||
| pip install zig-codeblocks --no-index --find-links dist --force-reinstall | ||
| pip install pytest | ||
| pytest | ||
| - name: pytest | ||
| if: ${{ !startsWith(matrix.platform.target, 'x86') }} | ||
| uses: uraimo/run-on-arch-action@v2 | ||
| with: | ||
| arch: ${{ matrix.platform.target }} | ||
| distro: alpine_latest | ||
| githubToken: ${{ github.token }} | ||
| install: | | ||
| apk add py3-virtualenv | ||
| run: | | ||
| set -e | ||
| python3 -m virtualenv .venv | ||
| source .venv/bin/activate | ||
| pip install pytest | ||
| pip install zig-codeblocks --find-links dist --force-reinstall | ||
| pytest | ||
| windows: | ||
| runs-on: ${{ matrix.platform.runner }} | ||
| strategy: | ||
| matrix: | ||
| platform: | ||
| - runner: windows-latest | ||
| target: x64 | ||
| - runner: windows-latest | ||
| target: x86 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: 3.x | ||
| architecture: ${{ matrix.platform.target }} | ||
| - name: Build wheels | ||
| uses: PyO3/maturin-action@v1 | ||
| with: | ||
| target: ${{ matrix.platform.target }} | ||
| args: --release --out dist | ||
| sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} | ||
| - name: Build free-threaded wheels | ||
| uses: PyO3/maturin-action@v1 | ||
| with: | ||
| target: ${{ matrix.platform.target }} | ||
| args: --release --out dist -i python3.13t | ||
| sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} | ||
| - name: Upload wheels | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: wheels-windows-${{ matrix.platform.target }} | ||
| path: dist | ||
| - name: pytest | ||
| if: ${{ !startsWith(matrix.platform.target, 'aarch64') }} | ||
| shell: bash | ||
| run: | | ||
| set -e | ||
| python3 -m venv .venv | ||
| source .venv/Scripts/activate | ||
| pip install zig-codeblocks --find-links dist --force-reinstall | ||
| pip install pytest | ||
| pytest | ||
| macos: | ||
| runs-on: ${{ matrix.platform.runner }} | ||
| strategy: | ||
| matrix: | ||
| platform: | ||
| - runner: macos-13 | ||
| target: x86_64 | ||
| - runner: macos-14 | ||
| target: aarch64 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: 3.x | ||
| - name: Build wheels | ||
| uses: PyO3/maturin-action@v1 | ||
| with: | ||
| target: ${{ matrix.platform.target }} | ||
| args: --release --out dist | ||
| sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} | ||
| - name: Build free-threaded wheels | ||
| uses: PyO3/maturin-action@v1 | ||
| with: | ||
| target: ${{ matrix.platform.target }} | ||
| args: --release --out dist -i python3.13t | ||
| sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} | ||
| - name: Upload wheels | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: wheels-macos-${{ matrix.platform.target }} | ||
| path: dist | ||
| - name: pytest | ||
| run: | | ||
| set -e | ||
| python3 -m venv .venv | ||
| source .venv/bin/activate | ||
| pip install zig-codeblocks --find-links dist --force-reinstall | ||
| pip install pytest | ||
| pytest | ||
| sdist: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Build sdist | ||
| uses: PyO3/maturin-action@v1 | ||
| with: | ||
| command: sdist | ||
| args: --out dist | ||
| - name: Upload sdist | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: wheels-sdist | ||
| path: dist | ||
| release: | ||
| name: Release | ||
| runs-on: ubuntu-latest | ||
| if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }} | ||
| needs: [linux, musllinux, windows, macos, sdist] | ||
| permissions: | ||
| # Use to sign the release artifacts | ||
| id-token: write | ||
| # Used to upload release artifacts | ||
| contents: write | ||
| # Used to generate artifact attestation | ||
| attestations: write | ||
| steps: | ||
| - uses: actions/download-artifact@v4 | ||
| - name: Generate artifact attestation | ||
| uses: actions/attest-build-provenance@v2 | ||
| with: | ||
| subject-path: 'wheels-*/*' | ||
| - name: Publish to PyPI | ||
| if: ${{ startsWith(github.ref, 'refs/tags/') }} | ||
| uses: PyO3/maturin-action@v1 | ||
| with: | ||
| command: upload | ||
| args: --non-interactive --skip-existing wheels-*/* |
+348
| # This file is automatically @generated by Cargo. | ||
| # It is not intended for manual editing. | ||
| version = 4 | ||
| [[package]] | ||
| name = "aho-corasick" | ||
| version = "1.1.3" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" | ||
| dependencies = [ | ||
| "memchr", | ||
| ] | ||
| [[package]] | ||
| name = "autocfg" | ||
| version = "1.4.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" | ||
| [[package]] | ||
| name = "cc" | ||
| version = "1.2.16" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" | ||
| dependencies = [ | ||
| "shlex", | ||
| ] | ||
| [[package]] | ||
| name = "cfg-if" | ||
| version = "1.0.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | ||
| [[package]] | ||
| name = "equivalent" | ||
| version = "1.0.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" | ||
| [[package]] | ||
| name = "hashbrown" | ||
| version = "0.15.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" | ||
| [[package]] | ||
| name = "heck" | ||
| version = "0.5.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" | ||
| [[package]] | ||
| name = "indexmap" | ||
| version = "2.8.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" | ||
| dependencies = [ | ||
| "equivalent", | ||
| "hashbrown", | ||
| ] | ||
| [[package]] | ||
| name = "indoc" | ||
| version = "2.0.6" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" | ||
| [[package]] | ||
| name = "itoa" | ||
| version = "1.0.15" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" | ||
| [[package]] | ||
| name = "libc" | ||
| version = "0.2.171" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" | ||
| [[package]] | ||
| name = "memchr" | ||
| version = "2.7.4" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" | ||
| [[package]] | ||
| name = "memoffset" | ||
| version = "0.9.1" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" | ||
| dependencies = [ | ||
| "autocfg", | ||
| ] | ||
| [[package]] | ||
| name = "once_cell" | ||
| version = "1.21.1" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" | ||
| [[package]] | ||
| name = "portable-atomic" | ||
| version = "1.11.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" | ||
| [[package]] | ||
| name = "proc-macro2" | ||
| version = "1.0.94" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" | ||
| dependencies = [ | ||
| "unicode-ident", | ||
| ] | ||
| [[package]] | ||
| name = "pyo3" | ||
| version = "0.24.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "7f1c6c3591120564d64db2261bec5f910ae454f01def849b9c22835a84695e86" | ||
| dependencies = [ | ||
| "cfg-if", | ||
| "indoc", | ||
| "libc", | ||
| "memoffset", | ||
| "once_cell", | ||
| "portable-atomic", | ||
| "pyo3-build-config", | ||
| "pyo3-ffi", | ||
| "pyo3-macros", | ||
| "unindent", | ||
| ] | ||
| [[package]] | ||
| name = "pyo3-build-config" | ||
| version = "0.24.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "e9b6c2b34cf71427ea37c7001aefbaeb85886a074795e35f161f5aecc7620a7a" | ||
| dependencies = [ | ||
| "once_cell", | ||
| "python3-dll-a", | ||
| "target-lexicon", | ||
| ] | ||
| [[package]] | ||
| name = "pyo3-ffi" | ||
| version = "0.24.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "5507651906a46432cdda02cd02dd0319f6064f1374c9147c45b978621d2c3a9c" | ||
| dependencies = [ | ||
| "libc", | ||
| "pyo3-build-config", | ||
| ] | ||
| [[package]] | ||
| name = "pyo3-macros" | ||
| version = "0.24.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "b0d394b5b4fd8d97d48336bb0dd2aebabad39f1d294edd6bcd2cccf2eefe6f42" | ||
| dependencies = [ | ||
| "proc-macro2", | ||
| "pyo3-macros-backend", | ||
| "quote", | ||
| "syn", | ||
| ] | ||
| [[package]] | ||
| name = "pyo3-macros-backend" | ||
| version = "0.24.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "fd72da09cfa943b1080f621f024d2ef7e2773df7badd51aa30a2be1f8caa7c8e" | ||
| dependencies = [ | ||
| "heck", | ||
| "proc-macro2", | ||
| "pyo3-build-config", | ||
| "quote", | ||
| "syn", | ||
| ] | ||
| [[package]] | ||
| name = "python3-dll-a" | ||
| version = "0.2.13" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "49fe4227a288cf9493942ad0220ea3f185f4d1f2a14f197f7344d6d02f4ed4ed" | ||
| dependencies = [ | ||
| "cc", | ||
| ] | ||
| [[package]] | ||
| name = "quote" | ||
| version = "1.0.40" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" | ||
| dependencies = [ | ||
| "proc-macro2", | ||
| ] | ||
| [[package]] | ||
| name = "regex" | ||
| version = "1.11.1" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" | ||
| dependencies = [ | ||
| "aho-corasick", | ||
| "memchr", | ||
| "regex-automata", | ||
| "regex-syntax", | ||
| ] | ||
| [[package]] | ||
| name = "regex-automata" | ||
| version = "0.4.9" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" | ||
| dependencies = [ | ||
| "aho-corasick", | ||
| "memchr", | ||
| "regex-syntax", | ||
| ] | ||
| [[package]] | ||
| name = "regex-syntax" | ||
| version = "0.8.5" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" | ||
| [[package]] | ||
| name = "ryu" | ||
| version = "1.0.20" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" | ||
| [[package]] | ||
| name = "serde" | ||
| version = "1.0.219" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" | ||
| dependencies = [ | ||
| "serde_derive", | ||
| ] | ||
| [[package]] | ||
| name = "serde_derive" | ||
| version = "1.0.219" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" | ||
| dependencies = [ | ||
| "proc-macro2", | ||
| "quote", | ||
| "syn", | ||
| ] | ||
| [[package]] | ||
| name = "serde_json" | ||
| version = "1.0.140" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" | ||
| dependencies = [ | ||
| "indexmap", | ||
| "itoa", | ||
| "memchr", | ||
| "ryu", | ||
| "serde", | ||
| ] | ||
| [[package]] | ||
| name = "shlex" | ||
| version = "1.3.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" | ||
| [[package]] | ||
| name = "streaming-iterator" | ||
| version = "0.1.9" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" | ||
| [[package]] | ||
| name = "syn" | ||
| version = "2.0.100" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" | ||
| dependencies = [ | ||
| "proc-macro2", | ||
| "quote", | ||
| "unicode-ident", | ||
| ] | ||
| [[package]] | ||
| name = "target-lexicon" | ||
| version = "0.13.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" | ||
| [[package]] | ||
| name = "tree-sitter" | ||
| version = "0.25.3" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "b9ac5ea5e7f2f1700842ec071401010b9c59bf735295f6e9fa079c3dc035b167" | ||
| dependencies = [ | ||
| "cc", | ||
| "regex", | ||
| "regex-syntax", | ||
| "serde_json", | ||
| "streaming-iterator", | ||
| "tree-sitter-language", | ||
| ] | ||
| [[package]] | ||
| name = "tree-sitter-language" | ||
| version = "0.1.5" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "c4013970217383f67b18aef68f6fb2e8d409bc5755227092d32efb0422ba24b8" | ||
| [[package]] | ||
| name = "tree-sitter-zig" | ||
| version = "1.1.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "ab11fc124851b0db4dd5e55983bbd9631192e93238389dcd44521715e5d53e28" | ||
| dependencies = [ | ||
| "cc", | ||
| "tree-sitter-language", | ||
| ] | ||
| [[package]] | ||
| name = "unicode-ident" | ||
| version = "1.0.18" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" | ||
| [[package]] | ||
| name = "unindent" | ||
| version = "0.2.4" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" | ||
| [[package]] | ||
| name = "zig_codeblocks" | ||
| version = "0.3.0" | ||
| dependencies = [ | ||
| "pyo3", | ||
| "regex", | ||
| "serde", | ||
| "serde_json", | ||
| "tree-sitter", | ||
| "tree-sitter-zig", | ||
| ] |
+21
| [package] | ||
| name = "zig_codeblocks" | ||
| version = "0.3.0" | ||
| edition = "2021" | ||
| [lib] | ||
| name = "_core" | ||
| # "cdylib" is necessary to produce a shared library for Python to import from. | ||
| crate-type = ["cdylib"] | ||
| [dependencies] | ||
| # "extension-module" tells pyo3 we want to build an extension module (skips linking against libpython.so) | ||
| # "abi3-py39" tells pyo3 (and maturin) to build using the stable ABI with minimum Python version 3.9 | ||
| pyo3 = { version = "0.24.0", features = ["extension-module", "abi3-py39", "generate-import-lib"] } | ||
| regex = "1.11.1" | ||
| tree-sitter = "0.25.3" | ||
| tree-sitter-zig = "1.1.2" | ||
| [dev-dependencies] | ||
| serde_json = "1.0.140" | ||
| serde = { version = "1.0.219", features = ["derive"] } |
| unstable_features = true | ||
| group_imports = "StdExternalCrate" | ||
| imports_granularity = "Crate" | ||
| reorder_imports = true | ||
| reorder_modules = true |
+317
| use std::{ | ||
| borrow::Cow, | ||
| collections::{HashMap, HashSet}, | ||
| hash::{DefaultHasher, Hash, Hasher}, | ||
| }; | ||
| use pyo3::{exceptions::PyValueError, prelude::*}; | ||
| use crate::{ | ||
| parse::{extract_codeblocks, tokenize_zig, Token}, | ||
| style::{Style, Theme, TokenType}, | ||
| }; | ||
| pub const RESET: &str = "\x1b[0m"; | ||
| const CODEBLOCK_START: &[u8] = b"```zig\n"; | ||
| const CODEBLOCK_END: &[u8] = b"```"; | ||
| const KEYWORDS: [&str; 49] = [ | ||
| "addrspace", | ||
| "align", | ||
| "allowzero", | ||
| "and", | ||
| "anyframe", | ||
| "anytype", | ||
| "asm", | ||
| "async", | ||
| "await", | ||
| "break", | ||
| "callconv", | ||
| "catch", | ||
| "comptime", | ||
| "const", | ||
| "continue", | ||
| "defer", | ||
| "else", | ||
| "enum", | ||
| "errdefer", | ||
| "error", | ||
| "export", | ||
| "extern", | ||
| "fn", | ||
| "for", | ||
| "if", | ||
| "inline", | ||
| "linksection", | ||
| "noalias", | ||
| "noinline", | ||
| "nosuspend", | ||
| "opaque", | ||
| "or", | ||
| "orelse", | ||
| "packed", | ||
| "pub", | ||
| "resume", | ||
| "return", | ||
| "struct", | ||
| "suspend", | ||
| "switch", | ||
| "test", | ||
| "threadlocal", | ||
| "try", | ||
| "union", | ||
| "unreachable", | ||
| "usingnamespace", | ||
| "var", | ||
| "volatile", | ||
| "while", | ||
| ]; | ||
| const IDENTIFIERS: [&str; 2] = ["identifier", "c"]; | ||
| const NUMERIC_LITERALS: [&str; 2] = ["integer", "float"]; | ||
| const PRIMITIVE_VALUES: [&str; 4] = ["true", "false", "null", "undefined"]; | ||
| const STRINGLIKE: [&str; 5] = [ | ||
| "string_content", | ||
| "multiline_string", | ||
| "\"", | ||
| "'", | ||
| "character_content", | ||
| ]; | ||
| const TYPES: [&str; 26] = [ | ||
| "anyerror", | ||
| "anyopaque", | ||
| "bool", | ||
| "builtin_type", | ||
| "c_char", | ||
| "c_int", | ||
| "c_long", | ||
| "c_longdouble", | ||
| "c_longlong", | ||
| "c_short", | ||
| "c_uint", | ||
| "c_ulong", | ||
| "c_ulonglong", | ||
| "c_ushort", | ||
| "comptime_float", | ||
| "comptime_int", | ||
| "f128", | ||
| "f16", | ||
| "f32", | ||
| "f64", | ||
| "f80", | ||
| "isize", | ||
| "noreturn", | ||
| "type", | ||
| "usize", | ||
| "void", | ||
| ]; | ||
| #[derive(Clone, PartialEq, Eq)] | ||
| enum Frag<'a> { | ||
| Text(Cow<'a, str>), | ||
| Sgr(Style), | ||
| } | ||
| impl std::fmt::Display for Frag<'_> { | ||
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
| let str = match self { | ||
| Self::Text(t) => t.to_string(), | ||
| Self::Sgr(s) => s.to_string(), | ||
| }; | ||
| write!(f, "{str}") | ||
| } | ||
| } | ||
| fn last_applied_style<'a>(body: &[Frag<'a>]) -> Option<Frag<'a>> { | ||
| body.iter() | ||
| .rev() | ||
| .find(|item| match item { | ||
| Frag::Text(s) => s == RESET, | ||
| Frag::Sgr(_) => true, | ||
| }) | ||
| .cloned() | ||
| } | ||
| fn get_style<'a>(kind: &str, theme: &'a Theme) -> Option<&'a Style> { | ||
| let variants: [(&[&str], TokenType); 6] = [ | ||
| (&IDENTIFIERS, TokenType::Identifier), | ||
| (&KEYWORDS, TokenType::Keyword), | ||
| (&NUMERIC_LITERALS, TokenType::Numeric), | ||
| (&PRIMITIVE_VALUES, TokenType::PrimitiveValue), | ||
| (&STRINGLIKE, TokenType::String), | ||
| (&TYPES, TokenType::Type), | ||
| ]; | ||
| for (options, token_type) in variants { | ||
| if options.contains(&kind) { | ||
| return theme.get(&token_type); | ||
| } | ||
| } | ||
| match kind { | ||
| "comment" => theme.get(&TokenType::Comment), | ||
| "builtin_identifier" => theme.get(&TokenType::BuiltinIdentifier), | ||
| _ => None, | ||
| } | ||
| } | ||
| fn skip_to_token(source: &[u8], pointer: &mut usize, body: &mut Vec<Frag>, current_token: &Token) { | ||
| let filler = String::from_utf8_lossy(&source[*pointer..current_token.byte_range.0]).to_string(); | ||
| let last_style = last_applied_style(body); | ||
| match (filler.trim().is_empty(), last_style) { | ||
| ( | ||
| true, | ||
| Some(Frag::Sgr( | ||
| Style { | ||
| underline: true, .. | ||
| } | ||
| | Style { bold: true, .. }, | ||
| )), | ||
| ) | ||
| | (false, Some(Frag::Sgr(Style { .. }))) => body.push(Frag::Text(RESET.into())), | ||
| _ => (), | ||
| }; | ||
| body.push(Frag::Text(filler.into())); | ||
| *pointer = current_token.byte_range.0; | ||
| } | ||
| fn check_end_index(body: &[Frag], idx: usize, target: &Frag) -> bool { | ||
| body.len() | ||
| .checked_sub(idx) | ||
| .is_some_and(|idx| body[idx] == *target) | ||
| } | ||
| fn adjust_string_idents(body: &mut Vec<Frag>, token: &Token, theme: &Theme) { | ||
| // Special case for `whatever.@"something here"`, | ||
| // which is an identifier, so should have no string highlighting | ||
| let identifier_style = theme.get(&TokenType::Identifier); | ||
| let string_style = theme.get(&TokenType::String); | ||
| if !((identifier_style.is_some() || string_style.is_some()) && token.kind == "\"") { | ||
| return; | ||
| } | ||
| let at = Frag::Text("@".into()); | ||
| if let Some(style) = string_style { | ||
| if last_applied_style(body) == Some(Frag::Sgr(*style)) && check_end_index(body, 4, &at) { | ||
| let idx = body.len() - 3; | ||
| if let Some(style) = identifier_style { | ||
| body[idx] = Frag::Sgr(*style); | ||
| } else { | ||
| body.remove(idx); | ||
| } | ||
| } | ||
| } else if check_end_index(body, 3, &at) { | ||
| body.insert( | ||
| body.len() - 2, | ||
| Frag::Sgr(*identifier_style.expect("guaranteed by prior logic")), | ||
| ); | ||
| } | ||
| } | ||
| fn process_zig_tokens(source: &[u8], tokens: Vec<Token>, theme: &Theme) -> String { | ||
| let mut body: Vec<Frag> = Vec::with_capacity(tokens.len() * 2); | ||
| let mut pointer = 0; | ||
| let mut tokens = tokens.into_iter().peekable(); | ||
| let Some(mut token) = tokens.next() else { | ||
| return String::from_utf8_lossy(source).into(); | ||
| }; | ||
| while pointer < source.len() { | ||
| if token.byte_range.0 > pointer { | ||
| skip_to_token(source, &mut pointer, &mut body, &token); | ||
| continue; | ||
| } | ||
| let style = | ||
| if token.kind == "identifier" && tokens.peek().map(|v| v.kind == "(") == Some(true) { | ||
| theme.get(&TokenType::Call) | ||
| } else { | ||
| get_style(&token.kind, theme) | ||
| }; | ||
| match style { | ||
| None => { | ||
| if matches!(last_applied_style(&body), Some(Frag::Sgr(_))) { | ||
| body.push(Frag::Text(RESET.into())); | ||
| } | ||
| } | ||
| Some(style) => { | ||
| if last_applied_style(&body) != Some(Frag::Sgr(*style)) { | ||
| body.push(Frag::Sgr(*style)); | ||
| } | ||
| } | ||
| } | ||
| adjust_string_idents(&mut body, &token, theme); | ||
| body.push(Frag::Text(Cow::Owned( | ||
| String::from_utf8_lossy(&token.value).into_owned(), | ||
| ))); | ||
| pointer = token.byte_range.1; | ||
| if let Some(next_token) = tokens.next() { | ||
| token = next_token; | ||
| } else { | ||
| break; | ||
| } | ||
| } | ||
| body.into_iter().map(|x| x.to_string()).collect::<String>() | ||
| } | ||
| pub fn build_theme(theme: HashMap<String, Style>) -> PyResult<Theme> { | ||
| theme | ||
| .into_iter() | ||
| .map(|(k, v)| (TokenType::try_from(k), v)) | ||
| .map(|(res, u)| res.map(|t| (t, u))) | ||
| .collect::<Result<HashMap<_, _>, _>>() | ||
| .map_err(|key| PyValueError::new_err(format!("Invalid theme key: {key:?}"))) | ||
| } | ||
| pub fn highlight_zig_code(source: &[u8], theme: &Theme) -> String { | ||
| process_zig_tokens(source, tokenize_zig(source), theme) | ||
| } | ||
| fn get_body_hash(body: &[u8]) -> u64 { | ||
| let mut hasher = DefaultHasher::new(); | ||
| body.hash(&mut hasher); | ||
| hasher.finish() | ||
| } | ||
| pub fn process_markdown(source: &[u8], theme: &Theme, only_code: bool) -> String { | ||
| let zig_codeblocks = extract_codeblocks(source) | ||
| .into_iter() | ||
| .filter_map(|cb| (cb.lang == Some("zig".into())).then_some(cb.body.as_bytes().to_vec())); | ||
| if only_code { | ||
| return zig_codeblocks | ||
| .map(|cb| format!("```ansi\n{}\n```", highlight_zig_code(&cb, theme))) | ||
| .collect::<Vec<_>>() | ||
| .join("\n"); | ||
| } | ||
| // Deduplicating the codeblocks | ||
| let mut seen = HashSet::new(); | ||
| let zig_codeblocks = zig_codeblocks.filter(|item| seen.insert(get_body_hash(item))); | ||
| let mut new_source = source.to_vec(); | ||
| for cb in zig_codeblocks { | ||
| let mut needle = Vec::with_capacity(CODEBLOCK_START.len() + cb.len() + CODEBLOCK_END.len()); | ||
| needle.extend_from_slice(CODEBLOCK_START); | ||
| needle.extend_from_slice(&cb); | ||
| needle.extend_from_slice(CODEBLOCK_END); | ||
| let start_positions = new_source | ||
| .windows(needle.len()) | ||
| .enumerate() | ||
| .filter_map(|(i, w)| if w == needle { Some(i) } else { None }) | ||
| .rev() | ||
| .collect::<Vec<_>>(); | ||
| let mut highlighted = highlight_zig_code(&cb, theme); | ||
| highlighted.insert_str(0, "```ansi\n"); | ||
| highlighted.push_str("\n```"); | ||
| let highlighted_bytes = highlighted.as_bytes(); | ||
| let end_pos_offset = needle.len(); | ||
| for start_pos in start_positions { | ||
| new_source.splice( | ||
| start_pos..start_pos + end_pos_offset, | ||
| highlighted_bytes.to_vec(), | ||
| ); | ||
| } | ||
| } | ||
| String::from_utf8_lossy(&new_source).to_string() | ||
| } |
+73
| use std::collections::HashMap; | ||
| use pyo3::prelude::*; | ||
| mod format; | ||
| mod parse; | ||
| mod style; | ||
| #[derive(FromPyObject)] | ||
| pub enum StrOrBytes { | ||
| #[pyo3(transparent)] | ||
| Str(String), | ||
| #[pyo3(transparent)] | ||
| Bytes(Vec<u8>), | ||
| } | ||
| impl StrOrBytes { | ||
| fn resolve(&self) -> &[u8] { | ||
| match self { | ||
| Self::Str(s) => s.as_bytes(), | ||
| Self::Bytes(b) => b, | ||
| } | ||
| } | ||
| } | ||
| /// Return an ANSI syntax-highlighted version of the given Zig source code. Assumes UTF-8. | ||
| #[pyfunction] | ||
| #[pyo3(signature = (source, theme=style::DEFAULT_THEME_PREPROCESSED.clone()))] | ||
| pub fn highlight_zig_code( | ||
| source: StrOrBytes, | ||
| theme: HashMap<String, style::Style>, | ||
| ) -> PyResult<String> { | ||
| Ok(format::highlight_zig_code( | ||
| source.resolve(), | ||
| &format::build_theme(theme)?, | ||
| )) | ||
| } | ||
| /// Return a Markdown source with Zig code blocks syntax-highlighted. | ||
| /// If `only_code` is True, only processed Zig code blocks will be returned. Assumes UTF-8. | ||
| #[pyfunction] | ||
| #[pyo3(signature = (source, theme=style::DEFAULT_THEME_PREPROCESSED.clone(), *, only_code=false))] | ||
| pub fn process_markdown( | ||
| source: StrOrBytes, | ||
| theme: HashMap<String, style::Style>, | ||
| only_code: bool, | ||
| ) -> PyResult<String> { | ||
| Ok(format::process_markdown( | ||
| source.resolve(), | ||
| &format::build_theme(theme)?, | ||
| only_code, | ||
| )) | ||
| } | ||
| /// Return CodeBlocks from a Markdown source. Assumes UTF-8. | ||
| #[pyfunction] | ||
| pub fn extract_codeblocks(source: StrOrBytes) -> Vec<parse::CodeBlock> { | ||
| parse::extract_codeblocks(source.resolve()) | ||
| } | ||
| /// A Python module implemented in Rust. The name of this function must match | ||
| /// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to | ||
| /// import the module. | ||
| #[pymodule] | ||
| fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> { | ||
| m.add_function(wrap_pyfunction!(extract_codeblocks, m)?)?; | ||
| m.add_function(wrap_pyfunction!(highlight_zig_code, m)?)?; | ||
| m.add_function(wrap_pyfunction!(process_markdown, m)?)?; | ||
| m.add_class::<parse::CodeBlock>()?; | ||
| m.add_class::<style::Color>()?; | ||
| m.add_class::<style::Style>()?; | ||
| Ok(()) | ||
| } |
+171
| use std::{borrow::Cow, sync::LazyLock}; | ||
| use pyo3::prelude::*; | ||
| use regex::bytes::{Match, Regex}; | ||
| #[derive(Debug, PartialEq, Eq)] | ||
| pub struct Token<'a> { | ||
| pub kind: Cow<'a, str>, | ||
| pub value: Cow<'a, [u8]>, | ||
| pub byte_range: (usize, usize), | ||
| } | ||
| /// A code block extracted from a Markdown source. | ||
| #[pyclass(eq, get_all, module = "zig_codeblocks._core")] | ||
| #[derive(PartialEq, Eq)] | ||
| pub struct CodeBlock { | ||
| pub lang: Option<String>, | ||
| pub body: String, | ||
| } | ||
| #[pymethods] | ||
| impl CodeBlock { | ||
| #[new] | ||
| pub fn new(lang: Option<String>, body: &str) -> Self { | ||
| Self { | ||
| lang, | ||
| body: body.to_owned(), | ||
| } | ||
| } | ||
| fn __repr__(&self) -> String { | ||
| let lang_repr = if let Some(lang) = &self.lang { | ||
| format!("{lang:?}") | ||
| } else { | ||
| String::from("None") | ||
| }; | ||
| format!("CodeBlock(lang={lang_repr}, body={:?})", self.body) | ||
| } | ||
| fn __str__(&self) -> String { | ||
| self.to_string() | ||
| } | ||
| } | ||
| impl std::fmt::Display for CodeBlock { | ||
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
| if let Some(lang) = &self.lang { | ||
| write!(f, "```{lang}\n{}```", self.body) | ||
| } else { | ||
| write!(f, "```{}```", self.body) | ||
| } | ||
| } | ||
| } | ||
| static CODE_BLOCK_PATTERN: LazyLock<Regex> = LazyLock::new(|| { | ||
| Regex::new(r"(?s)```(?:([A-Za-z0-9\-_\+\.#]+)(?:\r?\n)+([^\r\n].*?)|(.*?))```") | ||
| .expect("guaranteed to be valid") | ||
| }); | ||
| fn get_parser() -> tree_sitter::Parser { | ||
| let mut parser = tree_sitter::Parser::new(); | ||
| let language = tree_sitter_zig::LANGUAGE; | ||
| parser | ||
| .set_language(&language.into()) | ||
| .expect("tree-sitter-zig should work correctly"); | ||
| parser | ||
| } | ||
| pub fn tokenize_zig(src: &[u8]) -> Vec<Token> { | ||
| let mut parser = get_parser(); | ||
| let tree = parser | ||
| .parse(src, None) | ||
| .expect("should be Some, the parser was assigned a language"); | ||
| traverse(tree.root_node(), src) | ||
| } | ||
| fn traverse<'a>(root: tree_sitter::Node, src: &'a [u8]) -> Vec<Token<'a>> { | ||
| let mut tokens = Vec::new(); | ||
| let mut stack = vec![root]; | ||
| while let Some(node) = stack.pop() { | ||
| if node.child_count() > 0 { | ||
| stack.extend( | ||
| (0..node.child_count()) | ||
| .rev() | ||
| .map(|i| node.child(i).expect("should be in-bounds")), | ||
| ); | ||
| continue; | ||
| } | ||
| tokens.push(Token { | ||
| kind: Cow::Borrowed(node.kind()), | ||
| value: Cow::Borrowed(&src[node.start_byte()..node.end_byte()]), | ||
| byte_range: (node.start_byte(), node.end_byte()), | ||
| }); | ||
| } | ||
| tokens | ||
| } | ||
| fn match_to_utf8(r#match: Match<'_>) -> Cow<'_, str> { | ||
| String::from_utf8_lossy(r#match.as_bytes()) | ||
| } | ||
| pub fn extract_codeblocks(source: &[u8]) -> Vec<CodeBlock> { | ||
| CODE_BLOCK_PATTERN | ||
| .captures_iter(source) | ||
| .map(|m| { | ||
| let (lang, body, no_lang_body) = (m.get(1), m.get(2), m.get(3)); | ||
| if lang.is_some() { | ||
| CodeBlock::new( | ||
| lang.map(|m| match_to_utf8(m).to_string()), | ||
| &match_to_utf8(body.expect("should be present when lang is present")), | ||
| ) | ||
| } else { | ||
| CodeBlock::new( | ||
| None, | ||
| &match_to_utf8(no_lang_body.expect("should be present when lang is absent")), | ||
| ) | ||
| } | ||
| }) | ||
| .collect() | ||
| } | ||
| #[cfg(test)] | ||
| mod tests { | ||
| use std::fs::read_to_string; | ||
| use super::{tokenize_zig, Cow, Token}; | ||
| #[derive(serde::Serialize, serde::Deserialize)] | ||
| struct OutputToken { | ||
| kind: String, | ||
| value: Option<String>, | ||
| range: (usize, usize), | ||
| } | ||
| macro_rules! make_test { | ||
| ($name:ident) => { | ||
| #[test] | ||
| fn $name() { | ||
| let src_path = concat!("tests/sources/zig_inputs/", stringify!($name), ".zig"); | ||
| let out_path = | ||
| concat!("tests/sources/parsing_results/", stringify!($name), ".json"); | ||
| let source = read_to_string(src_path) | ||
| .expect("the file should be valid") | ||
| .replace("\r\n", "\n") | ||
| .into_bytes(); | ||
| let out_json = read_to_string(out_path).expect("the file should be valid"); | ||
| assert_eq!(tokenize_zig(&source), read_expected_tokens(&out_json)); | ||
| } | ||
| }; | ||
| } | ||
| fn read_expected_tokens(content: &str) -> Vec<Token> { | ||
| let t: Vec<OutputToken> = | ||
| serde_json::from_str(content).expect("the output json should be valid"); | ||
| t.into_iter() | ||
| .map(|ot| Token { | ||
| value: Cow::Owned(ot.value.unwrap_or(ot.kind.clone()).as_bytes().to_vec()), | ||
| kind: Cow::Owned(ot.kind), | ||
| byte_range: ot.range, | ||
| }) | ||
| .collect::<Vec<_>>() | ||
| } | ||
| make_test!(assign_undefined); | ||
| make_test!(comments); | ||
| make_test!(emoji); | ||
| make_test!(global_assembly); | ||
| make_test!(hello_again); | ||
| make_test!(identifiers); | ||
| } |
+204
| use std::{collections::HashMap, sync::LazyLock}; | ||
| use pyo3::{exceptions::PyValueError, prelude::*}; | ||
| /// An enumeration of 3-bit ANSI colors. | ||
| /// Some names were adjusted to match Discord's style. | ||
| #[pyclass(eq, eq_int, module = "zig_codeblocks._core")] | ||
| #[derive(PartialEq, Eq, Clone, Copy, Debug)] | ||
| pub enum Color { | ||
| Gray, | ||
| Red, | ||
| Green, | ||
| Orange, | ||
| Blue, | ||
| Magenta, | ||
| Cyan, | ||
| White, | ||
| } | ||
| #[pymethods] | ||
| impl Color { | ||
| #[staticmethod] | ||
| fn from_string(value: &str) -> PyResult<Self> { | ||
| match &value.to_lowercase()[..] { | ||
| "gray" => Ok(Self::Gray), | ||
| "red" => Ok(Self::Red), | ||
| "green" => Ok(Self::Green), | ||
| "orange" => Ok(Self::Orange), | ||
| "blue" => Ok(Self::Blue), | ||
| "magenta" => Ok(Self::Magenta), | ||
| "cyan" => Ok(Self::Cyan), | ||
| "white" => Ok(Self::White), | ||
| _ => Err(PyValueError::new_err(format!("Invalid color: {value:?}"))), | ||
| } | ||
| } | ||
| } | ||
| impl Color { | ||
| const fn code(self) -> &'static str { | ||
| match self { | ||
| Self::Gray => "30", | ||
| Self::Red => "31", | ||
| Self::Green => "32", | ||
| Self::Orange => "33", | ||
| Self::Blue => "34", | ||
| Self::Magenta => "35", | ||
| Self::Cyan => "36", | ||
| Self::White => "37", | ||
| } | ||
| } | ||
| } | ||
| const fn python_bool_repr(value: bool) -> &'static str { | ||
| if value { "True" } else { "False" } | ||
| } | ||
| /// A style for syntax highlighting. | ||
| /// Takes a `Color` and can optionally be bold and/or underlined. | ||
| /// Produces an SGR sequence when converted to a string. | ||
| #[pyclass(eq, module = "zig_codeblocks._core")] | ||
| #[derive(PartialEq, Eq, Clone, Copy, Debug)] | ||
| pub struct Style { | ||
| #[pyo3(get, set)] | ||
| color: Color, | ||
| #[pyo3(get, set)] | ||
| pub bold: bool, | ||
| #[pyo3(get, set)] | ||
| pub underline: bool, | ||
| } | ||
| #[pymethods] | ||
| impl Style { | ||
| #[new] | ||
| #[pyo3(signature = (color, *, bold=false, underline=false))] | ||
| fn new(color: Color, bold: bool, underline: bool) -> Self { | ||
| Self { | ||
| color, | ||
| bold, | ||
| underline, | ||
| } | ||
| } | ||
| #[staticmethod] | ||
| fn from_string(value: &str) -> PyResult<Self> { | ||
| let mut color: Option<Color> = None; | ||
| let mut bold = false; | ||
| let mut underline = false; | ||
| for part in value.to_lowercase().split('+') { | ||
| match part { | ||
| "bold" => bold = true, | ||
| "underline" => underline = true, | ||
| c => { | ||
| let Ok(valid_color) = Color::from_string(c) else { | ||
| return Err(PyValueError::new_err(format!("Invalid color {c:?}"))); | ||
| }; | ||
| if let Some(applied) = color { | ||
| return Err(PyValueError::new_err(format!( | ||
| "Multiple colors found: {applied:?} and {valid_color:?}" | ||
| ))); | ||
| } | ||
| color = Some(valid_color); | ||
| } | ||
| } | ||
| } | ||
| if let Some(color) = color { | ||
| Ok(Self { | ||
| color, | ||
| bold, | ||
| underline, | ||
| }) | ||
| } else { | ||
| Err(PyValueError::new_err("Missing color in input string")) | ||
| } | ||
| } | ||
| fn __repr__(&self) -> String { | ||
| format!( | ||
| "Style({}, bold={}, underline={})", | ||
| self.color.__pyo3__repr__(), | ||
| python_bool_repr(self.bold), | ||
| python_bool_repr(self.underline) | ||
| ) | ||
| } | ||
| fn __str__(&self) -> String { | ||
| self.to_string() | ||
| } | ||
| } | ||
| impl std::fmt::Display for Style { | ||
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
| let values = [self.color.code(), "1", "4"] | ||
| .iter() | ||
| .zip([true, self.bold, self.underline]) | ||
| .filter_map(|(code, enabled)| enabled.then_some(*code)) | ||
| .collect::<Vec<_>>(); | ||
| write!(f, "\x1b[{}m", values.join(";")) | ||
| } | ||
| } | ||
| impl From<Color> for Style { | ||
| fn from(color: Color) -> Self { | ||
| Self { | ||
| color, | ||
| bold: false, | ||
| underline: false, | ||
| } | ||
| } | ||
| } | ||
| #[derive(Hash, Eq, PartialEq, Clone, Copy)] | ||
| pub enum TokenType { | ||
| BuiltinIdentifier, | ||
| Call, | ||
| Comment, | ||
| Identifier, | ||
| Keyword, | ||
| Numeric, | ||
| String, | ||
| PrimitiveValue, | ||
| Type, | ||
| } | ||
| impl TryFrom<String> for TokenType { | ||
| type Error = String; | ||
| fn try_from(value: String) -> Result<Self, Self::Error> { | ||
| match value.as_str() { | ||
| "BuiltinIdentifier" => Ok(Self::BuiltinIdentifier), | ||
| "Call" => Ok(Self::Call), | ||
| "Comment" => Ok(Self::Comment), | ||
| "Identifier" => Ok(Self::Identifier), | ||
| "Keyword" => Ok(Self::Keyword), | ||
| "Numeric" => Ok(Self::Numeric), | ||
| "String" => Ok(Self::String), | ||
| "PrimitiveValue" => Ok(Self::PrimitiveValue), | ||
| "Type" => Ok(Self::Type), | ||
| _ => Err(value), | ||
| } | ||
| } | ||
| } | ||
| pub type Theme = HashMap<TokenType, Style>; | ||
| pub static DEFAULT_THEME_PREPROCESSED: LazyLock<HashMap<String, Style>> = LazyLock::new(|| { | ||
| HashMap::from([ | ||
| ( | ||
| "BuiltinIdentifier".into(), | ||
| Style { | ||
| color: Color::Blue, | ||
| bold: true, | ||
| underline: false, | ||
| }, | ||
| ), | ||
| ("Call".into(), Style::from(Color::Blue)), | ||
| ("Comment".into(), Style::from(Color::Gray)), | ||
| ("Keyword".into(), Style::from(Color::Magenta)), | ||
| ("Numeric".into(), Style::from(Color::Cyan)), | ||
| ("PrimitiveValue".into(), Style::from(Color::Cyan)), | ||
| ("String".into(), Style::from(Color::Green)), | ||
| ("Type".into(), Style::from(Color::Orange)), | ||
| ]) | ||
| }); |
| import sys | ||
| from pathlib import Path | ||
| from typing import Annotated, Optional, Union, cast | ||
| import zig_codeblocks as zc | ||
| try: | ||
| import typer | ||
| except ModuleNotFoundError: | ||
| sys.exit( | ||
| "Cannot launch the CLI (failed to import typer)." | ||
| " Make sure you have the [cli] extra installed." | ||
| ) | ||
| PATH_HELP_TEXT = "Path to read the {} source from. Reads from STDIN if omitted." | ||
| THEME_OPTION = typer.Option( | ||
| "-t", | ||
| "--theme", | ||
| metavar="THEME", | ||
| help="An optional custom theme to use for Zig highlighting.", | ||
| ) | ||
| THEME_OVERRIDE_OPTION = typer.Option( | ||
| "-o", | ||
| "--theme-override", | ||
| metavar="THEME", | ||
| help="Optional changes to apply to the default theme for Zig highlighting.", | ||
| ) | ||
| app = typer.Typer() | ||
| def read_in(path: Optional[Path]) -> str: | ||
| if path is None: | ||
| return sys.stdin.read() | ||
| return path.read_text() | ||
| def parse_theme_config(config: str) -> dict[str, Union[str, zc.Style]]: | ||
| theme = {} | ||
| for token_type, style in (item.split(":") for item in config.split(",")): | ||
| if token_type not in zc.Theme.__optional_keys__: | ||
| msg = f"invalid token type: {token_type!r}" | ||
| raise ValueError(msg) | ||
| theme[token_type] = style if style == "none" else zc.Style.from_string(style) | ||
| return theme | ||
| def resolve_theme(theme: Optional[str], theme_overrides: Optional[str]) -> zc.Theme: | ||
| if theme is None: | ||
| if theme_overrides is None: | ||
| return zc.DEFAULT_THEME | ||
| new_theme = zc.DEFAULT_THEME.copy() | ||
| for k, v in parse_theme_config(theme_overrides).items(): | ||
| if v == "none": | ||
| del new_theme[k] # type: ignore[misc] | ||
| else: | ||
| new_theme[k] = v # type: ignore[literal-required] | ||
| return new_theme | ||
| if theme_overrides is None: | ||
| return cast(zc.Theme, parse_theme_config(theme)) | ||
| msg = "can't provide --theme and --theme-overrides at once" | ||
| raise ValueError(msg) | ||
| @app.command(name="zig") | ||
| def process_zig( | ||
| path: Annotated[ | ||
| Optional[Path], | ||
| typer.Argument(help=PATH_HELP_TEXT.format("Zig")), | ||
| ] = None, | ||
| theme: Annotated[Optional[str], THEME_OPTION] = None, | ||
| theme_overrides: Annotated[Optional[str], THEME_OVERRIDE_OPTION] = None, | ||
| ) -> None: | ||
| print(zc.highlight_zig_code(read_in(path), resolve_theme(theme, theme_overrides))) | ||
| @app.command(name="markdown") | ||
| def process_markdown( | ||
| path: Annotated[ | ||
| Optional[Path], | ||
| typer.Argument(help=PATH_HELP_TEXT.format("Markdown")), | ||
| ] = None, | ||
| only_code: Annotated[ | ||
| bool, | ||
| typer.Option( | ||
| "-c", | ||
| "--only-code", | ||
| help="If true, only Zig codeblocks will be included in the output.", | ||
| ), | ||
| ] = False, | ||
| theme: Annotated[Optional[str], THEME_OPTION] = None, | ||
| theme_overrides: Annotated[Optional[str], THEME_OVERRIDE_OPTION] = None, | ||
| ) -> None: | ||
| theme_ = resolve_theme(theme, theme_overrides) | ||
| print(zc.process_markdown(read_in(path), theme_, only_code=only_code)) | ||
| @app.command(name="codeblocks") | ||
| def extract_codeblocks( | ||
| path: Annotated[ | ||
| Optional[Path], | ||
| typer.Argument(help=PATH_HELP_TEXT.format("Markdown")), | ||
| ] = None, | ||
| langs: Annotated[ | ||
| Optional[str], | ||
| typer.Option( | ||
| "-l", | ||
| "--langs", | ||
| metavar="LANGS", | ||
| help=( | ||
| "A comma-separated list of languages to include." | ||
| " Includes all if unspecified." | ||
| ), | ||
| ), | ||
| ] = None, | ||
| ) -> None: | ||
| allowed_langs = set((langs or "").split(",")) | ||
| for cb in zc.extract_codeblocks(read_in(path)): | ||
| if langs is None: | ||
| print(cb) | ||
| continue | ||
| if cb.lang in allowed_langs: | ||
| print(cb) | ||
| if __name__ == "__main__": | ||
| app() |
| from enum import Enum | ||
| from typing import TypedDict | ||
| class CodeBlock: | ||
| """A code block extracted from a Markdown source.""" | ||
| lang: str | None | ||
| body: str | ||
| def __init__(self, lang: str | None, body: str) -> None: ... | ||
| class Color(Enum): | ||
| """ | ||
| An enumeration of 3-bit ANSI colors. | ||
| Some names were adjusted to match Discord's style. | ||
| """ | ||
| Gray = ... | ||
| Red = ... | ||
| Green = ... | ||
| Orange = ... | ||
| Blue = ... | ||
| Magenta = ... | ||
| Cyan = ... | ||
| White = ... | ||
| @staticmethod | ||
| def from_string(color: str) -> Color: ... | ||
| class Style: | ||
| """ | ||
| A style for syntax highlighting. | ||
| Takes a `Color` and can optionally be bold and/or underlined. | ||
| Produces an SGR sequence when converted to a string. | ||
| """ | ||
| color: Color | ||
| bold: bool | ||
| underline: bool | ||
| def __init__( | ||
| self, color: Color, *, bold: bool = False, underline: bool = False | ||
| ) -> None: ... | ||
| @staticmethod | ||
| def from_string(value: str) -> Style: ... | ||
| class Theme(TypedDict, total=False): | ||
| BuiltinIdentifier: Style | ||
| Call: Style | ||
| Comment: Style | ||
| Identifier: Style | ||
| Keyword: Style | ||
| Numeric: Style | ||
| PrimitiveValue: Style | ||
| String: Style | ||
| Type: Style | ||
| def highlight_zig_code(source: str | bytes, theme: Theme = ...) -> str: | ||
| """ | ||
| Return an ANSI syntax-highlighted version of the given Zig source code. | ||
| Assumes UTF-8. | ||
| """ | ||
| def process_markdown( | ||
| source: str | bytes, theme: Theme = ..., *, only_code: bool = False | ||
| ) -> str: | ||
| """ | ||
| Return a Markdown source with Zig code blocks syntax-highlighted. | ||
| If `only_code` is True, only processed Zig code blocks will be returned. | ||
| Assumes UTF-8. | ||
| """ | ||
| def extract_codeblocks(source: str | bytes) -> list[CodeBlock]: | ||
| """Return CodeBlocks from a Markdown source. Assumes UTF-8.""" |
+3
| from zig_codeblocks import highlight_zig_code | ||
| print(highlight_zig_code("const stdip@0'sirjgoicjgoii gueve up")) |
@@ -11,14 +11,31 @@ name: CI | ||
| PY_COLORS: 1 | ||
| UV_VERSION: 0.5.28 | ||
| UV_VERSION: 0.6.7 | ||
| CARGO_TERM_COLOR: always | ||
| jobs: | ||
| ci: | ||
| rust-ci: | ||
| runs-on: "${{ matrix.platform }}-latest" | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| platform: ["ubuntu", "macos", "windows"] | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Setup Rust | ||
| uses: dtolnay/rust-toolchain@stable | ||
| - name: Run Clippy | ||
| run: cargo clippy --verbose | ||
| - name: Run Rust tests (parsing) | ||
| run: cargo test --verbose | ||
| python-ci: | ||
| runs-on: "${{ matrix.platform }}-latest" | ||
| strategy: | ||
| fail-fast: false | ||
| # https://blog.jaraco.com/efficient-use-of-ci-resources/ | ||
| matrix: | ||
| python: ["3.10", "3.13"] | ||
| python: ["3.9", "3.13"] | ||
| platform: ["ubuntu", "macos", "windows"] | ||
| include: | ||
| - python: "3.10" | ||
| platform: "ubuntu" | ||
| - python: "3.11" | ||
@@ -35,12 +52,12 @@ platform: "ubuntu" | ||
| - name: Install project | ||
| run: uv sync -p ${{ matrix.python }} | ||
| - name: Run tests (with coverage) | ||
| run: uv run pytest --cov src --cov-report term-missing | ||
| run: uv sync -p ${{ matrix.python }} --extra cli | ||
| - name: Run Python tests (parsing + highlighting + styling) | ||
| run: uv run -p ${{ matrix.python }} pytest | ||
| - name: Lint code | ||
| if: always() | ||
| run: | | ||
| uv run ruff check | ||
| uv run ruff format --check | ||
| uv run -p ${{ matrix.python }} ruff check | ||
| uv run -p ${{ matrix.python }} ruff format --check | ||
| - name: Run mypy | ||
| if: always() | ||
| run: uv run mypy --strict src | ||
| run: uv run -p ${{ matrix.python }} mypy --strict src tests |
+4
-0
@@ -11,1 +11,5 @@ # Python-generated files | ||
| .venv | ||
| # Rust/PyO3-generated files | ||
| target/ | ||
| *.so |
+31
-1
@@ -8,4 +8,33 @@ # Changelog | ||
| ## [v0.2.3] - 2025-02-15 | ||
| ## [v0.3.0] - 2025-04-15 | ||
| ### Added | ||
| - A command-line interface | ||
| - Python 3.9 support | ||
| - `CodeBlock` objects now return the fenced Markdown code block form when | ||
| converted to string | ||
| - `Style` objects can now be created from strings, e.g. | ||
| `Style.from_string("cyan+bold")` is the same as `Style(Color.Cyan, bold=True)` | ||
| ### Changed | ||
| - Most of the parsing/highlighting logic was moved to Rust, leading to | ||
| significant speedups for both small (<300 lines) and large (>10k lines) | ||
| inputs: | ||
| - `highlight_zig_code` is 4–10x faster for small inputs and ~300x faster for | ||
| large inputs | ||
| - `process_markdown(only_code=False)` is 3–6x faster for small inputs and ~50x | ||
| faster for large inputs | ||
| - `process_markdown(only_code=True)` is ~4x faster for all inputs | ||
| - `extract_codeblocks` is ~10% faster for large inputs | ||
| - `Color`: | ||
| - can no longer be instantiated with `Color["red"]`, use | ||
| `Color.from_string("red")` instead | ||
| - members now use PascalCase names, e.g. `Color.BLUE` is now `Color.Blue` | ||
| - `extract_codeblocks`: | ||
| - no longer strips CR and LF characters | ||
| - now returns a list instead of an iterator | ||
| - `Theme` keys are now PascalCase instead of snake_case | ||
| ## [v0.2.3] - 2025-02-16 | ||
| ### Fixed | ||
@@ -74,1 +103,2 @@ - Fixed call-highlight checks consuming tokens instead of peeking them | ||
| [v0.2.3]: https://github.com/trag1c/zig-codeblocks/compare/v0.2.2...v0.2.3 | ||
| [v0.3.0]: https://github.com/trag1c/zig-codeblocks/compare/v0.2.3...v0.3.0 |
+69
-50
| Metadata-Version: 2.4 | ||
| Name: zig-codeblocks | ||
| Version: 0.2.3 | ||
| Version: 0.3.0 | ||
| Requires-Dist: typer-slim>=0.15.2 ; extra == 'cli' | ||
| Provides-Extra: cli | ||
| License-File: LICENSE | ||
| Summary: Zig ANSI syntax highlighting library | ||
| Author-email: trag1c <dev@jakubr.me> | ||
| License: MIT | ||
| Requires-Python: >=3.9 | ||
| Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM | ||
| Project-URL: repository, https://github.com/trag1c/zig-codeblocks | ||
| Author-email: trag1c <trag1cdev@yahoo.com> | ||
| License-Expression: MIT | ||
| License-File: LICENSE | ||
| Requires-Python: >=3.10 | ||
| Requires-Dist: more-itertools~=10.6 | ||
| Requires-Dist: tree-sitter-zig<2,>=1.1.2 | ||
| Requires-Dist: tree-sitter~=0.24.0 | ||
| Description-Content-Type: text/markdown | ||
@@ -20,7 +19,18 @@ [](https://github.com/astral-sh/uv) | ||
| `zig-codeblocks` is a CPython 3.10+ library for adding syntax highlighting to | ||
| Zig code blocks in Markdown files through ANSI escape codes. | ||
| `zig-codeblocks` is a Rust-powered CPython 3.9+ library for adding syntax | ||
| highlighting to Zig code blocks in Markdown files through ANSI escape codes. | ||
| Originally intended for patching the lack of syntax highlighting for Zig on | ||
| Discord. | ||
| - [Installation](#installation) | ||
| - [API Reference](#api-reference) | ||
| - [`extract_codeblocks`](#extract_codeblocks) | ||
| - [`highlight_zig_code`](#highlight_zig_code) | ||
| - [`process_markdown`](#process_markdown) | ||
| - [`CodeBlock`](#codeblock) | ||
| - [`Color`](#color) | ||
| - [`Style`](#style) | ||
| - [`Theme`](#theme) | ||
| - [`DEFAULT_THEME`](#default_theme) | ||
| - [License](#license) | ||
@@ -36,2 +46,11 @@ ## Installation | ||
| ``` | ||
| --- | ||
| `zig-codeblocks` also exposes a CLI via a `cli` extra: | ||
| ```py | ||
| pip install "zig-codeblocks[cli]" | ||
| ``` | ||
| If the CLI is all you need, you can run it with `uvx`: | ||
| ```sh | ||
| uvx "zig-codeblocks[cli]" --help | ||
| ``` | ||
@@ -43,3 +62,3 @@ | ||
| ```py | ||
| def extract_codeblocks(source: str | bytes) -> Iterator[CodeBlock] | ||
| def extract_codeblocks(source: str | bytes) -> list[CodeBlock] | ||
| ``` | ||
@@ -92,5 +111,5 @@ Yields [`CodeBlock`](#codeblock)s from a Markdown source. | ||
| theme = DEFAULT_THEME.copy() | ||
| theme.builtin_identifiers = Style(Color.ORANGE, underline=True) | ||
| theme.strings = Style(Color.CYAN) | ||
| theme.types = None | ||
| theme["BuiltinIdentifier"] = Style(Color.Orange, underline=True) | ||
| theme["String"] = Style(Color.Cyan) | ||
| del theme["Type"] | ||
@@ -135,7 +154,7 @@ print( | ||
| ```py | ||
| class CodeBlock(NamedTuple): | ||
| class CodeBlock: | ||
| lang: str | ||
| body: str | ||
| ``` | ||
| A code block extracted from a Markdown source. | ||
| A code block extracted from a Markdown source. Immutable. | ||
@@ -146,13 +165,14 @@ | ||
| class Color(Enum): | ||
| GRAY = "30" | ||
| RED = "31" | ||
| GREEN = "32" | ||
| ORANGE = "33" | ||
| BLUE = "34" | ||
| MAGENTA = "35" | ||
| CYAN = "36" | ||
| WHITE = "37" # Black for light mode | ||
| Gray = "30" | ||
| Red = "31" | ||
| Green = "32" | ||
| Orange = "33" | ||
| Blue = "34" | ||
| Magenta = "35" | ||
| Cyan = "36" | ||
| White = "37" # Black for light mode | ||
| ``` | ||
| An enumeration of 3-bit ANSI colors. | ||
| Some names were adjusted to match Discord's style. | ||
| A color can be instantiated from a string too: `Color.from_string("Blue")`. | ||
@@ -162,6 +182,4 @@ | ||
| ```py | ||
| @dataclass(slots=True, frozen=True) | ||
| class Style: | ||
| color: Color | ||
| _: KW_ONLY | ||
| bold: bool = False | ||
@@ -179,11 +197,11 @@ underline: bool = False | ||
| class Theme(TypedDict, total=False): | ||
| builtin_identifiers: Style | ||
| calls: Style | ||
| comments: Style | ||
| identifiers: Style | ||
| keywords: Style | ||
| numeric: Style | ||
| strings: Style | ||
| primitive_values: Style | ||
| types: Style | ||
| BuiltinIdentifier: Style | ||
| Call: Style | ||
| Comment: Style | ||
| Identifier: Style | ||
| Keyword: Style | ||
| Numeric: Style | ||
| PrimitiveValue: Style | ||
| String: Style | ||
| Type: Style | ||
| ``` | ||
@@ -198,9 +216,9 @@ A theme dict for syntax highlighting Zig code. | ||
| theme_foo = Theme( | ||
| numeric=Style(Color.BLUE), | ||
| strings=Style(Color.GREEN), | ||
| Numeric=Style(Color.Blue), | ||
| String=Style(Color.Green), | ||
| ) | ||
| theme_bar: Theme = { | ||
| "numeric": Style(Color.BLUE), | ||
| "strings": Style(Color.GREEN), | ||
| "Numeric": Style(Color.Blue), | ||
| "String": Style(Color.Green), | ||
| } | ||
@@ -215,12 +233,12 @@ | ||
| ```py | ||
| DEFAULT_THEME = Theme( | ||
| builtin_identifiers=Style(Color.BLUE, bold=True), | ||
| calls=Style(Color.BLUE), | ||
| comments=Style(Color.GRAY), | ||
| keywords=Style(Color.MAGENTA), | ||
| numeric=Style(Color.CYAN), | ||
| primitive_values=Style(Color.CYAN), | ||
| strings=Style(Color.GREEN), | ||
| types=Style(Color.ORANGE), | ||
| ) | ||
| DEFAULT_THEME: Theme = { | ||
| "BuiltinIdentifier": Style(Color.Blue, bold=True), | ||
| "Call": Style(Color.Blue), | ||
| "Comment": Style(Color.Gray), | ||
| "Keyword": Style(Color.Magenta), | ||
| "Numeric": Style(Color.Cyan), | ||
| "PrimitiveValue": Style(Color.Cyan), | ||
| "String": Style(Color.Green), | ||
| "Type": Style(Color.Orange), | ||
| } | ||
| ``` | ||
@@ -235,1 +253,2 @@ | ||
| [trag1c]: https://github.com/trag1c/ | ||
+28
-22
| [project] | ||
| name = "zig-codeblocks" | ||
| version = "0.2.3" | ||
| version = "0.3.0" | ||
| description = "Zig ANSI syntax highlighting library" | ||
| readme = "README.md" | ||
| license = "MIT" | ||
| authors = [{ name = "trag1c", email = "trag1cdev@yahoo.com" }] | ||
| requires-python = ">=3.10" | ||
| dependencies = [ | ||
| "more-itertools~=10.6", | ||
| "tree-sitter~=0.24.0", | ||
| "tree-sitter-zig>=1.1.2,<2", | ||
| ] | ||
| authors = [{ name = "trag1c", email = "dev@jakubr.me" }] | ||
| requires-python = ">=3.9" | ||
| dependencies = [] | ||
@@ -18,11 +14,19 @@ [project.urls] | ||
| [project.scripts] | ||
| zig-codeblocks = "zig_codeblocks.__main__:app" | ||
| [project.optional-dependencies] | ||
| cli = ["typer-slim>=0.15.2"] | ||
| [build-system] | ||
| requires = ["hatchling"] | ||
| build-backend = "hatchling.build" | ||
| requires = ["maturin>=1.0,<2.0"] | ||
| build-backend = "maturin" | ||
| [dependency-groups] | ||
| dev = ["mypy>=1.14.1", "pytest>=8.3.4", "pytest-cov>=6.0.0", "ruff>=0.9.4"] | ||
| dev = ["mypy>=1.14.1", "pytest>=8.3.4", "ruff>=0.9.4"] | ||
| [tool.coverage.report] | ||
| exclude_also = ["if TYPE_CHECKING:"] | ||
| [tool.maturin] | ||
| module-name = "zig_codeblocks._core" | ||
| python-packages = ["zig_codeblocks"] | ||
| python-source = "src" | ||
@@ -32,11 +36,11 @@ [tool.ruff.lint] | ||
| ignore = [ | ||
| "COM", | ||
| "D", | ||
| "FIX", | ||
| "ANN401", | ||
| "ISC001", | ||
| "T201", | ||
| "TD003", | ||
| "PLR2004", | ||
| "S105", | ||
| "COM", | ||
| "D", | ||
| "FIX", | ||
| "ANN401", | ||
| "ISC001", | ||
| "T201", | ||
| "TD003", | ||
| "PLR2004", | ||
| "S105", | ||
| ] | ||
@@ -46,1 +50,3 @@ | ||
| "tests/*" = ["INP", "FBT", "PLC2701", "S101", "SLF001"] | ||
| "_core.pyi" = ["PYI021"] | ||
| "__main__.py" = ["FA", "TCH", "FBT002", "UP00"] |
+60
-41
@@ -6,7 +6,18 @@ [](https://github.com/astral-sh/uv) | ||
| `zig-codeblocks` is a CPython 3.10+ library for adding syntax highlighting to | ||
| Zig code blocks in Markdown files through ANSI escape codes. | ||
| `zig-codeblocks` is a Rust-powered CPython 3.9+ library for adding syntax | ||
| highlighting to Zig code blocks in Markdown files through ANSI escape codes. | ||
| Originally intended for patching the lack of syntax highlighting for Zig on | ||
| Discord. | ||
| - [Installation](#installation) | ||
| - [API Reference](#api-reference) | ||
| - [`extract_codeblocks`](#extract_codeblocks) | ||
| - [`highlight_zig_code`](#highlight_zig_code) | ||
| - [`process_markdown`](#process_markdown) | ||
| - [`CodeBlock`](#codeblock) | ||
| - [`Color`](#color) | ||
| - [`Style`](#style) | ||
| - [`Theme`](#theme) | ||
| - [`DEFAULT_THEME`](#default_theme) | ||
| - [License](#license) | ||
@@ -22,2 +33,11 @@ ## Installation | ||
| ``` | ||
| --- | ||
| `zig-codeblocks` also exposes a CLI via a `cli` extra: | ||
| ```py | ||
| pip install "zig-codeblocks[cli]" | ||
| ``` | ||
| If the CLI is all you need, you can run it with `uvx`: | ||
| ```sh | ||
| uvx "zig-codeblocks[cli]" --help | ||
| ``` | ||
@@ -29,3 +49,3 @@ | ||
| ```py | ||
| def extract_codeblocks(source: str | bytes) -> Iterator[CodeBlock] | ||
| def extract_codeblocks(source: str | bytes) -> list[CodeBlock] | ||
| ``` | ||
@@ -78,5 +98,5 @@ Yields [`CodeBlock`](#codeblock)s from a Markdown source. | ||
| theme = DEFAULT_THEME.copy() | ||
| theme.builtin_identifiers = Style(Color.ORANGE, underline=True) | ||
| theme.strings = Style(Color.CYAN) | ||
| theme.types = None | ||
| theme["BuiltinIdentifier"] = Style(Color.Orange, underline=True) | ||
| theme["String"] = Style(Color.Cyan) | ||
| del theme["Type"] | ||
@@ -121,7 +141,7 @@ print( | ||
| ```py | ||
| class CodeBlock(NamedTuple): | ||
| class CodeBlock: | ||
| lang: str | ||
| body: str | ||
| ``` | ||
| A code block extracted from a Markdown source. | ||
| A code block extracted from a Markdown source. Immutable. | ||
@@ -132,13 +152,14 @@ | ||
| class Color(Enum): | ||
| GRAY = "30" | ||
| RED = "31" | ||
| GREEN = "32" | ||
| ORANGE = "33" | ||
| BLUE = "34" | ||
| MAGENTA = "35" | ||
| CYAN = "36" | ||
| WHITE = "37" # Black for light mode | ||
| Gray = "30" | ||
| Red = "31" | ||
| Green = "32" | ||
| Orange = "33" | ||
| Blue = "34" | ||
| Magenta = "35" | ||
| Cyan = "36" | ||
| White = "37" # Black for light mode | ||
| ``` | ||
| An enumeration of 3-bit ANSI colors. | ||
| Some names were adjusted to match Discord's style. | ||
| A color can be instantiated from a string too: `Color.from_string("Blue")`. | ||
@@ -148,6 +169,4 @@ | ||
| ```py | ||
| @dataclass(slots=True, frozen=True) | ||
| class Style: | ||
| color: Color | ||
| _: KW_ONLY | ||
| bold: bool = False | ||
@@ -165,11 +184,11 @@ underline: bool = False | ||
| class Theme(TypedDict, total=False): | ||
| builtin_identifiers: Style | ||
| calls: Style | ||
| comments: Style | ||
| identifiers: Style | ||
| keywords: Style | ||
| numeric: Style | ||
| strings: Style | ||
| primitive_values: Style | ||
| types: Style | ||
| BuiltinIdentifier: Style | ||
| Call: Style | ||
| Comment: Style | ||
| Identifier: Style | ||
| Keyword: Style | ||
| Numeric: Style | ||
| PrimitiveValue: Style | ||
| String: Style | ||
| Type: Style | ||
| ``` | ||
@@ -184,9 +203,9 @@ A theme dict for syntax highlighting Zig code. | ||
| theme_foo = Theme( | ||
| numeric=Style(Color.BLUE), | ||
| strings=Style(Color.GREEN), | ||
| Numeric=Style(Color.Blue), | ||
| String=Style(Color.Green), | ||
| ) | ||
| theme_bar: Theme = { | ||
| "numeric": Style(Color.BLUE), | ||
| "strings": Style(Color.GREEN), | ||
| "Numeric": Style(Color.Blue), | ||
| "String": Style(Color.Green), | ||
| } | ||
@@ -201,12 +220,12 @@ | ||
| ```py | ||
| DEFAULT_THEME = Theme( | ||
| builtin_identifiers=Style(Color.BLUE, bold=True), | ||
| calls=Style(Color.BLUE), | ||
| comments=Style(Color.GRAY), | ||
| keywords=Style(Color.MAGENTA), | ||
| numeric=Style(Color.CYAN), | ||
| primitive_values=Style(Color.CYAN), | ||
| strings=Style(Color.GREEN), | ||
| types=Style(Color.ORANGE), | ||
| ) | ||
| DEFAULT_THEME: Theme = { | ||
| "BuiltinIdentifier": Style(Color.Blue, bold=True), | ||
| "Call": Style(Color.Blue), | ||
| "Comment": Style(Color.Gray), | ||
| "Keyword": Style(Color.Magenta), | ||
| "Numeric": Style(Color.Cyan), | ||
| "PrimitiveValue": Style(Color.Cyan), | ||
| "String": Style(Color.Green), | ||
| "Type": Style(Color.Orange), | ||
| } | ||
| ``` | ||
@@ -213,0 +232,0 @@ |
@@ -1,6 +0,40 @@ | ||
| from zig_codeblocks.consts import DEFAULT_THEME | ||
| from zig_codeblocks.formatting import highlight_zig_code, process_markdown | ||
| from zig_codeblocks.parsing import CodeBlock, extract_codeblocks | ||
| from zig_codeblocks.styling import Color, Style, Theme | ||
| from __future__ import annotations | ||
| from typing import TypedDict | ||
| from zig_codeblocks._core import ( | ||
| CodeBlock, | ||
| Color, | ||
| Style, | ||
| extract_codeblocks, | ||
| highlight_zig_code, | ||
| process_markdown, | ||
| ) | ||
| class Theme(TypedDict, total=False): | ||
| """A theme for syntax highlighting Zig code.""" | ||
| BuiltinIdentifier: Style | ||
| Call: Style | ||
| Comment: Style | ||
| Identifier: Style | ||
| Keyword: Style | ||
| Numeric: Style | ||
| PrimitiveValue: Style | ||
| String: Style | ||
| Type: Style | ||
| DEFAULT_THEME: Theme = { | ||
| "BuiltinIdentifier": Style(Color.Blue, bold=True), | ||
| "Call": Style(Color.Blue), | ||
| "Comment": Style(Color.Gray), | ||
| "Keyword": Style(Color.Magenta), | ||
| "Numeric": Style(Color.Cyan), | ||
| "PrimitiveValue": Style(Color.Cyan), | ||
| "String": Style(Color.Green), | ||
| "Type": Style(Color.Orange), | ||
| } | ||
| __all__ = ( | ||
@@ -7,0 +41,0 @@ "DEFAULT_THEME", |
| [ | ||
| { | ||
| "kind": "const", | ||
| "start": 0, | ||
| "end": 5 | ||
| "range": [0, 5] | ||
| }, | ||
@@ -10,9 +9,7 @@ { | ||
| "value": "print", | ||
| "start": 6, | ||
| "end": 11 | ||
| "range": [6, 11] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 12, | ||
| "end": 13 | ||
| "range": [12, 13] | ||
| }, | ||
@@ -22,14 +19,11 @@ { | ||
| "value": "@import", | ||
| "start": 14, | ||
| "end": 21 | ||
| "range": [14, 21] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 21, | ||
| "end": 22 | ||
| "range": [21, 22] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 22, | ||
| "end": 23 | ||
| "range": [22, 23] | ||
| }, | ||
@@ -39,19 +33,15 @@ { | ||
| "value": "std", | ||
| "start": 23, | ||
| "end": 26 | ||
| "range": [23, 26] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 26, | ||
| "end": 27 | ||
| "range": [26, 27] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 27, | ||
| "end": 28 | ||
| "range": [27, 28] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 28, | ||
| "end": 29 | ||
| "range": [28, 29] | ||
| }, | ||
@@ -61,9 +51,7 @@ { | ||
| "value": "debug", | ||
| "start": 29, | ||
| "end": 34 | ||
| "range": [29, 34] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 34, | ||
| "end": 35 | ||
| "range": [34, 35] | ||
| }, | ||
@@ -73,19 +61,15 @@ { | ||
| "value": "print", | ||
| "start": 35, | ||
| "end": 40 | ||
| "range": [35, 40] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 40, | ||
| "end": 41 | ||
| "range": [40, 41] | ||
| }, | ||
| { | ||
| "kind": "pub", | ||
| "start": 43, | ||
| "end": 46 | ||
| "range": [43, 46] | ||
| }, | ||
| { | ||
| "kind": "fn", | ||
| "start": 47, | ||
| "end": 49 | ||
| "range": [47, 49] | ||
| }, | ||
@@ -95,29 +79,23 @@ { | ||
| "value": "main", | ||
| "start": 50, | ||
| "end": 54 | ||
| "range": [50, 54] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 54, | ||
| "end": 55 | ||
| "range": [54, 55] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 55, | ||
| "end": 56 | ||
| "range": [55, 56] | ||
| }, | ||
| { | ||
| "kind": "void", | ||
| "start": 57, | ||
| "end": 61 | ||
| "range": [57, 61] | ||
| }, | ||
| { | ||
| "kind": "{", | ||
| "start": 62, | ||
| "end": 63 | ||
| "range": [62, 63] | ||
| }, | ||
| { | ||
| "kind": "var", | ||
| "start": 68, | ||
| "end": 71 | ||
| "range": [68, 71] | ||
| }, | ||
@@ -127,9 +105,7 @@ { | ||
| "value": "x", | ||
| "start": 72, | ||
| "end": 73 | ||
| "range": [72, 73] | ||
| }, | ||
| { | ||
| "kind": ":", | ||
| "start": 73, | ||
| "end": 74 | ||
| "range": [73, 74] | ||
| }, | ||
@@ -139,19 +115,15 @@ { | ||
| "value": "i32", | ||
| "start": 75, | ||
| "end": 78 | ||
| "range": [75, 78] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 79, | ||
| "end": 80 | ||
| "range": [79, 80] | ||
| }, | ||
| { | ||
| "kind": "undefined", | ||
| "start": 81, | ||
| "end": 90 | ||
| "range": [81, 90] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 90, | ||
| "end": 91 | ||
| "range": [90, 91] | ||
| }, | ||
@@ -161,9 +133,7 @@ { | ||
| "value": "x", | ||
| "start": 96, | ||
| "end": 97 | ||
| "range": [96, 97] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 98, | ||
| "end": 99 | ||
| "range": [98, 99] | ||
| }, | ||
@@ -173,9 +143,7 @@ { | ||
| "value": "1", | ||
| "start": 100, | ||
| "end": 101 | ||
| "range": [100, 101] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 101, | ||
| "end": 102 | ||
| "range": [101, 102] | ||
| }, | ||
@@ -185,14 +153,11 @@ { | ||
| "value": "print", | ||
| "start": 107, | ||
| "end": 112 | ||
| "range": [107, 112] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 112, | ||
| "end": 113 | ||
| "range": [112, 113] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 113, | ||
| "end": 114 | ||
| "range": [113, 114] | ||
| }, | ||
@@ -202,24 +167,19 @@ { | ||
| "value": "{d}", | ||
| "start": 114, | ||
| "end": 117 | ||
| "range": [114, 117] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 117, | ||
| "end": 118 | ||
| "range": [117, 118] | ||
| }, | ||
| { | ||
| "kind": ",", | ||
| "start": 118, | ||
| "end": 119 | ||
| "range": [118, 119] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 120, | ||
| "end": 121 | ||
| "range": [120, 121] | ||
| }, | ||
| { | ||
| "kind": "{", | ||
| "start": 121, | ||
| "end": 122 | ||
| "range": [121, 122] | ||
| }, | ||
@@ -229,25 +189,20 @@ { | ||
| "value": "x", | ||
| "start": 122, | ||
| "end": 123 | ||
| "range": [122, 123] | ||
| }, | ||
| { | ||
| "kind": "}", | ||
| "start": 123, | ||
| "end": 124 | ||
| "range": [123, 124] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 124, | ||
| "end": 125 | ||
| "range": [124, 125] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 125, | ||
| "end": 126 | ||
| "range": [125, 126] | ||
| }, | ||
| { | ||
| "kind": "}", | ||
| "start": 127, | ||
| "end": 128 | ||
| "range": [127, 128] | ||
| } | ||
| ] | ||
| ] |
| [ | ||
| { | ||
| "kind": "const", | ||
| "start": 0, | ||
| "end": 5 | ||
| "range": [0, 5] | ||
| }, | ||
@@ -10,9 +9,7 @@ { | ||
| "value": "print", | ||
| "start": 6, | ||
| "end": 11 | ||
| "range": [6, 11] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 12, | ||
| "end": 13 | ||
| "range": [12, 13] | ||
| }, | ||
@@ -22,14 +19,11 @@ { | ||
| "value": "@import", | ||
| "start": 14, | ||
| "end": 21 | ||
| "range": [14, 21] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 21, | ||
| "end": 22 | ||
| "range": [21, 22] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 22, | ||
| "end": 23 | ||
| "range": [22, 23] | ||
| }, | ||
@@ -39,19 +33,15 @@ { | ||
| "value": "std", | ||
| "start": 23, | ||
| "end": 26 | ||
| "range": [23, 26] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 26, | ||
| "end": 27 | ||
| "range": [26, 27] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 27, | ||
| "end": 28 | ||
| "range": [27, 28] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 28, | ||
| "end": 29 | ||
| "range": [28, 29] | ||
| }, | ||
@@ -61,9 +51,7 @@ { | ||
| "value": "debug", | ||
| "start": 29, | ||
| "end": 34 | ||
| "range": [29, 34] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 34, | ||
| "end": 35 | ||
| "range": [34, 35] | ||
| }, | ||
@@ -73,19 +61,15 @@ { | ||
| "value": "print", | ||
| "start": 35, | ||
| "end": 40 | ||
| "range": [35, 40] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 40, | ||
| "end": 41 | ||
| "range": [40, 41] | ||
| }, | ||
| { | ||
| "kind": "pub", | ||
| "start": 43, | ||
| "end": 46 | ||
| "range": [43, 46] | ||
| }, | ||
| { | ||
| "kind": "fn", | ||
| "start": 47, | ||
| "end": 49 | ||
| "range": [47, 49] | ||
| }, | ||
@@ -95,24 +79,19 @@ { | ||
| "value": "main", | ||
| "start": 50, | ||
| "end": 54 | ||
| "range": [50, 54] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 54, | ||
| "end": 55 | ||
| "range": [54, 55] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 55, | ||
| "end": 56 | ||
| "range": [55, 56] | ||
| }, | ||
| { | ||
| "kind": "void", | ||
| "start": 57, | ||
| "end": 61 | ||
| "range": [57, 61] | ||
| }, | ||
| { | ||
| "kind": "{", | ||
| "start": 62, | ||
| "end": 63 | ||
| "range": [62, 63] | ||
| }, | ||
@@ -122,4 +101,3 @@ { | ||
| "value": "// Comments in Zig start with \"//\" and end at the next LF byte (end of line).", | ||
| "start": 68, | ||
| "end": 145 | ||
| "range": [68, 145] | ||
| }, | ||
@@ -129,4 +107,3 @@ { | ||
| "value": "// The line below is a comment and won't be executed.", | ||
| "start": 150, | ||
| "end": 203 | ||
| "range": [150, 203] | ||
| }, | ||
@@ -136,4 +113,3 @@ { | ||
| "value": "//print(\"Hello?\", .{});", | ||
| "start": 209, | ||
| "end": 232 | ||
| "range": [209, 232] | ||
| }, | ||
@@ -143,14 +119,11 @@ { | ||
| "value": "print", | ||
| "start": 238, | ||
| "end": 243 | ||
| "range": [238, 243] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 243, | ||
| "end": 244 | ||
| "range": [243, 244] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 244, | ||
| "end": 245 | ||
| "range": [244, 245] | ||
| }, | ||
@@ -160,4 +133,3 @@ { | ||
| "value": "Hello, world!", | ||
| "start": 245, | ||
| "end": 258 | ||
| "range": [245, 258] | ||
| }, | ||
@@ -167,39 +139,31 @@ { | ||
| "value": "\\n", | ||
| "start": 258, | ||
| "end": 260 | ||
| "range": [258, 260] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 260, | ||
| "end": 261 | ||
| "range": [260, 261] | ||
| }, | ||
| { | ||
| "kind": ",", | ||
| "start": 261, | ||
| "end": 262 | ||
| "range": [261, 262] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 263, | ||
| "end": 264 | ||
| "range": [263, 264] | ||
| }, | ||
| { | ||
| "kind": "{", | ||
| "start": 264, | ||
| "end": 265 | ||
| "range": [264, 265] | ||
| }, | ||
| { | ||
| "kind": "}", | ||
| "start": 265, | ||
| "end": 266 | ||
| "range": [265, 266] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 266, | ||
| "end": 267 | ||
| "range": [266, 267] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 267, | ||
| "end": 268 | ||
| "range": [267, 268] | ||
| }, | ||
@@ -209,10 +173,8 @@ { | ||
| "value": "// another comment", | ||
| "start": 269, | ||
| "end": 287 | ||
| "range": [269, 287] | ||
| }, | ||
| { | ||
| "kind": "}", | ||
| "start": 288, | ||
| "end": 289 | ||
| "range": [288, 289] | ||
| } | ||
| ] | ||
| ] |
| [ | ||
| { | ||
| "kind": "const", | ||
| "start": 0, | ||
| "end": 5 | ||
| "range": [0, 5] | ||
| }, | ||
@@ -10,9 +9,7 @@ { | ||
| "value": "std", | ||
| "start": 6, | ||
| "end": 9 | ||
| "range": [6, 9] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 10, | ||
| "end": 11 | ||
| "range": [10, 11] | ||
| }, | ||
@@ -22,14 +19,11 @@ { | ||
| "value": "@import", | ||
| "start": 12, | ||
| "end": 19 | ||
| "range": [12, 19] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 19, | ||
| "end": 20 | ||
| "range": [19, 20] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 20, | ||
| "end": 21 | ||
| "range": [20, 21] | ||
| }, | ||
@@ -39,29 +33,23 @@ { | ||
| "value": "std", | ||
| "start": 21, | ||
| "end": 24 | ||
| "range": [21, 24] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 24, | ||
| "end": 25 | ||
| "range": [24, 25] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 25, | ||
| "end": 26 | ||
| "range": [25, 26] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 26, | ||
| "end": 27 | ||
| "range": [26, 27] | ||
| }, | ||
| { | ||
| "kind": "pub", | ||
| "start": 29, | ||
| "end": 32 | ||
| "range": [29, 32] | ||
| }, | ||
| { | ||
| "kind": "fn", | ||
| "start": 33, | ||
| "end": 35 | ||
| "range": [33, 35] | ||
| }, | ||
@@ -71,34 +59,27 @@ { | ||
| "value": "main", | ||
| "start": 36, | ||
| "end": 40 | ||
| "range": [36, 40] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 40, | ||
| "end": 41 | ||
| "range": [40, 41] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 41, | ||
| "end": 42 | ||
| "range": [41, 42] | ||
| }, | ||
| { | ||
| "kind": "!", | ||
| "start": 43, | ||
| "end": 44 | ||
| "range": [43, 44] | ||
| }, | ||
| { | ||
| "kind": "void", | ||
| "start": 44, | ||
| "end": 48 | ||
| "range": [44, 48] | ||
| }, | ||
| { | ||
| "kind": "{", | ||
| "start": 49, | ||
| "end": 50 | ||
| "range": [49, 50] | ||
| }, | ||
| { | ||
| "kind": "const", | ||
| "start": 55, | ||
| "end": 60 | ||
| "range": [55, 60] | ||
| }, | ||
@@ -108,9 +89,7 @@ { | ||
| "value": "stdout", | ||
| "start": 61, | ||
| "end": 67 | ||
| "range": [61, 67] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 68, | ||
| "end": 69 | ||
| "range": [68, 69] | ||
| }, | ||
@@ -120,9 +99,7 @@ { | ||
| "value": "std", | ||
| "start": 70, | ||
| "end": 73 | ||
| "range": [70, 73] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 73, | ||
| "end": 74 | ||
| "range": [73, 74] | ||
| }, | ||
@@ -132,9 +109,7 @@ { | ||
| "value": "io", | ||
| "start": 74, | ||
| "end": 76 | ||
| "range": [74, 76] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 76, | ||
| "end": 77 | ||
| "range": [76, 77] | ||
| }, | ||
@@ -144,19 +119,15 @@ { | ||
| "value": "getStdOut", | ||
| "start": 77, | ||
| "end": 86 | ||
| "range": [77, 86] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 86, | ||
| "end": 87 | ||
| "range": [86, 87] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 87, | ||
| "end": 88 | ||
| "range": [87, 88] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 88, | ||
| "end": 89 | ||
| "range": [88, 89] | ||
| }, | ||
@@ -166,24 +137,19 @@ { | ||
| "value": "writer", | ||
| "start": 89, | ||
| "end": 95 | ||
| "range": [89, 95] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 95, | ||
| "end": 96 | ||
| "range": [95, 96] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 96, | ||
| "end": 97 | ||
| "range": [96, 97] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 97, | ||
| "end": 98 | ||
| "range": [97, 98] | ||
| }, | ||
| { | ||
| "kind": "const", | ||
| "start": 104, | ||
| "end": 109 | ||
| "range": [104, 109] | ||
| }, | ||
@@ -193,14 +159,11 @@ { | ||
| "value": "greeting", | ||
| "start": 110, | ||
| "end": 118 | ||
| "range": [110, 118] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 119, | ||
| "end": 120 | ||
| "range": [119, 120] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 121, | ||
| "end": 122 | ||
| "range": [121, 122] | ||
| }, | ||
@@ -210,4 +173,3 @@ { | ||
| "value": "Hello, 🌍!", | ||
| "start": 122, | ||
| "end": 134 | ||
| "range": [122, 134] | ||
| }, | ||
@@ -217,19 +179,15 @@ { | ||
| "value": "\\n", | ||
| "start": 134, | ||
| "end": 136 | ||
| "range": [134, 136] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 136, | ||
| "end": 137 | ||
| "range": [136, 137] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 137, | ||
| "end": 138 | ||
| "range": [137, 138] | ||
| }, | ||
| { | ||
| "kind": "try", | ||
| "start": 143, | ||
| "end": 146 | ||
| "range": [143, 146] | ||
| }, | ||
@@ -239,9 +197,7 @@ { | ||
| "value": "stdout", | ||
| "start": 147, | ||
| "end": 153 | ||
| "range": [147, 153] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 153, | ||
| "end": 154 | ||
| "range": [153, 154] | ||
| }, | ||
@@ -251,14 +207,11 @@ { | ||
| "value": "print", | ||
| "start": 154, | ||
| "end": 159 | ||
| "range": [154, 159] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 159, | ||
| "end": 160 | ||
| "range": [159, 160] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 160, | ||
| "end": 161 | ||
| "range": [160, 161] | ||
| }, | ||
@@ -268,24 +221,19 @@ { | ||
| "value": "{s}", | ||
| "start": 161, | ||
| "end": 164 | ||
| "range": [161, 164] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 164, | ||
| "end": 165 | ||
| "range": [164, 165] | ||
| }, | ||
| { | ||
| "kind": ",", | ||
| "start": 165, | ||
| "end": 166 | ||
| "range": [165, 166] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 167, | ||
| "end": 168 | ||
| "range": [167, 168] | ||
| }, | ||
| { | ||
| "kind": "{", | ||
| "start": 168, | ||
| "end": 169 | ||
| "range": [168, 169] | ||
| }, | ||
@@ -295,24 +243,19 @@ { | ||
| "value": "greeting", | ||
| "start": 169, | ||
| "end": 177 | ||
| "range": [169, 177] | ||
| }, | ||
| { | ||
| "kind": "}", | ||
| "start": 177, | ||
| "end": 178 | ||
| "range": [177, 178] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 178, | ||
| "end": 179 | ||
| "range": [178, 179] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 179, | ||
| "end": 180 | ||
| "range": [179, 180] | ||
| }, | ||
| { | ||
| "kind": "const", | ||
| "start": 186, | ||
| "end": 191 | ||
| "range": [186, 191] | ||
| }, | ||
@@ -322,14 +265,11 @@ { | ||
| "value": "emoji_identifier", | ||
| "start": 192, | ||
| "end": 208 | ||
| "range": [192, 208] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 209, | ||
| "end": 210 | ||
| "range": [209, 210] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 211, | ||
| "end": 212 | ||
| "range": [211, 212] | ||
| }, | ||
@@ -339,4 +279,3 @@ { | ||
| "value": "✅ This is a test string with emojis 🚀🔥", | ||
| "start": 212, | ||
| "end": 258 | ||
| "range": [212, 258] | ||
| }, | ||
@@ -346,19 +285,15 @@ { | ||
| "value": "\\n", | ||
| "start": 258, | ||
| "end": 260 | ||
| "range": [258, 260] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 260, | ||
| "end": 261 | ||
| "range": [260, 261] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 261, | ||
| "end": 262 | ||
| "range": [261, 262] | ||
| }, | ||
| { | ||
| "kind": "try", | ||
| "start": 267, | ||
| "end": 270 | ||
| "range": [267, 270] | ||
| }, | ||
@@ -368,9 +303,7 @@ { | ||
| "value": "stdout", | ||
| "start": 271, | ||
| "end": 277 | ||
| "range": [271, 277] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 277, | ||
| "end": 278 | ||
| "range": [277, 278] | ||
| }, | ||
@@ -380,14 +313,11 @@ { | ||
| "value": "print", | ||
| "start": 278, | ||
| "end": 283 | ||
| "range": [278, 283] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 283, | ||
| "end": 284 | ||
| "range": [283, 284] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 284, | ||
| "end": 285 | ||
| "range": [284, 285] | ||
| }, | ||
@@ -397,24 +327,19 @@ { | ||
| "value": "{s}", | ||
| "start": 285, | ||
| "end": 288 | ||
| "range": [285, 288] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 288, | ||
| "end": 289 | ||
| "range": [288, 289] | ||
| }, | ||
| { | ||
| "kind": ",", | ||
| "start": 289, | ||
| "end": 290 | ||
| "range": [289, 290] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 291, | ||
| "end": 292 | ||
| "range": [291, 292] | ||
| }, | ||
| { | ||
| "kind": "{", | ||
| "start": 292, | ||
| "end": 293 | ||
| "range": [292, 293] | ||
| }, | ||
@@ -424,25 +349,20 @@ { | ||
| "value": "emoji_identifier", | ||
| "start": 293, | ||
| "end": 309 | ||
| "range": [293, 309] | ||
| }, | ||
| { | ||
| "kind": "}", | ||
| "start": 309, | ||
| "end": 310 | ||
| "range": [309, 310] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 310, | ||
| "end": 311 | ||
| "range": [310, 311] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 311, | ||
| "end": 312 | ||
| "range": [311, 312] | ||
| }, | ||
| { | ||
| "kind": "}", | ||
| "start": 313, | ||
| "end": 314 | ||
| "range": [313, 314] | ||
| } | ||
| ] | ||
| ] |
| [ | ||
| { | ||
| "kind": "const", | ||
| "start": 0, | ||
| "end": 5 | ||
| "range": [0, 5] | ||
| }, | ||
@@ -10,9 +9,7 @@ { | ||
| "value": "std", | ||
| "start": 6, | ||
| "end": 9 | ||
| "range": [6, 9] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 10, | ||
| "end": 11 | ||
| "range": [10, 11] | ||
| }, | ||
@@ -22,14 +19,11 @@ { | ||
| "value": "@import", | ||
| "start": 12, | ||
| "end": 19 | ||
| "range": [12, 19] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 19, | ||
| "end": 20 | ||
| "range": [19, 20] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 20, | ||
| "end": 21 | ||
| "range": [20, 21] | ||
| }, | ||
@@ -39,24 +33,19 @@ { | ||
| "value": "std", | ||
| "start": 21, | ||
| "end": 24 | ||
| "range": [21, 24] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 24, | ||
| "end": 25 | ||
| "range": [24, 25] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 25, | ||
| "end": 26 | ||
| "range": [25, 26] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 26, | ||
| "end": 27 | ||
| "range": [26, 27] | ||
| }, | ||
| { | ||
| "kind": "const", | ||
| "start": 28, | ||
| "end": 33 | ||
| "range": [28, 33] | ||
| }, | ||
@@ -66,9 +55,7 @@ { | ||
| "value": "expect", | ||
| "start": 34, | ||
| "end": 40 | ||
| "range": [34, 40] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 41, | ||
| "end": 42 | ||
| "range": [41, 42] | ||
| }, | ||
@@ -78,9 +65,7 @@ { | ||
| "value": "std", | ||
| "start": 43, | ||
| "end": 46 | ||
| "range": [43, 46] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 46, | ||
| "end": 47 | ||
| "range": [46, 47] | ||
| }, | ||
@@ -90,9 +75,7 @@ { | ||
| "value": "testing", | ||
| "start": 47, | ||
| "end": 54 | ||
| "range": [47, 54] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 54, | ||
| "end": 55 | ||
| "range": [54, 55] | ||
| }, | ||
@@ -102,29 +85,23 @@ { | ||
| "value": "expect", | ||
| "start": 55, | ||
| "end": 61 | ||
| "range": [55, 61] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 61, | ||
| "end": 62 | ||
| "range": [61, 62] | ||
| }, | ||
| { | ||
| "kind": "comptime", | ||
| "start": 64, | ||
| "end": 72 | ||
| "range": [64, 72] | ||
| }, | ||
| { | ||
| "kind": "{", | ||
| "start": 73, | ||
| "end": 74 | ||
| "range": [73, 74] | ||
| }, | ||
| { | ||
| "kind": "asm", | ||
| "start": 79, | ||
| "end": 82 | ||
| "range": [79, 82] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 83, | ||
| "end": 84 | ||
| "range": [83, 84] | ||
| }, | ||
@@ -134,29 +111,23 @@ { | ||
| "value": "\\\\.global my_func;\n \\\\.type my_func, @function;\n \\\\my_func:\n \\\\ lea (%rdi,%rsi,1),%eax\n \\\\ retq", | ||
| "start": 93, | ||
| "end": 218 | ||
| "range": [93, 218] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 223, | ||
| "end": 224 | ||
| "range": [223, 224] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 224, | ||
| "end": 225 | ||
| "range": [224, 225] | ||
| }, | ||
| { | ||
| "kind": "}", | ||
| "start": 226, | ||
| "end": 227 | ||
| "range": [226, 227] | ||
| }, | ||
| { | ||
| "kind": "extern", | ||
| "start": 229, | ||
| "end": 235 | ||
| "range": [229, 235] | ||
| }, | ||
| { | ||
| "kind": "fn", | ||
| "start": 236, | ||
| "end": 238 | ||
| "range": [236, 238] | ||
| }, | ||
@@ -166,9 +137,7 @@ { | ||
| "value": "my_func", | ||
| "start": 239, | ||
| "end": 246 | ||
| "range": [239, 246] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 246, | ||
| "end": 247 | ||
| "range": [246, 247] | ||
| }, | ||
@@ -178,9 +147,7 @@ { | ||
| "value": "a", | ||
| "start": 247, | ||
| "end": 248 | ||
| "range": [247, 248] | ||
| }, | ||
| { | ||
| "kind": ":", | ||
| "start": 248, | ||
| "end": 249 | ||
| "range": [248, 249] | ||
| }, | ||
@@ -190,9 +157,7 @@ { | ||
| "value": "i32", | ||
| "start": 250, | ||
| "end": 253 | ||
| "range": [250, 253] | ||
| }, | ||
| { | ||
| "kind": ",", | ||
| "start": 253, | ||
| "end": 254 | ||
| "range": [253, 254] | ||
| }, | ||
@@ -202,9 +167,7 @@ { | ||
| "value": "b", | ||
| "start": 255, | ||
| "end": 256 | ||
| "range": [255, 256] | ||
| }, | ||
| { | ||
| "kind": ":", | ||
| "start": 256, | ||
| "end": 257 | ||
| "range": [256, 257] | ||
| }, | ||
@@ -214,9 +177,7 @@ { | ||
| "value": "i32", | ||
| "start": 258, | ||
| "end": 261 | ||
| "range": [258, 261] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 261, | ||
| "end": 262 | ||
| "range": [261, 262] | ||
| }, | ||
@@ -226,19 +187,15 @@ { | ||
| "value": "i32", | ||
| "start": 263, | ||
| "end": 266 | ||
| "range": [263, 266] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 266, | ||
| "end": 267 | ||
| "range": [266, 267] | ||
| }, | ||
| { | ||
| "kind": "test", | ||
| "start": 269, | ||
| "end": 273 | ||
| "range": [269, 273] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 274, | ||
| "end": 275 | ||
| "range": [274, 275] | ||
| }, | ||
@@ -248,19 +205,15 @@ { | ||
| "value": "global assembly", | ||
| "start": 275, | ||
| "end": 290 | ||
| "range": [275, 290] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 290, | ||
| "end": 291 | ||
| "range": [290, 291] | ||
| }, | ||
| { | ||
| "kind": "{", | ||
| "start": 292, | ||
| "end": 293 | ||
| "range": [292, 293] | ||
| }, | ||
| { | ||
| "kind": "try", | ||
| "start": 298, | ||
| "end": 301 | ||
| "range": [298, 301] | ||
| }, | ||
@@ -270,9 +223,7 @@ { | ||
| "value": "expect", | ||
| "start": 302, | ||
| "end": 308 | ||
| "range": [302, 308] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 308, | ||
| "end": 309 | ||
| "range": [308, 309] | ||
| }, | ||
@@ -282,9 +233,7 @@ { | ||
| "value": "my_func", | ||
| "start": 309, | ||
| "end": 316 | ||
| "range": [309, 316] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 316, | ||
| "end": 317 | ||
| "range": [316, 317] | ||
| }, | ||
@@ -294,9 +243,7 @@ { | ||
| "value": "12", | ||
| "start": 317, | ||
| "end": 319 | ||
| "range": [317, 319] | ||
| }, | ||
| { | ||
| "kind": ",", | ||
| "start": 319, | ||
| "end": 320 | ||
| "range": [319, 320] | ||
| }, | ||
@@ -306,14 +253,11 @@ { | ||
| "value": "34", | ||
| "start": 321, | ||
| "end": 323 | ||
| "range": [321, 323] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 323, | ||
| "end": 324 | ||
| "range": [323, 324] | ||
| }, | ||
| { | ||
| "kind": "==", | ||
| "start": 325, | ||
| "end": 327 | ||
| "range": [325, 327] | ||
| }, | ||
@@ -323,20 +267,16 @@ { | ||
| "value": "46", | ||
| "start": 328, | ||
| "end": 330 | ||
| "range": [328, 330] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 330, | ||
| "end": 331 | ||
| "range": [330, 331] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 331, | ||
| "end": 332 | ||
| "range": [331, 332] | ||
| }, | ||
| { | ||
| "kind": "}", | ||
| "start": 333, | ||
| "end": 334 | ||
| "range": [333, 334] | ||
| } | ||
| ] | ||
| ] |
| [ | ||
| { | ||
| "kind": "const", | ||
| "start": 0, | ||
| "end": 5 | ||
| "range": [0, 5] | ||
| }, | ||
@@ -10,9 +9,7 @@ { | ||
| "value": "std", | ||
| "start": 6, | ||
| "end": 9 | ||
| "range": [6, 9] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 10, | ||
| "end": 11 | ||
| "range": [10, 11] | ||
| }, | ||
@@ -22,14 +19,11 @@ { | ||
| "value": "@import", | ||
| "start": 12, | ||
| "end": 19 | ||
| "range": [12, 19] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 19, | ||
| "end": 20 | ||
| "range": [19, 20] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 20, | ||
| "end": 21 | ||
| "range": [20, 21] | ||
| }, | ||
@@ -39,29 +33,23 @@ { | ||
| "value": "std", | ||
| "start": 21, | ||
| "end": 24 | ||
| "range": [21, 24] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 24, | ||
| "end": 25 | ||
| "range": [24, 25] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 25, | ||
| "end": 26 | ||
| "range": [25, 26] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 26, | ||
| "end": 27 | ||
| "range": [26, 27] | ||
| }, | ||
| { | ||
| "kind": "pub", | ||
| "start": 29, | ||
| "end": 32 | ||
| "range": [29, 32] | ||
| }, | ||
| { | ||
| "kind": "fn", | ||
| "start": 33, | ||
| "end": 35 | ||
| "range": [33, 35] | ||
| }, | ||
@@ -71,24 +59,19 @@ { | ||
| "value": "main", | ||
| "start": 36, | ||
| "end": 40 | ||
| "range": [36, 40] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 40, | ||
| "end": 41 | ||
| "range": [40, 41] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 41, | ||
| "end": 42 | ||
| "range": [41, 42] | ||
| }, | ||
| { | ||
| "kind": "void", | ||
| "start": 43, | ||
| "end": 47 | ||
| "range": [43, 47] | ||
| }, | ||
| { | ||
| "kind": "{", | ||
| "start": 48, | ||
| "end": 49 | ||
| "range": [48, 49] | ||
| }, | ||
@@ -98,9 +81,7 @@ { | ||
| "value": "std", | ||
| "start": 54, | ||
| "end": 57 | ||
| "range": [54, 57] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 57, | ||
| "end": 58 | ||
| "range": [57, 58] | ||
| }, | ||
@@ -110,9 +91,7 @@ { | ||
| "value": "debug", | ||
| "start": 58, | ||
| "end": 63 | ||
| "range": [58, 63] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 63, | ||
| "end": 64 | ||
| "range": [63, 64] | ||
| }, | ||
@@ -122,14 +101,11 @@ { | ||
| "value": "print", | ||
| "start": 64, | ||
| "end": 69 | ||
| "range": [64, 69] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 69, | ||
| "end": 70 | ||
| "range": [69, 70] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 70, | ||
| "end": 71 | ||
| "range": [70, 71] | ||
| }, | ||
@@ -139,4 +115,3 @@ { | ||
| "value": "Hello, world!", | ||
| "start": 71, | ||
| "end": 84 | ||
| "range": [71, 84] | ||
| }, | ||
@@ -146,45 +121,36 @@ { | ||
| "value": "\\n", | ||
| "start": 84, | ||
| "end": 86 | ||
| "range": [84, 86] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 86, | ||
| "end": 87 | ||
| "range": [86, 87] | ||
| }, | ||
| { | ||
| "kind": ",", | ||
| "start": 87, | ||
| "end": 88 | ||
| "range": [87, 88] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 89, | ||
| "end": 90 | ||
| "range": [89, 90] | ||
| }, | ||
| { | ||
| "kind": "{", | ||
| "start": 90, | ||
| "end": 91 | ||
| "range": [90, 91] | ||
| }, | ||
| { | ||
| "kind": "}", | ||
| "start": 91, | ||
| "end": 92 | ||
| "range": [91, 92] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 92, | ||
| "end": 93 | ||
| "range": [92, 93] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 93, | ||
| "end": 94 | ||
| "range": [93, 94] | ||
| }, | ||
| { | ||
| "kind": "}", | ||
| "start": 95, | ||
| "end": 96 | ||
| "range": [95, 96] | ||
| } | ||
| ] | ||
| ] |
| [ | ||
| { | ||
| "kind": "const", | ||
| "start": 0, | ||
| "end": 5 | ||
| "range": [0, 5] | ||
| }, | ||
| { | ||
| "kind": "@", | ||
| "start": 6, | ||
| "end": 7 | ||
| "range": [6, 7] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 7, | ||
| "end": 8 | ||
| "range": [7, 8] | ||
| }, | ||
@@ -20,14 +17,11 @@ { | ||
| "value": "identifier with spaces in it", | ||
| "start": 8, | ||
| "end": 36 | ||
| "range": [8, 36] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 36, | ||
| "end": 37 | ||
| "range": [36, 37] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 38, | ||
| "end": 39 | ||
| "range": [38, 39] | ||
| }, | ||
@@ -37,24 +31,19 @@ { | ||
| "value": "0xff", | ||
| "start": 40, | ||
| "end": 44 | ||
| "range": [40, 44] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 44, | ||
| "end": 45 | ||
| "range": [44, 45] | ||
| }, | ||
| { | ||
| "kind": "const", | ||
| "start": 46, | ||
| "end": 51 | ||
| "range": [46, 51] | ||
| }, | ||
| { | ||
| "kind": "@", | ||
| "start": 52, | ||
| "end": 53 | ||
| "range": [52, 53] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 53, | ||
| "end": 54 | ||
| "range": [53, 54] | ||
| }, | ||
@@ -64,14 +53,11 @@ { | ||
| "value": "1SmallStep4Man", | ||
| "start": 54, | ||
| "end": 68 | ||
| "range": [54, 68] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 68, | ||
| "end": 69 | ||
| "range": [68, 69] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 70, | ||
| "end": 71 | ||
| "range": [70, 71] | ||
| }, | ||
@@ -81,14 +67,11 @@ { | ||
| "value": "112358", | ||
| "start": 72, | ||
| "end": 78 | ||
| "range": [72, 78] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 78, | ||
| "end": 79 | ||
| "range": [78, 79] | ||
| }, | ||
| { | ||
| "kind": "const", | ||
| "start": 81, | ||
| "end": 86 | ||
| "range": [81, 86] | ||
| }, | ||
@@ -98,9 +81,7 @@ { | ||
| "value": "c", | ||
| "start": 87, | ||
| "end": 88 | ||
| "range": [87, 88] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 89, | ||
| "end": 90 | ||
| "range": [89, 90] | ||
| }, | ||
@@ -110,14 +91,11 @@ { | ||
| "value": "@import", | ||
| "start": 91, | ||
| "end": 98 | ||
| "range": [91, 98] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 98, | ||
| "end": 99 | ||
| "range": [98, 99] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 99, | ||
| "end": 100 | ||
| "range": [99, 100] | ||
| }, | ||
@@ -127,19 +105,15 @@ { | ||
| "value": "std", | ||
| "start": 100, | ||
| "end": 103 | ||
| "range": [100, 103] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 103, | ||
| "end": 104 | ||
| "range": [103, 104] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 104, | ||
| "end": 105 | ||
| "range": [104, 105] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 105, | ||
| "end": 106 | ||
| "range": [105, 106] | ||
| }, | ||
@@ -149,24 +123,19 @@ { | ||
| "value": "c", | ||
| "start": 106, | ||
| "end": 107 | ||
| "range": [106, 107] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 107, | ||
| "end": 108 | ||
| "range": [107, 108] | ||
| }, | ||
| { | ||
| "kind": "pub", | ||
| "start": 109, | ||
| "end": 112 | ||
| "range": [109, 112] | ||
| }, | ||
| { | ||
| "kind": "extern", | ||
| "start": 113, | ||
| "end": 119 | ||
| "range": [113, 119] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 120, | ||
| "end": 121 | ||
| "range": [120, 121] | ||
| }, | ||
@@ -176,24 +145,19 @@ { | ||
| "value": "c", | ||
| "start": 121, | ||
| "end": 122 | ||
| "range": [121, 122] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 122, | ||
| "end": 123 | ||
| "range": [122, 123] | ||
| }, | ||
| { | ||
| "kind": "fn", | ||
| "start": 124, | ||
| "end": 126 | ||
| "range": [124, 126] | ||
| }, | ||
| { | ||
| "kind": "@", | ||
| "start": 127, | ||
| "end": 128 | ||
| "range": [127, 128] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 128, | ||
| "end": 129 | ||
| "range": [128, 129] | ||
| }, | ||
@@ -203,44 +167,35 @@ { | ||
| "value": "error", | ||
| "start": 129, | ||
| "end": 134 | ||
| "range": [129, 134] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 134, | ||
| "end": 135 | ||
| "range": [134, 135] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 135, | ||
| "end": 136 | ||
| "range": [135, 136] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 136, | ||
| "end": 137 | ||
| "range": [136, 137] | ||
| }, | ||
| { | ||
| "kind": "void", | ||
| "start": 138, | ||
| "end": 142 | ||
| "range": [138, 142] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 142, | ||
| "end": 143 | ||
| "range": [142, 143] | ||
| }, | ||
| { | ||
| "kind": "pub", | ||
| "start": 144, | ||
| "end": 147 | ||
| "range": [144, 147] | ||
| }, | ||
| { | ||
| "kind": "extern", | ||
| "start": 148, | ||
| "end": 154 | ||
| "range": [148, 154] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 155, | ||
| "end": 156 | ||
| "range": [155, 156] | ||
| }, | ||
@@ -250,24 +205,19 @@ { | ||
| "value": "c", | ||
| "start": 156, | ||
| "end": 157 | ||
| "range": [156, 157] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 157, | ||
| "end": 158 | ||
| "range": [157, 158] | ||
| }, | ||
| { | ||
| "kind": "fn", | ||
| "start": 159, | ||
| "end": 161 | ||
| "range": [159, 161] | ||
| }, | ||
| { | ||
| "kind": "@", | ||
| "start": 162, | ||
| "end": 163 | ||
| "range": [162, 163] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 163, | ||
| "end": 164 | ||
| "range": [163, 164] | ||
| }, | ||
@@ -277,14 +227,11 @@ { | ||
| "value": "fstat$INODE64", | ||
| "start": 164, | ||
| "end": 177 | ||
| "range": [164, 177] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 177, | ||
| "end": 178 | ||
| "range": [177, 178] | ||
| }, | ||
| { | ||
| "kind": "(", | ||
| "start": 178, | ||
| "end": 179 | ||
| "range": [178, 179] | ||
| }, | ||
@@ -294,9 +241,7 @@ { | ||
| "value": "fd", | ||
| "start": 179, | ||
| "end": 181 | ||
| "range": [179, 181] | ||
| }, | ||
| { | ||
| "kind": ":", | ||
| "start": 181, | ||
| "end": 182 | ||
| "range": [181, 182] | ||
| }, | ||
@@ -306,9 +251,7 @@ { | ||
| "value": "c", | ||
| "start": 183, | ||
| "end": 184 | ||
| "range": [183, 184] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 184, | ||
| "end": 185 | ||
| "range": [184, 185] | ||
| }, | ||
@@ -318,9 +261,7 @@ { | ||
| "value": "fd_t", | ||
| "start": 185, | ||
| "end": 189 | ||
| "range": [185, 189] | ||
| }, | ||
| { | ||
| "kind": ",", | ||
| "start": 189, | ||
| "end": 190 | ||
| "range": [189, 190] | ||
| }, | ||
@@ -330,14 +271,11 @@ { | ||
| "value": "buf", | ||
| "start": 191, | ||
| "end": 194 | ||
| "range": [191, 194] | ||
| }, | ||
| { | ||
| "kind": ":", | ||
| "start": 194, | ||
| "end": 195 | ||
| "range": [194, 195] | ||
| }, | ||
| { | ||
| "kind": "*", | ||
| "start": 196, | ||
| "end": 197 | ||
| "range": [196, 197] | ||
| }, | ||
@@ -347,9 +285,7 @@ { | ||
| "value": "c", | ||
| "start": 197, | ||
| "end": 198 | ||
| "range": [197, 198] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 198, | ||
| "end": 199 | ||
| "range": [198, 199] | ||
| }, | ||
@@ -359,24 +295,19 @@ { | ||
| "value": "Stat", | ||
| "start": 199, | ||
| "end": 203 | ||
| "range": [199, 203] | ||
| }, | ||
| { | ||
| "kind": ")", | ||
| "start": 203, | ||
| "end": 204 | ||
| "range": [203, 204] | ||
| }, | ||
| { | ||
| "kind": "c_int", | ||
| "start": 205, | ||
| "end": 210 | ||
| "range": [205, 210] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 210, | ||
| "end": 211 | ||
| "range": [210, 211] | ||
| }, | ||
| { | ||
| "kind": "const", | ||
| "start": 213, | ||
| "end": 218 | ||
| "range": [213, 218] | ||
| }, | ||
@@ -386,19 +317,15 @@ { | ||
| "value": "Color", | ||
| "start": 219, | ||
| "end": 224 | ||
| "range": [219, 224] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 225, | ||
| "end": 226 | ||
| "range": [225, 226] | ||
| }, | ||
| { | ||
| "kind": "enum", | ||
| "start": 227, | ||
| "end": 231 | ||
| "range": [227, 231] | ||
| }, | ||
| { | ||
| "kind": "{", | ||
| "start": 232, | ||
| "end": 233 | ||
| "range": [232, 233] | ||
| }, | ||
@@ -408,19 +335,15 @@ { | ||
| "value": "red", | ||
| "start": 238, | ||
| "end": 241 | ||
| "range": [238, 241] | ||
| }, | ||
| { | ||
| "kind": ",", | ||
| "start": 241, | ||
| "end": 242 | ||
| "range": [241, 242] | ||
| }, | ||
| { | ||
| "kind": "@", | ||
| "start": 247, | ||
| "end": 248 | ||
| "range": [247, 248] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 248, | ||
| "end": 249 | ||
| "range": [248, 249] | ||
| }, | ||
@@ -430,29 +353,23 @@ { | ||
| "value": "really red", | ||
| "start": 249, | ||
| "end": 259 | ||
| "range": [249, 259] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 259, | ||
| "end": 260 | ||
| "range": [259, 260] | ||
| }, | ||
| { | ||
| "kind": ",", | ||
| "start": 260, | ||
| "end": 261 | ||
| "range": [260, 261] | ||
| }, | ||
| { | ||
| "kind": "}", | ||
| "start": 262, | ||
| "end": 263 | ||
| "range": [262, 263] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 263, | ||
| "end": 264 | ||
| "range": [263, 264] | ||
| }, | ||
| { | ||
| "kind": "const", | ||
| "start": 265, | ||
| "end": 270 | ||
| "range": [265, 270] | ||
| }, | ||
@@ -462,9 +379,7 @@ { | ||
| "value": "color", | ||
| "start": 271, | ||
| "end": 276 | ||
| "range": [271, 276] | ||
| }, | ||
| { | ||
| "kind": ":", | ||
| "start": 276, | ||
| "end": 277 | ||
| "range": [276, 277] | ||
| }, | ||
@@ -474,24 +389,19 @@ { | ||
| "value": "Color", | ||
| "start": 278, | ||
| "end": 283 | ||
| "range": [278, 283] | ||
| }, | ||
| { | ||
| "kind": "=", | ||
| "start": 284, | ||
| "end": 285 | ||
| "range": [284, 285] | ||
| }, | ||
| { | ||
| "kind": ".", | ||
| "start": 286, | ||
| "end": 287 | ||
| "range": [286, 287] | ||
| }, | ||
| { | ||
| "kind": "@", | ||
| "start": 287, | ||
| "end": 288 | ||
| "range": [287, 288] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 288, | ||
| "end": 289 | ||
| "range": [288, 289] | ||
| }, | ||
@@ -501,15 +411,12 @@ { | ||
| "value": "really red", | ||
| "start": 289, | ||
| "end": 299 | ||
| "range": [289, 299] | ||
| }, | ||
| { | ||
| "kind": "\"", | ||
| "start": 299, | ||
| "end": 300 | ||
| "range": [299, 300] | ||
| }, | ||
| { | ||
| "kind": ";", | ||
| "start": 300, | ||
| "end": 301 | ||
| "range": [300, 301] | ||
| } | ||
| ] | ||
| ] |
@@ -0,9 +1,14 @@ | ||
| from __future__ import annotations | ||
| import json | ||
| from pathlib import Path | ||
| from typing import TYPE_CHECKING | ||
| import pytest | ||
| from zig_codeblocks.formatting import highlight_zig_code, process_markdown | ||
| from zig_codeblocks.styling import Color, Style, Theme | ||
| from zig_codeblocks import Color, Style, highlight_zig_code, process_markdown | ||
| if TYPE_CHECKING: | ||
| from zig_codeblocks._core import Theme | ||
| SOURCE_DIR = Path(__file__).parent / "sources" | ||
@@ -50,4 +55,4 @@ | ||
| [ | ||
| {"identifiers": Style(Color.RED)}, | ||
| {"identifiers": Style(Color.RED), "strings": Style(Color.GREEN)}, | ||
| {"Identifier": Style(Color.Red)}, | ||
| {"Identifier": Style(Color.Red), "String": Style(Color.Green)}, | ||
| ], | ||
@@ -65,6 +70,6 @@ ) | ||
| source = " const x = 0xff;" | ||
| theme = Theme( | ||
| identifiers=(red := Style(Color.RED)), | ||
| keywords=(blue_u := Style(Color.BLUE, underline=True)), | ||
| ) | ||
| theme: Theme = { | ||
| "Identifier": (red := Style(Color.Red)), | ||
| "Keyword": (blue_u := Style(Color.Blue, underline=True)), | ||
| } | ||
| expected_highlighting = f" {blue_u}const\033[0m {red}x \033[0m= 0xff;" | ||
@@ -78,3 +83,3 @@ assert highlight_zig_code(source, theme) == expected_highlighting | ||
| theme = Theme(identifiers=(red := Style(Color.RED))) | ||
| theme: Theme = {"Identifier": (red := Style(Color.Red))} | ||
| assert highlight_zig_code(src, theme) == f"{red}{src}" |
+20
-37
@@ -1,2 +0,3 @@ | ||
| import json | ||
| from __future__ import annotations | ||
| from pathlib import Path | ||
@@ -6,3 +7,3 @@ | ||
| from zig_codeblocks.parsing import CodeBlock, Token, extract_codeblocks, tokenize_zig | ||
| from zig_codeblocks._core import CodeBlock, extract_codeblocks | ||
@@ -25,6 +26,8 @@ SOURCE_DIR = Path(__file__).parent / "sources" | ||
| for meth in (Path.read_text, Path.read_bytes): | ||
| assert list(extract_codeblocks(meth(src))) == [ | ||
| CodeBlock(lang="py", body="print(1)"), | ||
| CodeBlock(lang="zig", body='const std = @import("std");'), | ||
| ] | ||
| code_blocks = extract_codeblocks(meth(src)) | ||
| assert len(code_blocks) == 2 | ||
| py_block, zig_block = code_blocks | ||
| assert (py_block.lang, zig_block.lang) == ("py", "zig") | ||
| assert py_block.body.strip("\r\n") == "print(1)" | ||
| assert zig_block.body.strip("\r\n") == 'const std = @import("std");' | ||
@@ -36,8 +39,8 @@ | ||
| ("rust", (None, "rust")), | ||
| ("rust\n", (None, "rust")), | ||
| ("rust\n", (None, "rust\n")), | ||
| ("rust\nfn", ("rust", "fn")), | ||
| ("zig\na", ("zig", "a")), | ||
| ("zig\naa", ("zig", "aa")), | ||
| ("zig\na\n", ("zig", "a")), | ||
| ("rust\n\n\n\n\n\n", (None, "rust")), | ||
| ("zig\na\n", ("zig", "a\n")), | ||
| ("rust\n\n\n\n\n\n", (None, "rust\n\n\n\n\n\n")), | ||
| ("ruśt\nfn", (None, "ruśt\nfn")), | ||
@@ -49,3 +52,3 @@ ("1+2\nfn", ("1+2", "fn")), | ||
| def test_codeblock_with_language(source: str, expected: tuple[str | None, str]) -> None: | ||
| codeblocks = list(extract_codeblocks(f"```{source}```")) | ||
| codeblocks = extract_codeblocks(f"```{source}```") | ||
| assert len(codeblocks) == 1 | ||
@@ -55,32 +58,12 @@ assert codeblocks[0] == CodeBlock(*expected) | ||
| def read_expected_tokens(test_name: str) -> list[Token]: | ||
| return [ | ||
| Token( | ||
| kind=t["kind"], | ||
| value=(t.get("value") or t["kind"]).encode(), | ||
| byte_range=range(t["start"], t["end"]), | ||
| ) | ||
| for t in json.loads( | ||
| (SOURCE_DIR / "parsing_results" / f"{test_name}.json").read_bytes() | ||
| ) | ||
| ] | ||
| @pytest.mark.parametrize( | ||
| "test_name", | ||
| "source", | ||
| [ | ||
| "assign_undefined", | ||
| "comments", | ||
| "emoji", | ||
| "global_assembly", | ||
| "hello_again", | ||
| "identifiers", | ||
| '```zig\nconst std = @import("std");\n```', | ||
| "```py\nprint(1)\n```\n```woah```", | ||
| "```\n\n\nhi\n\n\n```", | ||
| ], | ||
| ) | ||
| def test_zig_parser(test_name: str) -> None: | ||
| source = ( | ||
| (SOURCE_DIR / "zig_inputs" / f"{test_name}.zig") | ||
| .read_bytes() | ||
| .replace(b"\r\n", b"\n") | ||
| ) | ||
| assert list(tokenize_zig(source)) == read_expected_tokens(test_name) | ||
| def test_codeblocks_are_reproducible(source: str) -> None: | ||
| codeblocks = extract_codeblocks(source) | ||
| assert "\n".join(map(str, codeblocks)) == source |
+61
-12
@@ -0,23 +1,72 @@ | ||
| import re | ||
| import pytest | ||
| from zig_codeblocks.styling import Color, Style | ||
| from zig_codeblocks._core import Color, Style | ||
| @pytest.mark.parametrize( | ||
| ("string", "expected"), | ||
| [ | ||
| ("Gray", Color.Gray), | ||
| ("gray", Color.Gray), | ||
| ("GRAY", Color.Gray), | ||
| ("magenta", Color.Magenta), | ||
| ], | ||
| ) | ||
| def test_color_from_string(string: str, expected: Color) -> None: | ||
| assert Color.from_string(string) == expected | ||
| def test_color_from_string_fail() -> None: | ||
| with pytest.raises(ValueError, match=re.escape('Invalid color: "blurple"')): | ||
| Color.from_string("blurple") | ||
| @pytest.mark.parametrize( | ||
| ("color", "bold", "underline", "expected_sgr"), | ||
| [ | ||
| ("WHITE", False, False, "\033[37m"), | ||
| ("BLUE", True, False, "\033[34;1m"), | ||
| ("ORANGE", False, False, "\033[33m"), | ||
| ("RED", True, False, "\033[31;1m"), | ||
| ("BLUE", True, True, "\033[34;1;4m"), | ||
| ("MAGENTA", False, True, "\033[35;4m"), | ||
| ("WHITE", True, True, "\033[37;1;4m"), | ||
| ("CYAN", True, True, "\033[36;1;4m"), | ||
| ("MAGENTA", True, True, "\033[35;1;4m"), | ||
| ("GRAY", False, False, "\033[30m"), | ||
| ("White", False, False, "\033[37m"), | ||
| ("Blue", True, False, "\033[34;1m"), | ||
| ("Orange", False, False, "\033[33m"), | ||
| ("Red", True, False, "\033[31;1m"), | ||
| ("Blue", True, True, "\033[34;1;4m"), | ||
| ("Magenta", False, True, "\033[35;4m"), | ||
| ("White", True, True, "\033[37;1;4m"), | ||
| ("Cyan", True, True, "\033[36;1;4m"), | ||
| ("Magenta", True, True, "\033[35;1;4m"), | ||
| ("Gray", False, False, "\033[30m"), | ||
| ], | ||
| ) | ||
| def test_style(color: str, bold: bool, underline: bool, expected_sgr: str) -> None: | ||
| style = Style(Color[color], bold=bold, underline=underline) | ||
| style = Style(Color.from_string(color), bold=bold, underline=underline) | ||
| assert str(style) == expected_sgr | ||
| assert eval(repr(style)) == style # noqa: S307 | ||
| @pytest.mark.parametrize( | ||
| ("string", "expected"), | ||
| [ | ||
| ("red", Style(Color.Red)), | ||
| ("blue+bold", Style(Color.Blue, bold=True)), | ||
| ("oRange+BOLD", Style(Color.Orange, bold=True)), | ||
| ("green+underline", Style(Color.Green, underline=True)), | ||
| ("bold+cyan+underline", Style(Color.Cyan, bold=True, underline=True)), | ||
| ("bold+underline+magenta", Style(Color.Magenta, bold=True, underline=True)), | ||
| ], | ||
| ) | ||
| def test_style_from_string(string: str, expected: Style) -> None: | ||
| assert Style.from_string(string) == expected | ||
| @pytest.mark.parametrize( | ||
| ("string", "err_msg"), | ||
| [ | ||
| ("underline+bold", "Missing color in input string"), | ||
| ("black+bold+underline", 'Invalid color "black"'), | ||
| ("red+cyan", "Multiple colors found: Red and Cyan"), | ||
| ], | ||
| ) | ||
| def test_style_from_string_fail(string: str, err_msg: str) -> None: | ||
| with pytest.raises(ValueError, match=re.escape(err_msg)): | ||
| Style.from_string(string) |
+32
-143
| version = 1 | ||
| revision = 1 | ||
| requires-python = ">=3.10" | ||
| requires-python = ">=3.9" | ||
| [[package]] | ||
| name = "colorama" | ||
| version = "0.4.6" | ||
| name = "click" | ||
| version = "8.1.8" | ||
| source = { registry = "https://pypi.org/simple" } | ||
| sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } | ||
| dependencies = [ | ||
| { name = "colorama", marker = "sys_platform == 'win32'" }, | ||
| ] | ||
| sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } | ||
| wheels = [ | ||
| { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, | ||
| { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, | ||
| ] | ||
| [[package]] | ||
| name = "coverage" | ||
| version = "7.6.10" | ||
| name = "colorama" | ||
| version = "0.4.6" | ||
| source = { registry = "https://pypi.org/simple" } | ||
| sdist = { url = "https://files.pythonhosted.org/packages/84/ba/ac14d281f80aab516275012e8875991bb06203957aa1e19950139238d658/coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23", size = 803868 } | ||
| sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } | ||
| wheels = [ | ||
| { url = "https://files.pythonhosted.org/packages/c5/12/2a2a923edf4ddabdffed7ad6da50d96a5c126dae7b80a33df7310e329a1e/coverage-7.6.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c912978f7fbf47ef99cec50c4401340436d200d41d714c7a4766f377c5b7b78", size = 207982 }, | ||
| { url = "https://files.pythonhosted.org/packages/ca/49/6985dbca9c7be3f3cb62a2e6e492a0c88b65bf40579e16c71ae9c33c6b23/coverage-7.6.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a01ec4af7dfeb96ff0078ad9a48810bb0cc8abcb0115180c6013a6b26237626c", size = 208414 }, | ||
| { url = "https://files.pythonhosted.org/packages/35/93/287e8f1d1ed2646f4e0b2605d14616c9a8a2697d0d1b453815eb5c6cebdb/coverage-7.6.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3b204c11e2b2d883946fe1d97f89403aa1811df28ce0447439178cc7463448a", size = 236860 }, | ||
| { url = "https://files.pythonhosted.org/packages/de/e1/cfdb5627a03567a10031acc629b75d45a4ca1616e54f7133ca1fa366050a/coverage-7.6.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32ee6d8491fcfc82652a37109f69dee9a830e9379166cb73c16d8dc5c2915165", size = 234758 }, | ||
| { url = "https://files.pythonhosted.org/packages/6d/85/fc0de2bcda3f97c2ee9fe8568f7d48f7279e91068958e5b2cc19e0e5f600/coverage-7.6.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675cefc4c06e3b4c876b85bfb7c59c5e2218167bbd4da5075cbe3b5790a28988", size = 235920 }, | ||
| { url = "https://files.pythonhosted.org/packages/79/73/ef4ea0105531506a6f4cf4ba571a214b14a884630b567ed65b3d9c1975e1/coverage-7.6.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f4f620668dbc6f5e909a0946a877310fb3d57aea8198bde792aae369ee1c23b5", size = 234986 }, | ||
| { url = "https://files.pythonhosted.org/packages/c6/4d/75afcfe4432e2ad0405c6f27adeb109ff8976c5e636af8604f94f29fa3fc/coverage-7.6.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4eea95ef275de7abaef630c9b2c002ffbc01918b726a39f5a4353916ec72d2f3", size = 233446 }, | ||
| { url = "https://files.pythonhosted.org/packages/86/5b/efee56a89c16171288cafff022e8af44f8f94075c2d8da563c3935212871/coverage-7.6.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e2f0280519e42b0a17550072861e0bc8a80a0870de260f9796157d3fca2733c5", size = 234566 }, | ||
| { url = "https://files.pythonhosted.org/packages/f2/db/67770cceb4a64d3198bf2aa49946f411b85ec6b0a9b489e61c8467a4253b/coverage-7.6.10-cp310-cp310-win32.whl", hash = "sha256:bc67deb76bc3717f22e765ab3e07ee9c7a5e26b9019ca19a3b063d9f4b874244", size = 210675 }, | ||
| { url = "https://files.pythonhosted.org/packages/8d/27/e8bfc43f5345ec2c27bc8a1fa77cdc5ce9dcf954445e11f14bb70b889d14/coverage-7.6.10-cp310-cp310-win_amd64.whl", hash = "sha256:0f460286cb94036455e703c66988851d970fdfd8acc2a1122ab7f4f904e4029e", size = 211518 }, | ||
| { url = "https://files.pythonhosted.org/packages/85/d2/5e175fcf6766cf7501a8541d81778fd2f52f4870100e791f5327fd23270b/coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3", size = 208088 }, | ||
| { url = "https://files.pythonhosted.org/packages/4b/6f/06db4dc8fca33c13b673986e20e466fd936235a6ec1f0045c3853ac1b593/coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43", size = 208536 }, | ||
| { url = "https://files.pythonhosted.org/packages/0d/62/c6a0cf80318c1c1af376d52df444da3608eafc913b82c84a4600d8349472/coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132", size = 240474 }, | ||
| { url = "https://files.pythonhosted.org/packages/a3/59/750adafc2e57786d2e8739a46b680d4fb0fbc2d57fbcb161290a9f1ecf23/coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f", size = 237880 }, | ||
| { url = "https://files.pythonhosted.org/packages/2c/f8/ef009b3b98e9f7033c19deb40d629354aab1d8b2d7f9cfec284dbedf5096/coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994", size = 239750 }, | ||
| { url = "https://files.pythonhosted.org/packages/a6/e2/6622f3b70f5f5b59f705e680dae6db64421af05a5d1e389afd24dae62e5b/coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99", size = 238642 }, | ||
| { url = "https://files.pythonhosted.org/packages/2d/10/57ac3f191a3c95c67844099514ff44e6e19b2915cd1c22269fb27f9b17b6/coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd", size = 237266 }, | ||
| { url = "https://files.pythonhosted.org/packages/ee/2d/7016f4ad9d553cabcb7333ed78ff9d27248ec4eba8dd21fa488254dff894/coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377", size = 238045 }, | ||
| { url = "https://files.pythonhosted.org/packages/a7/fe/45af5c82389a71e0cae4546413266d2195c3744849669b0bab4b5f2c75da/coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8", size = 210647 }, | ||
| { url = "https://files.pythonhosted.org/packages/db/11/3f8e803a43b79bc534c6a506674da9d614e990e37118b4506faf70d46ed6/coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609", size = 211508 }, | ||
| { url = "https://files.pythonhosted.org/packages/86/77/19d09ea06f92fdf0487499283b1b7af06bc422ea94534c8fe3a4cd023641/coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853", size = 208281 }, | ||
| { url = "https://files.pythonhosted.org/packages/b6/67/5479b9f2f99fcfb49c0d5cf61912a5255ef80b6e80a3cddba39c38146cf4/coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078", size = 208514 }, | ||
| { url = "https://files.pythonhosted.org/packages/15/d1/febf59030ce1c83b7331c3546d7317e5120c5966471727aa7ac157729c4b/coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0", size = 241537 }, | ||
| { url = "https://files.pythonhosted.org/packages/4b/7e/5ac4c90192130e7cf8b63153fe620c8bfd9068f89a6d9b5f26f1550f7a26/coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50", size = 238572 }, | ||
| { url = "https://files.pythonhosted.org/packages/dc/03/0334a79b26ecf59958f2fe9dd1f5ab3e2f88db876f5071933de39af09647/coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022", size = 240639 }, | ||
| { url = "https://files.pythonhosted.org/packages/d7/45/8a707f23c202208d7b286d78ad6233f50dcf929319b664b6cc18a03c1aae/coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b", size = 240072 }, | ||
| { url = "https://files.pythonhosted.org/packages/66/02/603ce0ac2d02bc7b393279ef618940b4a0535b0868ee791140bda9ecfa40/coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0", size = 238386 }, | ||
| { url = "https://files.pythonhosted.org/packages/04/62/4e6887e9be060f5d18f1dd58c2838b2d9646faf353232dec4e2d4b1c8644/coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852", size = 240054 }, | ||
| { url = "https://files.pythonhosted.org/packages/5c/74/83ae4151c170d8bd071924f212add22a0e62a7fe2b149edf016aeecad17c/coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359", size = 210904 }, | ||
| { url = "https://files.pythonhosted.org/packages/c3/54/de0893186a221478f5880283119fc40483bc460b27c4c71d1b8bba3474b9/coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247", size = 211692 }, | ||
| { url = "https://files.pythonhosted.org/packages/25/6d/31883d78865529257bf847df5789e2ae80e99de8a460c3453dbfbe0db069/coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9", size = 208308 }, | ||
| { url = "https://files.pythonhosted.org/packages/70/22/3f2b129cc08de00c83b0ad6252e034320946abfc3e4235c009e57cfeee05/coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b", size = 208565 }, | ||
| { url = "https://files.pythonhosted.org/packages/97/0a/d89bc2d1cc61d3a8dfe9e9d75217b2be85f6c73ebf1b9e3c2f4e797f4531/coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690", size = 241083 }, | ||
| { url = "https://files.pythonhosted.org/packages/4c/81/6d64b88a00c7a7aaed3a657b8eaa0931f37a6395fcef61e53ff742b49c97/coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18", size = 238235 }, | ||
| { url = "https://files.pythonhosted.org/packages/9a/0b/7797d4193f5adb4b837207ed87fecf5fc38f7cc612b369a8e8e12d9fa114/coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c", size = 240220 }, | ||
| { url = "https://files.pythonhosted.org/packages/65/4d/6f83ca1bddcf8e51bf8ff71572f39a1c73c34cf50e752a952c34f24d0a60/coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd", size = 239847 }, | ||
| { url = "https://files.pythonhosted.org/packages/30/9d/2470df6aa146aff4c65fee0f87f58d2164a67533c771c9cc12ffcdb865d5/coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e", size = 237922 }, | ||
| { url = "https://files.pythonhosted.org/packages/08/dd/723fef5d901e6a89f2507094db66c091449c8ba03272861eaefa773ad95c/coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694", size = 239783 }, | ||
| { url = "https://files.pythonhosted.org/packages/3d/f7/64d3298b2baf261cb35466000628706ce20a82d42faf9b771af447cd2b76/coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6", size = 210965 }, | ||
| { url = "https://files.pythonhosted.org/packages/d5/58/ec43499a7fc681212fe7742fe90b2bc361cdb72e3181ace1604247a5b24d/coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e", size = 211719 }, | ||
| { url = "https://files.pythonhosted.org/packages/ab/c9/f2857a135bcff4330c1e90e7d03446b036b2363d4ad37eb5e3a47bbac8a6/coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe", size = 209050 }, | ||
| { url = "https://files.pythonhosted.org/packages/aa/b3/f840e5bd777d8433caa9e4a1eb20503495709f697341ac1a8ee6a3c906ad/coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273", size = 209321 }, | ||
| { url = "https://files.pythonhosted.org/packages/85/7d/125a5362180fcc1c03d91850fc020f3831d5cda09319522bcfa6b2b70be7/coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8", size = 252039 }, | ||
| { url = "https://files.pythonhosted.org/packages/a9/9c/4358bf3c74baf1f9bddd2baf3756b54c07f2cfd2535f0a47f1e7757e54b3/coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098", size = 247758 }, | ||
| { url = "https://files.pythonhosted.org/packages/cf/c7/de3eb6fc5263b26fab5cda3de7a0f80e317597a4bad4781859f72885f300/coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb", size = 250119 }, | ||
| { url = "https://files.pythonhosted.org/packages/3e/e6/43de91f8ba2ec9140c6a4af1102141712949903dc732cf739167cfa7a3bc/coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0", size = 249597 }, | ||
| { url = "https://files.pythonhosted.org/packages/08/40/61158b5499aa2adf9e37bc6d0117e8f6788625b283d51e7e0c53cf340530/coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf", size = 247473 }, | ||
| { url = "https://files.pythonhosted.org/packages/50/69/b3f2416725621e9f112e74e8470793d5b5995f146f596f133678a633b77e/coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2", size = 248737 }, | ||
| { url = "https://files.pythonhosted.org/packages/3c/6e/fe899fb937657db6df31cc3e61c6968cb56d36d7326361847440a430152e/coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312", size = 211611 }, | ||
| { url = "https://files.pythonhosted.org/packages/1c/55/52f5e66142a9d7bc93a15192eba7a78513d2abf6b3558d77b4ca32f5f424/coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d", size = 212781 }, | ||
| { url = "https://files.pythonhosted.org/packages/a1/70/de81bfec9ed38a64fc44a77c7665e20ca507fc3265597c28b0d989e4082e/coverage-7.6.10-pp39.pp310-none-any.whl", hash = "sha256:fd34e7b3405f0cc7ab03d54a334c17a9e802897580d964bd8c2001f4b9fd488f", size = 200223 }, | ||
| { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, | ||
| ] | ||
| [package.optional-dependencies] | ||
| toml = [ | ||
| { name = "tomli", marker = "python_full_version <= '3.11'" }, | ||
| ] | ||
| [[package]] | ||
@@ -97,11 +45,2 @@ name = "exceptiongroup" | ||
| [[package]] | ||
| name = "more-itertools" | ||
| version = "10.6.0" | ||
| source = { registry = "https://pypi.org/simple" } | ||
| sdist = { url = "https://files.pythonhosted.org/packages/88/3b/7fa1fe835e2e93fd6d7b52b2f95ae810cf5ba133e1845f726f5a992d62c2/more-itertools-10.6.0.tar.gz", hash = "sha256:2cd7fad1009c31cc9fb6a035108509e6547547a7a738374f10bd49a09eb3ee3b", size = 125009 } | ||
| wheels = [ | ||
| { url = "https://files.pythonhosted.org/packages/23/62/0fe302c6d1be1c777cab0616e6302478251dfbf9055ad426f5d0def75c89/more_itertools-10.6.0-py3-none-any.whl", hash = "sha256:6eb054cb4b6db1473f6e15fcc676a08e4732548acd47c708f0e179c2c7c01e89", size = 63038 }, | ||
| ] | ||
| [[package]] | ||
| name = "mypy" | ||
@@ -141,2 +80,8 @@ version = "1.14.1" | ||
| { url = "https://files.pythonhosted.org/packages/54/da/3d6fc5d92d324701b0c23fb413c853892bfe0e1dbe06c9138037d459756b/mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107", size = 9885276 }, | ||
| { url = "https://files.pythonhosted.org/packages/ca/1f/186d133ae2514633f8558e78cd658070ba686c0e9275c5a5c24a1e1f0d67/mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35", size = 11200493 }, | ||
| { url = "https://files.pythonhosted.org/packages/af/fc/4842485d034e38a4646cccd1369f6b1ccd7bc86989c52770d75d719a9941/mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc", size = 10357702 }, | ||
| { url = "https://files.pythonhosted.org/packages/b4/e6/457b83f2d701e23869cfec013a48a12638f75b9d37612a9ddf99072c1051/mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9", size = 12091104 }, | ||
| { url = "https://files.pythonhosted.org/packages/f1/bf/76a569158db678fee59f4fd30b8e7a0d75bcbaeef49edd882a0d63af6d66/mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb", size = 12830167 }, | ||
| { url = "https://files.pythonhosted.org/packages/43/bc/0bc6b694b3103de9fed61867f1c8bd33336b913d16831431e7cb48ef1c92/mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60", size = 13013834 }, | ||
| { url = "https://files.pythonhosted.org/packages/b0/79/5f5ec47849b6df1e6943d5fd8e6632fbfc04b4fd4acfa5a5a9535d11b4e2/mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c", size = 9781231 }, | ||
| { url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905 }, | ||
@@ -190,15 +135,2 @@ ] | ||
| [[package]] | ||
| name = "pytest-cov" | ||
| version = "6.0.0" | ||
| source = { registry = "https://pypi.org/simple" } | ||
| dependencies = [ | ||
| { name = "coverage", extra = ["toml"] }, | ||
| { name = "pytest" }, | ||
| ] | ||
| sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 } | ||
| wheels = [ | ||
| { url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949 }, | ||
| ] | ||
| [[package]] | ||
| name = "ruff" | ||
@@ -268,50 +200,12 @@ version = "0.9.4" | ||
| [[package]] | ||
| name = "tree-sitter" | ||
| version = "0.24.0" | ||
| name = "typer-slim" | ||
| version = "0.15.2" | ||
| source = { registry = "https://pypi.org/simple" } | ||
| sdist = { url = "https://files.pythonhosted.org/packages/a7/a2/698b9d31d08ad5558f8bfbfe3a0781bd4b1f284e89bde3ad18e05101a892/tree-sitter-0.24.0.tar.gz", hash = "sha256:abd95af65ca2f4f7eca356343391ed669e764f37748b5352946f00f7fc78e734", size = 168304 } | ||
| wheels = [ | ||
| { url = "https://files.pythonhosted.org/packages/08/9a/bd627a02e41671af73222316e1fcf87772c7804dc2fba99405275eb1f3eb/tree_sitter-0.24.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f3f00feff1fc47a8e4863561b8da8f5e023d382dd31ed3e43cd11d4cae445445", size = 140890 }, | ||
| { url = "https://files.pythonhosted.org/packages/5b/9b/b1ccfb187f8be78e2116176a091a2f2abfd043a06d78f80c97c97f315b37/tree_sitter-0.24.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f9691be48d98c49ef8f498460278884c666b44129222ed6217477dffad5d4831", size = 134413 }, | ||
| { url = "https://files.pythonhosted.org/packages/01/39/e25b0042a049eb27e991133a7aa7c49bb8e49a8a7b44ca34e7e6353ba7ac/tree_sitter-0.24.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:098a81df9f89cf254d92c1cd0660a838593f85d7505b28249216661d87adde4a", size = 560427 }, | ||
| { url = "https://files.pythonhosted.org/packages/1c/59/4d132f1388da5242151b90acf32cc56af779bfba063923699ab28b276b62/tree_sitter-0.24.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b26bf9e958da6eb7e74a081aab9d9c7d05f9baeaa830dbb67481898fd16f1f5", size = 574327 }, | ||
| { url = "https://files.pythonhosted.org/packages/ec/97/3914e45ab9e0ff0f157e493caa91791372508488b97ff0961a0640a37d25/tree_sitter-0.24.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2a84ff87a2f2a008867a1064aba510ab3bd608e3e0cd6e8fef0379efee266c73", size = 577171 }, | ||
| { url = "https://files.pythonhosted.org/packages/c5/b0/266a529c3eef171137b73cde8ad7aa282734354609a8b2f5564428e8f12d/tree_sitter-0.24.0-cp310-cp310-win_amd64.whl", hash = "sha256:c012e4c345c57a95d92ab5a890c637aaa51ab3b7ff25ed7069834b1087361c95", size = 120260 }, | ||
| { url = "https://files.pythonhosted.org/packages/c1/c3/07bfaa345e0037ff75d98b7a643cf940146e4092a1fd54eed0359836be03/tree_sitter-0.24.0-cp310-cp310-win_arm64.whl", hash = "sha256:033506c1bc2ba7bd559b23a6bdbeaf1127cee3c68a094b82396718596dfe98bc", size = 108416 }, | ||
| { url = "https://files.pythonhosted.org/packages/66/08/82aaf7cbea7286ee2a0b43e9b75cb93ac6ac132991b7d3c26ebe5e5235a3/tree_sitter-0.24.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de0fb7c18c6068cacff46250c0a0473e8fc74d673e3e86555f131c2c1346fb13", size = 140733 }, | ||
| { url = "https://files.pythonhosted.org/packages/8c/bd/1a84574911c40734d80327495e6e218e8f17ef318dd62bb66b55c1e969f5/tree_sitter-0.24.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a7c9c89666dea2ce2b2bf98e75f429d2876c569fab966afefdcd71974c6d8538", size = 134243 }, | ||
| { url = "https://files.pythonhosted.org/packages/46/c1/c2037af2c44996d7bde84eb1c9e42308cc84b547dd6da7f8a8bea33007e1/tree_sitter-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ddb113e6b8b3e3b199695b1492a47d87d06c538e63050823d90ef13cac585fd", size = 562030 }, | ||
| { url = "https://files.pythonhosted.org/packages/4c/aa/2fb4d81886df958e6ec7e370895f7106d46d0bbdcc531768326124dc8972/tree_sitter-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01ea01a7003b88b92f7f875da6ba9d5d741e0c84bb1bd92c503c0eecd0ee6409", size = 575585 }, | ||
| { url = "https://files.pythonhosted.org/packages/e3/3c/5f997ce34c0d1b744e0f0c0757113bdfc173a2e3dadda92c751685cfcbd1/tree_sitter-0.24.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:464fa5b2cac63608915a9de8a6efd67a4da1929e603ea86abaeae2cb1fe89921", size = 578203 }, | ||
| { url = "https://files.pythonhosted.org/packages/d5/1f/f2bc7fa7c3081653ea4f2639e06ff0af4616c47105dbcc0746137da7620d/tree_sitter-0.24.0-cp311-cp311-win_amd64.whl", hash = "sha256:3b1f3cbd9700e1fba0be2e7d801527e37c49fc02dc140714669144ef6ab58dce", size = 120147 }, | ||
| { url = "https://files.pythonhosted.org/packages/c0/4c/9add771772c4d72a328e656367ca948e389432548696a3819b69cdd6f41e/tree_sitter-0.24.0-cp311-cp311-win_arm64.whl", hash = "sha256:f3f08a2ca9f600b3758792ba2406971665ffbad810847398d180c48cee174ee2", size = 108302 }, | ||
| { url = "https://files.pythonhosted.org/packages/e9/57/3a590f287b5aa60c07d5545953912be3d252481bf5e178f750db75572bff/tree_sitter-0.24.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:14beeff5f11e223c37be7d5d119819880601a80d0399abe8c738ae2288804afc", size = 140788 }, | ||
| { url = "https://files.pythonhosted.org/packages/61/0b/fc289e0cba7dbe77c6655a4dd949cd23c663fd62a8b4d8f02f97e28d7fe5/tree_sitter-0.24.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26a5b130f70d5925d67b47db314da209063664585a2fd36fa69e0717738efaf4", size = 133945 }, | ||
| { url = "https://files.pythonhosted.org/packages/86/d7/80767238308a137e0b5b5c947aa243e3c1e3e430e6d0d5ae94b9a9ffd1a2/tree_sitter-0.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fc5c3c26d83c9d0ecb4fc4304fba35f034b7761d35286b936c1db1217558b4e", size = 564819 }, | ||
| { url = "https://files.pythonhosted.org/packages/bf/b3/6c5574f4b937b836601f5fb556b24804b0a6341f2eb42f40c0e6464339f4/tree_sitter-0.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:772e1bd8c0931c866b848d0369b32218ac97c24b04790ec4b0e409901945dd8e", size = 579303 }, | ||
| { url = "https://files.pythonhosted.org/packages/0a/f4/bd0ddf9abe242ea67cca18a64810f8af230fc1ea74b28bb702e838ccd874/tree_sitter-0.24.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:24a8dd03b0d6b8812425f3b84d2f4763322684e38baf74e5bb766128b5633dc7", size = 581054 }, | ||
| { url = "https://files.pythonhosted.org/packages/8c/1c/ff23fa4931b6ef1bbeac461b904ca7e49eaec7e7e5398584e3eef836ec96/tree_sitter-0.24.0-cp312-cp312-win_amd64.whl", hash = "sha256:f9e8b1605ab60ed43803100f067eed71b0b0e6c1fb9860a262727dbfbbb74751", size = 120221 }, | ||
| { url = "https://files.pythonhosted.org/packages/b2/2a/9979c626f303177b7612a802237d0533155bf1e425ff6f73cc40f25453e2/tree_sitter-0.24.0-cp312-cp312-win_arm64.whl", hash = "sha256:f733a83d8355fc95561582b66bbea92ffd365c5d7a665bc9ebd25e049c2b2abb", size = 108234 }, | ||
| { url = "https://files.pythonhosted.org/packages/61/cd/2348339c85803330ce38cee1c6cbbfa78a656b34ff58606ebaf5c9e83bd0/tree_sitter-0.24.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0d4a6416ed421c4210f0ca405a4834d5ccfbb8ad6692d4d74f7773ef68f92071", size = 140781 }, | ||
| { url = "https://files.pythonhosted.org/packages/8b/a3/1ea9d8b64e8dcfcc0051028a9c84a630301290995cd6e947bf88267ef7b1/tree_sitter-0.24.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e0992d483677e71d5c5d37f30dfb2e3afec2f932a9c53eec4fca13869b788c6c", size = 133928 }, | ||
| { url = "https://files.pythonhosted.org/packages/fe/ae/55c1055609c9428a4aedf4b164400ab9adb0b1bf1538b51f4b3748a6c983/tree_sitter-0.24.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57277a12fbcefb1c8b206186068d456c600dbfbc3fd6c76968ee22614c5cd5ad", size = 564497 }, | ||
| { url = "https://files.pythonhosted.org/packages/ce/d0/f2ffcd04882c5aa28d205a787353130cbf84b2b8a977fd211bdc3b399ae3/tree_sitter-0.24.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d25fa22766d63f73716c6fec1a31ee5cf904aa429484256bd5fdf5259051ed74", size = 578917 }, | ||
| { url = "https://files.pythonhosted.org/packages/af/82/aebe78ea23a2b3a79324993d4915f3093ad1af43d7c2208ee90be9273273/tree_sitter-0.24.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7d5d9537507e1c8c5fa9935b34f320bfec4114d675e028f3ad94f11cf9db37b9", size = 581148 }, | ||
| { url = "https://files.pythonhosted.org/packages/a1/b4/6b0291a590c2b0417cfdb64ccb8ea242f270a46ed429c641fbc2bfab77e0/tree_sitter-0.24.0-cp313-cp313-win_amd64.whl", hash = "sha256:f58bb4956917715ec4d5a28681829a8dad5c342cafd4aea269f9132a83ca9b34", size = 120207 }, | ||
| { url = "https://files.pythonhosted.org/packages/a8/18/542fd844b75272630229c9939b03f7db232c71a9d82aadc59c596319ea6a/tree_sitter-0.24.0-cp313-cp313-win_arm64.whl", hash = "sha256:23641bd25dcd4bb0b6fa91b8fb3f46cc9f1c9f475efe4d536d3f1f688d1b84c8", size = 108232 }, | ||
| dependencies = [ | ||
| { name = "click" }, | ||
| { name = "typing-extensions" }, | ||
| ] | ||
| [[package]] | ||
| name = "tree-sitter-zig" | ||
| version = "1.1.2" | ||
| source = { registry = "https://pypi.org/simple" } | ||
| sdist = { url = "https://files.pythonhosted.org/packages/5c/97/75967b81460e0ce999de4736b9ac189dcd5ad1c85aabcc398ba529f4838e/tree_sitter_zig-1.1.2.tar.gz", hash = "sha256:da24db16df92f7fcfa34448e06a14b637b1ff985f7ce2ee19183c489e187a92e", size = 194084 } | ||
| sdist = { url = "https://files.pythonhosted.org/packages/29/67/88189eb827c491646511dc6c806e2e6e543241cae5438383aa042b1dfa40/typer_slim-0.15.2.tar.gz", hash = "sha256:4a666bb7839a88f51dd25d078d36dbc1d0f37c8c2696e184fbc1f3eaa314a91b", size = 100755 } | ||
| wheels = [ | ||
| { url = "https://files.pythonhosted.org/packages/b3/c6/db41d3f6c7c0174db56d9122a2a4d8b345c377ca87268e76557b2879675e/tree_sitter_zig-1.1.2-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:e7542354a5edba377b5692b2add4f346501306d455e192974b7e76bf1a61a282", size = 61900 }, | ||
| { url = "https://files.pythonhosted.org/packages/5a/78/93d32fea98b3b031bc0fbec44e27f2b8cc1a1a8ff5a99dfb1a8f85b11d43/tree_sitter_zig-1.1.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:daa2cdd7c1a2d278f2a917c85993adb6e84d37778bfc350ee9e342872e7f8be2", size = 67837 }, | ||
| { url = "https://files.pythonhosted.org/packages/40/45/ef5afd6b79bd58731dae2cf61ff7960dd616737397db4d2e926457ff24b7/tree_sitter_zig-1.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1962e95067ac5ee784daddd573f828ef32f15e9c871967df6833d3d389113eae", size = 83391 }, | ||
| { url = "https://files.pythonhosted.org/packages/78/02/275523eb05108d83e154f52c7255763bac8b588ae14163563e19479322a7/tree_sitter_zig-1.1.2-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e924509dcac5a6054da357e3d6bcf37ea82984ee1d2a376569753d32f61ea8bb", size = 82323 }, | ||
| { url = "https://files.pythonhosted.org/packages/ef/e9/ff3c11097e37d4d899155c8fbdf7531063b6d15ee252b2e01ce0063f0218/tree_sitter_zig-1.1.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d8f463c370cdd71025b8d40f90e21e8fc25c7394eb64ebd53b1e566d712a3a68", size = 81383 }, | ||
| { url = "https://files.pythonhosted.org/packages/ab/5c/f5fb2ce355bbd381e647b04e8b2078a4043e663b6df6145d87550d3c3fe5/tree_sitter_zig-1.1.2-cp39-abi3-win_amd64.whl", hash = "sha256:7b94f00a0e69231ac4ebf0aa763734b9b5637e0ff13634ebfe6d13fadece71e9", size = 65105 }, | ||
| { url = "https://files.pythonhosted.org/packages/34/8d/c0a481cc7bba9d39c533dd3098463854b5d3c4e6134496d9d83cd1331e51/tree_sitter_zig-1.1.2-cp39-abi3-win_arm64.whl", hash = "sha256:88152ebeaeca1431a6fc943a8b391fee6f6a8058f17435015135157735061ddf", size = 63219 }, | ||
| { url = "https://files.pythonhosted.org/packages/9e/84/9b68e98bf7417d25e38b27a0296bfcbc6719b15d7000f4c09d9716fa9d11/typer_slim-0.15.2-py3-none-any.whl", hash = "sha256:4273014a3378b24367bffed45c2ce8dd3d85bd201a6f02e51ba6b19f336009be", size = 45117 }, | ||
| ] | ||
@@ -330,8 +224,8 @@ | ||
| name = "zig-codeblocks" | ||
| version = "0.2.3" | ||
| version = "0.3.0" | ||
| source = { editable = "." } | ||
| dependencies = [ | ||
| { name = "more-itertools" }, | ||
| { name = "tree-sitter" }, | ||
| { name = "tree-sitter-zig" }, | ||
| [package.optional-dependencies] | ||
| cli = [ | ||
| { name = "typer-slim" }, | ||
| ] | ||
@@ -343,3 +237,2 @@ | ||
| { name = "pytest" }, | ||
| { name = "pytest-cov" }, | ||
| { name = "ruff" }, | ||
@@ -349,7 +242,4 @@ ] | ||
| [package.metadata] | ||
| requires-dist = [ | ||
| { name = "more-itertools", specifier = "~=10.6" }, | ||
| { name = "tree-sitter", specifier = "~=0.24.0" }, | ||
| { name = "tree-sitter-zig", specifier = ">=1.1.2,<2" }, | ||
| ] | ||
| requires-dist = [{ name = "typer-slim", marker = "extra == 'cli'", specifier = ">=0.15.2" }] | ||
| provides-extras = ["cli"] | ||
@@ -360,4 +250,3 @@ [package.metadata.requires-dev] | ||
| { name = "pytest", specifier = ">=8.3.4" }, | ||
| { name = "pytest-cov", specifier = ">=6.0.0" }, | ||
| { name = "ruff", specifier = ">=0.9.4" }, | ||
| ] |
| from zig_codeblocks.styling import Color, Style, Theme | ||
| KEYWORDS = frozenset( | ||
| { | ||
| "addrspace", | ||
| "align", | ||
| "allowzero", | ||
| "and", | ||
| "anyframe", | ||
| "anytype", | ||
| "asm", | ||
| "async", | ||
| "await", | ||
| "break", | ||
| "callconv", | ||
| "catch", | ||
| "comptime", | ||
| "const", | ||
| "continue", | ||
| "defer", | ||
| "else", | ||
| "enum", | ||
| "errdefer", | ||
| "error", | ||
| "export", | ||
| "extern", | ||
| "fn", | ||
| "for", | ||
| "if", | ||
| "inline", | ||
| "linksection", | ||
| "noalias", | ||
| "noinline", | ||
| "nosuspend", | ||
| "opaque", | ||
| "or", | ||
| "orelse", | ||
| "packed", | ||
| "pub", | ||
| "resume", | ||
| "return", | ||
| "struct", | ||
| "suspend", | ||
| "switch", | ||
| "test", | ||
| "threadlocal", | ||
| "try", | ||
| "union", | ||
| "unreachable", | ||
| "usingnamespace", | ||
| "var", | ||
| "volatile", | ||
| "while", | ||
| } | ||
| ) | ||
| IDENTIFIERS = frozenset({"identifier", "c"}) | ||
| NUMERIC_LITERALS = frozenset({"integer", "float"}) | ||
| PRIMITIVE_VALUES = frozenset({"true", "false", "null", "undefined"}) | ||
| TYPES = frozenset( | ||
| { | ||
| "anyerror", | ||
| "anyopaque", | ||
| "bool", | ||
| "builtin_type", | ||
| "c_char", | ||
| "c_int", | ||
| "c_long", | ||
| "c_longdouble", | ||
| "c_longlong", | ||
| "c_short", | ||
| "c_uint", | ||
| "c_ulong", | ||
| "c_ulonglong", | ||
| "c_ushort", | ||
| "comptime_float", | ||
| "comptime_int", | ||
| "f128", | ||
| "f16", | ||
| "f32", | ||
| "f64", | ||
| "f80", | ||
| "isize", | ||
| "noreturn", | ||
| "type", | ||
| "usize", | ||
| "void", | ||
| } | ||
| ) | ||
| STRINGLIKE = frozenset( | ||
| {"string_content", "multiline_string", '"', "'", "character_content"} | ||
| ) | ||
| DEFAULT_THEME = Theme( | ||
| builtin_identifiers=Style(Color.BLUE, bold=True), | ||
| calls=Style(Color.BLUE), | ||
| comments=Style(Color.GRAY), | ||
| keywords=Style(Color.MAGENTA), | ||
| numeric=Style(Color.CYAN), | ||
| primitive_values=Style(Color.CYAN), | ||
| strings=Style(Color.GREEN), | ||
| types=Style(Color.ORANGE), | ||
| ) |
| from __future__ import annotations | ||
| import re | ||
| from typing import TYPE_CHECKING, TypeVar, cast | ||
| from more_itertools import peekable | ||
| from zig_codeblocks import consts | ||
| from zig_codeblocks.parsing import extract_codeblocks, tokenize_zig | ||
| from zig_codeblocks.styling import RESET, Style, Theme | ||
| if TYPE_CHECKING: | ||
| from collections.abc import Iterator | ||
| from zig_codeblocks.parsing import Token | ||
| Body = list[str | Style] | ||
| T = TypeVar("T") | ||
| def _get_style(kind: str, theme: Theme) -> Style | None: | ||
| for options, style in ( | ||
| (consts.IDENTIFIERS, theme.get("identifiers")), | ||
| (consts.KEYWORDS, theme.get("keywords")), | ||
| (consts.NUMERIC_LITERALS, theme.get("numeric")), | ||
| (consts.PRIMITIVE_VALUES, theme.get("primitive_values")), | ||
| (consts.STRINGLIKE, theme.get("strings")), | ||
| (consts.TYPES, theme.get("types")), | ||
| ): | ||
| if kind in options: | ||
| return style | ||
| if kind == "comment": | ||
| return theme.get("comments") | ||
| if kind == "builtin_identifier": | ||
| return theme.get("builtin_identifiers") | ||
| return None | ||
| def _last_applied_style(body: Body) -> Style | str | None: | ||
| return next( | ||
| (item for item in body[::-1] if not isinstance(item, str) or item == RESET), | ||
| None, | ||
| ) | ||
| def _adjust_string_idents(body: Body, token: Token, theme: Theme) -> None: | ||
| # Special case for `whatever.@"something here"`, | ||
| # which is an identifier, so should have no string highlighting | ||
| identifier_style = theme.get("identifiers") | ||
| string_style = theme.get("strings") | ||
| if not ((identifier_style or string_style) and token.kind == '"'): | ||
| return | ||
| if not string_style: | ||
| if len(body) > 2 and body[-3] == "@": | ||
| body.insert(-2, cast(Style, identifier_style)) | ||
| return | ||
| if _last_applied_style(body) == string_style and len(body) > 3 and body[-4] == "@": | ||
| if identifier_style: | ||
| body[-3] = identifier_style | ||
| else: | ||
| del body[-3] | ||
| def _process_zig_tokens( | ||
| source: bytes, tokens: Iterator[Token], theme: Theme = consts.DEFAULT_THEME | ||
| ) -> str: | ||
| body: Body = [] | ||
| pointer = 0 | ||
| tokens = peekable(tokens) | ||
| token = next(tokens) | ||
| def skip_to_token() -> None: | ||
| nonlocal pointer | ||
| filler = source[pointer : token.byte_range.start] | ||
| match filler.isspace(), _last_applied_style(body): | ||
| case (_, None): | ||
| pass | ||
| case (True, Style(underline=True) | Style(bold=True)) | (False, Style()): | ||
| body.append(RESET) | ||
| body.append(filler.decode()) | ||
| pointer = token.byte_range.start | ||
| while pointer < len(source): | ||
| if token.byte_range.start > pointer: | ||
| skip_to_token() | ||
| continue | ||
| style = ( | ||
| theme.get("calls") | ||
| if token.kind == "identifier" | ||
| and (next_token := tokens.peek(None)) | ||
| and next_token.kind == "(" | ||
| else _get_style(token.kind, theme) | ||
| ) | ||
| if style is None: | ||
| if _last_applied_style(body) not in (RESET, None): | ||
| body.append(RESET) | ||
| elif _last_applied_style(body) is not style: | ||
| body.append(style) | ||
| _adjust_string_idents(body, token, theme) | ||
| body.append(token.value.decode()) | ||
| pointer = token.byte_range.stop | ||
| try: | ||
| token = next(tokens) | ||
| except StopIteration: | ||
| break | ||
| return "".join(map(str, body)) | ||
| def highlight_zig_code(source: str | bytes, theme: Theme = consts.DEFAULT_THEME) -> str: | ||
| """ | ||
| Return an ANSI syntax-highlighted version of the given Zig source code. | ||
| Assumes UTF-8 if source is `bytes`. | ||
| """ | ||
| if isinstance(source, str): | ||
| source = source.encode() | ||
| return _process_zig_tokens(source, tokenize_zig(source), theme) | ||
| def process_markdown( | ||
| source: str | bytes, theme: Theme = consts.DEFAULT_THEME, *, only_code: bool = False | ||
| ) -> str: | ||
| """ | ||
| Return a Markdown source with Zig code blocks syntax-highlighted. | ||
| If `only_code` is True, only processed Zig code blocks will be returned. | ||
| Assumes UTF-8 if source is `bytes`. | ||
| """ | ||
| if isinstance(source, bytes): | ||
| source = source.decode() | ||
| zig_codeblocks = ( | ||
| block.body for block in extract_codeblocks(source) if block.lang == "zig" | ||
| ) | ||
| if only_code: | ||
| return "\n".join( | ||
| f"```ansi\n{highlight_zig_code(code, theme)}\n```" | ||
| for code in zig_codeblocks | ||
| ) | ||
| for codeblock in zig_codeblocks: | ||
| highlighted_source = f"```ansi\n{highlight_zig_code(codeblock, theme)}\n```" | ||
| source = re.sub( | ||
| f"```zig\n{re.escape(codeblock)}(?:\r?\n)*```", | ||
| highlighted_source.replace("\\", r"\\"), | ||
| source, | ||
| ) | ||
| return source |
| import re | ||
| from collections.abc import Iterator | ||
| from itertools import chain | ||
| from typing import NamedTuple | ||
| import tree_sitter as ts | ||
| import tree_sitter_zig | ||
| CODE_BLOCK_PATTERN = re.compile( | ||
| r"```(?:([A-Za-z0-9\-_\+\.#]+)(?:\r?\n)+([^\r\n].*?)|(.*?))```", re.DOTALL | ||
| ) | ||
| ZIG_PARSER = ts.Parser(ts.Language(tree_sitter_zig.language())) | ||
| class Token(NamedTuple): | ||
| kind: str | ||
| value: bytes | ||
| byte_range: range | ||
| class CodeBlock(NamedTuple): | ||
| """A code block extracted from a Markdown source.""" | ||
| lang: str | None | ||
| body: str | ||
| def extract_codeblocks(source: str | bytes) -> Iterator[CodeBlock]: | ||
| """Yield CodeBlocks from a Markdown source. Assumes UTF-8 if source is `bytes`.""" | ||
| if isinstance(source, bytes): | ||
| source = source.decode() | ||
| for m in CODE_BLOCK_PATTERN.finditer(source): | ||
| lang, body, no_lang_body = m.groups() | ||
| yield ( | ||
| CodeBlock(lang, body=body.strip("\r\n")) | ||
| if lang | ||
| else CodeBlock(lang=None, body=no_lang_body.strip("\r\n")) | ||
| ) | ||
| def tokenize_zig(src: bytes) -> Iterator[Token]: | ||
| tree = ZIG_PARSER.parse(src) | ||
| return _traverse(tree.root_node, src) | ||
| def _traverse(node: ts.Node, src: bytes) -> Iterator[Token]: | ||
| if node.child_count == 0: | ||
| yield Token( | ||
| node.type, | ||
| src[node.start_byte : node.end_byte], | ||
| range(node.start_byte, node.end_byte), | ||
| ) | ||
| else: | ||
| yield from chain.from_iterable(_traverse(child, src) for child in node.children) |
| from __future__ import annotations | ||
| from dataclasses import KW_ONLY, dataclass | ||
| from enum import Enum | ||
| from itertools import compress | ||
| from typing import TypedDict | ||
| def _to_sgr(*args: str) -> str: | ||
| return f"\033[{';'.join(args)}m" | ||
| RESET = _to_sgr("0") | ||
| class Color(Enum): | ||
| """ | ||
| An enumeration of 3-bit ANSI colors. | ||
| Some names were adjusted to match Discord's style. | ||
| """ | ||
| GRAY = "30" | ||
| RED = "31" | ||
| GREEN = "32" | ||
| ORANGE = "33" | ||
| BLUE = "34" | ||
| MAGENTA = "35" | ||
| CYAN = "36" | ||
| WHITE = "37" # Black for light mode | ||
| @dataclass(slots=True, frozen=True) | ||
| class Style: | ||
| """ | ||
| A style for syntax highlighting. | ||
| Takes a `Color` and can optionally be bold and/or underlined. | ||
| Produces an SGR sequence when converted to a string. | ||
| """ | ||
| color: Color | ||
| _: KW_ONLY | ||
| bold: bool = False | ||
| underline: bool = False | ||
| def __str__(self) -> str: | ||
| modifiers = compress(("1", "4"), (self.bold, self.underline)) | ||
| return _to_sgr(self.color.value, *modifiers) | ||
| class Theme(TypedDict, total=False): | ||
| """A theme for syntax highlighting Zig code.""" | ||
| builtin_identifiers: Style | ||
| calls: Style | ||
| comments: Style | ||
| identifiers: Style | ||
| keywords: Style | ||
| numeric: Style | ||
| strings: Style | ||
| primitive_values: Style | ||
| types: Style |
Sorry, the diff of this file is not supported yet
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
640401
1.98%53
15.22%2083
-17.08%