mirror of
https://github.com/junegunn/fzf.git
synced 2026-10-13 00:20:20 +08:00
Preserve tmux window zoom when opening a floating pane
- Use new-pane -A on tmux 3.8+ to keep floating pane above zoomed pane - Detect -A from new-pane usage; keep unzoom fallback for 3.7 Fix #4927 Fix junegunn/fzf.vim#1625 Co-authored-by: Jere Viikari <jere.viikari@gmail.com>
This commit is contained in:
1 parent
981f1539b0
commit
d8aeec3058
2 files changed
+25
-16
No files matched your search
@@ -9,6 +9,8 @@ CHANGELOG
|
|||||||
- Fixed `focus` event not triggered after `reload` when the new item is at the same position as the previous one (#4930)
|
- Fixed `focus` event not triggered after `reload` when the new item is at the same position as the previous one (#4930)
|
||||||
- With `--id-nth`, the event is not triggered if the focus moves directly from an item to another item with the same key
|
- With `--id-nth`, the event is not triggered if the focus moves directly from an item to another item with the same key
|
||||||
- A `focus` binding that runs `reload` now triggers itself again after each reload, unless `--id-nth` is set and the key does not change
|
- A `focus` binding that runs `reload` now triggers itself again after each reload, unless `--id-nth` is set and the key does not change
|
||||||
|
- Fixed `--popup` unzooming the window when opened over a zoomed pane on tmux 3.8 or above (#4927, junegunn/fzf.vim#1625)
|
||||||
|
- On tmux 3.7, the window is still unzoomed, as tmux 3.7b crashes when a floating pane is created over a zoomed window
|
||||||
|
|
||||||
0.74.4
|
0.74.4
|
||||||
------
|
------
|
||||||
|
|||||||
+23
-16
@@ -5,14 +5,19 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/junegunn/fzf/src/tui"
|
"github.com/junegunn/fzf/src/tui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// The flag group of new-pane usage includes -A (tmux 3.8 or above)
|
||||||
|
var tmuxOverZoomFlag = regexp.MustCompile(`new-pane.*\[-[[:alpha:]]*A`)
|
||||||
|
|
||||||
// Returns the size of the current window if the tmux server supports
|
// Returns the size of the current window if the tmux server supports
|
||||||
// floating panes (tmux 3.7 or above)
|
// floating panes (tmux 3.7 or above), and whether a floating pane can stay
|
||||||
func tmuxFloatingPaneInfo() (int, int, bool) {
|
// above a zoomed pane
|
||||||
|
func tmuxFloatingPaneInfo() (int, int, bool, bool) {
|
||||||
// TMUX_PANE is not set when fzf is not started from within a pane
|
// TMUX_PANE is not set when fzf is not started from within a pane
|
||||||
// (e.g. 'bind-key 0 run-shell "fzf --popup"'). Do not use a floating
|
// (e.g. 'bind-key 0 run-shell "fzf --popup"'). Do not use a floating
|
||||||
// pane there; a blocking run-shell suspends key processing for the
|
// pane there; a blocking run-shell suspends key processing for the
|
||||||
@@ -25,7 +30,7 @@ func tmuxFloatingPaneInfo() (int, int, bool) {
|
|||||||
// https://github.com/tmux/tmux/issues/5384
|
// https://github.com/tmux/tmux/issues/5384
|
||||||
target := os.Getenv("TMUX_PANE")
|
target := os.Getenv("TMUX_PANE")
|
||||||
if target == "" {
|
if target == "" {
|
||||||
return 0, 0, false
|
return 0, 0, false, false
|
||||||
}
|
}
|
||||||
// A single invocation for both checks. Cannot rely on the exit status;
|
// A single invocation for both checks. Cannot rely on the exit status;
|
||||||
// tmux versions before 3.7 exit normally with empty output for an
|
// tmux versions before 3.7 exit normally with empty output for an
|
||||||
@@ -33,17 +38,17 @@ func tmuxFloatingPaneInfo() (int, int, bool) {
|
|||||||
out, err := exec.Command("tmux", "display-message", "-p", "-t", target,
|
out, err := exec.Command("tmux", "display-message", "-p", "-t", target,
|
||||||
"#{window_width} #{window_height}", ";", "list-commands", "new-pane").Output()
|
"#{window_width} #{window_height}", ";", "list-commands", "new-pane").Output()
|
||||||
if err != nil || !strings.Contains(string(out), "new-pane") {
|
if err != nil || !strings.Contains(string(out), "new-pane") {
|
||||||
return 0, 0, false
|
return 0, 0, false, false
|
||||||
}
|
}
|
||||||
var width, height int
|
var width, height int
|
||||||
if _, err := fmt.Sscanf(string(out), "%d %d", &width, &height); err != nil {
|
if _, err := fmt.Sscanf(string(out), "%d %d", &width, &height); err != nil {
|
||||||
return 0, 0, false
|
return 0, 0, false, false
|
||||||
}
|
}
|
||||||
// The window is too small to fit a floating pane of the minimum size
|
// The window is too small to fit a floating pane of the minimum size
|
||||||
if width < 3 || height < 3 {
|
if width < 3 || height < 3 {
|
||||||
return 0, 0, false
|
return 0, 0, false, false
|
||||||
}
|
}
|
||||||
return width, height, true
|
return width, height, tmuxOverZoomFlag.Match(out), true
|
||||||
}
|
}
|
||||||
|
|
||||||
// tmux ends a command at an argument ending in ';', so a trailing one is
|
// tmux ends a command at an argument ending in ';', so a trailing one is
|
||||||
@@ -85,7 +90,7 @@ func tmuxDim(spec sizeSpec, window int) int {
|
|||||||
return max(3, min(dim, window))
|
return max(3, min(dim, window))
|
||||||
}
|
}
|
||||||
|
|
||||||
func runTmuxFloatingPane(argStr string, dir string, windowWidth int, windowHeight int, opts *Options) (int, error) {
|
func runTmuxFloatingPane(argStr string, dir string, windowWidth int, windowHeight int, overZoom bool, opts *Options) (int, error) {
|
||||||
// Unlike display-popup, the size of a floating pane does not account for
|
// Unlike display-popup, the size of a floating pane does not account for
|
||||||
// the border around it, and the position is that of the content area. To
|
// the border around it, and the position is that of the content area. To
|
||||||
// stay consistent with popups, treat the requested size as the total
|
// stay consistent with popups, treat the requested size as the total
|
||||||
@@ -166,13 +171,15 @@ func runTmuxFloatingPane(argStr string, dir string, windowWidth int, windowHeigh
|
|||||||
}
|
}
|
||||||
paneCmd := fmt.Sprintf("%s%s %s; echo $? > %s; tmux wait-for -S %s",
|
paneCmd := fmt.Sprintf("%s%s %s; echo $? > %s; tmux wait-for -S %s",
|
||||||
setup, escapeSingleQuote(sh), escapeSingleQuote(temp), code, signal)
|
setup, escapeSingleQuote(sh), escapeSingleQuote(temp), code, signal)
|
||||||
// Unzoom the window first; creating a floating pane over a zoomed
|
|
||||||
// window crashes the tmux server on 3.7b, and newer versions of
|
|
||||||
// tmux unzoom the window anyway.
|
|
||||||
target := os.Getenv("TMUX_PANE")
|
target := os.Getenv("TMUX_PANE")
|
||||||
newPane := fmt.Sprintf(
|
newPane := "tmux new-pane -A"
|
||||||
"tmux if -F -t %s '#{window_zoomed_flag}' %s ';' new-pane -P -F '#{pane_id}' -t %s -c %s -x %d -y %d -X %d -Y %d %s -c %s",
|
if !overZoom {
|
||||||
escapeSingleQuote(target), escapeSingleQuote("resize-pane -Z -t "+target),
|
// Unzoom the window first; creating a floating pane over a
|
||||||
|
// zoomed window crashes the tmux server on 3.7b
|
||||||
|
newPane = fmt.Sprintf("tmux if -F -t %s '#{window_zoomed_flag}' %s ';' new-pane",
|
||||||
|
escapeSingleQuote(target), escapeSingleQuote("resize-pane -Z -t "+target))
|
||||||
|
}
|
||||||
|
newPane += fmt.Sprintf(" -P -F '#{pane_id}' -t %s -c %s -x %d -y %d -X %d -Y %d %s -c %s",
|
||||||
escapeSingleQuote(target), escapeSingleQuote(dir), width-2, height-2, x, y,
|
escapeSingleQuote(target), escapeSingleQuote(dir), width-2, height-2, x, y,
|
||||||
escapeSingleQuote(sh), escapeSingleQuote(paneCmd))
|
escapeSingleQuote(sh), escapeSingleQuote(paneCmd))
|
||||||
|
|
||||||
@@ -222,10 +229,10 @@ func runTmux(args []string, opts *Options) (int, error) {
|
|||||||
// popup is used instead so that the fzf-drawn border is the only border
|
// popup is used instead so that the fzf-drawn border is the only border
|
||||||
// shown; the native border of a tmux floating pane cannot be removed.
|
// shown; the native border of a tmux floating pane cannot be removed.
|
||||||
if nativeBorder(opts) {
|
if nativeBorder(opts) {
|
||||||
if windowWidth, windowHeight, ok := tmuxFloatingPaneInfo(); ok {
|
if windowWidth, windowHeight, overZoom, ok := tmuxFloatingPaneInfo(); ok {
|
||||||
opts.Tmux.border = true
|
opts.Tmux.border = true
|
||||||
argStr, dir := popupArgStr(args, opts)
|
argStr, dir := popupArgStr(args, opts)
|
||||||
return runTmuxFloatingPane(argStr, dir, windowWidth, windowHeight, opts)
|
return runTmuxFloatingPane(argStr, dir, windowWidth, windowHeight, overZoom, opts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user