Add every(N) bind event and FZF_IDLE_TIME env var

- every(N) fires every N seconds (fractional, floored to 0.01s)
- Encoded as tui.Every with duration in Char as milliseconds, so
  every(1) and every(2) coexist as distinct keymap entries
- FZF_IDLE_TIME exposes whole seconds since the last user activity
  (keystroke or mouse event); pair with every() for idle-based
  patterns like auto-accept/auto-quit

Close #1211
This commit is contained in:
Junegunn Choi
2026-05-16 14:31:46 +09:00
parent e0d081906f
commit 38c88e4753
8 changed files with 208 additions and 3 deletions
+37
View File
@@ -299,6 +299,43 @@ func TestBind(t *testing.T) {
check(tui.F1.AsEvent(), "", actAbort)
}
func TestParseEveryEvent(t *testing.T) {
pairs, _, err := parseKeyChords("every(2),every(0.5)", "")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(pairs) != 2 {
t.Errorf("expected 2 distinct every events, got %d", len(pairs))
}
if pairs[(tui.Event{Type: tui.Every, Char: 2000})] != "every(2)" {
t.Errorf("every(2) not registered")
}
if pairs[(tui.Event{Type: tui.Every, Char: 500})] != "every(0.5)" {
t.Errorf("every(0.5) not registered")
}
// Floor at 0.01s -> 10ms
pairs, _, err = parseKeyChords("every(0.001)", "")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if pairs[(tui.Event{Type: tui.Every, Char: 10})] != "every(0.001)" {
t.Errorf("every(0.001) should floor to 10ms")
}
// Reject zero and negatives
for _, bad := range []string{"every(0)", "every(-1)", "every(abc)", "every()"} {
if _, _, err := parseKeyChords(bad, ""); err == nil {
t.Errorf("%s should be rejected", bad)
}
}
// KeyName round-trips with the original duration
if got := (tui.Event{Type: tui.Every, Char: 2000}).KeyName(); got != "every(2)" {
t.Errorf("KeyName: %q != every(2)", got)
}
}
func TestColorSpec(t *testing.T) {
var base *tui.ColorTheme
theme := tui.Dark256