{"id":16639747,"url":"https://github.com/artemave/vigun","last_synced_at":"2026-05-18T02:36:36.160Z","repository":{"id":66735943,"uuid":"76599321","full_name":"artemave/vigun","owner":"artemave","description":"Unclutter your test diet","archived":false,"fork":false,"pushed_at":"2026-04-23T10:29:28.000Z","size":166,"stargazers_count":2,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-23T12:22:29.586Z","etag":null,"topics":["electron-mocha","mocha","testing","vim","vim-plugin"],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/artemave.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2016-12-15T21:54:45.000Z","updated_at":"2026-04-23T10:29:32.000Z","dependencies_parsed_at":"2023-11-07T16:41:09.766Z","dependency_job_id":"cbfc91a0-30dc-467e-8482-7bbaa85de644","html_url":"https://github.com/artemave/vigun","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/artemave/vigun","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artemave%2Fvigun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artemave%2Fvigun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artemave%2Fvigun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artemave%2Fvigun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/artemave","download_url":"https://codeload.github.com/artemave/vigun/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artemave%2Fvigun/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33162698,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-17T22:39:12.733Z","status":"online","status_checked_at":"2026-05-18T02:00:06.436Z","response_time":71,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["electron-mocha","mocha","testing","vim","vim-plugin"],"created_at":"2024-10-12T07:06:55.980Z","updated_at":"2026-05-18T02:36:36.154Z","avatar_url":"https://github.com/artemave.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vigun\nUnclutter your test diet.\n\n## What is this?\n\nNeovim plugin to run tests outside of Neovim. Out of the box it dispatches to a separate tmux window; other executors can be plugged in (see [Executors](#executors)).\n\n## Installation\n\nUsing [lazy](https://lazy.folke.io/):\n\n```lua\nrequire(\"lazy\").setup({\n  { \"artemave/vigun\" }\n})\n```\n\n## Usage\n\nVigun comes with no mappings, but it does add the following commands:\n\n#### VigunRun\n\nRun test(s): `:VigunRun \u003cmode\u003e`. The `\u003cmode\u003e` is any name you define in your runner’s `commands` table (see Configuration).\n\nIf invoked from a non‑test file, `:VigunRun \u003cmode\u003e` will attempt to run the last command.\n\n#### VigunToggleTestWindowToPane\n\nAsk the active executor to toggle its layout — for the tmux executor, that means joining the test window into the current vim window as a pane (or splitting it back out if it's already a pane). Errors if the active executor doesn't implement a layout toggle.\n\n#### VigunShowSpecIndex\n\nOpen quickfix window to quickly navigate between the tests.\n\n#### VigunCurrentTestBefore\n\nFold everything, except current test and all relevant setup code (e.g. before/beforeEach blocks).\n\n#### VigunToggleOnly\n\nToggle `.only` for a current test/context/describe.\n\n### Example bindings\n\nExample bindings for user‑defined modes (here: `file`, `focus`, `debug-focus`):\n\n```vim script\nau FileType {ruby,javascript,typescript,cucumber} nnoremap \u003cleader\u003et :VigunRun file\u003ccr\u003e\nau FileType {ruby,javascript,typescript,cucumber} nnoremap \u003cleader\u003eT :VigunRun focus\u003ccr\u003e\nau FileType {ruby,javascript,typescript,cucumber} nnoremap \u003cleader\u003ed :VigunRun debug-focus\u003ccr\u003e\n```\n\n## Configuration\n\n### Treesitter\n\nVigun relies on Treesitter for test discovery and folding. Ensure Neovim has relevant parsers installed for your languages. Example:\n\n```\n:TSInstall javascript typescript ruby python\n```\n\n### Lua setup()\n\nConfigure frameworks with Lua. Call `setup()` once or multiple times; each call merges into previous configuration.\n\nExample enabling rspec, pytest, and minitest_rails under the `runners` key with top‑level options. Command names are arbitrary and user‑defined:\n\n```lua\nrequire('vigun').setup({\n  tmux_window_name = 'test',\n  tmux_pane_orientation = 'vertical',\n  remember_last_command = true,\n  runners = {\n    rspec = {\n      enabled = function()\n        return vim.fn.expand('%'):match('_spec%.rb$') ~= nil\n      end,\n      test_nodes = { 'it', 'xit' },\n      context_nodes = { 'describe', 'context' },\n      commands = {\n        file = function(_)\n          return 'rspec ' .. vim.fn.expand('%')\n        end,\n        focus = function(_)\n          return 'rspec ' .. vim.fn.expand('%') .. ':' .. vim.fn.line('.')\n        end,\n      },\n    },\n    pytest = {\n      enabled = function()\n        return vim.fn.expand('%'):match('_test%.py$') ~= nil\n      end,\n      test_nodes = function(node, name)\n        return node and node:type() == 'function_definition' and type(name) == 'string' and name:match('^test_') ~= nil\n      end,\n      context_nodes = function(node, _)\n        return node and node:type() == 'class_definition'\n      end,\n      commands = {\n        file = function(_)\n          return 'pytest -s ' .. vim.fn.expand('%')\n        end,\n        focus = function(info)\n          local quoted = vim.fn.shellescape(info.test_title)\n          return 'pytest -k ' .. quoted .. ' -s ' .. vim.fn.expand('%')\n        end,\n        ['debug-file'] = function(_)\n          return 'pytest -vv -s ' .. vim.fn.expand('%')\n        end,\n        ['debug-focus'] = function(info)\n          local quoted = vim.fn.shellescape(info.test_title)\n          return 'pytest -vv -k ' .. quoted .. ' -s ' .. vim.fn.expand('%')\n        end,\n      },\n    },\n    minitest_rails = {\n      enabled = function()\n        return vim.fn.expand('%'):match('_test%.rb$') ~= nil\n      end,\n      commands = {\n        file = function(_)\n          return 'rails test ' .. vim.fn.expand('%')\n        end,\n        focus = function(_)\n          return 'rails test ' .. vim.fn.expand('%') .. ':' .. vim.fn.line('.')\n        end,\n      },\n   },\n  }\n})\n```\n\nYou can call `setup()` again (e.g., from a project `.exrc`) to override or add commands. Options are top‑level; runners live under `runners`:\n\n```lua\nrequire('vigun').setup({\n  runners = {\n  mocha = {\n    commands = {\n      file = function(_)\n        return 'electron-mocha --renderer ' .. vim.fn.expand('%')\n      end,\n    },\n  },\n}})\n```\n\n### Options\n\nOptions are top‑level keys of `setup()`:\n\n- `executor`: which executor to dispatch commands through (default: `'tmux'`). See [Executors](#executors).\n- `tmux_window_name`: name of the tmux window for tests (default: `test`). Tmux executor only.\n- `tmux_pane_orientation`: `vertical` or `horizontal` for `:VigunToggleTestWindowToPane` (default: `vertical`). Tmux executor only.\n- `hop_role`: role to pass to `hop run --role` (default: `'test'`). Hop executor only.\n- `remember_last_command`: rerun last command if no matching command is found (default: `true`).\n\n### Executors\n\nAn executor is the adapter that takes a shell command and makes it run somewhere observable. Select one via the `executor` option:\n\n```lua\nrequire('vigun').setup({ executor = 'tmux' })  -- default\nrequire('vigun').setup({ executor = 'hop' })\n```\n\nBuilt‑in executors:\n\n- **`tmux`** — sends commands to a dedicated tmux window (`tmux_window_name`, default `test`). Supports layout toggling via `:VigunToggleTestWindowToPane`.\n- **`hop`** — shells out to [`hop`](https://github.com/artemave/hop) as `hop run --focus --role \u003chop_role\u003e \u003ccmd\u003e`.\n\nYou can also pass a table with your own `run(cmd, on_done?)` (and optional `toggle_layout()`):\n\n```lua\nrequire('vigun').setup({\n  executor = {\n    run = function(cmd, on_done)\n      -- fire-and-forget when on_done is nil;\n      -- otherwise invoke on_done(output_string) when the command completes.\n    end,\n  },\n})\n```\n\n### on_result callback\n\nAttach a per‑runner `on_result` to react to a finished run.\n\n`on_result` takes an `info` argument with the following fields:\n  - `command`: exact command dispatched to the executor\n  - `mode`: the exact mode name you invoked (whatever you defined)\n  - `file`: current buffer filename at start\n  - `output`: output of the command\n  - `started_at`, `ended_at`: timestamps\n\nExample: populate diagnostics from failures\n\n```lua\nrequire('vigun').setup({\n  runners = {\n    rspec = {\n      -- ... other rspec config ...\n      on_result = function(info)\n        local ns = vim.api.nvim_create_namespace('vigun.tests')\n        vim.diagnostic.reset(ns)\n        local by_buf = {}\n        for path, line, msg in info.output:gmatch(\"([%./%w%-%_%/]+):(%d+):%s*(.-)\\n\") do\n          local bufnr = vim.fn.bufnr(vim.fn.fnamemodify(path, ':p'), true)\n          by_buf[bufnr] = by_buf[bufnr] or {}\n          table.insert(by_buf[bufnr], {\n            lnum = tonumber(line) - 1,\n            col = 0,\n            message = msg ~= '' and msg or 'Test failure',\n            severity = vim.diagnostic.severity.ERROR,\n            source = 'vigun',\n          })\n        end\n        for bufnr, items in pairs(by_buf) do\n          vim.diagnostic.set(ns, bufnr, items, { underline = true, virtual_text = true })\n        end\n      end,\n    },\n  },\n})\n```\n\nYou can adapt the parser to your runner’s format (RSpec, Minitest, PyTest, etc.) or populate quickfix/loclist instead of diagnostics.\n\n## Running Plugin Tests\n\n- `./run_vader_test` — run Vader specs.\n- `./run_vader_test test/run_ruby_tests.vader` — run a specific Vader file.\n- `./run_vader_test 'test/regressions/*.vader'` — run a subset via glob.\n- `./run_lua_tests` — run Lua tests (Plenary/Busted).\n- `./run_tests` — run both suites in sequence.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartemave%2Fvigun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fartemave%2Fvigun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartemave%2Fvigun/lists"}