diff --git a/CHANGELOG.md b/CHANGELOG.md index e33d4706..4cf6121e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ CHANGELOG ```sh fzf --popup --border-label ' fzf ' ``` +- On Zellij, `--popup` uses the native border by default, consistent with tmux, so that the pane can be moved and resized with the mouse; fzf draws its own border when a border style is explicitly specified with `--border` + - `--border-label` is set as the name of the pane, displayed on the native border - Added `result-final` event, a variant of `result` that is not triggered while the input stream is still open (#4835) - Use it for one-shot, per-query actions that would otherwise re-fire on every intermediate snapshot during loading ```sh diff --git a/man/man1/fzf.1 b/man/man1/fzf.1 index 17f04fd5..481c9c17 100644 --- a/man/man1/fzf.1 +++ b/man/man1/fzf.1 @@ -422,19 +422,20 @@ Start fzf in a tmux or Zellij floating pane (default \fBcenter,50%\fR). Requires tmux 3.3+ or Zellij 0.44+. This option is ignored if you are not running fzf inside tmux or Zellij. \fB\-\-tmux\fR is an alias for this option. -On tmux 3.7 or above, the floating pane is not modal; you can switch to -other panes and windows while fzf is running, move and resize the pane with -the mouse, zoom it to fullscreen, and use copy\-mode in it. The pane always -has a native border, which is what makes it movable and resizable, so -\fBborder\-native\fR is implied. \fB\-\-border\-label\fR is set as the title -of the pane, and is displayed on the border if \fBpane\-border\-status\fR -is enabled in tmux (\fB\-\-border\-label\-pos\fR is ignored). +On tmux 3.7 or above and on Zellij, the floating pane is not modal; you can +switch to other panes and windows while fzf is running, and move and resize +the pane with the mouse. The native border of the pane is the handle for +moving and resizing it, so it is used by default and \fBborder\-native\fR is +implied. On tmux, \fB\-\-border\-label\fR is set as the title of the pane, +and is displayed on the border if \fBpane\-border\-status\fR is enabled in +tmux (\fB\-\-border\-label\-pos\fR is ignored). -A modal tmux popup is used instead on tmux versions below 3.7, or when a -border style is explicitly specified with \fB\-\-border\fR, so that the -fzf\-drawn border is the only border shown. \fBnone\fR and \fBline\fR are -treated as no border. Give \fBborder\-native\fR to -force a floating pane nonetheless. +fzf draws its own border instead when a border style is explicitly specified +with \fB\-\-border\fR, so that it is the only border shown. \fBnone\fR and +\fBline\fR are treated as no border. Give \fBborder\-native\fR to keep the +native border nonetheless. On tmux, the fzf\-drawn border is shown in a modal +popup, since the native border of a tmux floating pane cannot be removed; +this is also the case on tmux versions below 3.7. e.g. \fB# Popup in the center with 70% width and height diff --git a/src/tmux.go b/src/tmux.go index 586d4e49..7c5c8b2c 100644 --- a/src/tmux.go +++ b/src/tmux.go @@ -183,17 +183,24 @@ exit "$code"`, newPane, code, signal, signal, code, code, code) }, opts, true) } +// Whether to use the multiplexer's native border for the floating pane. Its +// native border is the handle that makes the pane movable and resizable with +// the mouse, so it is the default; 'border-native' forces it. It is not used +// when a border style is explicitly specified with --border, so that the +// fzf-drawn border is the only one shown. 'none' and 'line' are treated as no +// border; fzf draws no box for either, and 'line' only makes sense with +// --height. +func nativeBorder(opts *Options) bool { + return opts.Tmux.border || opts.BorderShape == tui.BorderUndefined || + opts.BorderShape == tui.BorderLine || opts.BorderShape == tui.BorderNone +} + func runTmux(args []string, opts *Options) (int, error) { // On tmux 3.7 or above, fzf runs in a floating pane instead of a popup. - // A floating pane always has a native border, so 'border-native' is - // implied. When a border style is explicitly specified with --border, a + // When the native border is not used (an explicit --border style), a // popup is used instead so that the fzf-drawn border is the only border - // shown; the native border of a floating pane cannot be removed. 'none' - // and 'line' are treated as no border; fzf draws no box for either, and - // 'line' only makes sense with --height. Give 'border-native' to force - // a floating pane nonetheless. - if opts.Tmux.border || opts.BorderShape == tui.BorderUndefined || - opts.BorderShape == tui.BorderLine || opts.BorderShape == tui.BorderNone { + // shown; the native border of a tmux floating pane cannot be removed. + if nativeBorder(opts) { if windowWidth, windowHeight, ok := tmuxFloatingPaneInfo(); ok { opts.Tmux.border = true argStr, dir := popupArgStr(args, opts) diff --git a/src/zellij.go b/src/zellij.go index dce9dd40..f9e2bb92 100644 --- a/src/zellij.go +++ b/src/zellij.go @@ -2,9 +2,18 @@ package fzf import ( "os/exec" + + "github.com/junegunn/fzf/src/tui" ) func runZellij(args []string, opts *Options) (int, error) { + // Use the native Zellij border by default, consistent with tmux, so that + // the pane can be moved and resized with the mouse. Set before + // popupArgStr so that it does not inject an fzf border. fzf draws its own + // border instead when a border style is explicitly specified. + if nativeBorder(opts) { + opts.Tmux.border = true + } argStr, dir := popupArgStr(args, opts) zellijArgs := []string{ @@ -13,6 +22,22 @@ func runZellij(args []string, opts *Options) (int, error) { } if !opts.Tmux.border { zellijArgs = append(zellijArgs, "--borderless", "true") + } else { + // Set --border-label as the name of the pane, displayed on the + // native border. The label is left to fzf when it draws its own + // border with the label on it (border-native with an explicit + // --border style). Empty otherwise, to override the default name + // (the running command). Passed as a single argument in the + // --name=label form; the detached form fails to parse when the + // label starts with a hyphen. No escaping is needed beyond + // stripping ANSI sequences fzf would otherwise render itself. + // --border-label-pos is ignored. + label := "" + if opts.BorderShape == tui.BorderUndefined || opts.BorderShape == tui.BorderLine || + opts.BorderShape == tui.BorderNone { + label, _, _ = extractColor(opts.BorderLabel.label, nil, nil) + } + zellijArgs = append(zellijArgs, "--name="+label) } switch opts.Tmux.position { case posUp: