A Rex-Native Neovim frontend built in Zig.
One Neovim runs in the background behind all your panes, so buffers,
registers, undo and language servers are shared. :split and :vsplit open
real Rex panes where Neovim would put the window, and closing a pane in Rex
closes its window. Focusable floats, such as pickers, open in Rex floating
panes, along with any floats attached to them. The completion menu,
unfocusable floats like notifications, and statuslines are drawn inside the
pane they belong to.
Very early and rough, bugs / missing features are to be expected.
AI has been used heavily in building neorex due to limits on my available time. A lot of the code needs large improvements, cleanup, better design etc. I will be doing this incrementally - any contributions are welcome.
- macOS (it uses kqueue)
- Rex
- A recent Neovim. It's developed against 0.13-dev; older versions may show no statuslines.
- Zig 0.17 to build
zig build
zig build test
zig build test -Dgolden # also the golden tests; downloads Ghostty onceThe golden tests check every frame neorex draws against Ghostty's terminal emulator, pinned to one commit.
Run it in a Rex pane, with any Neovim arguments:
zig-out/bin/neorex some/file.txtneorex help lists the debug commands, which run each layer on its own:
keys, Neovim's redraw events, the renderer, and pane hand-off.
neorex keeps Neovim in step with Rex's theme:
- Light and dark. neorex asks Rex to report theme changes (mode 2031)
and sets
'background'to match, which reloads your colorscheme. Setvim.g.neorex_follow_theme = falseto keep'background'as you set it. - Palette colors. A highlight with only
ctermfg/ctermbg(no RGB color) is drawn as that palette color, so Rex fills it in from its current theme and it changes when the theme does. Highlights with RGB colors are drawn as before.
runtime/ has a colorscheme and a lualine theme, both named neorex, made
only of the 16 palette colors, so Neovim takes on Rex's colors exactly. To
use them only when Neovim runs in neorex (lazy.nvim / LazyVim shown):
-- neorex starts Neovim with `--listen $TMPDIR/neorex-<pid>.nvim.sock`
local in_neorex = vim.v.servername:match("/neorex%-%d+%.nvim%.sock$") ~= nil
if in_neorex then
vim.opt.rtp:append("/path/to/neorex/runtime")
end
return {
{ "LazyVim/LazyVim", opts = { colorscheme = in_neorex and "neorex" or nil } },
{
"nvim-lualine/lualine.nvim",
opts = function(_, opts)
if not in_neorex then return end
opts.options.theme = "neorex"
-- the theme's middle section has no background, so drop the separator glyphs
opts.options.section_separators = { left = "", right = "" }
end,
},
}Plugins that set their own RGB colors keep them.
- The
<C-w>resize, swap and move commands do nothing. Use Rex's own pane controls instead. - Plugins that arrange windows (sidebars, layout managers) don't get the placement they expect.
- Only one tab page: Neovim tab pages aren't Rex tabs.
- No external command line or messages: long messages still show "Press ENTER".
- No global statusline: with
laststatus=3, each pane still shows its own statusline.
Much of neorex will be split out into standalone Zig modules, and later into their own packages:
- a Neovim RPC client (msgpack, message framing, requests)
- a Rex API client (WebSocket and the control protocol)
- terminal key input (the kitty keyboard protocol)
neorex should then be easier to extend to other editors that provide similar processes for running external windows.
MIT
