Skip to content

Add every(N) bind event and FZF_IDLE_TIME env var#4797

Merged
junegunn merged 8 commits into
masterfrom
devel
May 17, 2026
Merged

Add every(N) bind event and FZF_IDLE_TIME env var#4797
junegunn merged 8 commits into
masterfrom
devel

Conversation

@junegunn
Copy link
Copy Markdown
Owner

  • 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

Acknowledgement

  • I confirm that this PR meets the above expectations and reflects my own understanding and real-world context.

@junegunn junegunn self-assigned this May 16, 2026
@junegunn junegunn added the feature New feature request label May 16, 2026
@junegunn junegunn requested a review from Copilot May 16, 2026 05:42
@github-actions github-actions Bot added docs Documentation go Go code test Tests labels May 16, 2026
- 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
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a timer-driven every(N) bind event and a new FZF_IDLE_TIME environment variable to support idle/time-based automations in fzf (e.g., periodic reloads, auto-accept after inactivity).

Changes:

  • Introduces every(N) as a new bindable event type (tui.Every) with millisecond resolution.
  • Starts per-every() tickers in the terminal loop and exports FZF_IDLE_TIME to child processes.
  • Adds Go + Ruby integration tests and updates the man page + changelog documentation.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/test_core.rb Adds integration tests for every() behavior, unbind, and FZF_IDLE_TIME.
src/tui/tui.go Adds Every event type and formats every(N) in Event.KeyName().
src/tui/eventtype_string.go Updates generated EventType stringer output to include Every.
src/terminal.go Adds timer channel + ticker startup and exports FZF_IDLE_TIME.
src/options.go Parses every(N) chord specs into a tui.Every event with ms payload.
src/options_test.go Adds unit coverage for parsing and key registration of every(N).
man/man1/fzf.1 Documents every(N) and FZF_IDLE_TIME, including usage examples.
CHANGELOG.md Announces the new event and environment variable with examples.
Files not reviewed (1)
  • src/tui/eventtype_string.go: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/options.go Outdated
Comment thread src/terminal.go
junegunn added 5 commits May 16, 2026 17:58
Char is rune (int32). Without an upper bound, secs * 1000 could
silently wrap to a non-positive value and panic time.NewTicker.
Move Invalid, Fatal, and BracketedPasteBegin/End into the same
synthetic block as Resize, Start, Load, etc. The single boundary
(>= Invalid) now covers every non-user event, replacing the explicit
list in the keyChan activity check.

BracketedPaste markers sit in the synthetic block because the paste
content itself arrives as Rune events and updates lastActivity.
Seconds resolution is too coarse to combine with sub-second every()
bindings. Switching to milliseconds gives idle-based scripts useful
resolution at any every() interval.
Seconds is more ergonomic for shell threshold checks; milliseconds
covers sub-second every() bindings. Exporting both lets the same
script pick whichever resolution matches its every() interval.
lastKey was overwritten every time a synthetic event (every(N), Focus,
Result, ...) was processed, so FZF_KEY would briefly show "every(1)"
or empty string instead of the user's actual last keystroke.

Gate the assignment on `< Invalid` so only user-input events update
lastKey, and drop the now-unused every() formatting in KeyName.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • src/tui/eventtype_string.go: Language not supported

Comment thread src/terminal.go
Comment thread test/test_core.rb
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • src/tui/eventtype_string.go: Language not supported

Comment thread src/terminal.go Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • src/tui/eventtype_string.go: Language not supported

@junegunn junegunn merged commit fcc3c6a into master May 17, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation feature New feature request go Go code test Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Proposal] "Cursor Hold" expect to trigger after some time without keypresses

2 participants