Skip to content

feat(ui): preserve buffers on toggle#229

Open
jensenojs wants to merge 2 commits intosudo-tee:mainfrom
jensenojs:impr/dont-close-buffer-when-toggle
Open

feat(ui): preserve buffers on toggle#229
jensenojs wants to merge 2 commits intosudo-tee:mainfrom
jensenojs:impr/dont-close-buffer-when-toggle

Conversation

@jensenojs
Copy link

@jensenojs jensenojs commented Feb 3, 2026

Background

This PR improves UI toggle behavior by introducing ui.persist_state (default: true) and refining window and buffer lifecycle handling.

Goal: when toggling UI off and on, preserve user context (buffers and cursor or scroll intent) without breaking close semantics.

Behavior Changes

  • Add ui.persist_state (default true):

    • toggle now hides windows and preserves buffers when enabled.
    • when disabled, behavior remains full close (buffers are deleted).
  • Normalize window state semantics:

    • visible: input or output window is currently visible
    • hidden: windows are closed but restorable hidden buffers exist
    • closed: no visible windows and no restorable hidden buffers
  • Fix toggle open-state detection:

    • output-only view (input auto-hidden) is treated as visible (not closed).
  • Make get_window_state() read-only:

    • remove cursor-saving side effects from getter.
  • Restore policy after hidden reopen:

    • if user was following bottom before hide, allow sync-to-latest behavior on reopen;
    • if user was reading in the middle, preserve reading position.
  • Explicit hidden-buffer lifecycle:

    • stash / consume / clear hidden snapshot
    • validity checks for restored buffers
  • Type and LSP cleanup:

    • reduce false diagnostics while keeping gd navigation targeting real implementations.

Test Coverage

Added and updated behavior-focused tests:

  • tests/unit/persist_state_spec.lua

    • config default and override
    • preserve on hide plus reopen reuse
    • closed, visible, hidden state transitions
    • get_window_state() purity (no mutation)
    • output-only visible semantics
    • persist_state=false full-close path
  • tests/unit/core_spec.lua

    • hidden restore render gating:
      • no forced full render when preserving reading position
      • full render allowed when previously at bottom

Reviewer Guide

Suggested review order:

  1. lua/opencode/state.lua: state model plus hidden snapshot lifecycle
  2. lua/opencode/ui/ui.lua: close and create window lifecycle split
  3. lua/opencode/core.lua: reopen render gating behavior
  4. lua/opencode/api.lua: toggle semantics plus getter purity
  5. tests for behavior lock-in

Risks / Compatibility

  • Default behavior changes toward preservation (persist_state=true).
  • Compatibility path is preserved via persist_state=false.
  • Main risk area is state transitions (visible/hidden/closed), covered by regression tests above.

@jensenojs jensenojs changed the title feat(ui):only hide buffer when keep_buffers_on_toggle=true feat(ui): preserve buffers on toggle Feb 3, 2026
@jensenojs jensenojs force-pushed the impr/dont-close-buffer-when-toggle branch from cf1203c to 6ab8fd6 Compare February 3, 2026 11:33
@jensenojs jensenojs mentioned this pull request Feb 3, 2026
15 tasks
@disrupted
Copy link
Contributor

great addition! this is so useful, imo it would make for a sensible default. there is still :Opencode close for when the user would want to actually close it

@sudo-tee
Copy link
Owner

sudo-tee commented Feb 3, 2026

This sems like a useful feature.

As I will have to maintain this in the future, I would like it if you add a couple of tests for this.

As well as updating the README file

Thanks a lot for the PR

@jensenojs
Copy link
Author

Sorry, I found some more subtle issues.

I'm glad you reviewed so carefully, including that it should probably be the default behavior. I will resolve all the above issues as soon as possible.

Add `persist_state` configuration option (default: true) that preserves
buffers and cursor positions when toggling the UI off. This enables
faster restore and maintains scroll position across toggle operations.
@jensenojs jensenojs force-pushed the impr/dont-close-buffer-when-toggle branch from 6ab8fd6 to ec6711e Compare February 5, 2026 19:06
@jensenojs
Copy link
Author

jensenojs commented Feb 5, 2026

I am quite satisfied with my local behavior, (my nvim configuration will switch when the position is both left and center, plus I want to retain the cursor position when toggling, so although the code is relatively complex, I also spent quite a while calibrating through actual testing. I might record a video hhh)

The overall code writing and cleanup were all done by kimi2.5. There may be some unnecessary comments or still overdesigned parts here. I will carefully review my PR tomorrow and clean up that junk (it's late night here now, I have to sleep). I pushed the code up first in case someone might want to try it out early. @sudo-tee @disrupted


update :

iShot_2026-02-06_14.55.30.mp4

@jensenojs jensenojs requested a review from sudo-tee February 6, 2026 07:27
@disrupted
Copy link
Contributor

at 0:13 in the video it looks like the cursor jumped up a little when re-opening the output buffer. do you know why that's happening?

@sudo-tee
Copy link
Owner

sudo-tee commented Feb 6, 2026

Thanks for the PR,

I will play with it a little bit in the coming days as welle a redo a finale review.

@jensenojs
Copy link
Author

at 0:13 in the video it looks like the cursor jumped up a little when re-opening the output buffer. do you know why that's happening?在视频的 0:13 处,重新打开 output buffer 时光标似乎稍微向上跳了一下。你知道这是为什么吗?

When the cursor bounces back from the editing window to the opencode output window, if it wasn't at the bottom before (for example, if I was looking at messages in the middle), I want it to reappear at the corresponding position.

Actually, it's not just the cursor jumping up; it seems to be one of my autojump commands that centers the entire window, although it does create a bit of visual noise.

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.

3 participants