mirror of
https://github.com/junegunn/fzf
synced 2026-08-10 20:01:42 +00:00
50e6c026ec
--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
66 lines
1.7 KiB
Go
66 lines
1.7 KiB
Go
package fzf
|
|
|
|
import (
|
|
"strconv"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestLabelUpdater(t *testing.T) {
|
|
var mu sync.Mutex
|
|
applied := []int{}
|
|
// The goroutine can still be running after the test function returns, so
|
|
// it records the label instead of reporting it, and -1 stands in for one
|
|
// that could not be parsed
|
|
updater := &labelUpdater{set: func(label string) {
|
|
n, err := strconv.Atoi(label)
|
|
if err != nil {
|
|
n = -1
|
|
}
|
|
mu.Lock()
|
|
applied = append(applied, n)
|
|
mu.Unlock()
|
|
// Long enough for the burst to pile up behind the first update
|
|
time.Sleep(time.Millisecond)
|
|
}}
|
|
|
|
const last = 99
|
|
for i := 0; i <= last; i++ {
|
|
updater.update(strconv.Itoa(i))
|
|
}
|
|
|
|
// However many updates are dropped, the final one is always applied
|
|
deadline := time.Now().Add(5 * time.Second)
|
|
for {
|
|
mu.Lock()
|
|
done := len(applied) > 0 && applied[len(applied)-1] == last
|
|
mu.Unlock()
|
|
if done {
|
|
break
|
|
}
|
|
if time.Now().After(deadline) {
|
|
t.Fatalf("last update was not applied: %v", applied)
|
|
}
|
|
time.Sleep(time.Millisecond)
|
|
}
|
|
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
// Updates are never applied out of order, so the border cannot be left
|
|
// showing a label older than the last one requested
|
|
for i, n := range applied {
|
|
if i > 0 && n <= applied[i-1] {
|
|
t.Errorf("applied out of order: %v", applied)
|
|
break
|
|
}
|
|
}
|
|
// A burst collapses instead of running one command per update. The
|
|
// updates are queued in a tight loop while each one takes a millisecond
|
|
// to apply, so all of them landing would mean no coalescing at all
|
|
if len(applied) >= last+1 {
|
|
t.Errorf("expected updates to be coalesced, applied all %d", len(applied))
|
|
}
|
|
t.Logf("applied %d of %d updates", len(applied), last+1)
|
|
}
|