Skip to content

feat(ui): make <C-w>o work inside opencode windows#327

Open
jugarpeupv wants to merge 14 commits intosudo-tee:mainfrom
jugarpeupv:feature/ctrl-w-o
Open

feat(ui): make <C-w>o work inside opencode windows#327
jugarpeupv wants to merge 14 commits intosudo-tee:mainfrom
jugarpeupv:feature/ctrl-w-o

Conversation

@jugarpeupv
Copy link
Contributor

@jugarpeupv jugarpeupv commented Mar 17, 2026

Description:

Pressing <C-w>o while inside an opencode window previously had no effect or caused errors because Neovim's built-in "close all other windows" command does not know about opencode's window pair. This PR makes it work correctly.

It is in fact useful to have two buffers in the chat (1 por the user input and 1 for the output) so the only thing i am missing is the ability to <c-w>o in it

@sudo-tee if you find another implementation better, i am up for it, this one at least is working for me

What changed

<C-w>o support (autocmds.lua, state.lua)

Buffer-local keymaps for <C-w>o / <C-w><C-o> are set on both opencode buffers. The handler closes all non-floating windows that are not part of the opencode pair (input + output + footer), preserving the opencode layout intact. The saved window-width ratio is also cleared so the next toggle opens at the configured default width rather than the now-meaningless pre-<C-w>o width.

A new are_opencode_only_windows() helper in state.lua detects when opencode is the only thing left on screen (i.e. after <C-w>o was used). This is wired into the toggle-action rule table so that pressing the toggle key after <C-w>o correctly hides opencode instead of trying to re-open it.

Replace winfixbuf with buf_fix_win (input_window.lua, output_window.lua, ui.lua)

winfixbuf = true was set on the opencode windows to prevent other code from redirecting their buffer. However this is a hard lock: any plugin or Neovim feature that tries to switch a buffer in a window (pickers like snacks.nvim/telescope, :buffer, etc.) will crash with:

E1513: Cannot switch buffer. 'winfixbuf' is enabled

The codebase already contained buf_fix_win.lua — an autocmd-based module that closes any duplicate window that shows an opencode buffer — but it was never wired up. This PR activates it as the replacement:

  • winfixbuf = true is removed from both input_window.setup() and output_window.setup()
  • buf_fix_win.fix_to_win() is called for each buffer, achieving the same "this buffer stays in its intended window" guarantee without the hard lock that breaks pickers
  • The now-unnecessary winfixbuf = false unset calls in ui.lua are removed

Allow users to customize window-local options for the input window via
`ui.input.win_options` in config. Any valid Neovim window option can be set,
such as signcolumn, cursorline, number, relativenumber, etc. This improves
flexibility for user preferences and editor appearance.
Adds a new command and API to insert the current visual selection as a
formatted code block directly into the input buffer. This includes a new
`add_visual_selection_inline` function, a corresponding keymap, and a
helper to build the formatted text. Unit tests are provided to ensure
correct formatting and error handling for edge cases.
Move winfixbuf handling for input and output windows to a shared
`buf_fix_win.fix_to_win` utility. This reduces duplication and ensures
consistent buffer-to-window pinning logic. Also removes redundant
winfixbuf resets and last-window buffer swap logic from ui.lua, as this
is now handled in a single place.
Update the inline visual selection text to use bolded file path formatting
(**`path/to/file`**) instead of the previous "Here is some code from"
prefix. Adjust unit tests to match the new output format. This change
makes the inserted context more visually distinct and concise.
Add new action `add_visual_selection_inline` with keymap `<leader>oY` to
insert visually selected code directly into the input buffer as a Markdown
code block, prefixed with the file path. Updates documentation with usage
details and example. Leaves cursor in normal mode for prompt editing.
Add a warning notification when a part update references a message that
cannot be found in the render state. This helps with debugging and
improves visibility into potential state inconsistencies.
Store the ratio of the output window's width to the total columns when
hiding windows, unless the UI position is 'current'. This enables
restoring window sizes more accurately.
@sudo-tee
Copy link
Owner

sudo-tee commented Mar 18, 2026

Thanks for the PR.

I did some tests on the branch, and found some issues, removing the winfixbuf means that the buffer can be switched in the window. So you can end up in an inconsistent state

image

using the command :e somefile will do that.

once the buffer is not there anymore you get a lot of errors.

image

The util buf_fix_win does the opposite it prevents the opencode buffer to ever appearing in another window.

I will have a look if there is another way of doing it. some pickers also will use the window without winfixbuf so you will end up with the same situation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants