Files
junegunn--fzf/src/zellij.go
T
Junegunn Choi 50e6c026ec Separate floating pane border label from pane title
--border-label of a tmux floating pane was stored in the pane title and
read back by pane-border-format as '#{pane_title}', so any program in the
pane could replace the border text by setting the title. On Zellij the
name was only set when the pane was created. Either way the built-in
label actions could not touch it, as fzf draws no border of its own
there.

- tmux: hold the label in pane-scoped @fzf-border-label. Set the option
  even without a label, so a later change-border-label has somewhere to
  write. Drop select-pane -T; the pane title is left to the user
- Zellij: run 'zellij action rename-pane' on label change. 'zellij run'
  has no option to set the environment of the new pane, so the command
  exports the target itself
- change-border-label and transform-border-label now update the native
  border, through the setter nativeLabelSetter picks by multiplexer
- The pane is named in a __FZF_INTERNAL_ variable that runProxy withholds
  from the environment replay, so the same name in the outer environment
  cannot redirect the update to another pane
2026-07-29 20:59:52 +09:00

84 lines
2.9 KiB
Go

package fzf
import (
"fmt"
"os/exec"
)
const zellijBorderLabelEnv = internalEnvPrefix + "ZELLIJ_LABEL_PANE"
// Errors are ignored. The pane may be gone
func setZellijBorderLabel(pane string, label string) {
// Strip ANSI sequences fzf would otherwise render itself
label, _, _ = extractColor(label, nil, nil)
// '--' so that a label starting with a hyphen is not parsed as a flag
exec.Command("zellij", "action", "rename-pane", "-p", pane, "--", label).Run()
}
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{
"run", "--floating", "--close-on-exit", "--block-until-exit",
"--cwd", dir,
}
ownsLabel := false
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 := ""
ownsLabel = noBorderSpecified(opts)
if ownsLabel {
label, _, _ = extractColor(opts.BorderLabel.label, nil, nil)
}
zellijArgs = append(zellijArgs, "--name="+label)
}
switch opts.Tmux.position {
case posUp:
zellijArgs = append(zellijArgs, "-y", "0")
case posDown:
zellijArgs = append(zellijArgs, "-y", "9999")
case posLeft:
zellijArgs = append(zellijArgs, "-x", "0")
case posRight:
zellijArgs = append(zellijArgs, "-x", "9999")
case posCenter:
// Zellij centers floating panes by default
}
zellijArgs = append(zellijArgs, "--width", opts.Tmux.width.String())
zellijArgs = append(zellijArgs, "--height", opts.Tmux.height.String())
zellijArgs = append(zellijArgs, "--")
return runProxy(argStr, func(temp string, needBash bool) (*exec.Cmd, error) {
sh, err := sh(needBash)
if err != nil {
return nil, err
}
if ownsLabel {
// 'zellij run' cannot set the new pane's environment, so the
// command exports it itself. exec avoids a lingering shell
zellijArgs = append(zellijArgs, sh, "-c", fmt.Sprintf(`export %s="$ZELLIJ_PANE_ID"; exec %s %s`,
zellijBorderLabelEnv, escapeSingleQuote(sh), escapeSingleQuote(temp)))
} else {
zellijArgs = append(zellijArgs, sh, temp)
}
return exec.Command("zellij", zellijArgs...), nil
}, opts, true)
}