diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml
new file mode 100644
index 0000000..159b445
--- /dev/null
+++ b/.github/workflows/gh-pages.yml
@@ -0,0 +1,72 @@
+name: github pages
+
+on:
+ push:
+ branches:
+ - main # Set a branch to deploy
+ workflow_dispatch:
+ pull_request:
+
+# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+# Allow one concurrent deployment
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+env:
+ USE_MKDOCS_MATERIAL_INSIDERS: false
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ environment: github-pages
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # for rss
+
+ # for social cards
+ - run: sudo apt-get install libcairo2-dev libfreetype6-dev libffi-dev libjpeg-dev libpng-dev libz-dev
+
+ - name: Install uv
+ uses: astral-sh/setup-uv@v5
+ with:
+ enable-cache: true
+ cache-dependency-glob: "uv.lock"
+
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version-file: "pyproject.toml"
+
+ - name: Install Mkdocs-Material
+ run: uv sync
+
+ - name: Install Mkdocs-Material-Insiders
+ run: |
+ uv pip uninstall mkdocs-material
+ uv pip install --upgrade git+https://${{ secrets.MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git
+ if: ${{ env.USE_MKDOCS_MATERIAL_INSIDERS == 'true' }}
+
+ - name: Build
+ run: uv run mkdocs build
+
+ - name: Setup Pages
+ if: github.event_name != 'pull_request'
+ uses: actions/configure-pages@v5
+
+ - name: Upload artifact
+ if: github.event_name != 'pull_request'
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: "./site"
+
+ - name: Deploy to GitHub Pages
+ if: github.event_name != 'pull_request'
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.gitignore b/.gitignore
index f0d4bc0..6f41501 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
.tests
+site
diff --git a/.pkgx.yml b/.pkgx.yml
index 8291bfc..2759a1b 100644
--- a/.pkgx.yml
+++ b/.pkgx.yml
@@ -1,2 +1,3 @@
dependencies:
- go.dev
+ - python
diff --git a/README.md b/README.md
index 443a93a..0ae4232 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ Reliable Neotest adapter for running Go tests in Neovim.
![neotest-golang](https://github.com/fredrikaverpil/neotest-golang/assets/994357/afb6e936-b355-4d7b-ab73-65c21ee66ae7)
-## ⭐️ Features
+## Features
- Supports all [Neotest usage](https://github.com/nvim-neotest/neotest#usage).
- Supports table tests and nested test functions (based on treesitter AST
@@ -22,878 +22,7 @@ Reliable Neotest adapter for running Go tests in Neovim.
- Supports [testify](https://github.com/stretchr/testify) suites.
- Option to sanitize test output from non-UTF8 characters.
-
-Why a second Neotest adapter for Go? 🤔
+---
-While using [neotest-go](https://github.com/nvim-neotest/neotest-go) I stumbled
-upon many problems which seemed difficult to solve in that codebase.
-
-I have full respect for the time and efforts put in by the developer(s) of
-neotest-go. I do not aim in any way to diminish their needs or efforts. However,
-I wanted to see if I could fix these issues by diving into the 🕳️🐇 of Neotest
-and building my own adapter. Below is a list of neotest-go issues which are not
-present in neotest-golang (this project):
-
-| Neotest-go issue | URL |
-| ------------------------------------------------------- | --------------------------------------------------------------------- |
-| Support for Testify framework | [neotest-go#6](https://github.com/nvim-neotest/neotest-go/issues/6) |
-| DAP support | [neotest-go#12](https://github.com/nvim-neotest/neotest-go/issues/12) |
-| Test Output in JSON, making it difficult to read | [neotest-go#52](https://github.com/nvim-neotest/neotest-go/issues/52) |
-| Support for Nested Subtests | [neotest-go#74](https://github.com/nvim-neotest/neotest-go/issues/74) |
-| Diagnostics for table tests on the line of failure | [neotest-go#75](https://github.com/nvim-neotest/neotest-go/issues/75) |
-| "Run nearest" runs all tests | [neotest-go#83](https://github.com/nvim-neotest/neotest-go/issues/83) |
-| Table tests not recognized when defined inside for-loop | [neotest-go#86](https://github.com/nvim-neotest/neotest-go/issues/86) |
-| Running test suite doesn't work | [neotest-go#89](https://github.com/nvim-neotest/neotest-go/issues/89) |
-
-And here, a comparison in number of GitHub stars between the projects:
-
-[![Star History Chart](https://api.star-history.com/svg?repos=fredrikaverpil/neotest-golang,nvim-neotest/neotest-go&type=Date)](https://star-history.com/#fredrikaverpil/neotest-golang&nvim-neotest/neotest-go&Date)
-
-
-
-## 🥸 Installation
-
-> [!NOTE]
->
-> Requires Neovim 0.10.0 and above.
-
-
-💤 Lazy.nvim
-
-```lua
-return {
- {
- "nvim-neotest/neotest",
- dependencies = {
- "nvim-neotest/nvim-nio",
- "nvim-lua/plenary.nvim",
- "antoinemadec/FixCursorHold.nvim",
- "nvim-treesitter/nvim-treesitter",
- { "fredrikaverpil/neotest-golang", version = "*" }, -- Installation
- },
- config = function()
- require("neotest").setup({
- adapters = {
- require("neotest-golang"), -- Registration
- },
- })
- end,
- },
-}
-```
-
-For increased stability and less updating noise, I recommend that you track
-official releases by setting `version = "*"`. By omitting this option (or
-setting `version = false`), you will get the latest and greatest directly from
-the main branch.
-
-I do not recommend pinning to a specific version or to a major version. But
-ultimately it is up to you what you want :smile:.
-
-See the [Lazy versioning spec](https://lazy.folke.io/spec/versioning) for more
-details.
-
-
-
-
-🌒 Rocks.nvim
-
-The adapter is available via
-[luarocks package](https://luarocks.org/modules/fredrikaverpil/neotest-golang):
-
-```vim
-:Rocks install neotest-golang
-```
-
-[rocks.nvim](https://github.com/nvim-neorocks/rocks.nvim) will automatically
-install dependencies if they are not already installed. You will need to call
-neotest's `setup` function to register this adapter. If you use
-[rocks-config.nvim](https://github.com/nvim-neorocks/rocks-config.nvim),
-consider setting up neotest and its adapters in a
-[plugin bundle](https://github.com/nvim-neorocks/rocks-config.nvim?tab=readme-ov-file#plugin-bundles).
-
-> [!NOTE]
->
-> Please note that [leoluz/nvim-dap-go](https://github.com/leoluz/nvim-dap-go)
-> (required for DAP) is not on luarocks as of writing this.
-
-
-
-
-❄️ Nix & Home manager
-
-```nix
-{
- config,
- pkgs,
- ...
-}: {
- home.packages = with pkgs; [];
- programs = {
- neovim = {
- plugins = [
- # neotest and dependencies
- pkgs.vimPlugins.neotest
- pkgs.vimPlugins.nvim-nio
- pkgs.vimPlugins.plenary-nvim
- pkgs.vimPlugins.FixCursorHold-nvim
- pkgs.vimPlugins.nvim-treesitter
- (pkgs.vimPlugins.nvim-treesitter.withPlugins (plugins: [plugins.go]))
- pkgs.vimPlugins.neotest-golang
-
- ## debugging
- pkgs.vimPlugins.nvim-dap
- pkgs.vimPlugins.nvim-dap-ui
- pkgs.vimPlugins.nvim-nio
- pkgs.vimPlugins.nvim-dap-virtual-text
- pkgs.vimPlugins.nvim-dap-go
- ];
- enable = true;
- extraConfig = ''
- lua << EOF
- require("neotest").setup({
- adapters = {
- require("neotest-golang")
- },
- })
- EOF
- '';
- };
- };
-}
-```
-
-
-
-## ⚙️ Configuration
-
-| Argument | Default value | Description |
-| ------------------------ | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `runner` | `go` | Defines the test runner. Valid values: `go` or `gotestsum`. |
-| `go_test_args` | `{ "-v", "-race", "-count=1" }` | Arguments to pass into `go test`. Notes: [`-tags` usage](https://github.com/fredrikaverpil/neotest-golang#using-build-tags), [pass args as function](https://github.com/fredrikaverpil/neotest-golang#pass-arguments-as-function-instead-of-table). |
-| `gotestsum_args` | `{ "--format=standard-verbose" }` | Arguments to pass into `gotestsum`. Notes: [`-tags` usage](https://github.com/fredrikaverpil/neotest-golang#using-build-tags), [pass args as function](https://github.com/fredrikaverpil/neotest-golang#pass-arguments-as-function-instead-of-table). Will only be used if `runner = "gotestsum"`. The `go_test_args` still applies. |
-| `go_list_args` | `{}` | Arguments to pass into `go list`. Note: [`-tags` usage](https://github.com/fredrikaverpil/neotest-golang#using-build-tags), [pass args as function](https://github.com/fredrikaverpil/neotest-golang#pass-arguments-as-function-instead-of-table). |
-| `dap_mode` | `dap-go` | Set to `manual` for manual configuration. |
-| `dap_go_opts` | `{}` | Options to pass into `require("dap-go").setup()`. Note: [`-tags` usage](https://github.com/fredrikaverpil/neotest-golang#using-build-tags), [pass args as function](https://github.com/fredrikaverpil/neotest-golang#pass-arguments-as-function-instead-of-table). |
-| `dap_manual_config` | `{}` | The configuration to apply if `dap_mode == "manual"`. |
-| `testify_enabled` | `false` | Enable support for [testify](https://github.com/stretchr/testify) suites. See [here](https://github.com/fredrikaverpil/neotest-golang#testify-suites) for more info. |
-| `colorize_test_output` | `true` | Enable output color for `SUCCESS`, `FAIL`, and `SKIP` tests. |
-| `warn_test_name_dupes` | `true` | Warn about duplicate test names within the same Go package. |
-| `warn_test_not_executed` | `true` | Warn if test was not executed. |
-| `log_level` | `vim.log.levels.WARN` | Log level. |
-| `sanitize_output` | `false` | Filter control characters and non-printable characters from test output. Note: [usage](https://github.com/fredrikaverpil/neotest-golang#example-configuration-sanitize-output). |
-
-> [!NOTE]
->
-> The `-race` flag (in `go_test_args`) requires CGO to be enabled
-> (`CGO_ENABLED=1` is the default) and a C compiler (such as GCC) to be
-> installed. However, since Go 1.20, this is not a requirement on macOS. I have
-> included the `-race` argument as default, as it provides good production
-> defaults. See [this issue](https://github.com/golang/go/issues/9918) for more
-> details.
-
-> [!IMPORTANT]
->
-> The `gotestsum` runner is recommended for Windows users or if you are using
-> Ubuntu snaps. You can read more below on `gotestsum`.
-
-### Example configuration: custom `go test` arguments
-
-```lua
-local config = { -- Specify configuration
- go_test_args = {
- "-v",
- "-race",
- "-count=1",
- "-coverprofile=" .. vim.fn.getcwd() .. "/coverage.out",
- },
-}
-require("neotest").setup({
- adapters = {
- require("neotest-golang")(config), -- Apply configuration
- },
-})
-```
-
-Note that the example above writes a coverage file. You can use
-[andythigpen/nvim-coverage](https://github.com/andythigpen/nvim-coverage) to
-show the coverage in Neovim.
-
-See `go help test`, `go help testflag`, `go help build` for possible arguments.
-
-### Example configuration: debugging
-
-To debug tests, make sure you depend on
-[mfussenegger/nvim-dap](https://github.com/mfussenegger/nvim-dap) and
-[rcarriga/nvim-dap-ui](https://github.com/rcarriga/nvim-dap-ui). Then you have
-two options:
-
-
-
- Adapter-provided DAP configuration,
- leveraging leoluz/nvim-dap-go (recommended).
-
-
-```diff
-return {
-+ {
-+ "rcarriga/nvim-dap-ui",
-+ dependencies = {
-+ "nvim-neotest/nvim-nio",
-+ "mfussenegger/nvim-dap",
-+ },
-+ },
-+
- {
- "nvim-neotest/neotest",
- dependencies = {
- "nvim-neotest/nvim-nio",
- "nvim-lua/plenary.nvim",
- "antoinemadec/FixCursorHold.nvim",
- "nvim-treesitter/nvim-treesitter",
-- "fredrikaverpil/neotest-golang", -- Installation
-+ {
-+ "fredrikaverpil/neotest-golang", -- Installation
-+ dependencies = {
-+ "leoluz/nvim-dap-go",
-+ },
-+ },
- },
- config = function()
- require("neotest").setup({
- adapters = {
- require("neotest-golang"), -- Registration
- },
- })
- end,
- },
-}
-```
-
-
-
-
-Use your own custom DAP configuration (no additional dependency needed).
-
-```diff
-return {
-+ {
-+ "rcarriga/nvim-dap-ui",
-+ dependencies = {
-+ "nvim-neotest/nvim-nio",
-+ "mfussenegger/nvim-dap",
-+ },
-+ },
-+
- {
- "nvim-neotest/neotest",
- dependencies = {
- "nvim-neotest/nvim-nio",
- "nvim-lua/plenary.nvim",
- "antoinemadec/FixCursorHold.nvim",
- "nvim-treesitter/nvim-treesitter",
- "fredrikaverpil/neotest-golang", -- Installation
- },
- config = function()
-+ local options = {
-+ dap_mode = "manual",
-+ dap_manual_config = {
-+ name = "Debug go tests",
-+ type = "go", -- Preconfigured DAP adapter name
-+ request = "launch",
-+ mode = "test",
-+ },
-+ }
- require("neotest").setup({
- adapters = {
-+ require("neotest-golang")(options) -- Registration
- },
- })
- end,
- },
-}
-```
-
-
-
-Finally, set a keymap, like:
-
-```lua
-return {
- {
- "nvim-neotest/neotest",
- ...
- keys = {
- {
- "td",
- function()
- require("neotest").run.run({ suite = false, strategy = "dap" })
- end,
- desc = "Debug nearest test",
- },
- },
- },
-}
-```
-
-For a more verbose example, see the "extra everything" example config.
-
-### Using `gotestsum` as test runner
-
-To improve reliability, you can choose to set
-[`gotestsum`](https://github.com/gotestyourself/gotestsum) as the test runner.
-This tool allows the adapter to write test command output directly to a JSON
-file, without going through stdout.
-
-Using `gotestsum` offers the following benefits:
-
-- When you "attach" to a running test, you'll see clean `go test` output instead
- of having to navigate through difficult-to-read JSON.
-- On certain platforms (such as Windows) or terminals, there's a risk of ANSI
- codes or other characters being seemingly randomly inserted into the JSON test
- output. This can corrupt the data and cause problems with test output JSON
- decoding. Enabling `gotestsum` eliminates these issues, as the test output is
- then written directly to file.
-
-`gotestsum` calls `go test` behind the scenes, so your `go_test_args`
-configuration remains valid and will still apply.
-
-> [!NOTE]
->
-> See
-> [this issue comment](https://github.com/fredrikaverpil/neotest-golang/issues/193#issuecomment-2362845806)
-> for more details on reported issues on Windows and Ubuntu snaps.
-
-#### Configure neotest-golang to use `gotestsum` as test runner
-
-Make the `gotestsum` command availalbe via
-[mason.nvim](https://github.com/williamboman/mason.nvim) or by running the
-following in your shell:
-
-```bash
-go install gotest.tools/gotestsum@latest
-```
-
-Then add the required configuration:
-
-```lua
-local config = { -- Specify configuration
- runner = "gotestsum"
-}
-require("neotest").setup({
- adapters = {
- require("neotest-golang")(config), -- Apply configuration
- },
-})
-```
-
-### Example configuration: sanitize output
-
-When tests write non-printable characters to stdout/stderr, they can cause
-various issues like failing to write output to disk or UI rendering problems.
-The `sanitize_output` option helps clean up such output by preserving UTF-8 and
-replacing control characters with the Unicode replacement character (�).
-
-This is particularly useful when:
-
-- Tests write bytes to stdout/stderr.
-- Test output contains terminal control sequences.
-- Test output includes non-printable characters.
-
-The sanitization preserves all regular printable characters including tabs,
-newlines, and carriage returns.
-
-```diff
-return {
- {
- "nvim-neotest/neotest",
- dependencies = {
- "nvim-neotest/nvim-nio",
- "nvim-lua/plenary.nvim",
- "antoinemadec/FixCursorHold.nvim",
- "nvim-treesitter/nvim-treesitter",
-- "fredrikaverpil/neotest-golang", -- Installation
-+ {
-+ "fredrikaverpil/neotest-golang", -- Installation
-+ dependencies = {
-+ "uga-rosa/utf8.nvim", -- Additional dependency required
-+ },
-+ },
- },
- config = function()
- require("neotest").setup({
- adapters = {
-- require("neotest-golang"), -- Registration
-+ require("neotest-golang")({ sanitize_output = true }), -- Registration
- },
- })
- end,
- },
-}
-```
-
-### Example configuration: extra everything
-
-In the below code block, I've provided a pretty hefty configuration example,
-which includes the required setup for testing and debugging along with all the
-keymaps. This is a merged snapshot of my own config, which I hope you can draw
-inspiration from. To view my current config, which is divided up into several
-files, see:
-
-- [plugins/neotest.lua](https://github.com/fredrikaverpil/dotfiles/blob/main/nvim-fredrik/lua/fredrik/plugins/core/neotest.lua)
-- [plugins/dap.lua](https://github.com/fredrikaverpil/dotfiles/blob/main/nvim-fredrik/lua/fredrik/plugins/core/dap.lua)
-- [lang/go.lua](https://github.com/fredrikaverpil/dotfiles/blob/main/nvim-fredrik/lua/fredrik/plugins/lang/go.lua)
-
-
-Click to expand
-
-```lua
-return {
-
- -- Neotest setup
- {
- "nvim-neotest/neotest",
- event = "VeryLazy",
- dependencies = {
- "nvim-neotest/nvim-nio",
- "nvim-lua/plenary.nvim",
- "antoinemadec/FixCursorHold.nvim",
- "nvim-treesitter/nvim-treesitter",
-
- "nvim-neotest/neotest-plenary",
- "nvim-neotest/neotest-vim-test",
-
- {
- "fredrikaverpil/neotest-golang",
- dependencies = {
- {
- "leoluz/nvim-dap-go",
- opts = {},
- },
- },
- branch = "main",
- },
- },
- opts = function(_, opts)
- opts.adapters = opts.adapters or {}
- opts.adapters["neotest-golang"] = {
- go_test_args = {
- "-v",
- "-race",
- "-coverprofile=" .. vim.fn.getcwd() .. "/coverage.out",
- },
- }
- end,
- config = function(_, opts)
- if opts.adapters then
- local adapters = {}
- for name, config in pairs(opts.adapters or {}) do
- if type(name) == "number" then
- if type(config) == "string" then
- config = require(config)
- end
- adapters[#adapters + 1] = config
- elseif config ~= false then
- local adapter = require(name)
- if type(config) == "table" and not vim.tbl_isempty(config) then
- local meta = getmetatable(adapter)
- if adapter.setup then
- adapter.setup(config)
- elseif adapter.adapter then
- adapter.adapter(config)
- adapter = adapter.adapter
- elseif meta and meta.__call then
- adapter(config)
- else
- error("Adapter " .. name .. " does not support setup")
- end
- end
- adapters[#adapters + 1] = adapter
- end
- end
- opts.adapters = adapters
- end
-
- require("neotest").setup(opts)
- end,
- keys = {
- { "ta", function() require("neotest").run.attach() end, desc = "[t]est [a]ttach" },
- { "tf", function() require("neotest").run.run(vim.fn.expand("%")) end, desc = "[t]est run [f]ile" },
- { "tA", function() require("neotest").run.run(vim.uv.cwd()) end, desc = "[t]est [A]ll files" },
- { "tS", function() require("neotest").run.run({ suite = true }) end, desc = "[t]est [S]uite" },
- { "tn", function() require("neotest").run.run() end, desc = "[t]est [n]earest" },
- { "tl", function() require("neotest").run.run_last() end, desc = "[t]est [l]ast" },
- { "ts", function() require("neotest").summary.toggle() end, desc = "[t]est [s]ummary" },
- { "to", function() require("neotest").output.open({ enter = true, auto_close = true }) end, desc = "[t]est [o]utput" },
- { "tO", function() require("neotest").output_panel.toggle() end, desc = "[t]est [O]utput panel" },
- { "tt", function() require("neotest").run.stop() end, desc = "[t]est [t]erminate" },
- { "td", function() require("neotest").run.run({ suite = false, strategy = "dap" }) end, desc = "Debug nearest test" },
- { "tD", function() require("neotest").run.run({ vim.fn.expand("%"), strategy = "dap" }) end, desc = "Debug current file" },
- },
- },
-
- -- DAP setup
- {
- "mfussenegger/nvim-dap",
- event = "VeryLazy",
- keys = {
- {"db", function() require("dap").toggle_breakpoint() end, desc = "toggle [d]ebug [b]reakpoint" },
- {"dB", function() require("dap").set_breakpoint(vim.fn.input("Breakpoint condition: ")) end, desc = "[d]ebug [B]reakpoint"},
- {"dc", function() require("dap").continue() end, desc = "[d]ebug [c]ontinue (start here)" },
- {"dC", function() require("dap").run_to_cursor() end, desc = "[d]ebug [C]ursor" },
- {"dg", function() require("dap").goto_() end, desc = "[d]ebug [g]o to line" },
- {"do", function() require("dap").step_over() end, desc = "[d]ebug step [o]ver" },
- {"dO", function() require("dap").step_out() end, desc = "[d]ebug step [O]ut" },
- {"di", function() require("dap").step_into() end, desc = "[d]ebug [i]nto" },
- {"dj", function() require("dap").down() end, desc = "[d]ebug [j]ump down" },
- {"dk", function() require("dap").up() end, desc = "[d]ebug [k]ump up" },
- {"dl", function() require("dap").run_last() end, desc = "[d]ebug [l]ast" },
- {"dp", function() require("dap").pause() end, desc = "[d]ebug [p]ause" },
- {"dr", function() require("dap").repl.toggle() end, desc = "[d]ebug [r]epl" },
- {"dR", function() require("dap").clear_breakpoints() end, desc = "[d]ebug [R]emove breakpoints" },
- {"ds", function() require("dap").session() end, desc ="[d]ebug [s]ession" },
- {"dt", function() require("dap").terminate() end, desc = "[d]ebug [t]erminate" },
- {"dw", function() require("dap.ui.widgets").hover() end, desc = "[d]ebug [w]idgets" },
- },
- },
-
- -- DAP UI setup
- {
- "rcarriga/nvim-dap-ui",
- event = "VeryLazy",
- dependencies = {
- "nvim-neotest/nvim-nio",
- "mfussenegger/nvim-dap",
- },
- opts = {},
- config = function(_, opts)
- -- setup dap config by VsCode launch.json file
- -- require("dap.ext.vscode").load_launchjs()
- local dap = require("dap")
- local dapui = require("dapui")
- dapui.setup(opts)
- dap.listeners.after.event_initialized["dapui_config"] = function()
- dapui.open({})
- end
- dap.listeners.before.event_terminated["dapui_config"] = function()
- dapui.close({})
- end
- dap.listeners.before.event_exited["dapui_config"] = function()
- dapui.close({})
- end
- end,
- keys = {
- { "du", function() require("dapui").toggle({}) end, desc = "[d]ap [u]i" },
- { "de", function() require("dapui").eval() end, desc = "[d]ap [e]val" },
- },
- },
- {
- "theHamsta/nvim-dap-virtual-text",
- opts = {},
- },
-}
-```
-
-
-
-## ⛑️ Tips & troubleshooting
-
-### Issues with setting up or using the adapter
-
-> [!TIP]
->
-> You can run `:checkhealth neotest-golang` to review common issues. If you need
-> configuring neotest-golang help, please open a discussion
-> [here](https://github.com/fredrikaverpil/neotest-golang/discussions/new?category=configuration).
-
-You can also enable logging to further inspect what's going on under the hood.
-Neotest-golang piggybacks on the Neotest logger but writes its own file. The
-default log level is `WARN` but during troubleshooting you want to increase
-this:
-
-```lua
-local config = {
- log_level = vim.log.levels.TRACE, -- set log level
-}
-
-require("neotest").setup({
- adapters = {
- require("neotest-golang")(config), -- Apply configuration
- },
-})
-```
-
-The neotest-golang logs can be opened using this convenient vim command:
-
-```vim
-:exe 'edit' stdpath('log').'/neotest-golang.log'
-```
-
-This usually corresponds to something like
-`~/.local/state/nvim/neotest-golang.log`.
-
-> [!WARNING]
->
-> Don't forget to revert back to `WARN` level once you are done troubleshooting,
-> as the `TRACE` level can degrade performance.
-
-### Neotest is slowing down Neovim
-
-Neotest, out of the box with default settings, can appear very slow in large
-projects (here, I'm referring to
-[this kind of large](https://github.com/kubernetes/kubernetes)). There are a few
-things you can do to speed up the Neotest appearance and experience in such
-cases, by tweaking the Neotest settings.
-
-You can for example limit the AST-parsing (to detect tests) to the currently
-opened file, which in my opinion makes Neotest a joy to work with, even in
-ginormous projects. Second, you can tweak the concurrency settings, again for
-AST-parsing but also for concurrent test execution. Here is a simplistic example
-for [lazy.nvim](https://github.com/folke/lazy.nvim) to show what I mean:
-
-```lua
-return {
- {
- "nvim-neotest/neotest",
- opts = {
- -- See all config options with :h neotest.Config
- discovery = {
- -- Drastically improve performance in ginormous projects by
- -- only AST-parsing the currently opened buffer.
- enabled = false,
- -- Number of workers to parse files concurrently.
- -- A value of 0 automatically assigns number based on CPU.
- -- Set to 1 if experiencing lag.
- concurrent = 1,
- },
- running = {
- -- Run tests concurrently when an adapter provides multiple commands to run.
- concurrent = true,
- },
- summary = {
- -- Enable/disable animation of icons.
- animated = false,
- },
- },
- },
-}
-```
-
-See `:h neotest.Config` for more information.
-
-[Here](https://github.com/fredrikaverpil/dotfiles/blob/main/nvim-fredrik/lua/fredrik/plugins/core/neotest.lua)
-is my personal Neotest configuration, for inspiration. Please note that I am
-configuring Go and the neotest-golang adapter in a separate file
-[here](https://github.com/fredrikaverpil/dotfiles/blob/main/nvim-fredrik/lua/fredrik/plugins/lang/go.lua).
-
-### Go test execution and parallelism
-
-You can set the optional `go_test_args` to control the number of test binaries
-and number of tests to run in parallel using the `-p` and `-parallel` flags,
-respectively. Execute `go help test`, `go help testflag`, `go help build` for
-more information on this. There's also an excellent article written by
-[@roblaszczak](https://github.com/roblaszczak) posted
-[here](https://threedots.tech/post/go-test-parallelism/) that touches on this
-subject further.
-
-### Testify suites
-
-> [!WARNING]
->
-> This feature comes with some caveats and nuances, which is why it is not
-> enabled by default. I advise you to only enable this if you need it.
-
-There are some real shenaningans going on behind the scenes to make this work.
-😅 First, an in-memory lookup of "receiver type-to-suite test function" will be
-created of all Go test files in your project. Then, the generated Neotest node
-tree is modified by mutating private attributes and merging of nodes to avoid
-duplicates. I'm personally a bit afraid of the maintenance burden of this
-feature... 🙈
-
-> [!NOTE]
->
-> Right now, nested tests and table tests are not supported. All of this can be
-> remedied at any time by extending the treesitter queries. Feel free to dig in
-> and open a PR!
-
-### Using build tags
-
-If you need to set build tags (like e.g. `-tags debug` or `-tags "tag1 tag2"`),
-you need to provide these arguments both in the `go_test_args` and
-`go_list_args` adapter options. If you want to be able to debug, you also need
-to set `dap_go_opts`. Full example:
-
-```lua
-return {
- {
- "nvim-neotest/neotest",
- config = function()
- require("neotest").setup({
- adapters = {
- require("neotest-golang")({
- go_test_args = { "-count=1", "-tags=integration" },
- go_list_args = { "-tags=integration" },
- dap_go_opts = {
- delve = {
- build_flags = { "-tags=integration" },
- },
- },
- }),
- },
- })
- end,
- },
-}
-```
-
-> [!TIP]
->
-> Depending on how you have Neovim setup, you can define this on a per-project
-> basis by placing a `.lazy.lua` with overrides in the project. This requires
-> the [lazy.nvim](https://github.com/folke/lazy.nvim) plugin manager.
-
-### Pass arguments as function instead of table
-
-Some use cases may require you to pass in dynamically generated arguments during
-runtime. To cater for this, you can provide arguments as a function.
-
-```lua
-return {
- {
- "nvim-neotest/neotest",
- config = function()
- require("neotest").setup({
- adapters = {
- require("neotest-golang")({
- go_test_args = function()
- -- provide custom logic here..
- return { "-count=1", "-tags=integration" }
- end,
- go_list_args = function()
- -- provide custom logic here..
- return { "-tags=integration" }
- end,
- dap_go_opts = function()
- -- provide custom logic here..
- return {
- delve = {
- build_flags = { "-tags=integration" },
- },
- }
- end,
- },
- }),
- },
- })
- end,
- },
-}
-```
-
-## 🙏 PRs are welcome
-
-Improvement suggestion PRs to this repo are very much welcome, and I encourage
-you to begin by reading the below paragraph on the adapter design and engage in
-the [discussions](https://github.com/fredrikaverpil/neotest-golang/discussions)
-in case the change is not trivial.
-
-You can run tests, formatting and linting locally with `make all`. Install
-dependencies with `make install`. Have a look at the [Makefile](Makefile) for
-more details. You can also use the neotest-plenary and neotest-golang adapters
-to run the tests of this repo within Neovim.
-
-### AST and tree-sitter
-
-To figure out new tree-sitter queries (for detecting tests), the following
-commands are available in Neovim to aid you:
-
-- `:Inspect` to show the highlight groups under the cursor.
-- `:InspectTree` to show the parsed syntax tree (formerly known as
- "TSPlayground").
-- `:EditQuery` to open the Live Query Editor (Nvim 0.10+).
-
-For example, open up a Go test file and then execute `:InspectTree`. A new
-window will appear which shows what the tree-sitter query syntax representation
-looks like for the Go test file.
-
-Again, from the Go test file, execute `:EditQuery` to open up the query editor
-in a separate window. In the editor, you can now start creating your syntax
-query and play around. You can paste in queries from
-[`query.lua`](https://github.com/fredrikaverpil/neotest-golang/blob/main/lua/neotest-golang/query.lua)
-in the editor, to see how the query behaves and highlights parts of your Go test
-file.
-
-## General design of the adapter
-
-### Treesitter queries detect tests
-
-Neotest leverages treesitter AST-parsing of source code to detect tests. This
-adapter supplies queries so to figure out what is considered a test.
-
-From the result of these queries, a Neotest "position" tree is built (can be
-visualized through the "Neotest summary"). Each position in the tree represents
-either a `dir`, `file` or `test` type. Neotest also has a notion of a
-`namespace` position type, but this is ignored by default by this adapter (but
-leveraged to supply testify support).
-
-### Generating valid `go test` commands
-
-The `dir`, `file` and `test` tree position types cannot be directly translated
-over to Go so to produce a valid `go test` command. Go primarily cares about a
-Go package's import path, test name regexp filters and the current working
-directory.
-
-For example, these are all valid `go test` command:
-
-```bash
-# run all tests, recursing sub-packages, in the current working directory.
-go test ./...
-
-# run all tests in a given package 'x', by specifying the full import path
-go test github.com/fredrikaverpil/neotest-golang/x
-
-# run all tests in a given package 'x', recursing sub-packages
-go test github.com/fredrikaverpil/neotest-golang/x/...
-
-# run _some_ tests in a given package, based on a regexp filter
-go test github.com/fredrikaverpil/neotest-golang -run "^(^TestFoo$|^TestBar$)$"
-```
-
-> [!NOTE]
->
-> All the above commands must be run somewhere beneath the location of the
-> `go.mod` file specifying the _module_ name, which in this example is
-> `github.com/fredrikaverpil/neotest-golang`.
-
-I figured out that by executing `go list -json ./...` in the `go.mod` root
-location, the output provides valuable information about test files/folders and
-their corresponding Go package's import path. This data is key to being able to
-take the Neotest/treesitter position type and generate a valid `go test` command
-for it. In essence, this approach is what makes neotest-golang so robust.
-
-### Output processing
-
-Neotest captures the stdout from the test execution command and writes it to
-disk as a temporary file. The adapter is responsible for reading the file(s) and
-reporting back status and output to the Neotest tree (and specifically the
-position in the tree which was executed). It is therefore crucial for outputting
-structured data, which in this case is done with `go test -json`.
-
-One challenge here is that Go build errors are not part of the strucutured JSON
-output (although captured in the stdout) and needs to be looked for in other
-ways.
-
-Another challenge is to properly populate statuses and errors into the
-corresponding Neotest tree position. This becomes increasingly difficult when
-you consider running tests in a recursive manner (e.g. `go test -json ./...`).
-
-Errors are recorded and populated, per position type, along with its
-corresponding buffer's line number. Neotest can then show the errors inline as
-diagnostics.
-
-I've taken an approach with this adapter where I record test outcome for each
-Neotest position type and populate it onto each of them, when applicable.
-
-On some systems and terminals, there are great issues with the `go test` output.
-I've therefore made it possible to make the adapter rely on output saved
-directly to disk without going through stdout, by leveraging `gotestsum`.
+Documentation is available at
+[https://fredrikaverpil.github.io/neotest-golang](https://fredrikaverpil.github.io/neotest-golang)
diff --git a/docs/config.md b/docs/config.md
new file mode 100644
index 0000000..6db2535
--- /dev/null
+++ b/docs/config.md
@@ -0,0 +1,238 @@
+---
+icon: material/cog
+---
+
+# Configuration
+
+## Options
+
+!!! tip "Recipes"
+
+ See [the recipes](recipes.md) for usage examples of the below options.
+
+### `runner`
+
+Default value: `"go"`
+
+This option defines the test execution runner, which by default is set to `"go"`
+and will use `go test` to write test output to stdout.
+
+!!! warning "Windows, Ubuntu Snaps"
+
+ If you are on Windows or using Ubuntu snaps, you might want to set the runner
+ to `"gotestsum"` and/or enable the [`sanitize_output`](#sanitize_output) option. See
+ [this issue comment](https://github.com/fredrikaverpil/neotest-golang/issues/193#issuecomment-2362845806)
+ for more details and continue reading.
+
+To improve reliability, you can choose to set
+[`gotestsum`](https://github.com/gotestyourself/gotestsum) as the test runner.
+This tool allows the adapter to write test command output directly to a JSON
+file without having to go through stdout.
+
+Using `gotestsum` offers the following benefits:
+
+- On certain platforms (such as Windows) or in certain terminals, there's a risk
+ of ANSI codes or other characters being seemingly randomly inserted into the
+ JSON test output. This can corrupt the data and cause problems with test
+ output JSON decoding. Enabling `gotestsum` eliminates these issues, as the
+ test output is then written directly to file.
+- When you "attach" (in the Neotest summary window) to a running test, you'll
+ see clean `go test` output instead of having to navigate through
+ difficult-to-read JSON, as `gotestsum` is configured to _also_ output non-JSON
+ test execution to stdout.
+
+Gotestsum calls `go test` behind the scenes, so your `go_test_args`
+configuration remains valid and will still apply.
+
+??? example "Configure neotest-golang to use `gotestsum` as test runner"
+
+ Make the `gotestsum` command available via e.g.
+ [mason.nvim](https://github.com/williamboman/mason.nvim) or by running the
+ following in your shell:
+
+ ```bash
+ go install gotest.tools/gotestsum@latest
+ ```
+
+ Then add the required configuration:
+
+ ```lua
+ local config = { -- Specify configuration
+ runner = "gotestsum"
+ }
+ require("neotest").setup({
+ adapters = {
+ require("neotest-golang")(config), -- Apply configuration
+ },
+ })
+ ```
+
+### `go_test_args`
+
+Default value: `{ "-v", "-race", "-count=1" }`
+
+Arguments to pass into `go test`. See `go help test`, `go help testflag`,
+`go help build` for possible arguments.
+
+The `-json` flag is mandatory and is always appended to `go test` automatically.
+
+The value can also be passed in as a function.
+
+!!! warning "CGO"
+
+ The `-race` flag (in `go_test_args`) requires CGO to be enabled
+ (`CGO_ENABLED=1` is the default) and a C compiler (such as GCC) to be
+ installed. However, since Go 1.20, this is not a requirement on macOS. I have
+ included the `-race` argument as default, as it provides good production
+ defaults. See [this issue](https://github.com/golang/go/issues/9918) for more
+ details.
+
+### `gotestsum_args`
+
+Default value: `{ "--format=standard-verbose" }`
+
+Arguments to pass into `gotestsum`. Will only be applicable if
+`runner = "gotestsum"`.
+
+The value can also be passed in as a function.
+
+### `go_list_args`
+
+Default value: `{}`
+
+Arguments to pass into `go list`. The main purpose of `go list` is to internally
+translate between filepaths and Go package import paths.
+
+A mandatory query is passed into the `-f` flag and is always appended
+automatically, so that the necessary fields can be extracted.
+
+The value can also be passed in as a function.
+
+### `dap_mode`
+
+Default value: `"dap-go"`
+
+This option toggles between relying on
+[leoluz/nvim-dap-go](https://github.com/leoluz/nvim-dap-go) so supply the delve
+DAP configuration, or whether you wish to bring your own DAP configuration.
+
+Set to `"manual"` for manual configuration.
+
+The value can also be passed in as a function.
+
+### `dap_go_opts`
+
+Default value: `{}`
+
+If using `dap_mode = "dap-go"`, you can supply dap-go with custom options.
+
+The value can also be passed in as a function.
+
+### `dap_manual_config`
+
+Default value: `{}`
+
+The configuration to apply if `dap_mode == "manual"`.
+
+The value can also be passed in as a function.
+
+### `testify_enabled`
+
+Default value: `false`
+
+Enable support for [testify](https://github.com/stretchr/testify) suites.
+
+!!! warning "Not enabled by default"
+
+ This feature comes with some caveats and nuances, which is why it is not enabled
+ by default. I advise you to only enable this if you need it.
+
+ There are some real shenaningans going on behind the scenes to make this work.
+ 😅 First, an in-memory lookup of "receiver type-to-suite test function" will be
+ created of all Go test files in your project. Then, the generated Neotest node
+ tree is modified by mutating private attributes and merging of nodes to avoid
+ duplicates. I'm personally a bit afraid of the maintenance burden of this
+ feature... 🙈
+
+!!! note "Subtests not supported"
+
+ Right now, nested tests and table tests are not supported. All of this can be
+ remedied at any time by extending the treesitter queries. Feel free to dig in
+ and open a PR!
+
+### `colorize_test_output`
+
+Default value: `true`
+
+Enable output color for `SUCCESS`, `FAIL`, and `SKIP` tests.
+
+### `warn_test_name_dupes`
+
+Default value: `true`
+
+Warn about duplicate test names within the same Go package.
+
+### `warn_test_not_executed`
+
+Default value: `true`
+
+Warn if test was not executed.
+
+### `log_level`
+
+Default value: `"vim.log.levels.WARN"`
+
+The `neotest-golang.log` log-level.
+
+### `sanitize_output`
+
+Default value: `false`
+
+Filter control characters and non-printable characters from test output.
+Requires the [uga-rosa/utf8.nvim](https://github.com/uga-rosa/utf8.nvim)
+library.
+
+When tests write non-printable characters to stdout/stderr, they can cause
+various issues like failing to write output to disk or UI rendering problems.
+The `sanitize_output` option helps clean up such output by preserving UTF-8 and
+replacing control characters with the Unicode replacement character (�).
+
+This is particularly useful when:
+
+- Tests write bytes to stdout/stderr.
+- Test output contains terminal control sequences.
+- Test output includes non-printable characters.
+
+The sanitization preserves all regular printable characters including tabs,
+newlines, and carriage returns.
+
+??? example "Example config"
+
+ ```diff
+ return {
+ {
+ "nvim-neotest/neotest",
+ dependencies = {
+ "nvim-neotest/nvim-nio",
+ "nvim-lua/plenary.nvim",
+ "antoinemadec/FixCursorHold.nvim",
+ "nvim-treesitter/nvim-treesitter",
+ - "fredrikaverpil/neotest-golang", -- Installation
+ + {
+ + "fredrikaverpil/neotest-golang", -- Installation
+ + dependencies = {
+ + "uga-rosa/utf8.nvim", -- Additional dependency required
+ + },
+ + },
+ },
+ config = function()
+ require("neotest").setup({
+ adapters = {
+ - require("neotest-golang"), -- Registration
+ + require("neotest-golang")({ sanitize_output = true }), -- Registration
+ },
+ })
+ end,
+ },
+ }
+ ```
diff --git a/docs/contrib.md b/docs/contrib.md
new file mode 100644
index 0000000..23c7b80
--- /dev/null
+++ b/docs/contrib.md
@@ -0,0 +1,111 @@
+---
+icon: material/heart-multiple-outline
+---
+
+# 🙏 PRs are welcome
+
+Improvement suggestion PRs to this repo are very much welcome, and I encourage
+you to begin by reading the below paragraph on the adapter design and engage in
+the [discussions](https://github.com/fredrikaverpil/neotest-golang/discussions)
+in case the change is not trivial.
+
+You can run tests, formatting and linting locally with `make all`. Install
+dependencies with `make install`. Have a look at the `Makefile` for more
+details. You can also use the neotest-plenary and neotest-golang adapters to run
+the tests of this repo within Neovim.
+
+### AST and tree-sitter
+
+To figure out new tree-sitter queries (for detecting tests), the following
+commands are available in Neovim to aid you:
+
+- `:Inspect` to show the highlight groups under the cursor.
+- `:InspectTree` to show the parsed syntax tree (formerly known as
+ "TSPlayground").
+- `:EditQuery` to open the Live Query Editor (Nvim 0.10+).
+
+For example, open up a Go test file and then execute `:InspectTree`. A new
+window will appear which shows what the tree-sitter query syntax representation
+looks like for the Go test file.
+
+Again, from the Go test file, execute `:EditQuery` to open up the query editor
+in a separate window. In the editor, you can now start creating your syntax
+query and play around. You can paste in queries from
+[`query.lua`](https://github.com/fredrikaverpil/neotest-golang/blob/main/lua/neotest-golang/query.lua)
+in the editor, to see how the query behaves and highlights parts of your Go test
+file.
+
+## General design of the adapter
+
+### Treesitter queries detect tests
+
+Neotest leverages treesitter AST-parsing of source code to detect tests. This
+adapter supplies queries so to figure out what is considered a test.
+
+From the result of these queries, a Neotest "position" tree is built (can be
+visualized through the "Neotest summary"). Each position in the tree represents
+either a `dir`, `file` or `test` type. Neotest also has a notion of a
+`namespace` position type, but this is ignored by default by this adapter (but
+leveraged to supply testify support).
+
+### Generating valid `go test` commands
+
+The `dir`, `file` and `test` tree position types cannot be directly translated
+over to Go so to produce a valid `go test` command. Go primarily cares about a
+Go package's import path, test name regexp filters and the current working
+directory.
+
+For example, these are all valid `go test` command:
+
+```bash
+# run all tests, recursing sub-packages, in the current working directory.
+go test ./...
+
+# run all tests in a given package 'x', by specifying the full import path
+go test github.com/fredrikaverpil/neotest-golang/x
+
+# run all tests in a given package 'x', recursing sub-packages
+go test github.com/fredrikaverpil/neotest-golang/x/...
+
+# run _some_ tests in a given package, based on a regexp filter
+go test github.com/fredrikaverpil/neotest-golang -run "^(^TestFoo$|^TestBar$)$"
+```
+
+> [!NOTE]
+>
+> All the above commands must be run somewhere beneath the location of the
+> `go.mod` file specifying the _module_ name, which in this example is
+> `github.com/fredrikaverpil/neotest-golang`.
+
+I figured out that by executing `go list -json ./...` in the `go.mod` root
+location, the output provides valuable information about test files/folders and
+their corresponding Go package's import path. This data is key to being able to
+take the Neotest/treesitter position type and generate a valid `go test` command
+for it. In essence, this approach is what makes neotest-golang so robust.
+
+### Output processing
+
+Neotest captures the stdout from the test execution command and writes it to
+disk as a temporary file. The adapter is responsible for reading the file(s) and
+reporting back status and output to the Neotest tree (and specifically the
+position in the tree which was executed). It is therefore crucial for outputting
+structured data, which in this case is done with `go test -json`.
+
+One challenge here is that Go build errors are not part of the strucutured JSON
+output (although captured in the stdout) and needs to be looked for in other
+ways.
+
+Another challenge is to properly populate statuses and errors into the
+corresponding Neotest tree position. This becomes increasingly difficult when
+you consider running tests in a recursive manner (e.g. `go test -json ./...`).
+
+Errors are recorded and populated, per position type, along with its
+corresponding buffer's line number. Neotest can then show the errors inline as
+diagnostics.
+
+I've taken an approach with this adapter where I record test outcome for each
+Neotest position type and populate it onto each of them, when applicable.
+
+On some systems and terminals, there are great issues with the `go test` output.
+I've therefore made it possible to make the adapter rely on output saved
+directly to disk without going through stdout, by leveraging `gotestsum`.
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..343493a
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,33 @@
+---
+icon: material/information
+---
+
+--8<-- "README.md"
+
+---
+
+??? question "Why a second Neotest adapter for Go? 🤔"
+
+ While using [neotest-go](https://github.com/nvim-neotest/neotest-go) I stumbled
+ upon many problems which seemed difficult to solve in that codebase.
+
+ I have full respect for the time and efforts put in by the developer(s) of
+ neotest-go. I do not aim in any way to diminish their needs or efforts. However,
+ I wanted to see if I could fix these issues by diving into the 🕳️🐇 of Neotest
+ and building my own adapter. Below is a list of neotest-go issues which are not
+ present in neotest-golang (this project):
+
+ | Neotest-go issue | URL |
+ | ------------------------------------------------------- | --------------------------------------------------------------------- |
+ | Support for Testify framework | [neotest-go#6](https://github.com/nvim-neotest/neotest-go/issues/6) |
+ | DAP support | [neotest-go#12](https://github.com/nvim-neotest/neotest-go/issues/12) |
+ | Test Output in JSON, making it difficult to read | [neotest-go#52](https://github.com/nvim-neotest/neotest-go/issues/52) |
+ | Support for Nested Subtests | [neotest-go#74](https://github.com/nvim-neotest/neotest-go/issues/74) |
+ | Diagnostics for table tests on the line of failure | [neotest-go#75](https://github.com/nvim-neotest/neotest-go/issues/75) |
+ | "Run nearest" runs all tests | [neotest-go#83](https://github.com/nvim-neotest/neotest-go/issues/83) |
+ | Table tests not recognized when defined inside for-loop | [neotest-go#86](https://github.com/nvim-neotest/neotest-go/issues/86) |
+ | Running test suite doesn't work | [neotest-go#89](https://github.com/nvim-neotest/neotest-go/issues/89) |
+
+ A comparison in number of GitHub stars between the projects:
+
+ [![Star History Chart](https://api.star-history.com/svg?repos=fredrikaverpil/neotest-golang,nvim-neotest/neotest-go&type=Date)](https://star-history.com/#fredrikaverpil/neotest-golang&nvim-neotest/neotest-go&Date)
diff --git a/docs/install.md b/docs/install.md
new file mode 100644
index 0000000..a8bec70
--- /dev/null
+++ b/docs/install.md
@@ -0,0 +1,109 @@
+---
+icon: material/progress-check
+---
+
+# Installation
+
+!!! warning "Minimum Neovim version"
+
+ Neovim v0.10.0 or above is required.
+
+## 💤 Lazy.nvim
+
+```lua
+return {
+ {
+ "nvim-neotest/neotest",
+ dependencies = {
+ "nvim-neotest/nvim-nio",
+ "nvim-lua/plenary.nvim",
+ "antoinemadec/FixCursorHold.nvim",
+ "nvim-treesitter/nvim-treesitter",
+ { "fredrikaverpil/neotest-golang", version = "*" }, -- Installation
+ },
+ config = function()
+ local neotest_golang_opts = {} -- Specify custom configuration
+ require("neotest").setup({
+ adapters = {
+ require("neotest-golang")(neotest_golang_opts), -- Registration
+ },
+ })
+ end,
+ },
+}
+```
+
+For increased stability and less updating noise, I recommend that you track
+official releases by setting `version = "*"`. By omitting this option (or
+setting `version = false`), you will get the latest and greatest directly from
+the main branch.
+
+I do not recommend pinning to a specific version or to a major version. But
+ultimately it is up to you what you want.
+
+See the [Lazy versioning spec](https://lazy.folke.io/spec/versioning) for more
+details.
+
+## 🌒 Rocks.nvim
+
+The adapter is available via
+[luarocks package](https://luarocks.org/modules/fredrikaverpil/neotest-golang):
+
+```vim
+:Rocks install neotest-golang
+```
+
+[rocks.nvim](https://github.com/nvim-neorocks/rocks.nvim) will automatically
+install dependencies if they are not already installed. You will need to call
+neotest's `setup` function to register this adapter. If you use
+[rocks-config.nvim](https://github.com/nvim-neorocks/rocks-config.nvim),
+consider setting up neotest and its adapters in a
+[plugin bundle](https://github.com/nvim-neorocks/rocks-config.nvim?tab=readme-ov-file#plugin-bundles).
+
+!!! note "Luarocks"
+
+ Please note that [leoluz/nvim-dap-go](https://github.com/leoluz/nvim-dap-go)
+ (required for DAP) is not on luarocks as of writing this.
+
+## ❄️ Nix & Home manager
+
+```nix
+{
+ config,
+ pkgs,
+ ...
+}: {
+ home.packages = with pkgs; [];
+ programs = {
+ neovim = {
+ plugins = [
+ # neotest and dependencies
+ pkgs.vimPlugins.neotest
+ pkgs.vimPlugins.nvim-nio
+ pkgs.vimPlugins.plenary-nvim
+ pkgs.vimPlugins.FixCursorHold-nvim
+ pkgs.vimPlugins.nvim-treesitter
+ (pkgs.vimPlugins.nvim-treesitter.withPlugins (plugins: [plugins.go]))
+ pkgs.vimPlugins.neotest-golang
+
+ ## debugging
+ pkgs.vimPlugins.nvim-dap
+ pkgs.vimPlugins.nvim-dap-ui
+ pkgs.vimPlugins.nvim-nio
+ pkgs.vimPlugins.nvim-dap-virtual-text
+ pkgs.vimPlugins.nvim-dap-go
+ ];
+ enable = true;
+ extraConfig = ''
+ lua << EOF
+ require("neotest").setup({
+ adapters = {
+ require("neotest-golang")
+ },
+ })
+ EOF
+ '';
+ };
+ };
+}
+```
diff --git a/docs/recipes.md b/docs/recipes.md
new file mode 100644
index 0000000..891d93a
--- /dev/null
+++ b/docs/recipes.md
@@ -0,0 +1,405 @@
+---
+icon: material/food
+---
+
+# Recipes
+
+## Debugging
+
+To debug tests, make sure you depend on
+[mfussenegger/nvim-dap](https://github.com/mfussenegger/nvim-dap) and
+[rcarriga/nvim-dap-ui](https://github.com/rcarriga/nvim-dap-ui).
+
+Then you have two options:
+
+- DAP configuration provided by
+ [leoluz/nvim-dap-go](https://github.com/leoluz/nvim-dap-go) (recommended)
+- Use your own custom DAP configuration (no additional dependency needed)
+
+??? example "Adapter-provided (recommended)"
+
+ ```diff
+ return {
+ + {
+ + "rcarriga/nvim-dap-ui",
+ + dependencies = {
+ + "nvim-neotest/nvim-nio",
+ + "mfussenegger/nvim-dap",
+ + },
+ + },
+ +
+ {
+ "nvim-neotest/neotest",
+ dependencies = {
+ "nvim-neotest/nvim-nio",
+ "nvim-lua/plenary.nvim",
+ "antoinemadec/FixCursorHold.nvim",
+ "nvim-treesitter/nvim-treesitter",
+ - "fredrikaverpil/neotest-golang", -- Installation
+ + {
+ + "fredrikaverpil/neotest-golang", -- Installation
+ + dependencies = {
+ + "leoluz/nvim-dap-go",
+ + },
+ + },
+ },
+ config = function()
+ require("neotest").setup({
+ adapters = {
+ require("neotest-golang"), -- Registration
+ },
+ })
+ end,
+ },
+ }
+ ```
+
+??? example "Use your own custom DAP configuration"
+
+ ```diff
+ return {
+ + {
+ + "rcarriga/nvim-dap-ui",
+ + dependencies = {
+ + "nvim-neotest/nvim-nio",
+ + "mfussenegger/nvim-dap",
+ + },
+ + },
+ +
+ {
+ "nvim-neotest/neotest",
+ dependencies = {
+ "nvim-neotest/nvim-nio",
+ "nvim-lua/plenary.nvim",
+ "antoinemadec/FixCursorHold.nvim",
+ "nvim-treesitter/nvim-treesitter",
+ "fredrikaverpil/neotest-golang", -- Installation
+ },
+ config = function()
+ + local options = {
+ + dap_mode = "manual",
+ + dap_manual_config = {
+ + name = "Debug go tests",
+ + type = "go", -- Preconfigured DAP adapter name
+ + request = "launch",
+ + mode = "test",
+ + },
+ + }
+ require("neotest").setup({
+ adapters = {
+ + require("neotest-golang")(options) -- Registration
+ },
+ })
+ end,
+ },
+ }
+ ```
+
+
+
+Finally, set keymaps to run Neotest commands.
+
+!!! example "Keymap for running nearest test"
+
+ ```lua
+ return {
+ {
+ "nvim-neotest/neotest",
+ -- ...
+ keys = {
+ {
+ "td",
+ function()
+ require("neotest").run.run({ suite = false, strategy = "dap" })
+ end,
+ desc = "Debug nearest test",
+ },
+ },
+ },
+ }
+ ```
+
+## Coverage
+
+You can use
+[andythigpen/nvim-coverage](https://github.com/andythigpen/nvim-coverage) to
+show coverage in Neovim.
+
+!!! example "Coverage"
+
+ ```lua
+ return {
+ {
+ "nvim-neotest/neotest",
+ dependencies = {
+ "nvim-neotest/nvim-nio",
+ "nvim-lua/plenary.nvim",
+ "antoinemadec/FixCursorHold.nvim",
+ "nvim-treesitter/nvim-treesitter",
+ {
+ "fredrikaverpil/neotest-golang",
+ version = "*",
+ dependencies = {
+ "andythigpen/nvim-coverage", -- Added dependency
+ },
+ },
+ },
+ config = function()
+ local neotest_golang_opts = { -- Specify configuration
+ runner = "go",
+ go_test_args = {
+ "-v",
+ "-race",
+ "-count=1",
+ "-coverprofile=" .. vim.fn.getcwd() .. "/coverage.out",
+ },
+ }
+ require("neotest").setup({
+ adapters = {
+ require("neotest-golang")(neotest_golang_opts), -- Registration
+ },
+ })
+ end,
+ },
+ }
+ ```
+
+## Using build tags
+
+If you need to set build tags (like e.g. `-tags debug` or `-tags "tag1 tag2"`),
+you need to provide these arguments both in the `go_test_args` and
+`go_list_args` adapter options. If you want to be able to debug, you also need
+to set `dap_go_opts`. Full example:
+
+!!! example "Build tags"
+
+ ```lua
+ return {
+ {
+ "nvim-neotest/neotest",
+ config = function()
+ require("neotest").setup({
+ adapters = {
+ require("neotest-golang")({
+ go_test_args = { "-count=1", "-tags=integration" },
+ go_list_args = { "-tags=integration" },
+ dap_go_opts = {
+ delve = {
+ build_flags = { "-tags=integration" },
+ },
+ },
+ }),
+ },
+ })
+ end,
+ },
+ }
+ ```
+
+## Pass arguments as function instead of table
+
+Some use cases may require you to pass in dynamically generated arguments during
+runtime. To cater for this, you can provide arguments as a function.
+
+!!! example "Args passed as functions"
+
+ ```lua
+ return {
+ {
+ "nvim-neotest/neotest",
+ config = function()
+ require("neotest").setup({
+ adapters = {
+ require("neotest-golang")({
+ go_test_args = function()
+ -- provide custom logic here..
+ return { "-count=1", "-tags=integration" }
+ end,
+ go_list_args = function()
+ -- provide custom logic here..
+ return { "-tags=integration" }
+ end,
+ dap_go_opts = function()
+ -- provide custom logic here..
+ return {
+ delve = {
+ build_flags = { "-tags=integration" },
+ },
+ }
+ end,
+ },
+ }),
+ },
+ })
+ end,
+ },
+ }
+ ```
+
+## Per-project configuration
+
+Depending on how you have Neovim setup, you can define the neotest-golang config
+on a per-project basis by placing a `.lazy.lua` with overrides in the project.
+This requires the [lazy.nvim](https://github.com/folke/lazy.nvim) plugin
+manager.
+
+## Example configuration: extra everything
+
+In the below code block, I've provided a pretty hefty configuration example,
+which includes the required setup for testing and debugging along with all the
+keymaps. This is a merged snapshot of my own config, which I hope you can draw
+inspiration from. To view my current config, which is divided up into several
+files, see:
+
+- [plugins/neotest.lua](https://github.com/fredrikaverpil/dotfiles/blob/main/nvim-fredrik/lua/fredrik/plugins/core/neotest.lua)
+- [plugins/dap.lua](https://github.com/fredrikaverpil/dotfiles/blob/main/nvim-fredrik/lua/fredrik/plugins/core/dap.lua)
+- [lang/go.lua](https://github.com/fredrikaverpil/dotfiles/blob/main/nvim-fredrik/lua/fredrik/plugins/lang/go.lua)
+
+!!! tip "Extra everything"
+
+ ```lua
+ return {
+
+ -- Neotest setup
+ {
+ "nvim-neotest/neotest",
+ event = "VeryLazy",
+ dependencies = {
+ "nvim-neotest/nvim-nio",
+ "nvim-lua/plenary.nvim",
+ "antoinemadec/FixCursorHold.nvim",
+ "nvim-treesitter/nvim-treesitter",
+
+ "nvim-neotest/neotest-plenary",
+ "nvim-neotest/neotest-vim-test",
+
+ {
+ "fredrikaverpil/neotest-golang",
+ dependencies = {
+ {
+ "leoluz/nvim-dap-go",
+ opts = {},
+ },
+ },
+ branch = "main",
+ },
+ },
+ opts = function(_, opts)
+ opts.adapters = opts.adapters or {}
+ opts.adapters["neotest-golang"] = {
+ go_test_args = {
+ "-v",
+ "-race",
+ "-coverprofile=" .. vim.fn.getcwd() .. "/coverage.out",
+ },
+ }
+ end,
+ config = function(_, opts)
+ if opts.adapters then
+ local adapters = {}
+ for name, config in pairs(opts.adapters or {}) do
+ if type(name) == "number" then
+ if type(config) == "string" then
+ config = require(config)
+ end
+ adapters[#adapters + 1] = config
+ elseif config ~= false then
+ local adapter = require(name)
+ if type(config) == "table" and not vim.tbl_isempty(config) then
+ local meta = getmetatable(adapter)
+ if adapter.setup then
+ adapter.setup(config)
+ elseif adapter.adapter then
+ adapter.adapter(config)
+ adapter = adapter.adapter
+ elseif meta and meta.__call then
+ adapter(config)
+ else
+ error("Adapter " .. name .. " does not support setup")
+ end
+ end
+ adapters[#adapters + 1] = adapter
+ end
+ end
+ opts.adapters = adapters
+ end
+
+ require("neotest").setup(opts)
+ end,
+ keys = {
+ { "ta", function() require("neotest").run.attach() end, desc = "[t]est [a]ttach" },
+ { "tf", function() require("neotest").run.run(vim.fn.expand("%")) end, desc = "[t]est run [f]ile" },
+ { "tA", function() require("neotest").run.run(vim.uv.cwd()) end, desc = "[t]est [A]ll files" },
+ { "tS", function() require("neotest").run.run({ suite = true }) end, desc = "[t]est [S]uite" },
+ { "tn", function() require("neotest").run.run() end, desc = "[t]est [n]earest" },
+ { "tl", function() require("neotest").run.run_last() end, desc = "[t]est [l]ast" },
+ { "ts", function() require("neotest").summary.toggle() end, desc = "[t]est [s]ummary" },
+ { "to", function() require("neotest").output.open({ enter = true, auto_close = true }) end, desc = "[t]est [o]utput" },
+ { "tO", function() require("neotest").output_panel.toggle() end, desc = "[t]est [O]utput panel" },
+ { "tt", function() require("neotest").run.stop() end, desc = "[t]est [t]erminate" },
+ { "td", function() require("neotest").run.run({ suite = false, strategy = "dap" }) end, desc = "Debug nearest test" },
+ { "tD", function() require("neotest").run.run({ vim.fn.expand("%"), strategy = "dap" }) end, desc = "Debug current file" },
+ },
+ },
+
+ -- DAP setup
+ {
+ "mfussenegger/nvim-dap",
+ event = "VeryLazy",
+ keys = {
+ {"db", function() require("dap").toggle_breakpoint() end, desc = "toggle [d]ebug [b]reakpoint" },
+ {"dB", function() require("dap").set_breakpoint(vim.fn.input("Breakpoint condition: ")) end, desc = "[d]ebug [B]reakpoint"},
+ {"dc", function() require("dap").continue() end, desc = "[d]ebug [c]ontinue (start here)" },
+ {"dC", function() require("dap").run_to_cursor() end, desc = "[d]ebug [C]ursor" },
+ {"dg", function() require("dap").goto_() end, desc = "[d]ebug [g]o to line" },
+ {"do", function() require("dap").step_over() end, desc = "[d]ebug step [o]ver" },
+ {"dO", function() require("dap").step_out() end, desc = "[d]ebug step [O]ut" },
+ {"di", function() require("dap").step_into() end, desc = "[d]ebug [i]nto" },
+ {"dj", function() require("dap").down() end, desc = "[d]ebug [j]ump down" },
+ {"dk", function() require("dap").up() end, desc = "[d]ebug [k]ump up" },
+ {"dl", function() require("dap").run_last() end, desc = "[d]ebug [l]ast" },
+ {"dp", function() require("dap").pause() end, desc = "[d]ebug [p]ause" },
+ {"dr", function() require("dap").repl.toggle() end, desc = "[d]ebug [r]epl" },
+ {"dR", function() require("dap").clear_breakpoints() end, desc = "[d]ebug [R]emove breakpoints" },
+ {"ds", function() require("dap").session() end, desc ="[d]ebug [s]ession" },
+ {"dt", function() require("dap").terminate() end, desc = "[d]ebug [t]erminate" },
+ {"dw", function() require("dap.ui.widgets").hover() end, desc = "[d]ebug [w]idgets" },
+ },
+ },
+
+ -- DAP UI setup
+ {
+ "rcarriga/nvim-dap-ui",
+ event = "VeryLazy",
+ dependencies = {
+ "nvim-neotest/nvim-nio",
+ "mfussenegger/nvim-dap",
+ },
+ opts = {},
+ config = function(_, opts)
+ -- setup dap config by VsCode launch.json file
+ -- require("dap.ext.vscode").load_launchjs()
+ local dap = require("dap")
+ local dapui = require("dapui")
+ dapui.setup(opts)
+ dap.listeners.after.event_initialized["dapui_config"] = function()
+ dapui.open({})
+ end
+ dap.listeners.before.event_terminated["dapui_config"] = function()
+ dapui.close({})
+ end
+ dap.listeners.before.event_exited["dapui_config"] = function()
+ dapui.close({})
+ end
+ end,
+ keys = {
+ { "du", function() require("dapui").toggle({}) end, desc = "[d]ap [u]i" },
+ { "de", function() require("dapui").eval() end, desc = "[d]ap [e]val" },
+ },
+ },
+ {
+ "theHamsta/nvim-dap-virtual-text",
+ opts = {},
+ },
+ }
+ ```
diff --git a/docs/trouble.md b/docs/trouble.md
new file mode 100644
index 0000000..50f3655
--- /dev/null
+++ b/docs/trouble.md
@@ -0,0 +1,103 @@
+---
+icon: material/bug
+---
+
+# Troubleshooting
+
+## Issues with setting up or using the adapter
+
+> [!TIP]
+>
+> You can run `:checkhealth neotest-golang` to review common issues. If you need
+> configuring neotest-golang help, please open a discussion
+> [here](https://github.com/fredrikaverpil/neotest-golang/discussions/new?category=configuration).
+
+You can also enable logging to further inspect what's going on under the hood.
+Neotest-golang piggybacks on the Neotest logger but writes its own file. The
+default log level is `WARN` but during troubleshooting you want to increase
+this:
+
+```lua
+local config = {
+ log_level = vim.log.levels.TRACE, -- set log level
+}
+
+require("neotest").setup({
+ adapters = {
+ require("neotest-golang")(config), -- Apply configuration
+ },
+})
+```
+
+The neotest-golang logs can be opened using this convenient vim command:
+
+```vim
+:exe 'edit' stdpath('log').'/neotest-golang.log'
+```
+
+This usually corresponds to something like
+`~/.local/state/nvim/neotest-golang.log`.
+
+> [!WARNING]
+>
+> Don't forget to revert back to `WARN` level once you are done troubleshooting,
+> as the `TRACE` level can degrade performance.
+
+## Neotest is slowing down Neovim
+
+Neotest, out of the box with default settings, can appear very slow in large
+projects (here, I'm referring to
+[this kind of large](https://github.com/kubernetes/kubernetes)). There are a few
+things you can do to speed up the Neotest appearance and experience in such
+cases, by tweaking the Neotest settings.
+
+You can for example limit the AST-parsing (to detect tests) to the currently
+opened file, which in my opinion makes Neotest a joy to work with, even in
+ginormous projects. Second, you can tweak the concurrency settings, again for
+AST-parsing but also for concurrent test execution. Here is a simplistic example
+for [lazy.nvim](https://github.com/folke/lazy.nvim) to show what I mean:
+
+```lua
+return {
+ {
+ "nvim-neotest/neotest",
+ opts = {
+ -- See all config options with :h neotest.Config
+ discovery = {
+ -- Drastically improve performance in ginormous projects by
+ -- only AST-parsing the currently opened buffer.
+ enabled = false,
+ -- Number of workers to parse files concurrently.
+ -- A value of 0 automatically assigns number based on CPU.
+ -- Set to 1 if experiencing lag.
+ concurrent = 1,
+ },
+ running = {
+ -- Run tests concurrently when an adapter provides multiple commands to run.
+ concurrent = true,
+ },
+ summary = {
+ -- Enable/disable animation of icons.
+ animated = false,
+ },
+ },
+ },
+}
+```
+
+See `:h neotest.Config` for more information.
+
+[Here](https://github.com/fredrikaverpil/dotfiles/blob/main/nvim-fredrik/lua/fredrik/plugins/core/neotest.lua)
+is my personal Neotest configuration, for inspiration. Please note that I am
+configuring Go and the neotest-golang adapter in a separate file
+[here](https://github.com/fredrikaverpil/dotfiles/blob/main/nvim-fredrik/lua/fredrik/plugins/lang/go.lua).
+
+## Go test execution and parallelism
+
+You can set the optional `go_test_args` to control the number of test binaries
+and number of tests to run in parallel using the `-p` and `-parallel` flags,
+respectively. Execute `go help test`, `go help testflag`, `go help build` for
+more information on this. There's also an excellent article written by
+[@roblaszczak](https://github.com/roblaszczak) posted
+[here](https://threedots.tech/post/go-test-parallelism/) that touches on this
+subject further.
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 0000000..8c16ece
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,86 @@
+site_name: neotest-golang
+site_url: https://neotest-golang.github.io
+repo_url: https://github.com/fredrikaverpil/neotest-golang
+docs_dir: docs
+watch:
+ - pyproject.toml
+ - uv.lock
+ - mkdocs.yml
+ - README.md
+ - docs
+theme:
+ name: material
+ font: false
+ icon:
+ logo: material/test-tube
+ admonition:
+ # note: octicons/tag-16
+ # abstract: octicons/checklist-16
+ # info: octicons/info-16
+ # tip: octicons/squirrel-16
+ # success: octicons/check-16
+ # question: octicons/question-16
+ # warning: octicons/alert-16
+ # failure: octicons/x-circle-16
+ # danger: octicons/zap-16
+ # bug: octicons/bug-16
+ # example: octicons/beaker-16
+ # quote: octicons/quote-16
+ edit_uri: edit/main/docs/
+ features:
+ - navigation.tracking
+ # - navigation.tabs
+ # - navigation.tabs.sticky
+ # - navigation.sections
+ # - navigation.indexes
+ - content.action.edit
+ - content.action.view
+ - content.code.copy
+
+ palette:
+ # Palette toggle for automatic mode
+ - media: "(prefers-color-scheme)"
+ toggle:
+ icon: material/brightness-auto
+ name: Switch to light mode
+ # Palette toggle for dark mode
+ - media: "(prefers-color-scheme: dark)"
+ scheme: slate
+ primary: black
+ toggle:
+ icon: material/brightness-4
+ name: Switch to system preference
+ # Palette toggle for light mode
+ - media: "(prefers-color-scheme: light)"
+ scheme: default
+ toggle:
+ icon: material/brightness-7
+ name: Switch to dark mode
+plugins:
+ - search
+markdown_extensions:
+ - tables
+ - md_in_html
+ - admonition
+ - pymdownx.details
+ - pymdownx.superfences
+ - pymdownx.tabbed:
+ alternate_style: true
+ - pymdownx.highlight:
+ # use_pygments: true
+ auto_title: true
+ anchor_linenums: true
+ line_spans: __span
+ pygments_lang_class: true
+ - pymdownx.inlinehilite
+ - pymdownx.smartsymbols
+ - pymdownx.snippets:
+ url_download: true
+ check_paths: true
+nav:
+ - About this project: index.md
+ - Installation: install.md
+ - Configuration: config.md
+ - Recipes: recipes.md
+ - Troubleshooting: trouble.md
+ - Contributing: contrib.md
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..5425f91
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,7 @@
+[project]
+name = "neotest-golang"
+version = "0.1.0"
+description = "Neotest-golang docs"
+readme = "README.md"
+requires-python = ">=3.13"
+dependencies = ["mkdocs-material", "mkdocs-simple-hooks"]
diff --git a/uv.lock b/uv.lock
new file mode 100644
index 0000000..297d87f
--- /dev/null
+++ b/uv.lock
@@ -0,0 +1,414 @@
+version = 1
+requires-python = ">=3.13"
+
+[[package]]
+name = "babel"
+version = "2.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/2a/74/f1bc80f23eeba13393b7222b11d95ca3af2c1e28edca18af487137eefed9/babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316", size = 9348104 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ed/20/bc79bc575ba2e2a7f70e8a1155618bb1301eaa5132a8271373a6903f73f8/babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b", size = 9587599 },
+]
+
+[[package]]
+name = "certifi"
+version = "2024.12.14"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/bd/1d41ee578ce09523c81a15426705dd20969f5abf006d1afe8aeff0dd776a/certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db", size = 166010 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a5/32/8f6669fc4798494966bf446c8c4a162e0b5d893dff088afddf76414f70e1/certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56", size = 164927 },
+]
+
+[[package]]
+name = "charset-normalizer"
+version = "3.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/38/94/ce8e6f63d18049672c76d07d119304e1e2d7c6098f0841b51c666e9f44a0/charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", size = 195698 },
+ { url = "https://files.pythonhosted.org/packages/24/2e/dfdd9770664aae179a96561cc6952ff08f9a8cd09a908f259a9dfa063568/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", size = 140162 },
+ { url = "https://files.pythonhosted.org/packages/24/4e/f646b9093cff8fc86f2d60af2de4dc17c759de9d554f130b140ea4738ca6/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", size = 150263 },
+ { url = "https://files.pythonhosted.org/packages/5e/67/2937f8d548c3ef6e2f9aab0f6e21001056f692d43282b165e7c56023e6dd/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", size = 142966 },
+ { url = "https://files.pythonhosted.org/packages/52/ed/b7f4f07de100bdb95c1756d3a4d17b90c1a3c53715c1a476f8738058e0fa/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", size = 144992 },
+ { url = "https://files.pythonhosted.org/packages/96/2c/d49710a6dbcd3776265f4c923bb73ebe83933dfbaa841c5da850fe0fd20b/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", size = 147162 },
+ { url = "https://files.pythonhosted.org/packages/b4/41/35ff1f9a6bd380303dea55e44c4933b4cc3c4850988927d4082ada230273/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", size = 140972 },
+ { url = "https://files.pythonhosted.org/packages/fb/43/c6a0b685fe6910d08ba971f62cd9c3e862a85770395ba5d9cad4fede33ab/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", size = 149095 },
+ { url = "https://files.pythonhosted.org/packages/4c/ff/a9a504662452e2d2878512115638966e75633519ec11f25fca3d2049a94a/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", size = 152668 },
+ { url = "https://files.pythonhosted.org/packages/6c/71/189996b6d9a4b932564701628af5cee6716733e9165af1d5e1b285c530ed/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", size = 150073 },
+ { url = "https://files.pythonhosted.org/packages/e4/93/946a86ce20790e11312c87c75ba68d5f6ad2208cfb52b2d6a2c32840d922/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", size = 145732 },
+ { url = "https://files.pythonhosted.org/packages/cd/e5/131d2fb1b0dddafc37be4f3a2fa79aa4c037368be9423061dccadfd90091/charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", size = 95391 },
+ { url = "https://files.pythonhosted.org/packages/27/f2/4f9a69cc7712b9b5ad8fdb87039fd89abba997ad5cbe690d1835d40405b0/charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", size = 102702 },
+ { url = "https://files.pythonhosted.org/packages/0e/f6/65ecc6878a89bb1c23a086ea335ad4bf21a588990c3f535a227b9eea9108/charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", size = 49767 },
+]
+
+[[package]]
+name = "click"
+version = "8.1.8"
+source = { registry = "https://pypi.org/simple" }
+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/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+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 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
+]
+
+[[package]]
+name = "ghp-import"
+version = "2.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "python-dateutil" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/d9/29/d40217cbe2f6b1359e00c6c307bb3fc876ba74068cbab3dde77f03ca0dc4/ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343", size = 10943 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034 },
+]
+
+[[package]]
+name = "idna"
+version = "3.10"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
+]
+
+[[package]]
+name = "jinja2"
+version = "3.1.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markupsafe" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/af/92/b3130cbbf5591acf9ade8708c365f3238046ac7cb8ccba6e81abccb0ccff/jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb", size = 244674 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/bd/0f/2ba5fbcd631e3e88689309dbe978c5769e883e4b84ebfe7da30b43275c5a/jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb", size = 134596 },
+]
+
+[[package]]
+name = "markdown"
+version = "3.7"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/54/28/3af612670f82f4c056911fbbbb42760255801b3068c48de792d354ff4472/markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2", size = 357086 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3f/08/83871f3c50fc983b88547c196d11cf8c3340e37c32d2e9d6152abe2c61f7/Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803", size = 106349 },
+]
+
+[[package]]
+name = "markupsafe"
+version = "3.0.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 },
+ { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 },
+ { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 },
+ { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 },
+ { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 },
+ { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 },
+ { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 },
+ { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 },
+ { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 },
+ { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 },
+ { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 },
+ { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 },
+ { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 },
+ { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 },
+ { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 },
+ { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 },
+ { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 },
+ { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 },
+ { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 },
+ { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 },
+]
+
+[[package]]
+name = "mergedeep"
+version = "1.3.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/3a/41/580bb4006e3ed0361b8151a01d324fb03f420815446c7def45d02f74c270/mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", size = 4661 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354 },
+]
+
+[[package]]
+name = "mkdocs"
+version = "1.6.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "click" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "ghp-import" },
+ { name = "jinja2" },
+ { name = "markdown" },
+ { name = "markupsafe" },
+ { name = "mergedeep" },
+ { name = "mkdocs-get-deps" },
+ { name = "packaging" },
+ { name = "pathspec" },
+ { name = "pyyaml" },
+ { name = "pyyaml-env-tag" },
+ { name = "watchdog" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/bc/c6/bbd4f061bd16b378247f12953ffcb04786a618ce5e904b8c5a01a0309061/mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2", size = 3889159 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e", size = 3864451 },
+]
+
+[[package]]
+name = "mkdocs-get-deps"
+version = "0.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mergedeep" },
+ { name = "platformdirs" },
+ { name = "pyyaml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/98/f5/ed29cd50067784976f25ed0ed6fcd3c2ce9eb90650aa3b2796ddf7b6870b/mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c", size = 10239 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134", size = 9521 },
+]
+
+[[package]]
+name = "mkdocs-material"
+version = "9.5.50"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "babel" },
+ { name = "colorama" },
+ { name = "jinja2" },
+ { name = "markdown" },
+ { name = "mkdocs" },
+ { name = "mkdocs-material-extensions" },
+ { name = "paginate" },
+ { name = "pygments" },
+ { name = "pymdown-extensions" },
+ { name = "regex" },
+ { name = "requests" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c7/16/c48d5a28bc4a67c49808180b6009d4d1b4c0753739ffee3cc37046ab29d7/mkdocs_material-9.5.50.tar.gz", hash = "sha256:ae5fe16f3d7c9ccd05bb6916a7da7420cf99a9ce5e33debd9d40403a090d5825", size = 3923354 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ee/b5/1bf29cd744896ae83bd38c72970782c843ba13e0240b1a85277bd3928637/mkdocs_material-9.5.50-py3-none-any.whl", hash = "sha256:f24100f234741f4d423a9d672a909d859668a4f404796be3cf035f10d6050385", size = 8645274 },
+]
+
+[[package]]
+name = "mkdocs-material-extensions"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/79/9b/9b4c96d6593b2a541e1cb8b34899a6d021d208bb357042823d4d2cabdbe7/mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443", size = 11847 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31", size = 8728 },
+]
+
+[[package]]
+name = "mkdocs-simple-hooks"
+version = "0.1.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mkdocs" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/f1/93/565f98d6810e3b493e61160aea1cceb8653331576e7fa7f048ac7e7cdf62/mkdocs-simple-hooks-0.1.5.tar.gz", hash = "sha256:dddbdf151a18723c9302a133e5cf79538be8eb9d274e8e07d2ac3ac34890837c", size = 4037 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7a/e9/7bf0f928f5b6cdd602d4a01d52e5fc1eba8d3ba6d97619a88fc271a625f8/mkdocs_simple_hooks-0.1.5-py3-none-any.whl", hash = "sha256:efeabdbb98b0850a909adee285f3404535117159d5cb3a34f541d6eaa644d50a", size = 4596 },
+]
+
+[[package]]
+name = "neotest-golang"
+version = "0.1.0"
+source = { virtual = "." }
+dependencies = [
+ { name = "mkdocs-material" },
+ { name = "mkdocs-simple-hooks" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "mkdocs-material" },
+ { name = "mkdocs-simple-hooks" },
+]
+
+[[package]]
+name = "packaging"
+version = "24.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 },
+]
+
+[[package]]
+name = "paginate"
+version = "0.5.7"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ec/46/68dde5b6bc00c1296ec6466ab27dddede6aec9af1b99090e1107091b3b84/paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945", size = 19252 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746 },
+]
+
+[[package]]
+name = "pathspec"
+version = "0.12.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 },
+]
+
+[[package]]
+name = "platformdirs"
+version = "4.3.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 },
+]
+
+[[package]]
+name = "pygments"
+version = "2.19.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 },
+]
+
+[[package]]
+name = "pymdown-extensions"
+version = "10.14"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown" },
+ { name = "pyyaml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/8b/96/b4337b778d2e9e77541a8d1cab00989aaeb1d6003c891cdc89221bd25651/pymdown_extensions-10.14.tar.gz", hash = "sha256:741bd7c4ff961ba40b7528d32284c53bc436b8b1645e8e37c3e57770b8700a34", size = 844927 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/00/ae/55d347eda5a4c57a2a042fe2e7616d14981115f566b9f8f69901aba3c0c6/pymdown_extensions-10.14-py3-none-any.whl", hash = "sha256:202481f716cc8250e4be8fce997781ebf7917701b59652458ee47f2401f818b5", size = 264264 },
+]
+
+[[package]]
+name = "python-dateutil"
+version = "2.9.0.post0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "six" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 },
+]
+
+[[package]]
+name = "pyyaml"
+version = "6.0.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 },
+ { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 },
+ { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 },
+ { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 },
+ { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 },
+ { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 },
+ { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 },
+ { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 },
+ { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 },
+]
+
+[[package]]
+name = "pyyaml-env-tag"
+version = "0.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "pyyaml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/fb/8e/da1c6c58f751b70f8ceb1eb25bc25d524e8f14fe16edcce3f4e3ba08629c/pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb", size = 5631 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069", size = 3911 },
+]
+
+[[package]]
+name = "regex"
+version = "2024.11.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/8e/5f/bd69653fbfb76cf8604468d3b4ec4c403197144c7bfe0e6a5fc9e02a07cb/regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519", size = 399494 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/90/73/bcb0e36614601016552fa9344544a3a2ae1809dc1401b100eab02e772e1f/regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84", size = 483525 },
+ { url = "https://files.pythonhosted.org/packages/0f/3f/f1a082a46b31e25291d830b369b6b0c5576a6f7fb89d3053a354c24b8a83/regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4", size = 288324 },
+ { url = "https://files.pythonhosted.org/packages/09/c9/4e68181a4a652fb3ef5099e077faf4fd2a694ea6e0f806a7737aff9e758a/regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0", size = 284617 },
+ { url = "https://files.pythonhosted.org/packages/fc/fd/37868b75eaf63843165f1d2122ca6cb94bfc0271e4428cf58c0616786dce/regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0", size = 795023 },
+ { url = "https://files.pythonhosted.org/packages/c4/7c/d4cd9c528502a3dedb5c13c146e7a7a539a3853dc20209c8e75d9ba9d1b2/regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7", size = 833072 },
+ { url = "https://files.pythonhosted.org/packages/4f/db/46f563a08f969159c5a0f0e722260568425363bea43bb7ae370becb66a67/regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7", size = 823130 },
+ { url = "https://files.pythonhosted.org/packages/db/60/1eeca2074f5b87df394fccaa432ae3fc06c9c9bfa97c5051aed70e6e00c2/regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c", size = 796857 },
+ { url = "https://files.pythonhosted.org/packages/10/db/ac718a08fcee981554d2f7bb8402f1faa7e868c1345c16ab1ebec54b0d7b/regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3", size = 784006 },
+ { url = "https://files.pythonhosted.org/packages/c2/41/7da3fe70216cea93144bf12da2b87367590bcf07db97604edeea55dac9ad/regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07", size = 781650 },
+ { url = "https://files.pythonhosted.org/packages/a7/d5/880921ee4eec393a4752e6ab9f0fe28009435417c3102fc413f3fe81c4e5/regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e", size = 789545 },
+ { url = "https://files.pythonhosted.org/packages/dc/96/53770115e507081122beca8899ab7f5ae28ae790bfcc82b5e38976df6a77/regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6", size = 853045 },
+ { url = "https://files.pythonhosted.org/packages/31/d3/1372add5251cc2d44b451bd94f43b2ec78e15a6e82bff6a290ef9fd8f00a/regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4", size = 860182 },
+ { url = "https://files.pythonhosted.org/packages/ed/e3/c446a64984ea9f69982ba1a69d4658d5014bc7a0ea468a07e1a1265db6e2/regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d", size = 787733 },
+ { url = "https://files.pythonhosted.org/packages/2b/f1/e40c8373e3480e4f29f2692bd21b3e05f296d3afebc7e5dcf21b9756ca1c/regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff", size = 262122 },
+ { url = "https://files.pythonhosted.org/packages/45/94/bc295babb3062a731f52621cdc992d123111282e291abaf23faa413443ea/regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a", size = 273545 },
+]
+
+[[package]]
+name = "requests"
+version = "2.32.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "charset-normalizer" },
+ { name = "idna" },
+ { name = "urllib3" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 },
+]
+
+[[package]]
+name = "six"
+version = "1.17.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 },
+]
+
+[[package]]
+name = "urllib3"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 },
+]
+
+[[package]]
+name = "watchdog"
+version = "6.0.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480 },
+ { url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451 },
+ { url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057 },
+ { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079 },
+ { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078 },
+ { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076 },
+ { url = "https://files.pythonhosted.org/packages/ab/cc/da8422b300e13cb187d2203f20b9253e91058aaf7db65b74142013478e66/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f", size = 79077 },
+ { url = "https://files.pythonhosted.org/packages/2c/3b/b8964e04ae1a025c44ba8e4291f86e97fac443bca31de8bd98d3263d2fcf/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26", size = 79078 },
+ { url = "https://files.pythonhosted.org/packages/62/ae/a696eb424bedff7407801c257d4b1afda455fe40821a2be430e173660e81/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c", size = 79077 },
+ { url = "https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2", size = 79078 },
+ { url = "https://files.pythonhosted.org/packages/07/f6/d0e5b343768e8bcb4cda79f0f2f55051bf26177ecd5651f84c07567461cf/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a", size = 79065 },
+ { url = "https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680", size = 79070 },
+ { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067 },
+]