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
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ local DEFAULT_CONFIG = {
win = {
win = 0,
split = "below",
height = math.max(1, math.floor(vim.o.lines * 0.3)),
},
keymap = {
jump = "<C-g>",
Expand All @@ -82,6 +81,9 @@ local DEFAULT_CONFIG = {
keymap = {
toggle = "<C-t>",
refresh = "<C-r>",
prev = "<M-p>",
next = "<M-n>",
detail = "<CR>",
},
},
}
Expand Down Expand Up @@ -112,7 +114,7 @@ The window label is automatically `Codex [session-id]`.

Codex's built-in Vim mode is too limited for full Neovim editing workflows, so mini.codex offers an optional input pane backed by a real normal buffer. It is not loaded or opened by default. Enable it with an `input` table; mini.codex divides the Codex window into an upper terminal and lower input buffer.

By default, the input opens below the Codex window with a height of 30% of the screen. The `win` table is passed directly to `nvim_open_win()`, so split and floating layouts, dimensions, position, and appearance are controlled by native Neovim window configuration. For a floating Codex window, the default input follows the main window's position and width; use `relative = "win"` for the same behavior with a custom floating configuration. An explicitly positioned `relative = "editor"` configuration is kept unchanged. Resizing one split follows Neovim's native behavior.
By default, the input opens below the Codex window with a height of 30% of the main window. The `win` table is passed directly to `nvim_open_win()`, so split and floating layouts, dimensions, position, and appearance are controlled by native Neovim window configuration. For a floating Codex window, the default input follows the main window's position, width, and 30% height; use `relative = "win"` for the same behavior with a custom floating configuration. An explicitly positioned `relative = "editor"` configuration is kept unchanged. Resizing one split follows Neovim's native behavior.

The buffer uses the `markdown.codex` filetype, allowing the [codex-prompt-lsp](https://github.com/ishi-o/codex-prompt-lsp) Neovim adapter to attach automatically and provide completions. The adapter is optional; mini.codex does not depend on it.

Expand Down Expand Up @@ -179,11 +181,11 @@ local opts = {
require("mini.codex").setup(opts)
```

`mini.codex.Config`, `mini.codex.InputConfig`, and `mini.codex.OutputConfig` are exported LuaLS annotations. `win` uses Neovim's `vim.api.keyset.win_config`, so native window fields also receive completion and diagnostics.
`mini.codex.Config`, `mini.codex.InputConfig`, `mini.codex.OutputConfig`, `mini.codex.OutputChatTurnKind`, and `mini.codex.OutputChatTurnLabel` are exported LuaLS annotations. `win` uses Neovim's `vim.api.keyset.win_config`, so native window fields also receive completion and diagnostics.

## Output preview (optional)

The optional output preview displays the response history of the active Codex session in a dedicated read-only window. It is disabled by default. Each turn includes its question and response, and the window title identifies the latest turn.
The optional output preview displays one complete chat from the active Codex session in a dedicated read-only window. It is disabled by default. User and assistant messages are shown in full; every other internal turn is compacted to its type, state, and a short description for fast rendering. Each turn uses a `#` heading and no horizontal separator.

Enable it with an `output` table:

Expand All @@ -204,14 +206,17 @@ local opts = {
keymap = {
toggle = "<C-t>",
refresh = "<C-r>",
prev = "<M-p>", -- show the previous chat
next = "<M-n>", -- show the next chat
detail = "<CR>", -- show or dismiss the turn under the cursor
},
},
}

require("mini.codex").setup(opts)
```

The `output.win` table uses Neovim's native window configuration. By default, the preview is a split to the right of the Codex window, with a width of 50% of the Codex window's width and the same height. An explicit `width` or `height` overrides the default. For a floating preview, use `relative = "editor"` with the desired position and dimensions. The toggle key opens or hides the preview, and the refresh key (default `<C-r>`) updates the response history.
The `output.win` table uses Neovim's native window configuration. By default, the preview is a split to the right of the Codex window, with a width of 50% of the Codex window's width and the same height. When both input and output are enabled, the preview occupies the full right column, while the Codex window stays above the input pane on the left. The combined region keeps the bounds that the Codex/input stack had before the preview opened. An explicit `split`, `win`, `width`, or `height` is respected, including left-side and horizontal splits. For a floating preview, use `relative = "editor"` with the desired position and dimensions. Toggling preserves the surrounding layout, the main window view, and preview sizes changed manually after opening. The refresh key (default `<C-r>`) reloads the session while preserving the selected chat when possible. Put the cursor on a turn and press the detail key (default `<CR>`) to load only that turn's full database record; press it again to return to the compact chat.

## Commands

Expand All @@ -226,4 +231,4 @@ The `output.win` table uses Neovim's native window configuration. By default, th
:Codex stop # close current session
```

Session navigation reads Codex's local `$CODEX_HOME/state_5.sqlite` database, falling back to `~/.codex/state_5.sqlite`.
Session and output navigation read Codex's local `$CODEX_HOME/state_5.sqlite` and `$CODEX_HOME/thread_history_1.sqlite` databases, falling back to `~/.codex/`.
56 changes: 36 additions & 20 deletions doc/mini-codex.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ The complete default configuration is:
keymap = {
toggle = "<C-t>",
refresh = "<C-r>",
prev = "<M-p>",
next = "<M-n>",
detail = "<CR>",
},
},
}
Expand Down Expand Up @@ -125,13 +128,13 @@ is not loaded or opened by default. Enable it with an `input` table; mini.codex
divides the Codex window into an upper terminal and lower input buffer.

By default, the input opens below the Codex window with a height of 30% of the
screen. The `win` table is passed directly to `nvim_open_win()`, so split and
floating layouts, dimensions, position, and appearance are controlled by native
Neovim window configuration. For a floating Codex window, the default input
follows the main window’s position and width; use `relative = "win"` for the
same behavior with a custom floating configuration. An explicitly positioned
`relative = "editor"` configuration is kept unchanged. Resizing one split
follows Neovim’s native behavior.
main window. The `win` table is passed directly to `nvim_open_win()`, so split
and floating layouts, dimensions, position, and appearance are controlled by
native Neovim window configuration. For a floating Codex window, the default
input follows the main window’s position, width, and 30% height; use
`relative = "win"` for the same behavior with a custom floating configuration.
An explicitly positioned `relative = "editor"` configuration is kept
unchanged. Resizing one split follows Neovim’s native behavior.

The buffer uses the `markdown.codex` filetype, allowing the codex-prompt-lsp
<https://github.com/ishi-o/codex-prompt-lsp> Neovim adapter to attach
Expand Down Expand Up @@ -189,7 +192,6 @@ disable it again:
win = {
win = 0,
split = "below",
height = math.max(1, math.floor(vim.o.lines * 0.3)),
},
keymap = {
jump = "<C-g>", -- key that synchronizes and switches inputs
Expand All @@ -204,18 +206,20 @@ disable it again:
require("mini.codex").setup(opts)
<

`mini.codex.Config`, `mini.codex.InputConfig`, and `mini.codex.OutputConfig`
are exported LuaLS annotations. `win` uses Neovim’s
`mini.codex.Config`, `mini.codex.InputConfig`, `mini.codex.OutputConfig`,
`mini.codex.OutputChatTurnKind`, and `mini.codex.OutputChatTurnLabel` are
exported LuaLS annotations. `win` uses Neovim’s
`vim.api.keyset.win_config`, so native window fields also receive completion
and diagnostics.


OUTPUT PREVIEW (OPTIONAL) *mini-codex-mini.codex-output-preview-(optional)*

The optional output preview displays the response history of the active Codex
session in a dedicated read-only window. It is disabled by default. Each turn
includes its question and response, and the window title identifies the latest
turn.
The optional output preview displays one complete chat from the active Codex
session in a dedicated read-only window. It is disabled by default. User and
assistant messages are shown in full; every other internal turn is compacted to
its type, state, and a short description for fast rendering. Each turn uses a
`#` heading and no horizontal separator.

Enable it with an `output` table:

Expand All @@ -236,6 +240,9 @@ Enable it with an `output` table:
keymap = {
toggle = "<C-t>",
refresh = "<C-r>",
prev = "<M-p>", -- show the previous chat
next = "<M-n>", -- show the next chat
detail = "<CR>", -- show or dismiss the turn under the cursor
},
},
}
Expand All @@ -245,10 +252,19 @@ Enable it with an `output` table:

The `output.win` table uses Neovim’s native window configuration. By default,
the preview is a split to the right of the Codex window, with a width of 50% of
the Codex window’s width and the same height. An explicit `width` or `height`
overrides the default. For a floating preview, use `relative = "editor"` with
the desired position and dimensions. The toggle key opens or hides the preview,
and the refresh key (default `<C-r>`) updates the response history.
the Codex window’s width and the same height. When both input and output are
enabled, the preview remains on the right and occupies the full column, while
the Codex window stays above the input pane on the left. The combined region
keeps the bounds that the Codex/input stack had before the preview opened. An
explicit `split`, `win`, `width`, or `height` is respected, including left-side
and horizontal splits. Toggling preserves the surrounding layout, the main
window view, and preview sizes changed manually after opening.
For a floating preview, use `relative = "editor"` with the desired position and
dimensions. The toggle key opens or hides the preview, and the refresh key
(default `<C-r>`) reloads the session while preserving the selected chat when
possible. Put the cursor on a turn and press the detail key (default `<CR>`) to
load only that turn’s full database record; press it again to return to the
compact chat.


COMMANDS *mini-codex-mini.codex-commands*
Expand All @@ -264,8 +280,8 @@ COMMANDS *mini-codex-mini.codex-commands*
:Codex stop # close current session
<

Session navigation reads Codex’s local `$CODEX_HOME/state_5.sqlite` database,
falling back to `~/.codex/state_5.sqlite`.
Session and output navigation read Codex’s local `$CODEX_HOME/state_5.sqlite`
and `$CODEX_HOME/thread_history_1.sqlite` databases, falling back to `~/.codex/`.

Generated by panvimdoc <https://github.com/kdheepak/panvimdoc>

Expand Down
42 changes: 22 additions & 20 deletions lua/mini/codex.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ local DEFAULT_CONFIG = {
win = {
win = 0,
split = "below",
height = math.max(1, math.floor(vim.o.lines * 0.3)),
},
keymap = {
jump = "<C-g>",
Expand All @@ -41,6 +40,9 @@ local DEFAULT_CONFIG = {
keymap = {
toggle = "<C-t>",
refresh = "<C-r>",
prev = "<M-p>",
next = "<M-n>",
detail = "<CR>",
},
},
}
Expand All @@ -58,6 +60,14 @@ local function output_call(method, ...)
return output and output[method](...)
end

local function merge_component_config(current, opts)
local merged = vim.tbl_deep_extend("force", vim.deepcopy(current), opts)
if opts.win then
merged.win = vim.deepcopy(opts.win)
end
return merged
end

local function codex_executable()
local path = vim.fn.exepath("codex")
if path == "" then
Expand All @@ -82,7 +92,7 @@ local function configure_window()
end

local function open_input()
input_call("open", T.winid, function()
return input_call("open", T.winid, function()
return T.jobid
end)
end
Expand All @@ -99,8 +109,8 @@ local function open_terminal(win_config)
end

local function close_terminal()
input_call("close")
output_call("close")
input_call("close")
if T.winid then
pcall(vim.api.nvim_win_close, T.winid, true)
end
Expand Down Expand Up @@ -178,8 +188,8 @@ local function start_job(executable, args, token, fallback)
T.jobid = id
vim.b[T.bufnr].terminal_job_id = id
configure_window()
output_call("attach", T.winid, T.session_id, token)
open_input()
local input_win = open_input()
output_call("attach", T.winid, T.session_id, token, input_win)
return id
end

Expand All @@ -206,15 +216,15 @@ local function start_codex(mode)
local active = T.bufnr and vim.api.nvim_buf_is_valid(T.bufnr)
if active and step == nil and (mode == "" or current_mode == mode) then
if T.winid and vim.api.nvim_win_is_valid(T.winid) then
input_call("hide")
output_call("hide")
input_call("hide")
T.win_config = vim.api.nvim_win_get_config(T.winid)
vim.api.nvim_win_hide(T.winid)
T.winid = nil
else
open_terminal(T.win_config)
open_input()
output_call("attach", T.winid, T.session_id, T.token)
local input_win = open_input()
output_call("attach", T.winid, T.session_id, T.token, input_win)
end
return
elseif active then
Expand Down Expand Up @@ -277,13 +287,9 @@ end
---@param opts? mini.codex.Config
function M.setup(opts)
opts = opts or {}
config.win = opts.win or config.win
config.win = vim.deepcopy(opts.win or config.win)
if opts.input then
local input_config = vim.tbl_deep_extend("force", config.input, opts.input)
if opts.input.win then
input_config.win = vim.deepcopy(opts.input.win)
end
config.input = input_config
config.input = merge_component_config(config.input, opts.input)
input_call("close")
input = nil
if config.input.enabled then
Expand All @@ -292,18 +298,14 @@ function M.setup(opts)
end
end
if opts.output then
local output_config = vim.tbl_deep_extend("force", config.output, opts.output)
if opts.output.win then
output_config.win = vim.deepcopy(opts.output.win)
end
config.output = output_config
config.output = merge_component_config(config.output, opts.output)
output_call("close")
output = nil
if config.output.enabled then
output = require("mini.codex.output")
output.setup(config.output)
if T.winid then
output.attach(T.winid, T.session_id, T.token)
output.attach(T.winid, T.session_id, T.token, input_call("window"))
end
end
end
Expand Down
Loading
Loading