From 51c207448da6eb1cea3352d72c2d22682f604b6d Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Mon, 27 Jan 2025 20:33:47 +0900 Subject: [PATCH] Set the default value of --min-height depending on other options --- ADVANCED.md | 2 +- src/options.go | 50 +++++++++++++++++++++++++++++++++++++++++++++++-- src/terminal.go | 12 +----------- 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/ADVANCED.md b/ADVANCED.md index 71ee15ae..012fb62b 100644 --- a/ADVANCED.md +++ b/ADVANCED.md @@ -93,7 +93,7 @@ fzf --height=40% --layout=reverse --info=inline --border --margin=1 --padding=1 ![image](https://user-images.githubusercontent.com/700826/113379932-dfeac200-93b5-11eb-9e28-df1a2ee71f90.png) -*(See `Layout` section of the man page to see the full list of options)* +*(See man page to see the full list of options)* But you definitely don't want to repeat `--height=40% --layout=reverse --info=inline --border --margin=1 --padding=1` every time you use fzf. You diff --git a/src/options.go b/src/options.go index 79a70825..9c0bd2ed 100644 --- a/src/options.go +++ b/src/options.go @@ -70,7 +70,7 @@ Usage: fzf [options] If prefixed with '~', fzf will determine the height according to the input size. --min-height=HEIGHT Minimum height for percent --height is given in percent - (default: 10) + (default: 10 or above depending on the other options) --tmux[=OPTS] Start fzf in a tmux popup (requires tmux 3.3+) [center|top|bottom|left|right][,SIZE[%]][,SIZE[%]] [,border-native] (default: center,50%) @@ -673,7 +673,7 @@ func defaultOptions() *Options { Theme: theme, Black: false, Bold: true, - MinHeight: 10, + MinHeight: -1, Layout: layoutDefault, Cycle: false, Wrap: false, @@ -3038,6 +3038,21 @@ func validateOptions(opts *Options) error { return nil } +func noSeparatorLine(style infoStyle, separator bool) bool { + switch style { + case infoInline: + return true + case infoHidden, infoInlineRight: + return !separator + } + return false +} + +func (opts *Options) noSeparatorLine() bool { + sep := opts.Separator == nil && !opts.InputBorderShape.Visible() || opts.Separator != nil && len(*opts.Separator) > 0 + return noSeparatorLine(opts.InfoStyle, sep) +} + // This function can have side-effects and alter some global states. // So we run it on fzf.Run and not on ParseOptions. func postProcessOptions(opts *Options) error { @@ -3203,6 +3218,37 @@ func postProcessOptions(opts *Options) error { opts.Height = heightSpec{} } + // Sets --min-height automatically + if opts.Height.size > 0 && opts.Height.percent && opts.MinHeight < 0 { + // 10 items and 1 prompt line + opts.MinHeight = 10 + 1 + borderLines(opts.BorderShape) + borderLines(opts.ListBorderShape) + borderLines(opts.InputBorderShape) + if len(opts.Header) > 0 { + opts.MinHeight += borderLines(opts.HeaderBorderShape) + len(opts.Header) + } + if opts.HeaderLines > 0 { + borderShape := opts.HeaderBorderShape + if opts.HeaderLinesShape.Visible() { + borderShape = opts.HeaderLinesShape + } + opts.MinHeight += borderLines(borderShape) + opts.HeaderLines + } + if !opts.noSeparatorLine() { + opts.MinHeight++ + } + if len(opts.Preview.command) > 0 && (opts.Preview.position == posUp || opts.Preview.position == posDown) && opts.Preview.Visible() && opts.Preview.position == posUp { + borderShape := opts.Preview.border + if opts.Preview.border == tui.BorderLine { + borderShape = tui.BorderTop + } + opts.MinHeight += borderLines(borderShape) + 10 + } + for _, s := range []sizeSpec{opts.Margin[0], opts.Margin[2], opts.Padding[0], opts.Padding[2]} { + if !s.percent { + opts.MinHeight += int(s.size) + } + } + } + if err := opts.initProfiling(); err != nil { return errors.New("failed to start pprof profiles: " + err.Error()) } diff --git a/src/terminal.go b/src/terminal.go index af6c8a8c..da3b863c 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -799,7 +799,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor if previewBox != nil && opts.Preview.aboveOrBelow() { effectiveMinHeight += 1 + borderLines(opts.Preview.Border()) } - if noSeparatorLine(opts.InfoStyle, opts.Separator == nil || uniseg.StringWidth(*opts.Separator) > 0) { + if opts.noSeparatorLine() { effectiveMinHeight-- } effectiveMinHeight += borderLines(opts.BorderShape) @@ -1264,16 +1264,6 @@ func (t *Terminal) parsePrompt(prompt string) (func(), int) { return output, promptLen } -func noSeparatorLine(style infoStyle, separator bool) bool { - switch style { - case infoInline: - return true - case infoHidden, infoInlineRight: - return !separator - } - return false -} - func (t *Terminal) noSeparatorLine() bool { return noSeparatorLine(t.infoStyle, t.separatorLen > 0) }