diff options
| author | Junegunn Choi <junegunn.c@gmail.com> | 2025-06-10 00:26:57 +0900 |
|---|---|---|
| committer | Junegunn Choi <junegunn.c@gmail.com> | 2025-06-10 23:02:23 +0900 |
| commit | 3b68dcdd81394f1ac9f743e1f74ff754f95eef9e (patch) | |
| tree | e4856fba0fee27eb1ae98ca15844ec04bf60ff5a /src/options.go | |
| parent | 39db02616158020b180a56dc8f1bdcf9f8365945 (diff) | |
| download | fzf-3b68dcdd81394f1ac9f743e1f74ff754f95eef9e.tar.gz | |
Add footer
Options:
--footer=STR String to print as footer
--footer-border[=STYLE] Draw border around the footer section
[rounded|sharp|bold|block|thinblock|double|horizontal|vertical|
top|bottom|left|right|line|none] (default: line)
--footer-label=LABEL Label to print on the footer border
--footer-label-pos=COL Position of the footer label
[POSITIVE_INTEGER: columns from left|
NEGATIVE_INTEGER: columns from right][:bottom]
(default: 0 or center)
The default border type for footer is 'line', which draws a single
separator between the footer and the list. It changes its position
depending on `--layout`, so you don't have to manually switch between
'top' and 'bottom'
The 'line' style is now supported by other border types as well.
`--list-border` is the only exception.
Diffstat (limited to 'src/options.go')
| -rw-r--r-- | src/options.go | 108 |
1 files changed, 92 insertions, 16 deletions
diff --git a/src/options.go b/src/options.go index 142179e5..2fd6f821 100644 --- a/src/options.go +++ b/src/options.go @@ -83,7 +83,7 @@ Usage: fzf [options] --padding=PADDING Padding inside border (TRBL | TB,RL | T,RL,B | T,R,B,L) --border[=STYLE] Draw border around the finder [rounded|sharp|bold|block|thinblock|double|horizontal|vertical| - top|bottom|left|right|none] (default: rounded) + top|bottom|left|right|line|none] (default: rounded) --border-label=LABEL Label to print on the border --border-label-pos=COL Position of the border label [POSITIVE_INTEGER: columns from left| @@ -140,7 +140,7 @@ Usage: fzf [options] --filepath-word Make word-wise movements respect path separators --input-border[=STYLE] Draw border around the input section [rounded|sharp|bold|block|thinblock|double|horizontal|vertical| - top|bottom|left|right|none] (default: rounded) + top|bottom|left|right|line|none] (default: rounded) --input-label=LABEL Label to print on the input border --input-label-pos=COL Position of the input label [POSITIVE_INTEGER: columns from left| @@ -168,7 +168,7 @@ Usage: fzf [options] --header-first Print header before the prompt line --header-border[=STYLE] Draw border around the header section [rounded|sharp|bold|block|thinblock|double|horizontal|vertical| - top|bottom|left|right|none] (default: rounded) + top|bottom|left|right|line|none] (default: rounded) --header-lines-border[=STYLE] Display header from --header-lines with a separate border. Pass 'none' to still separate it but without a border. @@ -178,6 +178,17 @@ Usage: fzf [options] NEGATIVE_INTEGER: columns from right][:bottom] (default: 0 or center) + FOOTER + --footer=STR String to print as footer + --footer-border[=STYLE] Draw border around the footer section + [rounded|sharp|bold|block|thinblock|double|horizontal|vertical| + top|bottom|left|right|line|none] (default: line) + --footer-label=LABEL Label to print on the footer border + --footer-label-pos=COL Position of the footer label + [POSITIVE_INTEGER: columns from left| + NEGATIVE_INTEGER: columns from right][:bottom] + (default: 0 or center) + SCRIPTING -q, --query=STR Start the finder with the given query -1, --select-1 Automatically select the only match @@ -599,6 +610,7 @@ type Options struct { Header []string HeaderLines int HeaderFirst bool + Footer []string Gap int GapLine *string Ellipsis *string @@ -610,8 +622,10 @@ type Options struct { InputBorderShape tui.BorderShape HeaderBorderShape tui.BorderShape HeaderLinesShape tui.BorderShape + FooterBorderShape tui.BorderShape InputLabel labelOpts HeaderLabel labelOpts + FooterLabel labelOpts BorderLabel labelOpts ListLabel labelOpts PreviewLabel labelOpts @@ -716,6 +730,7 @@ func defaultOptions() *Options { Header: make([]string, 0), HeaderLines: 0, HeaderFirst: false, + Footer: make([]string, 0), Gap: 0, Ellipsis: nil, Scrollbar: nil, @@ -880,12 +895,9 @@ func parseAlgo(str string) (algo.Algo, error) { return nil, errors.New("invalid algorithm (expected: v1 or v2)") } -func parseBorder(str string, optional bool, allowLine bool) (tui.BorderShape, error) { +func parseBorder(str string, optional bool) (tui.BorderShape, error) { switch str { case "line": - if !allowLine { - return tui.BorderNone, errors.New("'line' is only allowed for preview border") - } return tui.BorderLine, nil case "rounded": return tui.BorderRounded, nil @@ -1348,6 +1360,10 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) (*tui.ColorTheme, erro mergeAttr(&theme.HeaderBorder) case "header-label": mergeAttr(&theme.HeaderLabel) + case "footer-border": + mergeAttr(&theme.FooterBorder) + case "footer-label": + mergeAttr(&theme.FooterLabel) case "spinner": mergeAttr(&theme.Spinner) case "info": @@ -1360,6 +1376,10 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) (*tui.ColorTheme, erro mergeAttr(&theme.Header) case "header-bg": mergeAttr(&theme.HeaderBg) + case "footer", "footer-fg": + mergeAttr(&theme.Footer) + case "footer-bg": + mergeAttr(&theme.FooterBg) case "gap-line": mergeAttr(&theme.GapLine) default: @@ -1415,7 +1435,7 @@ const ( func init() { executeRegexp = regexp.MustCompile( - `(?si)[:+](become|execute(?:-multi|-silent)?|reload(?:-sync)?|preview|(?:change|transform)-(?:query|prompt|(?:border|list|preview|input|header)-label|header|search|nth|pointer|ghost)|transform|change-(?:preview-window|preview|multi)|(?:re|un|toggle-)bind|pos|put|print|search)`) + `(?si)[:+](become|execute(?:-multi|-silent)?|reload(?:-sync)?|preview|(?:change|transform)-(?:query|prompt|(?:border|list|preview|input|header|footer)-label|header|footer|search|nth|pointer|ghost)|transform|change-(?:preview-window|preview|multi)|(?:re|un|toggle-)bind|pos|put|print|search)`) splitRegexp = regexp.MustCompile("[,:]+") actionNameRegexp = regexp.MustCompile("(?i)^[a-z-]+") } @@ -1800,6 +1820,8 @@ func isExecuteAction(str string) actionType { return actPreview case "change-header": return actChangeHeader + case "change-footer": + return actChangeFooter case "change-list-label": return actChangeListLabel case "change-border-label": @@ -1810,6 +1832,8 @@ func isExecuteAction(str string) actionType { return actChangeInputLabel case "change-header-label": return actChangeHeaderLabel + case "change-footer-label": + return actChangeFooterLabel case "change-ghost": return actChangeGhost case "change-pointer": @@ -1850,6 +1874,10 @@ func isExecuteAction(str string) actionType { return actTransformInputLabel case "transform-header-label": return actTransformHeaderLabel + case "transform-footer-label": + return actTransformFooterLabel + case "transform-footer": + return actTransformFooter case "transform-header": return actTransformHeader case "transform-ghost": @@ -2729,6 +2757,14 @@ func parseOptions(index *int, opts *Options, allArgs []string) error { if opts.HeaderLines, err = nextInt("number of header lines required"); err != nil { return err } + case "--no-footer": + opts.Footer = []string{} + case "--footer": + str, err := nextString("footer string required") + if err != nil { + return err + } + opts.Footer = strLines(str) case "--header-first": opts.HeaderFirst = true case "--no-header-first": @@ -2773,7 +2809,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error { opts.Preview.border = tui.BorderNone case "--preview-border": hasArg, arg := optionalNextString() - if opts.Preview.border, err = parseBorder(arg, !hasArg, true); err != nil { + if opts.Preview.border, err = parseBorder(arg, !hasArg); err != nil { return err } case "--height": @@ -2812,14 +2848,17 @@ func parseOptions(index *int, opts *Options, allArgs []string) error { opts.BorderShape = tui.BorderNone case "--border": hasArg, arg := optionalNextString() - if opts.BorderShape, err = parseBorder(arg, !hasArg, false); err != nil { + if opts.BorderShape, err = parseBorder(arg, !hasArg); err != nil { return err } case "--list-border": hasArg, arg := optionalNextString() - if opts.ListBorderShape, err = parseBorder(arg, !hasArg, false); err != nil { + if opts.ListBorderShape, err = parseBorder(arg, !hasArg); err != nil { return err } + if opts.ListBorderShape == tui.BorderLine { + return errors.New("list border cannot be 'line'") + } case "--no-list-border": opts.ListBorderShape = tui.BorderNone case "--no-list-label": @@ -2841,14 +2880,14 @@ func parseOptions(index *int, opts *Options, allArgs []string) error { opts.HeaderBorderShape = tui.BorderNone case "--header-border": hasArg, arg := optionalNextString() - if opts.HeaderBorderShape, err = parseBorder(arg, !hasArg, false); err != nil { + if opts.HeaderBorderShape, err = parseBorder(arg, !hasArg); err != nil { return err } case "--no-header-lines-border": opts.HeaderLinesShape = tui.BorderNone case "--header-lines-border": hasArg, arg := optionalNextString() - if opts.HeaderLinesShape, err = parseBorder(arg, !hasArg, false); err != nil { + if opts.HeaderLinesShape, err = parseBorder(arg, !hasArg); err != nil { return err } case "--no-header-label": @@ -2865,11 +2904,32 @@ func parseOptions(index *int, opts *Options, allArgs []string) error { if err := parseLabelPosition(&opts.HeaderLabel, pos); err != nil { return err } + case "--no-footer-border": + opts.FooterBorderShape = tui.BorderNone + case "--footer-border": + hasArg, arg := optionalNextString() + if opts.FooterBorderShape, err = parseBorder(arg, !hasArg); err != nil { + return err + } + case "--no-footer-label": + opts.FooterLabel.label = "" + case "--footer-label": + if opts.FooterLabel.label, err = nextString("footer label required"); err != nil { + return err + } + case "--footer-label-pos": + pos, err := nextString("footer label position required (positive or negative integer or 'center')") + if err != nil { + return err + } + if err := parseLabelPosition(&opts.FooterLabel, pos); err != nil { + return err + } case "--no-input-border": opts.InputBorderShape = tui.BorderNone case "--input-border": hasArg, arg := optionalNextString() - if opts.InputBorderShape, err = parseBorder(arg, !hasArg, false); err != nil { + if opts.InputBorderShape, err = parseBorder(arg, !hasArg); err != nil { return err } case "--no-input-label": @@ -3077,6 +3137,7 @@ func applyPreset(opts *Options, preset string) error { opts.ListBorderShape = tui.BorderUndefined opts.InputBorderShape = tui.BorderUndefined opts.HeaderBorderShape = tui.BorderUndefined + opts.FooterBorderShape = tui.BorderUndefined opts.Preview.border = defaultBorderShape opts.Preview.info = true opts.InfoStyle = infoDefault @@ -3088,6 +3149,7 @@ func applyPreset(opts *Options, preset string) error { opts.ListBorderShape = tui.BorderUndefined opts.InputBorderShape = tui.BorderUndefined opts.HeaderBorderShape = tui.BorderUndefined + opts.FooterBorderShape = tui.BorderLine opts.Preview.border = tui.BorderLine opts.Preview.info = false opts.InfoStyle = infoDefault @@ -3103,16 +3165,22 @@ func applyPreset(opts *Options, preset string) error { } if len(tokens) == 2 && len(tokens[1]) > 0 { var err error - defaultBorderShape, err = parseBorder(tokens[1], false, false) + defaultBorderShape, err = parseBorder(tokens[1], false) if err != nil { return err } } - opts.ListBorderShape = defaultBorderShape + if defaultBorderShape != tui.BorderLine { + opts.ListBorderShape = defaultBorderShape + } opts.InputBorderShape = defaultBorderShape opts.HeaderBorderShape = defaultBorderShape + opts.FooterBorderShape = defaultBorderShape opts.Preview.border = defaultBorderShape + if defaultBorderShape == tui.BorderLine { + opts.BorderShape = defaultBorderShape + } opts.Preview.info = true opts.InfoStyle = infoInlineRight opts.Theme.Gutter = tui.NewColorAttr() @@ -3185,6 +3253,10 @@ func noSeparatorLine(style infoStyle, separator bool) bool { return false } +func (opts *Options) useTmux() bool { + return opts.Tmux != nil && len(os.Getenv("TMUX")) > 0 && opts.Tmux.index >= opts.Height.index +} + func (opts *Options) noSeparatorLine() bool { if opts.Inputless { return true @@ -3216,6 +3288,10 @@ func postProcessOptions(opts *Options) error { opts.HeaderBorderShape = tui.BorderNone } + if opts.FooterBorderShape == tui.BorderUndefined { + opts.FooterBorderShape = tui.BorderLine + } + if opts.HeaderLinesShape == tui.BorderNone { opts.HeaderLinesShape = tui.BorderPhantom } |
