mirror of
https://github.com/junegunn/fzf.git
synced 2026-08-12 02:42:37 +08:00
Debounce visual feedback
This commit is contained in:
+32
-10
@@ -322,6 +322,7 @@ type Terminal struct {
|
|||||||
trackSync bool
|
trackSync bool
|
||||||
trackKeyCache map[int32]bool
|
trackKeyCache map[int32]bool
|
||||||
waitBlocked bool
|
waitBlocked bool
|
||||||
|
waitBlockedAt time.Time
|
||||||
pendingActions []*action
|
pendingActions []*action
|
||||||
searchInProgress bool
|
searchInProgress bool
|
||||||
pendingSelections map[string]selectedItem
|
pendingSelections map[string]selectedItem
|
||||||
@@ -3274,7 +3275,7 @@ func (t *Terminal) printPrompt() {
|
|||||||
color := tui.ColInput
|
color := tui.ColInput
|
||||||
if t.paused {
|
if t.paused {
|
||||||
color = tui.ColDisabled
|
color = tui.ColDisabled
|
||||||
} else if t.trackBlocked || t.waitBlocked {
|
} else if t.trackBlocked || t.waitFeedback() {
|
||||||
color = color.WithAttr(tui.Dim)
|
color = color.WithAttr(tui.Dim)
|
||||||
}
|
}
|
||||||
w.CPrint(color, string(before))
|
w.CPrint(color, string(before))
|
||||||
@@ -3366,9 +3367,6 @@ func (t *Terminal) printInfoImpl() {
|
|||||||
output += fmt.Sprintf(" (%d/%d)", len(t.selected), t.multi)
|
output += fmt.Sprintf(" (%d/%d)", len(t.selected), t.multi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if t.progress > 0 && t.progress < 100 {
|
|
||||||
output += fmt.Sprintf(" (%d%%)", t.progress)
|
|
||||||
}
|
|
||||||
if t.toggleSort {
|
if t.toggleSort {
|
||||||
if t.sort {
|
if t.sort {
|
||||||
output += " +S"
|
output += " +S"
|
||||||
@@ -3389,9 +3387,14 @@ func (t *Terminal) printInfoImpl() {
|
|||||||
output += " +t"
|
output += " +t"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if t.waitBlocked {
|
if t.waitFeedback() {
|
||||||
output += " (..)"
|
output += " (..)"
|
||||||
}
|
}
|
||||||
|
// Keep the search progress at the end so the other indicators don't shift
|
||||||
|
// as it appears and disappears.
|
||||||
|
if t.progress > 0 && t.progress < 100 {
|
||||||
|
output += fmt.Sprintf(" (%d%%)", t.progress)
|
||||||
|
}
|
||||||
if t.failed != nil && t.count == 0 {
|
if t.failed != nil && t.count == 0 {
|
||||||
output = fmt.Sprintf("[Command failed: %s]", *t.failed)
|
output = fmt.Sprintf("[Command failed: %s]", *t.failed)
|
||||||
}
|
}
|
||||||
@@ -5804,9 +5807,14 @@ func (t *Terminal) unblockTrack() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debounce visual feedback so quick searches don't cause flashing
|
||||||
|
func (t *Terminal) waitFeedback() bool {
|
||||||
|
return t.waitBlocked && time.Since(t.waitBlockedAt) > progressMinDuration
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Terminal) unblockWait() {
|
func (t *Terminal) unblockWait() {
|
||||||
t.waitBlocked = false
|
t.waitBlocked = false
|
||||||
// Only show cursor if not blocked by tracking
|
// Restore the cursor unless it's still hidden for another reason
|
||||||
if !t.inputless && !t.trackBlocked {
|
if !t.inputless && !t.trackBlocked {
|
||||||
t.tui.ShowCursor()
|
t.tui.ShowCursor()
|
||||||
}
|
}
|
||||||
@@ -6437,6 +6445,10 @@ func (t *Terminal) Loop() error {
|
|||||||
t.printFooter()
|
t.printFooter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Hide the cursor while the debounced waiting feedback is shown
|
||||||
|
if !t.inputless && !t.trackBlocked && t.waitFeedback() {
|
||||||
|
t.tui.HideCursor()
|
||||||
|
}
|
||||||
t.flush()
|
t.flush()
|
||||||
t.mutex.Unlock()
|
t.mutex.Unlock()
|
||||||
t.uiMutex.Unlock()
|
t.uiMutex.Unlock()
|
||||||
@@ -6646,11 +6658,21 @@ func (t *Terminal) Loop() error {
|
|||||||
// Block if search is in progress or will be triggered
|
// Block if search is in progress or will be triggered
|
||||||
if changed || newCommand != nil || t.searchInProgress {
|
if changed || newCommand != nil || t.searchInProgress {
|
||||||
t.waitBlocked = true
|
t.waitBlocked = true
|
||||||
|
t.waitBlockedAt = time.Now()
|
||||||
t.pendingActions = actions[i+1:]
|
t.pendingActions = actions[i+1:]
|
||||||
if !t.inputless {
|
// Show the waiting feedback only if the search takes long enough,
|
||||||
t.tui.HideCursor()
|
// so that quick searches don't cause flickering.
|
||||||
}
|
go func() {
|
||||||
req(reqPrompt, reqInfo)
|
timer := time.NewTimer(progressMinDuration)
|
||||||
|
<-timer.C
|
||||||
|
t.mutex.Lock()
|
||||||
|
blocked := t.waitBlocked
|
||||||
|
t.mutex.Unlock()
|
||||||
|
if blocked {
|
||||||
|
t.reqBox.Set(reqPrompt, nil)
|
||||||
|
t.reqBox.Set(reqInfo, nil)
|
||||||
|
}
|
||||||
|
}()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// No search, wait is a no-op; continue to next action
|
// No search, wait is a no-op; continue to next action
|
||||||
|
|||||||
Reference in New Issue
Block a user