From f09d9810fa135bae78b7b102cee380e1171d98ea Mon Sep 17 00:00:00 2001 From: David Herman Date: Fri, 5 Jun 2026 09:48:06 +0200 Subject: [PATCH] fix(session-picker): fix fzf-lua preview gutter and list entry layout Three fzf-lua-specific issues with the session picker preview: 1. The formatter's vertical border extmarks use virt_text_win_col = -3, targeting the 3-column gutter (signcolumn + foldcolumn) present in the main output window. The fzf-lua preview window has no gutter by default (set_style_minimal), so the overlay lands on column 0 of the text. Set signcolumn='yes' and foldcolumn='1' in the preview window to match. 2. Entries are formatted to opts.width (e.g. 100 columns), but fzf-lua's preview split leaves ~40% of the window for the list pane. Time columns end up off-screen. After building the fzf config (which keeps the full winopts.width), narrow opts.width to the list pane width so the format function sizes entries to fit. 3. Drop session IDs from picker list entries. The title + datetime is sufficient for identification, and IDs are visible in the preview pane when a session is selected. --- lua/opencode/ui/base_picker.lua | 11 +++++++++++ lua/opencode/ui/session_picker.lua | 13 +++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lua/opencode/ui/base_picker.lua b/lua/opencode/ui/base_picker.lua index bda35b20..78d7c8fa 100644 --- a/lua/opencode/ui/base_picker.lua +++ b/lua/opencode/ui/base_picker.lua @@ -515,6 +515,17 @@ local function fzf_ui(opts) local fzf_config = create_fzf_config() fzf_config.actions = actions_config + -- When a preview pane is active, fzf-lua splits the window (default + -- right:60% preview, left:40% list). Narrow opts.width so that the + -- format function produces entries sized for the list pane, not the + -- full window. The format closure reads opts.width on each call. + local has_preview = opts.preview and opts.preview ~= 'none' and opts.preview ~= false + if has_preview and opts.width then + local window_cols = opts.width + 8 + -- list pane ≈ 40% of the window, minus a small border/padding allowance + opts.width = math.floor(window_cols * 0.4) - 4 + end + fzf_lua.fzf_exec(create_finder(), fzf_config) end diff --git a/lua/opencode/ui/session_picker.lua b/lua/opencode/ui/session_picker.lua index ffc41a55..78106275 100644 --- a/lua/opencode/ui/session_picker.lua +++ b/lua/opencode/ui/session_picker.lua @@ -31,9 +31,8 @@ end ---@param session Session object ---@return PickerItem function format_session_item(session, width) - local debug_text = 'ID: ' .. (session.id or 'N/A') local updated_time = (session.time and session.time.updated) or 'N/A' - return base_picker.create_time_picker_item(session.title, updated_time, debug_text, width) + return base_picker.create_time_picker_item(session.title, updated_time, nil, width) end --- Normalize message order to oldest-first (chronological) @@ -195,10 +194,16 @@ local function render_preview_buffer(target, formatted) pcall(vim.api.nvim_buf_clear_namespace, bufnr, output_window.namespace, 0, -1) output_window.apply_extmarks(bufnr, formatted.extmarks) - -- Apply folds (window-local operation) - target:with_window(function() + -- Configure preview window to match the main output window's gutter. + -- The formatter places vertical border extmarks at virt_text_win_col = -3 + -- which requires a 3-column gutter (signcolumn=yes + foldcolumn=1) so + -- the border renders in the gutter instead of overlaying column 0 of text. + target:with_window(function() vim.api.nvim_set_option_value('number', false, { win = 0 }) vim.api.nvim_set_option_value('relativenumber', false, { win = 0 }) + vim.api.nvim_set_option_value('signcolumn', 'yes', { win = 0 }) + vim.api.nvim_set_option_value('foldcolumn', '1', { win = 0 }) + vim.api.nvim_set_option_value('statuscolumn', '', { win = 0 }) vim.api.nvim_set_option_value('foldmethod', 'manual', { win = 0 }) vim.cmd('silent! normal! zE') -- clear existing manual folds local line_count = vim.api.nvim_buf_line_count(bufnr)