mirror of
https://github.com/junegunn/fzf.git
synced 2026-04-27 09:41:31 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a099d76fa6 | |||
| a5646b46e8 |
@@ -3,6 +3,10 @@ CHANGELOG
|
|||||||
|
|
||||||
0.71.0
|
0.71.0
|
||||||
------
|
------
|
||||||
|
- Added `--popup` as a new name for `--tmux` with Zellij support
|
||||||
|
- `--popup` starts fzf in a tmux popup or a Zellij floating pane
|
||||||
|
- `--tmux` is now an alias for `--popup`
|
||||||
|
- Requires tmux 3.3+ or Zellij 0.44+
|
||||||
- Cross-reload item identity with `--id-nth`
|
- Cross-reload item identity with `--id-nth`
|
||||||
- Added `--id-nth=NTH` to define item identity fields for cross-reload operations
|
- Added `--id-nth=NTH` to define item identity fields for cross-reload operations
|
||||||
- When a `reload` is triggered with tracking enabled, fzf searches for the tracked item by its identity fields in the new list.
|
- When a `reload` is triggered with tracking enabled, fzf searches for the tracked item by its identity fields in the new list.
|
||||||
|
|||||||
+10
-9
@@ -415,25 +415,26 @@ layout options so that the specified number of items are visible in the list
|
|||||||
section (default: \fB10+\fR).
|
section (default: \fB10+\fR).
|
||||||
Ignored when \fB\-\-height\fR is not specified or set as an absolute value.
|
Ignored when \fB\-\-height\fR is not specified or set as an absolute value.
|
||||||
.TP
|
.TP
|
||||||
.BI "\-\-tmux" "[=[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]][,border-native]]"
|
.BI "\-\-popup" "[=[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]][,border-native]]"
|
||||||
Start fzf in a tmux popup (default \fBcenter,50%\fR). Requires tmux 3.3 or
|
Start fzf in a tmux popup or in a Zellij floating pane (default
|
||||||
later. This option is ignored if you are not running fzf inside tmux.
|
\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.
|
||||||
|
|
||||||
e.g.
|
e.g.
|
||||||
\fB# Popup in the center with 70% width and height
|
\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
|
# 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
|
# 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
|
# Popup on the top with 80% width and 40% height
|
||||||
fzf \-\-tmux top,80%,40%
|
fzf \-\-popup top,80%,40%
|
||||||
|
|
||||||
# Popup with a native tmux border in the center with 80% width and height
|
# Popup with a native tmux or Zellij border in the center with 80% width and height
|
||||||
fzf \-\-tmux center,80%,border\-native\fR
|
fzf \-\-popup center,80%,border\-native\fR
|
||||||
|
|
||||||
.SS LAYOUT
|
.SS LAYOUT
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ func Run(opts *Options) (int, error) {
|
|||||||
if opts.useTmux() {
|
if opts.useTmux() {
|
||||||
return runTmux(os.Args, opts)
|
return runTmux(os.Args, opts)
|
||||||
}
|
}
|
||||||
|
if opts.useZellij() {
|
||||||
|
return runZellij(os.Args, opts)
|
||||||
|
}
|
||||||
|
|
||||||
if needWinpty(opts) {
|
if needWinpty(opts) {
|
||||||
return runWinpty(os.Args, opts)
|
return runWinpty(os.Args, opts)
|
||||||
|
|||||||
+9
-4
@@ -75,9 +75,10 @@ Usage: fzf [options]
|
|||||||
--min-height=HEIGHT[+] Minimum height when --height is given as a percentage.
|
--min-height=HEIGHT[+] Minimum height when --height is given as a percentage.
|
||||||
Add '+' to automatically increase the value
|
Add '+' to automatically increase the value
|
||||||
according to the other layout options (default: 10+).
|
according to the other layout options (default: 10+).
|
||||||
--tmux[=OPTS] Start fzf in a tmux popup (requires tmux 3.3+)
|
--popup[=OPTS] Start fzf in a popup window (requires tmux 3.3+ or Zellij 0.44+)
|
||||||
[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]]
|
[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]]
|
||||||
[,border-native] (default: center,50%)
|
[,border-native] (default: center,50%)
|
||||||
|
--tmux[=OPTS] Alias for --popup
|
||||||
|
|
||||||
LAYOUT
|
LAYOUT
|
||||||
--layout=LAYOUT Choose layout: [default|reverse|reverse-list]
|
--layout=LAYOUT Choose layout: [default|reverse|reverse-list]
|
||||||
@@ -417,7 +418,7 @@ func parseTmuxOptions(arg string, index int) (*tmuxOptions, error) {
|
|||||||
var err error
|
var err error
|
||||||
opts := defaultTmuxOptions(index)
|
opts := defaultTmuxOptions(index)
|
||||||
tokens := splitRegexp.Split(arg, -1)
|
tokens := splitRegexp.Split(arg, -1)
|
||||||
errorToReturn := errors.New("invalid tmux option: " + arg + " (expected: [center|top|bottom|left|right][,SIZE[%]][,SIZE[%][,border-native]])")
|
errorToReturn := errors.New("invalid popup option: " + arg + " (expected: [center|top|bottom|left|right][,SIZE[%]][,SIZE[%][,border-native]])")
|
||||||
if len(tokens) == 0 || len(tokens) > 4 {
|
if len(tokens) == 0 || len(tokens) > 4 {
|
||||||
return nil, errorToReturn
|
return nil, errorToReturn
|
||||||
}
|
}
|
||||||
@@ -2636,7 +2637,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
opts.Version = true
|
opts.Version = true
|
||||||
case "--no-winpty":
|
case "--no-winpty":
|
||||||
opts.NoWinpty = true
|
opts.NoWinpty = true
|
||||||
case "--tmux":
|
case "--tmux", "--popup":
|
||||||
given, str := optionalNextString()
|
given, str := optionalNextString()
|
||||||
if given {
|
if given {
|
||||||
if opts.Tmux, err = parseTmuxOptions(str, index); err != nil {
|
if opts.Tmux, err = parseTmuxOptions(str, index); err != nil {
|
||||||
@@ -2645,7 +2646,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
} else {
|
} else {
|
||||||
opts.Tmux = defaultTmuxOptions(index)
|
opts.Tmux = defaultTmuxOptions(index)
|
||||||
}
|
}
|
||||||
case "--no-tmux":
|
case "--no-tmux", "--no-popup":
|
||||||
opts.Tmux = nil
|
opts.Tmux = nil
|
||||||
case "--tty-default":
|
case "--tty-default":
|
||||||
if opts.TtyDefault, err = nextString("tty device name required"); err != nil {
|
if opts.TtyDefault, err = nextString("tty device name required"); err != nil {
|
||||||
@@ -3627,6 +3628,10 @@ func (opts *Options) useTmux() bool {
|
|||||||
return opts.Tmux != nil && len(os.Getenv("TMUX")) > 0 && opts.Tmux.index >= opts.Height.index
|
return opts.Tmux != nil && len(os.Getenv("TMUX")) > 0 && opts.Tmux.index >= opts.Height.index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (opts *Options) useZellij() bool {
|
||||||
|
return opts.Tmux != nil && len(os.Getenv("ZELLIJ")) > 0 && opts.Tmux.index >= opts.Height.index
|
||||||
|
}
|
||||||
|
|
||||||
func (opts *Options) noSeparatorLine() bool {
|
func (opts *Options) noSeparatorLine() bool {
|
||||||
if opts.Inputless {
|
if opts.Inputless {
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -23,6 +23,32 @@ func escapeSingleQuote(str string) string {
|
|||||||
return "'" + strings.ReplaceAll(str, "'", "'\\''") + "'"
|
return "'" + strings.ReplaceAll(str, "'", "'\\''") + "'"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func popupArgStr(args []string, opts *Options) (string, string) {
|
||||||
|
fzf, rest := args[0], args[1:]
|
||||||
|
args = []string{"--bind=ctrl-z:ignore"}
|
||||||
|
if !opts.Tmux.border && (opts.BorderShape == tui.BorderUndefined || opts.BorderShape == tui.BorderLine) {
|
||||||
|
if tui.DefaultBorderShape == tui.BorderRounded {
|
||||||
|
rest = append(rest, "--border=rounded")
|
||||||
|
} else {
|
||||||
|
rest = append(rest, "--border=sharp")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if opts.Tmux.border && opts.Margin == defaultMargin() {
|
||||||
|
args = append(args, "--margin=0,1")
|
||||||
|
}
|
||||||
|
argStr := escapeSingleQuote(fzf)
|
||||||
|
for _, arg := range append(args, rest...) {
|
||||||
|
argStr += " " + escapeSingleQuote(arg)
|
||||||
|
}
|
||||||
|
argStr += ` --no-popup --no-height`
|
||||||
|
|
||||||
|
dir, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
dir = "."
|
||||||
|
}
|
||||||
|
return argStr, dir
|
||||||
|
}
|
||||||
|
|
||||||
func fifo(name string) (string, error) {
|
func fifo(name string) (string, error) {
|
||||||
ns := time.Now().UnixNano()
|
ns := time.Now().UnixNano()
|
||||||
output := filepath.Join(os.TempDir(), fmt.Sprintf("fzf-%s-%d", name, ns))
|
output := filepath.Join(os.TempDir(), fmt.Sprintf("fzf-%s-%d", name, ns))
|
||||||
|
|||||||
+1
-1
@@ -2243,7 +2243,7 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
|||||||
width := screenWidth - marginInt[1] - marginInt[3]
|
width := screenWidth - marginInt[1] - marginInt[3]
|
||||||
height := screenHeight - marginInt[0] - marginInt[2]
|
height := screenHeight - marginInt[0] - marginInt[2]
|
||||||
|
|
||||||
t.prevLines = make([]itemLine, screenHeight)
|
t.prevLines = make([]itemLine, max(1, screenHeight))
|
||||||
if t.border != nil && redrawBorder {
|
if t.border != nil && redrawBorder {
|
||||||
t.border = nil
|
t.border = nil
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-29
@@ -1,39 +1,11 @@
|
|||||||
package fzf
|
package fzf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/junegunn/fzf/src/tui"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func runTmux(args []string, opts *Options) (int, error) {
|
func runTmux(args []string, opts *Options) (int, error) {
|
||||||
// Prepare arguments
|
argStr, dir := popupArgStr(args, opts)
|
||||||
fzf, rest := args[0], args[1:]
|
|
||||||
args = []string{"--bind=ctrl-z:ignore"}
|
|
||||||
if !opts.Tmux.border && (opts.BorderShape == tui.BorderUndefined || opts.BorderShape == tui.BorderLine) {
|
|
||||||
// We append --border option at the end, because `--style=full:STYLE`
|
|
||||||
// may have changed the default border style.
|
|
||||||
if tui.DefaultBorderShape == tui.BorderRounded {
|
|
||||||
rest = append(rest, "--border=rounded")
|
|
||||||
} else {
|
|
||||||
rest = append(rest, "--border=sharp")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if opts.Tmux.border && opts.Margin == defaultMargin() {
|
|
||||||
args = append(args, "--margin=0,1")
|
|
||||||
}
|
|
||||||
argStr := escapeSingleQuote(fzf)
|
|
||||||
for _, arg := range append(args, rest...) {
|
|
||||||
argStr += " " + escapeSingleQuote(arg)
|
|
||||||
}
|
|
||||||
argStr += ` --no-tmux --no-height`
|
|
||||||
|
|
||||||
// Get current directory
|
|
||||||
dir, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
dir = "."
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set tmux options for popup placement
|
// Set tmux options for popup placement
|
||||||
// C Both The centre of the terminal
|
// C Both The centre of the terminal
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package fzf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
func runZellij(args []string, opts *Options) (int, error) {
|
||||||
|
argStr, dir := popupArgStr(args, opts)
|
||||||
|
|
||||||
|
zellijArgs := []string{
|
||||||
|
"run", "--floating", "--close-on-exit", "--block-until-exit",
|
||||||
|
"--cwd", dir,
|
||||||
|
}
|
||||||
|
if !opts.Tmux.border {
|
||||||
|
zellijArgs = append(zellijArgs, "--borderless", "true")
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
zellijArgs = append(zellijArgs, sh, temp)
|
||||||
|
return exec.Command("zellij", zellijArgs...), nil
|
||||||
|
}, opts, true)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user