mirror of
https://github.com/junegunn/fzf.git
synced 2026-04-22 07:38:05 +08:00
Let inline sections take precedence over --header-first
--header-first previously was rejected with --header-border=inline or --header-lines-border=inline. Now, inline placement wins: an inline section stays inside the list frame, and --header-first only affects non-inline sections (mainly the main --header).
This commit is contained in:
@@ -1107,9 +1107,10 @@ shape that has both top and bottom segments (rounded / sharp / bold /
|
||||
double / block / thinblock / horizontal) and falls back to \fBline\fR
|
||||
otherwise. When the list border also has side segments, the separator
|
||||
joins them with T-junctions; \fBhorizontal\fR has no side borders, so the
|
||||
separator is drawn without T-junction endpoints. Not compatible with
|
||||
\fB\-\-header\-first\fR, and when \fB\-\-header\-lines\fR is also set
|
||||
\fB\-\-header\-lines\-border\fR must also be \fBinline\fR.
|
||||
separator is drawn without T-junction endpoints. Takes precedence over
|
||||
\fB\-\-header\-first\fR (the section stays inside the list frame), and
|
||||
when \fB\-\-header\-lines\fR is also set \fB\-\-header\-lines\-border\fR
|
||||
must also be \fBinline\fR.
|
||||
|
||||
.TP
|
||||
.BI "\-\-header\-label" [=LABEL]
|
||||
@@ -1128,7 +1129,7 @@ a single separator line between the header lines and the list section.
|
||||
\fBinline\fR style embeds the header lines inside the list border frame
|
||||
with a horizontal separator; it requires a \fB\-\-list\-border\fR shape
|
||||
that has both top and bottom segments, falls back to \fBline\fR
|
||||
otherwise, and is not compatible with \fB\-\-header\-first\fR.
|
||||
otherwise.
|
||||
|
||||
.SS FOOTER
|
||||
|
||||
|
||||
@@ -3619,9 +3619,6 @@ func validateOptions(opts *Options) error {
|
||||
opts.Preview.border == tui.BorderInline {
|
||||
return errors.New("inline border is only supported for --header-border, --header-lines-border, and --footer-border")
|
||||
}
|
||||
if opts.HeaderFirst && (opts.HeaderBorderShape == tui.BorderInline || opts.HeaderLinesShape == tui.BorderInline) {
|
||||
return errors.New("--header-first is not compatible with --header-border=inline or --header-lines-border=inline")
|
||||
}
|
||||
if opts.HeaderBorderShape == tui.BorderInline &&
|
||||
opts.HeaderLinesShape != tui.BorderInline &&
|
||||
opts.HeaderLinesShape != tui.BorderUndefined &&
|
||||
|
||||
@@ -2844,7 +2844,11 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
|
||||
if hasInputWindow {
|
||||
var btop int
|
||||
if (hasHeaderWindow || hasHeaderLinesWindow) && t.headerFirst {
|
||||
// Inline sections live inside the list frame, so they don't participate
|
||||
// in --header-first repositioning; only non-inline sections do.
|
||||
hasNonInlineHeader := hasHeaderWindow && t.headerBorderShape != tui.BorderInline
|
||||
hasNonInlineHeaderLines := hasHeaderLinesWindow && headerLinesShape != tui.BorderInline
|
||||
if (hasNonInlineHeader || hasNonInlineHeaderLines) && t.headerFirst {
|
||||
switch t.layout {
|
||||
case layoutDefault:
|
||||
btop = w.Top() + w.Height()
|
||||
|
||||
@@ -1491,6 +1491,42 @@ class TestLayout < TestInteractive
|
||||
tmux.send_keys 'Escape'
|
||||
end
|
||||
|
||||
# Inline takes precedence over --header-first: the main header stays
|
||||
# inside the list frame instead of moving below the input.
|
||||
def test_inline_header_border_overrides_header_first
|
||||
tmux.send_keys %(seq 5 | #{FZF} --style full --header foo --header-first --header-border inline), :Enter
|
||||
tmux.until do |lines|
|
||||
foo_idx = lines.index { |l| l.match?(/\A│\s+foo\s+│\z/) }
|
||||
input_idx = lines.index { |l| l.match?(/\A│\s+>\s+\d+\/\d+\s+│\z/) }
|
||||
foo_idx && input_idx && foo_idx < input_idx
|
||||
end
|
||||
end
|
||||
|
||||
# With both sections present, --header-first still moves the main --header
|
||||
# below the input while --header-lines-border=inline keeps header-lines
|
||||
# inside the list frame.
|
||||
def test_inline_header_lines_with_header_first_and_main_header
|
||||
tmux.send_keys %(seq 5 | #{FZF} --style full --header foo --header-lines 1 --header-first --header-lines-border inline), :Enter
|
||||
tmux.until do |lines|
|
||||
one_idx = lines.index { |l| l.match?(/\A│\s+1\s+│\z/) }
|
||||
foo_idx = lines.index { |l| l.match?(/\A│\s+foo\s+│\z/) }
|
||||
input_idx = lines.index { |l| l.match?(/\A│\s+>\s+\d+\/\d+\s+│\z/) }
|
||||
one_idx && foo_idx && input_idx && one_idx < input_idx && input_idx < foo_idx
|
||||
end
|
||||
end
|
||||
|
||||
# With no main --header, --header-first previously repositioned
|
||||
# header-lines. Inline now takes precedence: header-lines stays inside
|
||||
# the list frame.
|
||||
def test_inline_header_lines_with_header_first_no_main_header
|
||||
tmux.send_keys %(seq 5 | #{FZF} --style full --header-lines 1 --header-first --header-lines-border inline), :Enter
|
||||
tmux.until do |lines|
|
||||
one_idx = lines.index { |l| l.match?(/\A│\s+1\s+│\z/) }
|
||||
input_idx = lines.index { |l| l.match?(/\A│\s+>\s+\d+\/\d+\s+│\z/) }
|
||||
one_idx && input_idx && one_idx < input_idx
|
||||
end
|
||||
end
|
||||
|
||||
# Invalid inline combinations must be rejected at startup.
|
||||
def test_inline_rejected_on_unsupported_options
|
||||
[
|
||||
@@ -1498,8 +1534,6 @@ class TestLayout < TestInteractive
|
||||
['--list-border=inline', 'inline border is only supported'],
|
||||
['--input-border=inline', 'inline border is only supported'],
|
||||
['--preview-window=border-inline --preview :', 'invalid preview window option: border-inline'],
|
||||
['--header-first --header-border=inline', '--header-first is not compatible'],
|
||||
['--header-first --header-lines-border=inline --header-lines=1', '--header-first is not compatible'],
|
||||
['--header-border=inline --header-lines-border=sharp --header-lines=1',
|
||||
'--header-border=inline requires --header-lines-border to be inline or unset']
|
||||
].each do |args, expected|
|
||||
|
||||
Reference in New Issue
Block a user