mirror of
https://github.com/junegunn/fzf.git
synced 2026-04-27 01:40:34 +08:00
Add --header-border=inline / --header-lines-border=inline / --footer-border=inline
Adds a new BorderShape, BorderInline, accepted as a value for
--header-border, --header-lines-border, and --footer-border. When the
surrounding --list-border has both top and bottom horizontals (rounded,
sharp, bold, double, thinblock, block, horizontal), the corresponding
section is rendered inside the list frame separated from the list
content by a horizontal line whose endpoints join the list border as
T-junctions. Without a compatible list border, the shape falls back to
BorderLine.
Supports:
- All three layouts (default, reverse, reverse-list).
- Any combination of the three inline sections, producing stacked
separators.
- --header-label and --footer-label rendered on their separator row.
- Section colors: the portion of the list frame adjacent to an inline
section (left/right verticals on the section's content rows plus the
outer top/bottom edge + corners when the section is at the edge)
inherits the section's --color *-border and *-bg, giving each section
a uniform color block. The separator itself carries the section's
colors since it acts as the section's inner edge.
- When --color header-border / --color footer-border is not set, the
inline section inherits --color list-border so the default palette
stays coherent.
- thinblock / block styles pick the horizontal char (top vs bottom)
based on which side of the list content the separator sits on, so
the thin line visually hugs the list content.
Rejects combinations that do not make sense:
- --input-border=inline / --list-border=inline / --preview-border=inline
- --header-first + (--header-border=inline | --header-lines-border=inline)
- --header-border=inline with a non-inline --header-lines-border
(inline has to propagate inward toward the list content).
This commit is contained in:
@@ -1392,5 +1392,64 @@ class TestLayout < TestInteractive
|
||||
input: "(printf 'Xaa\\nYbb\\nZcc\\n'; seq 5)",
|
||||
clicks: clicks)
|
||||
end
|
||||
|
||||
# Inline header inside a rounded list border.
|
||||
define_method(:"test_click_header_border_inline_#{slug}") do
|
||||
opts = %(--layout=#{layout} --style full --header $'Aaa\\nBbb\\nCcc' )
|
||||
verify_clicks(kind: :header, opts: opts, input: 'seq 5', clicks: HEADER_CLICKS)
|
||||
end
|
||||
|
||||
# Inline header inside a horizontal list border (top+bottom only, no T-junctions).
|
||||
define_method(:"test_click_header_border_inline_horizontal_list_#{slug}") do
|
||||
opts = %(--layout=#{layout} --style full --header $'Aaa\\nBbb\\nCcc' )
|
||||
verify_clicks(kind: :header, opts: opts, input: 'seq 5', clicks: HEADER_CLICKS)
|
||||
end
|
||||
|
||||
# Inline header-lines inside a rounded list border.
|
||||
define_method(:"test_click_header_lines_border_inline_#{slug}") do
|
||||
clicks_hl = if layout == 'default'
|
||||
[%w[Xaa 3], %w[Ybb 2], %w[Zcc 1]]
|
||||
else
|
||||
[%w[Xaa 1], %w[Ybb 2], %w[Zcc 3]]
|
||||
end
|
||||
opts = %(--layout=#{layout} --style full --header-lines 3 )
|
||||
verify_clicks(kind: :header, opts: opts,
|
||||
input: "(printf 'Xaa\\nYbb\\nZcc\\n'; seq 5)",
|
||||
clicks: clicks_hl)
|
||||
end
|
||||
|
||||
# Inline footer inside a rounded list border.
|
||||
define_method(:"test_click_footer_border_inline_#{slug}") do
|
||||
opts = %(--layout=#{layout} --style full --footer $'Foo\\nBar\\nBaz' )
|
||||
verify_clicks(kind: :footer, opts: opts, input: 'seq 5',
|
||||
clicks: [%w[Foo 1], %w[Bar 2], %w[Baz 3]])
|
||||
end
|
||||
end
|
||||
|
||||
# An inline section requesting far more rows than the terminal can fit must not
|
||||
# break the layout. The list frame must still render inside the pane with both
|
||||
# corners visible and the prompt line present.
|
||||
def test_inline_header_lines_oversized
|
||||
tmux.send_keys %(seq 10000 | #{FZF} --style full --header-border inline --header-lines 9999), :Enter
|
||||
tmux.until { |lines| lines.any_include?(%r{ [0-9]+/[0-9]+}) }
|
||||
lines = tmux.capture
|
||||
# Rounded (light) and sharp (tcell) default border glyphs.
|
||||
top_corners = /[╭┌]/
|
||||
bottom_corners = /[╰└]/
|
||||
assert(lines.any? { |l| l.match?(top_corners) }, "list frame top missing: #{lines.inspect}")
|
||||
assert(lines.any? { |l| l.match?(bottom_corners) }, "list frame bottom missing: #{lines.inspect}")
|
||||
assert(lines.any? { |l| l.include?('>') }, "prompt missing: #{lines.inspect}")
|
||||
tmux.send_keys 'Escape'
|
||||
end
|
||||
|
||||
# A non-inline section that consumes all available rows must still render without
|
||||
# crashing when another section is inline but has no budget. The inline section's
|
||||
# content is clipped to 0 but the layout proceeds.
|
||||
def test_inline_footer_starved_by_non_inline_header
|
||||
tmux.send_keys %(seq 10000 | #{FZF} --style full --footer-border inline --footer "$(seq 1000)" --header "$(seq 1000)"), :Enter
|
||||
tmux.until { |lines| lines.any_include?(%r{ [0-9]+/[0-9]+}) }
|
||||
lines = tmux.capture
|
||||
assert(lines.any? { |l| l.include?('>') }, "prompt missing: #{lines.inspect}")
|
||||
tmux.send_keys 'Escape'
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user