mirror of
https://github.com/junegunn/fzf.git
synced 2026-07-11 19:10:50 +08:00
Unlike a popup, a floating pane is not modal; you can switch to other panes and windows while fzf is running, move and resize the pane with the mouse, zoom it to fullscreen, and use copy-mode in it. - Floating pane always has a native border, so 'border-native' is implied; give new 'border-fzf' option to fall back to a popup where fzf draws its own border - Popup is also used on tmux versions below 3.7, or when the window is too small to fit a floating pane - new-pane does not block until the command finishes and does not propagate the exit status; block on a wait-for channel signaled by the pane and pass the exit status through a temporary file - Watchdog process signals the channel when the pane is closed abnormally (e.g. kill-pane) - Kill the pane when the proxy process is interrupted, like a popup dying with its client - Unzoom the window before creating the floating pane; doing so over a zoomed window crashes the tmux server on 3.7b, and newer versions of tmux unzoom the window anyway - Floating pane size excludes the border and the position is that of the content area; treat the requested size as the total footprint including the border for consistency with popups - Close the pane on exit even when remain-on-exit is on - Pre-create the exit status file with O_EXCL to prevent tampering on a shared TMPDIR
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'shellwords'
|
||||
require 'tmpdir'
|
||||
require_relative 'lib/common'
|
||||
|
||||
# Tests for running fzf in a tmux floating pane (--popup on tmux 3.7 or above)
|
||||
class TestTmux < TestInteractive
|
||||
def setup
|
||||
super
|
||||
# Cannot rely on the exit status; tmux versions before 3.7 exit
|
||||
# normally with empty output for an unknown command name
|
||||
supported = IO.popen(%w[tmux list-commands new-pane], err: File::NULL, &:read).include?('new-pane')
|
||||
skip('floating panes not supported') unless supported
|
||||
end
|
||||
|
||||
def test_floating_pane
|
||||
tmux.send_keys "seq 100 | #{fzf('--popup center,80% --margin 0')}", :Enter
|
||||
tmux.until { |lines| assert_equal 100, lines.item_count }
|
||||
tmux.send_keys '99'
|
||||
tmux.until { |lines| assert_equal 1, lines.match_count }
|
||||
tmux.send_keys :Enter
|
||||
assert_equal '99', fzf_output
|
||||
end
|
||||
|
||||
def test_floating_pane_killed
|
||||
tmux.send_keys "seq 100 | #{FZF} --popup bottom,50% --margin 0; echo code:$?", :Enter
|
||||
tmux.until { |lines| assert_equal 100, lines.item_count }
|
||||
pane = floating_pane
|
||||
refute_nil pane
|
||||
assert system('tmux', 'kill-pane', '-t', pane)
|
||||
tmux.until { |lines| assert lines.any_include?('code:130') }
|
||||
end
|
||||
|
||||
def test_border_fzf_falls_back_to_popup
|
||||
# display-popup requires an attached client, which the test environment
|
||||
# may not have; intercept it with a tmux shim on PATH
|
||||
dir = Dir.mktmpdir
|
||||
real = `command -v tmux`.chomp
|
||||
shim = File.join(dir, 'tmux')
|
||||
File.write(shim, <<~SH)
|
||||
#!/bin/sh
|
||||
if [ "$1" = display-popup ]; then
|
||||
echo popup-used >&2
|
||||
exit 0
|
||||
fi
|
||||
exec #{real.shellescape} "$@"
|
||||
SH
|
||||
FileUtils.chmod(0o755, shim)
|
||||
tmux.send_keys "seq 100 | PATH=#{dir.shellescape}:$PATH #{FZF} --popup center,border-fzf", :Enter
|
||||
tmux.until { |lines| assert lines.any_include?('popup-used') }
|
||||
refute floating_pane
|
||||
ensure
|
||||
FileUtils.remove_entry(dir) if dir
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def floating_pane
|
||||
format = "\#{pane_id} \#{pane_floating_flag}"
|
||||
lines = IO.popen(['tmux', 'list-panes', '-t', tmux.win, '-F', format]) { |io| io.readlines(chomp: true) }
|
||||
lines.filter_map { |line| line.split.first if line.end_with?(' 1') }.first
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user