Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@

## Validation

<!-- There is no automated test suite yet. Describe what you ran manually. -->
<!-- Check the automated commands you ran and describe any manual coverage. -->

- [ ] `make test` passes
- [ ] `make check-shell` passes
- [ ] Plugin loads with no errors in a Neovim + Herdr session (`HERDR_ENV=1`)
- [ ] `:checkhealth herdr-splits` reports no failures
- [ ] Navigation (`<C-h/j/k/l>`) works across Neovim splits and Herdr panes
- [ ] Resizing (`<M-h/j/k/l>`) works across Neovim splits and Herdr panes
- [ ] Edge cases relevant to this change exercised (at_edge, count prefix,
floats, auto-unzoom)
- [ ] Bash changes checked with `bash -n scripts/*.sh` (if applicable)
- [ ] `README.md` / `herdr-plugin.toml` updated (if user-facing)

## Notes for review
Expand Down
43 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: CI

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
shell:
name: Bash syntax
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false
- run: make check-shell

test:
name: Neovim ${{ matrix.neovim-version }}
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
neovim-version: [v0.10.0, stable]
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false
submodules: true
- uses: rhysd/action-setup-vim@febef33995d6649302e9d88dda81e071b68f16a7 # v1.6.1
with:
neovim: true
version: ${{ matrix.neovim-version }}
- run: make test
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "deps/mini.test"]
path = deps/mini.test
url = https://github.com/nvim-mini/mini.test.git
18 changes: 15 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ lua/herdr-splits/ Neovim plugin source
health.lua :checkhealth herdr-splits
scripts/herdr-nav.sh Herdr-side navigation action
scripts/herdr-resize.sh Herdr-side resize action
scripts/minimal_init.lua Isolated Neovim test bootstrap
tests/ mini.test suites
Makefile Local and CI validation commands
herdr-plugin.toml Herdr plugin manifest (actions + metadata)
```

Expand Down Expand Up @@ -77,7 +80,18 @@ After changing `scripts/*.sh` or `herdr-plugin.toml`, run

## Validation

There is no automated test suite yet, so changes must be validated manually:
The Make targets initialize and update the pinned test dependency automatically.
To prepare it separately, run `make deps`.

Run the automated checks with:

```bash
make test # isolated mini.test suite in headless Neovim
make check-shell # bash syntax checks for both shipped scripts
make check # all of the above
```

Cross-pane behaviour still requires manual validation in a Herdr session:

1. Load the plugin in Neovim inside a Herdr session (`HERDR_ENV=1`).
2. Run `:checkhealth herdr-splits` and confirm it reports no failures.
Expand All @@ -87,8 +101,6 @@ There is no automated test suite yet, so changes must be validated manually:
- count prefixes (e.g. `3<C-h>`)
- floating windows and embedded-sidebar floats
- auto-unzoom when crossing into a sibling Herdr pane
4. For bash changes, run `bash -n scripts/herdr-nav.sh` /
`bash -n scripts/herdr-resize.sh` to catch syntax errors.

## Submitting changes

Expand Down
21 changes: 21 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
ROOT := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
NVIM ?= nvim

.PHONY: deps test check-shell check

deps:
@if git -C "$(ROOT)" ls-files --error-unmatch deps/mini.test >/dev/null 2>&1; then \
git -C "$(ROOT)" submodule update --init --depth 1 --checkout deps/mini.test; \
else \
test -f "$(ROOT)/deps/mini.test/lua/mini/test.lua"; \
fi

test: deps
cd "$(ROOT)" && "$(NVIM)" --headless --noplugin -i NONE \
-u "$(ROOT)/scripts/minimal_init.lua" -c "lua MiniTest.run()"

check-shell:
bash -n "$(ROOT)/scripts/herdr-nav.sh"
bash -n "$(ROOT)/scripts/herdr-resize.sh"

check: check-shell test
1 change: 1 addition & 0 deletions deps/mini.test
Submodule mini.test added at 35c67c
26 changes: 22 additions & 4 deletions lua/herdr-splits/herdr.lua
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,20 @@ function M.current_pane_at_edge(direction)
end

local ok, data = pcall(vim.json.decode, stdout)
if not ok or not data or not data.result or not data.result.edges then
if
not ok
or type(data) ~= 'table'
or type(data.result) ~= 'table'
or type(data.result.edges) ~= 'table'
then
return nil
end

return data.result.edges[edge_key] == true
local at_edge = data.result.edges[edge_key]
if type(at_edge) ~= 'boolean' then
return nil
end
return at_edge
end

---Check if the current Herdr pane is zoomed.
Expand All @@ -73,11 +82,20 @@ function M.current_pane_is_zoomed()
end

local ok, data = pcall(vim.json.decode, stdout)
if not ok or not data or not data.result or not data.result.layout then
if
not ok
or type(data) ~= 'table'
or type(data.result) ~= 'table'
or type(data.result.layout) ~= 'table'
then
return nil
end

return data.result.layout.zoomed == true
local zoomed = data.result.layout.zoomed
if type(zoomed) ~= 'boolean' then
return nil
end
return zoomed
end

---Focus a Herdr pane in the given direction.
Expand Down
27 changes: 3 additions & 24 deletions lua/herdr-splits/nav.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,13 @@ local function is_sidebar()
return win.is_ignored_or_preview() or win.is_embedded_floating_window()
end

---Split a new Neovim window at the edge in the given direction.
---Temporarily overrides splitright/splitbelow to place the new window correctly.
---Split a new Neovim window using the user's placement preferences.
---@param direction '"left"'|'"right"'|'"up"'|'"down"'
local function split_edge(direction)
if direction == 'left' or direction == 'right' then
local orig_splitright = vim.opt.splitright:get()
if direction == 'left' then
vim.opt.splitright = false
vim.cmd('vsp')
vim.opt.splitright = orig_splitright
else
vim.cmd('vsp')
if orig_splitright then
vim.cmd('wincmd h')
end
end
vim.cmd('vsp')
else
local orig_splitbelow = vim.opt.splitbelow:get()
if direction == 'up' then
vim.opt.splitbelow = false
vim.cmd('sp')
vim.opt.splitbelow = orig_splitbelow
else
vim.cmd('sp')
if orig_splitbelow then
vim.cmd('wincmd k')
end
end
vim.cmd('sp')
end
end

Expand Down
14 changes: 14 additions & 0 deletions scripts/minimal_init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
local source = debug.getinfo(1, 'S').source
assert(source:sub(1, 1) == '@', 'could not locate minimal_init.lua')

local root = vim.fn.fnamemodify(source:sub(2), ':p:h:h')
vim.opt.runtimepath:prepend(root)
vim.opt.runtimepath:prepend(root .. '/deps/mini.test')

require('mini.test').setup({
collect = {
find_files = function()
return vim.fn.glob(root .. '/tests/test_*.lua', true, true)
end,
},
})
Loading
Loading