feat: Added support for backend-specific layouts#82
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds per-backend diff layout overrides so different AI backends (e.g., codex/opencode) can open diffs using different layouts while preserving the existing default layout behavior.
Changes:
- Introduces
diff.layoutsconfig map and backend-aware layout selection. - Threads
backendthrough pre-tool handling intodiff.show_diff(...). - Adds tests and README docs covering backend-vs-default layout precedence and fallback.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/plugin/diff_lifecycle_spec.lua | Adds test coverage for backend layout override precedence and fallback behavior. |
| lua/code-preview/pre_tool/init.lua | Propagates backend information to diff rendering calls. |
| lua/code-preview/init.lua | Adds diff.layouts to default configuration. |
| lua/code-preview/diff.lua | Implements backend-aware layout resolution and logs selected backend/layout. |
| README.md | Documents diff.layouts configuration and provides an example. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| local function layout_for_backend(cfg, backend) | ||
| local diff_cfg = (cfg and cfg.diff) or {} | ||
| local layouts = diff_cfg.layouts or {} | ||
|
|
||
| if backend and layouts[backend] then | ||
| return layouts[backend] | ||
| end | ||
|
|
||
| return diff_cfg.layout or "tab" | ||
| end |
| function M.handle(raw, backend) | ||
| local cfg = require("code-preview").config or {} | ||
| local input = normalisers.normalise(raw, backend) | ||
| if input then | ||
| input.backend = backend | ||
| end | ||
| local tool_name = input and input.tool_name |
| it("backend layout override wins over the default layout", function() | ||
| local orig = tmp_file("backend_vs_orig.txt", "alpha\nbeta") | ||
| local prop = tmp_file("backend_vs_prop.txt", "alpha\ngamma") | ||
|
|
||
| local tabs_before = #vim.api.nvim_list_tabpages() | ||
| local tab = vim.api.nvim_get_current_tabpage() | ||
| local wins_before = #vim.api.nvim_tabpage_list_wins(tab) | ||
|
|
||
| with_layout("tab", function() | ||
| diff.show_diff(orig, prop, "layout_backend_vsplit.txt", nil, nil, "codex") | ||
| end, { codex = "vsplit" }) | ||
|
|
||
| assert.is_true(diff.is_open()) | ||
| assert.equals(tabs_before, #vim.api.nvim_list_tabpages()) | ||
| assert.equals(wins_before + 2, #vim.api.nvim_tabpage_list_wins(tab)) | ||
|
|
||
| diff.close_diff() | ||
| os.remove(orig) | ||
| os.remove(prop) | ||
| end) |
| debug = false, -- enable debug logging to stdpath("log")/code-preview.log | ||
| diff = { | ||
| layout = "tab", -- "tab", "vsplit", or "inline" | ||
| layouts = {}, -- add layouts overrides for specific backends: { opencode = "tab", codex = "vsplit" } |
| debug = false, -- enable debug logging to stdpath("log")/code-preview.log | ||
| diff = { | ||
| layout = "tab", -- "tab" (new tab) | "vsplit" (current tab) | "inline" (GitHub-style) | ||
| layouts = {}, -- add layouts overrides for specific backends: { opencode = "tab", codex = "vsplit" } |
|
I'll work on the resolving the other remarks tomorrow. |
|
Thanks for this — clean feature and nice test coverage. A few notes:
|
…ough the function calls
|
Hopefully these changes were what you had in mind, feel free to let me know if not! |
|
Merging now. Thanks again for contributing — glad the plugin's been useful to you, and hope to see you around the repo! 🎉 |
|
Awesome, thanks for the merge! :) |
Hey there,
I started trying out your plugin and I like it, I don't like using AI without the git diffs inside of my neovim so this nicely bridges the gap.
Personally I prefer working with splits, however it seems Opencode doesn't support this properly.
That made me consider the option for different layouts depending on the backend, which is what this PR adds.
This lets you configure the plugin as follows:
So if you want to use
vsplitby default, you can, but you can also specify a different layout for a different backend.All tests passed and I added 2 additional ones that test the new behaviour, and also test the fallback behaviour (for when no layout-specific backend is provided).
Please let me know if there's anything you'd like to see changed or if this isn't something you're interested in merging!
Tests