Skip to content

fix(ui_select): add native preview for fzf-native/fzf-tmux#2753

Merged
phanen merged 1 commit into
mainfrom
fix/ui_select
Jul 3, 2026
Merged

fix(ui_select): add native preview for fzf-native/fzf-tmux#2753
phanen merged 1 commit into
mainfrom
fix/ui_select

Conversation

@phanen

@phanen phanen commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Close #2743

Summary by CodeRabbit

  • New Features
    • Added a default ui_select configuration for single-select with native preview behavior.
    • Ensured the native and tmux profiles use native preview for ui_select.
  • Bug Fixes
    • Improved ui_select preview resolution and rendering for both native and buffer modes, including safer handling when preview data is missing.
    • Improved temporary preview cleanup when the picker closes.
  • Tests
    • Expanded ui_select coverage for native/tmux preview, async preview startup, empty preview regression, and abort via escape.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 88ce0d38-a7df-4dd4-8ad5-bad82c3f3e5b

📥 Commits

Reviewing files that changed from the base of the PR and between d2a8395 and 8bbdcd3.

📒 Files selected for processing (5)
  • lua/fzf-lua/defaults.lua
  • lua/fzf-lua/profiles/fzf-native.lua
  • lua/fzf-lua/profiles/fzf-tmux.lua
  • lua/fzf-lua/providers/ui_select.lua
  • tests/ui_select_spec.lua
🚧 Files skipped from review as they are similar to previous changes (4)
  • lua/fzf-lua/profiles/fzf-native.lua
  • lua/fzf-lua/defaults.lua
  • lua/fzf-lua/profiles/fzf-tmux.lua
  • lua/fzf-lua/providers/ui_select.lua

📝 Walkthrough

Walkthrough

Adds ui_select native preview handling, configures defaults and profiles to opt into it, reworks provider preview selection and rendering, and expands tests for buffer preview, native preview, async preview items, and abort behavior.

Changes

ui_select native preview support

Layer / File(s) Summary
Default and profile configuration for ui_select preview
lua/fzf-lua/defaults.lua, lua/fzf-lua/profiles/fzf-native.lua, lua/fzf-lua/profiles/fzf-tmux.lua
Adds M.defaults.ui_select with single-select options, native preview, and an accept_item enter action, and sets ui_select.preview_type = "native" in the fzf-native and fzf-tmux profiles.
ui_select preview resolution and rendering
lua/fzf-lua/providers/ui_select.lua
Adds preview type resolution, normalizes ui_select options, removes the inline enter mapping merge, and branches preview setup between native temp-file rendering and the buffer/file previewer with structured missing-preview handling.
ui_select test suite
tests/ui_select_spec.lua
Adds a child-Neovim test suite with cleanup and picker helpers, plus cases for default buffer preview, native preview via fzf-tmux, async preview_item, and escape abort behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant UiSelect as lua/fzf-lua/providers/ui_select.lua
  participant Config as config.normalize_opts
  participant PreviewType as resolve_preview_type
  participant Fzf as fzf preview

  Caller->>UiSelect: ui_select(items, opts, on_choice)
  UiSelect->>Config: normalize_opts(opts, "ui_select")
  Config-->>UiSelect: normalized opts
  UiSelect->>PreviewType: resolve_preview_type(ui_opts, opts)
  PreviewType-->>UiSelect: native or buffer

  alt native
    UiSelect->>Fzf: preview command writes temp file and renders via bat/type
  else buffer
    UiSelect->>Fzf: buffer_or_file previewer parses entry and previews item
  end
Loading

Possibly related PRs

  • ibhagwan/fzf-lua#2722: Both PRs modify lua/fzf-lua/providers/ui_select.lua preview handling and preview_item result processing.

Suggested reviewers: ibhagwan

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR adds native ui_select preview paths, but the issue required fixing the fzf-tmux border assert for builtin/native preview windows. Update the fzf-tmux preview border logic to handle m.type == "nvim" or use a safe fallback instead of asserting.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: native preview support for ui_select in fzf-native/fzf-tmux.
Out of Scope Changes check ✅ Passed The listed changes all support ui_select native preview behavior or test it; no clearly unrelated code changes are evident.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ui_select

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ibhagwan

Copy link
Copy Markdown
Owner

Tysm @phanen!

@phanen phanen force-pushed the fix/ui_select branch 5 times, most recently from 82c7776 to 4b17264 Compare July 3, 2026 13:52
@phanen phanen marked this pull request as ready for review July 3, 2026 13:54

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lua/fzf-lua/profiles/fzf-tmux.lua (1)

14-22: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Drop the hard assert in the preview border callback
ui_select = { preview_type = "native" } only covers ui_select; this same border function is still used by manpages, helptags, undotree, and lsp.code_actions under fzf-tmux, where the metadata path is m.type = "nvim". Mirror fzf-native.lua and remove the assert.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lua/fzf-lua/profiles/fzf-tmux.lua` around lines 14 - 22, The preview border
callback in fzf-tmux currently hard-asserts that m.type is "fzf", but this
function is also used by manpages, helptags, undotree, and lsp.code_actions
where m.type can be "nvim". Update the border function to match the behavior in
fzf-native.lua by removing the assert and keeping the border selection logic
based on FzfLua.utils.has(m.opts, "fzf", { 0, 63 }), so the callback works for
both metadata paths.
🧹 Nitpick comments (1)
tests/ui_select_spec.lua (1)

100-149: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Good coverage, but missing a nil-returning preview_item case.

Consider adding a case where preview_item returns nil for the non-native (buffer) path — this would have caught the assert() crash risk flagged in providers/ui_select.lua (Lines 226-249).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/ui_select_spec.lua` around lines 100 - 149, Add a regression test in
ui_select spec for the non-native buffer preview path where preview_item returns
nil, since the current async test only covers a non-nil empty table. Use the
existing T["ui_select"]["async preview_item opens without crash"] pattern with
open_picker/register/reload and target the buffer backend, then assert the
picker stays alive and does not crash; this should cover the assert() failure
risk in providers/ui_select.lua within the preview_item handling logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lua/fzf-lua/defaults.lua`:
- Around line 2213-2223: The ui_select default is nesting preview_type under
M.defaults.ui_select.ui_select, but resolve_preview_type() only checks the
top-level opts.preview_type, so the default never takes effect. Move
preview_type to the top level of M.defaults.ui_select in defaults.lua and keep
the existing ui_select table for any nested provider-specific settings, so the
native preview default is actually picked up.

In `@lua/fzf-lua/providers/ui_select.lua`:
- Around line 214-217: Guard the preview-offset setup in ui_select’s item
handling so empty selections do not call ui_opts.preview_item with nil. In
ui_select.lua, before evaluating ui_opts.preview_item(items[1]) and assigning
opts.preview_offset, add an explicit check that items[1] exists (or that items
is non-empty) and only then compute first from preview_item; keep the existing
first.pos[1] logic unchanged for valid items.
- Around line 56-65: The fallback preview-type heuristic in resolve_preview_type
only checks opts[1] for "fzf-tmux", so combined profile tables can miss
native-preview detection and incorrectly fall back to "buffer". Update the
detection logic in resolve_preview_type to also recognize when opts[1] is a
table containing "fzf-tmux" (while preserving the existing opts.profile and
opts.fzf_opts checks), so combined profiles still resolve to "native".
- Around line 226-249: The builtin preview path in ui_select’s previewer
parse_entry currently asserts the result of ui_opts.preview_item, which will
crash on nil/false instead of falling back gracefully. Update the
previewer:_ctor parse_entry logic to handle a missing or invalid preview_item
result without assert, mirroring the native branch’s fallback behavior by
returning the “No preview available” content when preview_item returns nil/false
or lacks buf/pos, and keep the existing reverse_lookup/items flow intact.
- Around line 194-207: The preview command built in the UI select fallback
interpolates tmpfile directly, which breaks paths containing spaces and uses a
Unix-only stderr redirect. Update the command assembly in this preview builder
to properly shell-escape tmpfile for both the bat and fallback cat/type
commands, and switch the redirection target to NUL when utils.__IS_WINDOWS is
true while keeping the existing filetype-based language handling intact.
- Around line 184-224: The native preview path in ui_select.lua reuses a single
tmpfile inside the preview function, which can let an older bat/cat process read
newer content when fzf keeps previews alive. Update the preview handling in
opts.preview.fn to use a per-invocation temp file or stream the buffer content
via stdin instead of the shared tmpfile, and keep the cleanup in
opts.winopts.on_close consistent with the new per-preview lifecycle.

---

Outside diff comments:
In `@lua/fzf-lua/profiles/fzf-tmux.lua`:
- Around line 14-22: The preview border callback in fzf-tmux currently
hard-asserts that m.type is "fzf", but this function is also used by manpages,
helptags, undotree, and lsp.code_actions where m.type can be "nvim". Update the
border function to match the behavior in fzf-native.lua by removing the assert
and keeping the border selection logic based on FzfLua.utils.has(m.opts, "fzf",
{ 0, 63 }), so the callback works for both metadata paths.

---

Nitpick comments:
In `@tests/ui_select_spec.lua`:
- Around line 100-149: Add a regression test in ui_select spec for the
non-native buffer preview path where preview_item returns nil, since the current
async test only covers a non-nil empty table. Use the existing
T["ui_select"]["async preview_item opens without crash"] pattern with
open_picker/register/reload and target the buffer backend, then assert the
picker stays alive and does not crash; this should cover the assert() failure
risk in providers/ui_select.lua within the preview_item handling logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cdcf4253-924e-4c5c-9084-8858b62f763e

📥 Commits

Reviewing files that changed from the base of the PR and between 09880d5 and 4b17264.

📒 Files selected for processing (5)
  • lua/fzf-lua/defaults.lua
  • lua/fzf-lua/profiles/fzf-native.lua
  • lua/fzf-lua/profiles/fzf-tmux.lua
  • lua/fzf-lua/providers/ui_select.lua
  • tests/ui_select_spec.lua

Comment thread lua/fzf-lua/defaults.lua
Comment thread lua/fzf-lua/providers/ui_select.lua
Comment thread lua/fzf-lua/providers/ui_select.lua
Comment thread lua/fzf-lua/providers/ui_select.lua
Comment thread lua/fzf-lua/providers/ui_select.lua Outdated
Comment thread lua/fzf-lua/providers/ui_select.lua
@phanen phanen force-pushed the fix/ui_select branch 3 times, most recently from 37621d4 to d2a8395 Compare July 3, 2026 14:48
@phanen phanen merged commit 4a602e1 into main Jul 3, 2026
10 checks passed
@ibhagwan

ibhagwan commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Tysm for this wonderful addition @phanen !

@phanen phanen deleted the fix/ui_select branch July 4, 2026 07:34
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.

Bug: fzf-tmux profile errors with builtin previewer / vim.ui.select preview_item

2 participants