mirror of
https://github.com/junegunn/fzf.git
synced 2025-05-19 04:40:22 -07:00
Support zellij floating pane via --popup (new name for --tmux)
This commit is contained in:
parent
b2c3e567da
commit
81366c548b
@ -271,22 +271,23 @@ 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[%]]]"
|
||||
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.
|
||||
.BI "\-\-popup" "[=[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]]]"
|
||||
Start fzf in a tmux popup or in a zellij floating pane (default
|
||||
\fBcenter,50%\fR). Requires tmux 3.3+ or zellij. This option is ignored if you
|
||||
are not running fzf inside tmux or zellij.
|
||||
|
||||
e.g.
|
||||
\fB# Popup in the center with 70% width and height
|
||||
fzf \-\-tmux 70%
|
||||
fzf \-\-popup 70%
|
||||
|
||||
# Popup on the left with 40% width and 100% height
|
||||
fzf \-\-tmux right,40%
|
||||
fzf \-\-popup right,40%
|
||||
|
||||
# Popup on the bottom with 100% width and 30% height
|
||||
fzf \-\-tmux bottom,30%
|
||||
fzf \-\-popup bottom,30%
|
||||
|
||||
# Popup on the top with 80% width and 40% height
|
||||
fzf \-\-tmux top,80%,40%\fR
|
||||
fzf \-\-popup top,80%,40%\fR
|
||||
|
||||
.TP
|
||||
.BI "\-\-layout=" "LAYOUT"
|
||||
|
@ -39,8 +39,13 @@ func (r revision) compatible(other revision) bool {
|
||||
// Run starts fzf
|
||||
func Run(opts *Options) (int, error) {
|
||||
if opts.Filter == nil {
|
||||
if opts.Tmux != nil && len(os.Getenv("TMUX")) > 0 && opts.Tmux.index >= opts.Height.index {
|
||||
return runTmux(os.Args, opts)
|
||||
if opts.Tmux != nil && opts.Tmux.index >= opts.Height.index {
|
||||
if len(os.Getenv("TMUX")) > 0 {
|
||||
return runTmux(os.Args, opts)
|
||||
}
|
||||
if len(os.Getenv("ZELLIJ")) > 0 {
|
||||
return runZellij(os.Args, opts)
|
||||
}
|
||||
}
|
||||
|
||||
if needWinpty(opts) {
|
||||
|
@ -75,7 +75,7 @@ Usage: fzf [options]
|
||||
according to the input size.
|
||||
--min-height=HEIGHT Minimum height when --height is given in percent
|
||||
(default: 10)
|
||||
--tmux[=OPTS] Start fzf in a tmux popup (requires tmux 3.3+)
|
||||
--popup[=OPTS] Start fzf in a popup (requires tmux 3.3+ or zellij)
|
||||
[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]]
|
||||
(default: center,50%)
|
||||
--layout=LAYOUT Choose layout: [default|reverse|reverse-list]
|
||||
@ -299,7 +299,7 @@ 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[%]])")
|
||||
errorToReturn := errors.New("invalid popup option: " + arg + " (expected: [center|top|bottom|left|right][,SIZE[%]][,SIZE[%]])")
|
||||
if len(tokens) == 0 || len(tokens) > 3 {
|
||||
return nil, errorToReturn
|
||||
}
|
||||
@ -2031,7 +2031,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
||||
opts.Version = true
|
||||
case "--no-winpty":
|
||||
opts.NoWinpty = true
|
||||
case "--tmux":
|
||||
case "--tmux", "--popup":
|
||||
given, str := optionalNextString(allArgs, &i)
|
||||
if given {
|
||||
if opts.Tmux, err = parseTmuxOptions(str, index); err != nil {
|
||||
@ -2040,7 +2040,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
||||
} else {
|
||||
opts.Tmux = defaultTmuxOptions(index)
|
||||
}
|
||||
case "--no-tmux":
|
||||
case "--no-tmux", "--no-popup":
|
||||
opts.Tmux = nil
|
||||
case "--force-tty-in":
|
||||
// NOTE: We need this because `system('fzf --tmux < /dev/tty')` doesn't
|
||||
@ -2577,6 +2577,10 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
||||
if opts.FuzzyAlgo, err = parseAlgo(value); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if match, value := optString(arg, "--popup="); match {
|
||||
if opts.Tmux, err = parseTmuxOptions(value, index); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if match, value := optString(arg, "--tmux="); match {
|
||||
if opts.Tmux, err = parseTmuxOptions(value, index); err != nil {
|
||||
return err
|
||||
|
@ -1539,7 +1539,7 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
width := screenWidth - marginInt[1] - marginInt[3]
|
||||
height := screenHeight - marginInt[0] - marginInt[2]
|
||||
|
||||
t.prevLines = make([]itemLine, screenHeight)
|
||||
t.prevLines = make([]itemLine, util.Max(1, screenHeight))
|
||||
if t.border != nil && redrawBorder {
|
||||
t.border = nil
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ func runTmux(args []string, opts *Options) (int, error) {
|
||||
for _, arg := range args {
|
||||
argStr += " " + escapeSingleQuote(arg)
|
||||
}
|
||||
argStr += ` --no-tmux --no-height`
|
||||
argStr += ` --no-popup --no-height`
|
||||
|
||||
// Get current directory
|
||||
dir, err := os.Getwd()
|
||||
|
103
src/zellij.go
Normal file
103
src/zellij.go
Normal file
@ -0,0 +1,103 @@
|
||||
package fzf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
|
||||
"github.com/junegunn/fzf/src/tui"
|
||||
)
|
||||
|
||||
func runZellij(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 {
|
||||
args = append(args, "--no-border")
|
||||
}
|
||||
argStr := escapeSingleQuote(fzf)
|
||||
for _, arg := range args {
|
||||
argStr += " " + escapeSingleQuote(arg)
|
||||
}
|
||||
argStr += ` --no-popup --no-height`
|
||||
|
||||
// Get current directory
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
dir = "."
|
||||
}
|
||||
|
||||
sh, err := sh(false)
|
||||
if err != nil {
|
||||
return ExitError, err
|
||||
}
|
||||
|
||||
fifo, err := fifo("zellij-fifo")
|
||||
if err != nil {
|
||||
return ExitError, err
|
||||
}
|
||||
|
||||
zopts := " --width " + opts.Tmux.width.String() + " --height " + opts.Tmux.height.String()
|
||||
centerX := func() {
|
||||
// TODO: Handle non-percent values
|
||||
if opts.Tmux.width.percent {
|
||||
x := (100.0 - opts.Tmux.width.size) / 2
|
||||
if x <= 0 {
|
||||
zopts += " -x0"
|
||||
} else {
|
||||
zopts += fmt.Sprintf(" -x%d%%", int(x))
|
||||
}
|
||||
} else if cols := os.Getenv("COLUMNS"); len(cols) > 0 {
|
||||
if w, e := strconv.Atoi(cols); e == nil {
|
||||
x := (float64(w) - opts.Tmux.width.size) / 2
|
||||
zopts += fmt.Sprintf(" -x%d", int(x))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
centerY := func() {
|
||||
if opts.Tmux.height.percent {
|
||||
y := (100.0 - opts.Tmux.height.size) / 2
|
||||
if y <= 0 {
|
||||
zopts += " -y0"
|
||||
} else {
|
||||
zopts += fmt.Sprintf(" -y%d%%", int(y))
|
||||
}
|
||||
} else if lines := os.Getenv("LINES"); len(lines) > 0 {
|
||||
if h, e := strconv.Atoi(lines); e == nil {
|
||||
y := (float64(h) - opts.Tmux.height.size) / 2
|
||||
zopts += fmt.Sprintf(" -y%d", int(y))
|
||||
}
|
||||
}
|
||||
}
|
||||
switch opts.Tmux.position {
|
||||
case posUp:
|
||||
zopts += " -y0"
|
||||
centerX()
|
||||
case posDown:
|
||||
zopts += " -y9999"
|
||||
centerX()
|
||||
case posLeft:
|
||||
zopts += " -x0"
|
||||
centerY()
|
||||
case posRight:
|
||||
zopts += " -x9999"
|
||||
centerY()
|
||||
case posCenter:
|
||||
centerX()
|
||||
centerY()
|
||||
}
|
||||
|
||||
lines := []string{
|
||||
"#!/bin/sh",
|
||||
fmt.Sprintf(`zellij run --name '' --floating --close-on-exit --cwd %s %s -- %s -c "%s $1; echo \$? > %s" || exit $?`, dir, zopts, sh, sh, fifo),
|
||||
fmt.Sprintf(`exit $(cat %s)`, fifo),
|
||||
}
|
||||
temptemp := WriteTemporaryFile(lines, "\n")
|
||||
defer os.Remove(temptemp)
|
||||
|
||||
return runProxy(argStr, func(temp string, needBash bool) (*exec.Cmd, error) {
|
||||
return exec.Command(sh, temptemp, temp), nil
|
||||
}, opts, true)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user