From fb16c09fbefcb8b2fd29c5e9aa27a0f7c80ebfcc Mon Sep 17 00:00:00 2001 From: Andreas Auernhammer Date: Fri, 3 Jan 2025 16:06:33 +0100 Subject: [PATCH 1/7] add `border-native` option to `--tmux` flag This commit adds the `border-native` resulting in the following: ``` --tmux[=[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]][,border-native]] ``` By default, when not specified, the `-B` flag is passed to the `tmux popup-window` command such that no border is drawn around the tmux popup window. When the `border-native` option is present the `-B` flag is omitted and the popup window is drawn using the border style configured in the tmux config file. Fixes #4156 Signed-off-by: Andreas Auernhammer --- ADVANCED.md | 2 +- README.md | 2 +- man/man1/fzf.1 | 8 ++++++-- src/options.go | 26 ++++++++++++++++++++------ src/tmux.go | 5 ++++- 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/ADVANCED.md b/ADVANCED.md index b152d5a67ee..bafe9708fac 100644 --- a/ADVANCED.md +++ b/ADVANCED.md @@ -128,7 +128,7 @@ fzf --height 70% --tmux 70% You can also specify the position, width, and height of the popup window in the following format: -* `[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]]` +* `[center|top|bottom|left|right][,SIZE[%]][,SIZE[%][,border-native]]` ```sh # 100% width and 60% height diff --git a/README.md b/README.md index 1172d12ff75..0faa552e51f 100644 --- a/README.md +++ b/README.md @@ -343,7 +343,7 @@ fzf --height -3 With `--tmux` option, fzf will start in a tmux popup. ```sh -# --tmux [center|top|bottom|left|right][,SIZE[%]][,SIZE[%]] +# --tmux [center|top|bottom|left|right][,SIZE[%]][,SIZE[%][,border-native]] fzf --tmux center # Center, 50% width and height fzf --tmux 80% # Center, 80% width and height diff --git a/man/man1/fzf.1 b/man/man1/fzf.1 index 28d27f181ff..87ddf134134 100644 --- a/man/man1/fzf.1 +++ b/man/man1/fzf.1 @@ -271,7 +271,7 @@ Adaptive height has the following limitations: Minimum height when \fB\-\-height\fR is given in percent (default: 10). Ignored when \fB\-\-height\fR is not specified. .TP -.BI "\-\-tmux" "[=[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]]]" +.BI "\-\-tmux" "[=[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]][,border-native]]" Start fzf in a tmux popup (default \fBcenter,50%\fR). Requires tmux 3.3 or later. This option is ignored if you are not running fzf inside tmux. @@ -286,7 +286,11 @@ e.g. fzf \-\-tmux bottom,30% # Popup on the top with 80% width and 40% height - fzf \-\-tmux top,80%,40%\fR + fzf \-\-tmux top,80%,40% + + # Popup with a native window border in the center + # with 80% width and 50% height. + fzf \-\-tmux center,80%,50%,border-native\fR .TP .BI "\-\-layout=" "LAYOUT" diff --git a/src/options.go b/src/options.go index 0b6250f35e7..d70a5f44d06 100644 --- a/src/options.go +++ b/src/options.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "regexp" + "slices" "strconv" "strings" "unicode" @@ -254,6 +255,7 @@ type tmuxOptions struct { height sizeSpec position windowPosition index int + border bool } type layoutType int @@ -309,15 +311,16 @@ func defaultTmuxOptions(index int) *tmuxOptions { position: posCenter, width: sizeSpec{50, true}, height: sizeSpec{50, true}, - index: index} + index: index, + } } func parseTmuxOptions(arg string, index int) (*tmuxOptions, error) { var err error opts := defaultTmuxOptions(index) tokens := splitRegexp.Split(arg, -1) - errorToReturn := errors.New("invalid tmux option: " + arg + " (expected: [center|top|bottom|left|right][,SIZE[%]][,SIZE[%]])") - if len(tokens) == 0 || len(tokens) > 3 { + errorToReturn := errors.New("invalid tmux option: " + arg + " (expected: [center|top|bottom|left|right][,SIZE[%]][,SIZE[%][,border-native]])") + if len(tokens) == 0 || len(tokens) > 4 { return nil, errorToReturn } @@ -340,6 +343,15 @@ func parseTmuxOptions(arg string, index int) (*tmuxOptions, error) { tokens = append([]string{"center"}, tokens...) } + if i := slices.Index(tokens, "border-native"); i >= 0 { + // The border option, if present, is the last one + if i != len(tokens)-1 { + return nil, errorToReturn + } + tokens = slices.Delete(tokens, i, i+1) + opts.border = true + } + // One size given var size1 sizeSpec if len(tokens) > 1 { @@ -650,7 +662,8 @@ func defaultOptions() *Options { WalkerRoot: []string{"."}, WalkerSkip: []string{".git", "node_modules"}, Help: false, - Version: false} + Version: false, + } } func optString(arg string, prefixes ...string) (bool, string) { @@ -1725,7 +1738,7 @@ func strLines(str string) []string { } func parseSize(str string, maxPercent float64, label string) (sizeSpec, error) { - var spec = sizeSpec{} + spec := sizeSpec{} var val float64 var err error percent := strings.HasSuffix(str, "%") @@ -1811,7 +1824,8 @@ func parseInfoStyle(str string) (infoStyle, string, error) { } for _, spec := range []infoSpec{ {"inline", infoInline}, - {"inline-right", infoInlineRight}} { + {"inline-right", infoInlineRight}, + } { if strings.HasPrefix(str, spec.name+":") { return spec.style, strings.ReplaceAll(str[len(spec.name)+1:], "\n", " "), nil } diff --git a/src/tmux.go b/src/tmux.go index b2315dcd2c3..d8e268d2da1 100644 --- a/src/tmux.go +++ b/src/tmux.go @@ -33,7 +33,10 @@ func runTmux(args []string, opts *Options) (int, error) { // M Both The mouse position // W Both The window position on the status line // S -y The line above or below the status line - tmuxArgs := []string{"display-popup", "-E", "-B", "-d", dir} + tmuxArgs := []string{"display-popup", "-E", "-d", dir} + if !opts.Tmux.border { + tmuxArgs = append(tmuxArgs, "-B") + } switch opts.Tmux.position { case posUp: tmuxArgs = append(tmuxArgs, "-xC", "-y0") From 2939e3894ac9dd575e718ffa8a2815da8956c599 Mon Sep 17 00:00:00 2001 From: Andreas Auernhammer Date: Fri, 3 Jan 2025 17:10:52 +0100 Subject: [PATCH 2/7] review: remove `slices` package due to Go version Signed-off-by: Andreas Auernhammer --- src/options.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/options.go b/src/options.go index d70a5f44d06..09858cae1c1 100644 --- a/src/options.go +++ b/src/options.go @@ -5,7 +5,6 @@ import ( "fmt" "os" "regexp" - "slices" "strconv" "strings" "unicode" @@ -343,13 +342,12 @@ func parseTmuxOptions(arg string, index int) (*tmuxOptions, error) { tokens = append([]string{"center"}, tokens...) } - if i := slices.Index(tokens, "border-native"); i >= 0 { - // The border option, if present, is the last one - if i != len(tokens)-1 { - return nil, errorToReturn + for i, token := range tokens { + if token == "border-native" { + tokens = append(tokens[:i], tokens[i+1:]...) // cut the 'border-native' option + opts.border = true + break } - tokens = slices.Delete(tokens, i, i+1) - opts.border = true } // One size given From f95c318994a601fa3befa1b864a2d12ab92a03f5 Mon Sep 17 00:00:00 2001 From: Andreas Auernhammer Date: Fri, 3 Jan 2025 19:52:04 +0100 Subject: [PATCH 3/7] review: do not auto. set `--border` with native popup border Signed-off-by: Andreas Auernhammer --- src/options.go | 11 ++++------- src/tmux.go | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/options.go b/src/options.go index 09858cae1c1..edfee07f53d 100644 --- a/src/options.go +++ b/src/options.go @@ -310,8 +310,7 @@ func defaultTmuxOptions(index int) *tmuxOptions { position: posCenter, width: sizeSpec{50, true}, height: sizeSpec{50, true}, - index: index, - } + index: index} } func parseTmuxOptions(arg string, index int) (*tmuxOptions, error) { @@ -660,8 +659,7 @@ func defaultOptions() *Options { WalkerRoot: []string{"."}, WalkerSkip: []string{".git", "node_modules"}, Help: false, - Version: false, - } + Version: false} } func optString(arg string, prefixes ...string) (bool, string) { @@ -1736,7 +1734,7 @@ func strLines(str string) []string { } func parseSize(str string, maxPercent float64, label string) (sizeSpec, error) { - spec := sizeSpec{} + var spec = sizeSpec{} var val float64 var err error percent := strings.HasSuffix(str, "%") @@ -1822,8 +1820,7 @@ func parseInfoStyle(str string) (infoStyle, string, error) { } for _, spec := range []infoSpec{ {"inline", infoInline}, - {"inline-right", infoInlineRight}, - } { + {"inline-right", infoInlineRight}} { if strings.HasPrefix(str, spec.name+":") { return spec.style, strings.ReplaceAll(str[len(spec.name)+1:], "\n", " "), nil } diff --git a/src/tmux.go b/src/tmux.go index d8e268d2da1..ff24e81eb0e 100644 --- a/src/tmux.go +++ b/src/tmux.go @@ -11,7 +11,7 @@ func runTmux(args []string, opts *Options) (int, error) { // Prepare arguments fzf := args[0] args = append([]string{"--bind=ctrl-z:ignore"}, args[1:]...) - if opts.BorderShape == tui.BorderUndefined { + if opts.BorderShape == tui.BorderUndefined && !opts.Tmux.border { args = append(args, "--border") } argStr := escapeSingleQuote(fzf) From cbc9a92fdd9c4d5e5359f2abab4cfa9d4b718fc0 Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Sat, 4 Jan 2025 12:10:52 +0900 Subject: [PATCH 4/7] Put 1-column margin on the sides when native border is used For more consistent look --- src/tmux.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/tmux.go b/src/tmux.go index ff24e81eb0e..e459000a265 100644 --- a/src/tmux.go +++ b/src/tmux.go @@ -9,13 +9,16 @@ import ( func runTmux(args []string, opts *Options) (int, error) { // Prepare arguments - fzf := args[0] - args = append([]string{"--bind=ctrl-z:ignore"}, args[1:]...) - if opts.BorderShape == tui.BorderUndefined && !opts.Tmux.border { + fzf, rest := args[0], args[1:] + args = []string{"--bind=ctrl-z:ignore"} + if !opts.Tmux.border && opts.BorderShape == tui.BorderUndefined { args = append(args, "--border") } + if opts.Tmux.border && opts.Margin == defaultMargin() { + args = append(args, "--margin=0,1") + } argStr := escapeSingleQuote(fzf) - for _, arg := range args { + for _, arg := range append(args, rest...) { argStr += " " + escapeSingleQuote(arg) } argStr += ` --no-tmux --no-height` From 5f774bc7d1c4b8b34a29e8151083cb595ed94cbf Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Sat, 4 Jan 2025 18:23:54 +0900 Subject: [PATCH 5/7] Allow border-native at the front --- src/options.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/options.go b/src/options.go index edfee07f53d..4aaae65a7db 100644 --- a/src/options.go +++ b/src/options.go @@ -322,6 +322,14 @@ func parseTmuxOptions(arg string, index int) (*tmuxOptions, error) { return nil, errorToReturn } + for i, token := range tokens { + if token == "border-native" { + tokens = append(tokens[:i], tokens[i+1:]...) // cut the 'border-native' option + opts.border = true + break + } + } + // Defaults to 'center' switch tokens[0] { case "top", "up": @@ -341,14 +349,6 @@ func parseTmuxOptions(arg string, index int) (*tmuxOptions, error) { tokens = append([]string{"center"}, tokens...) } - for i, token := range tokens { - if token == "border-native" { - tokens = append(tokens[:i], tokens[i+1:]...) // cut the 'border-native' option - opts.border = true - break - } - } - // One size given var size1 sizeSpec if len(tokens) > 1 { From c6967f9aae1e939f3c303b53d306e07e2ba3d484 Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Sat, 4 Jan 2025 18:25:45 +0900 Subject: [PATCH 6/7] Update --help output --- src/options.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/options.go b/src/options.go index 4aaae65a7db..a3096d1131b 100644 --- a/src/options.go +++ b/src/options.go @@ -77,7 +77,7 @@ Usage: fzf [options] (default: 10) --tmux[=OPTS] Start fzf in a tmux popup (requires tmux 3.3+) [center|top|bottom|left|right][,SIZE[%]][,SIZE[%]] - (default: center,50%) + [,border-native] (default: center,50%) --layout=LAYOUT Choose layout: [default|reverse|reverse-list] --border[=STYLE] Draw border around the finder [rounded|sharp|bold|block|thinblock|double|horizontal|vertical| From f0ad66bb142b08476e2bf5ec3948eef1ac45ad1c Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Sat, 4 Jan 2025 18:28:41 +0900 Subject: [PATCH 7/7] Update man --- man/man1/fzf.1 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/man/man1/fzf.1 b/man/man1/fzf.1 index 87ddf134134..8d499697c98 100644 --- a/man/man1/fzf.1 +++ b/man/man1/fzf.1 @@ -287,10 +287,9 @@ e.g. # Popup on the top with 80% width and 40% height fzf \-\-tmux top,80%,40% - - # Popup with a native window border in the center - # with 80% width and 50% height. - fzf \-\-tmux center,80%,50%,border-native\fR + + # Popup with a native tmux border in the center with 80% width and height + fzf \-\-tmux center,80%,border\-native\fR .TP .BI "\-\-layout=" "LAYOUT"