mirror of
https://github.com/junegunn/fzf.git
synced 2025-07-31 04:02:01 -07:00
Fix panic caused by incorrect update ordering
Fix #4442 Make sure to prepare windows before rendering elements. Thanks to @nugged for the report.
This commit is contained in:
@@ -450,31 +450,35 @@ func (a byTimeOrder) Less(i, j int) bool {
|
||||
return a[i].at.Before(a[j].at)
|
||||
}
|
||||
|
||||
// EventTypes are listed in the order of their priority.
|
||||
const (
|
||||
reqPrompt util.EventType = iota
|
||||
reqResize util.EventType = iota
|
||||
reqReinit
|
||||
reqFullRedraw
|
||||
reqRedraw
|
||||
|
||||
reqJump
|
||||
reqPrompt
|
||||
reqInfo
|
||||
reqHeader
|
||||
reqFooter
|
||||
reqList
|
||||
reqJump
|
||||
reqActivate
|
||||
reqReinit
|
||||
reqFullRedraw
|
||||
reqResize
|
||||
reqRedraw
|
||||
reqRedrawInputLabel
|
||||
reqRedrawHeaderLabel
|
||||
reqRedrawFooterLabel
|
||||
reqRedrawListLabel
|
||||
reqRedrawBorderLabel
|
||||
reqRedrawPreviewLabel
|
||||
reqClose
|
||||
reqPrintQuery
|
||||
|
||||
reqPreviewReady
|
||||
reqPreviewEnqueue
|
||||
reqPreviewDisplay
|
||||
reqPreviewRefresh
|
||||
reqPreviewDelayed
|
||||
|
||||
reqActivate
|
||||
reqClose
|
||||
reqPrintQuery
|
||||
reqBecome
|
||||
reqQuit
|
||||
reqFatal
|
||||
@@ -1624,14 +1628,12 @@ func (t *Terminal) changeHeader(header string) bool {
|
||||
return needFullRedraw
|
||||
}
|
||||
|
||||
func (t *Terminal) changeFooter(footer string) bool {
|
||||
func (t *Terminal) changeFooter(footer string) {
|
||||
var lines []string
|
||||
if len(footer) > 0 {
|
||||
lines = strings.Split(strings.TrimSuffix(footer, "\n"), "\n")
|
||||
}
|
||||
needFullRedraw := len(t.footer) != len(lines)
|
||||
t.footer = lines
|
||||
return needFullRedraw
|
||||
}
|
||||
|
||||
// UpdateHeader updates the header
|
||||
@@ -2889,6 +2891,13 @@ func (t *Terminal) resizeIfNeeded() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check footer window
|
||||
if len(t.footer) > 0 && (t.footerWindow == nil || t.footerWindow.Height() != len(t.footer)) ||
|
||||
len(t.footer) == 0 && t.footerWindow != nil {
|
||||
t.printAll()
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if the header borders are used and header has changed
|
||||
allHeaderLines := t.visibleHeaderLines()
|
||||
primaryHeaderLines := allHeaderLines
|
||||
@@ -5116,6 +5125,8 @@ func (t *Terminal) Loop() error {
|
||||
t.uiMutex.Lock()
|
||||
t.mutex.Lock()
|
||||
info := false
|
||||
header := false
|
||||
footer := false
|
||||
for _, key := range keys {
|
||||
req := util.EventType(key)
|
||||
value := (*events)[req]
|
||||
@@ -5153,13 +5164,9 @@ func (t *Terminal) Loop() error {
|
||||
}
|
||||
t.printList()
|
||||
case reqHeader:
|
||||
if !t.resizeIfNeeded() {
|
||||
t.printHeader()
|
||||
}
|
||||
header = true
|
||||
case reqFooter:
|
||||
if !t.resizeIfNeeded() {
|
||||
t.printFooter()
|
||||
}
|
||||
footer = true
|
||||
case reqActivate:
|
||||
t.suppress = false
|
||||
if t.hasPreviewer() {
|
||||
@@ -5243,8 +5250,16 @@ func (t *Terminal) Loop() error {
|
||||
return
|
||||
}
|
||||
}
|
||||
if info && !t.resizeIfNeeded() {
|
||||
t.printInfo()
|
||||
if (info || header || footer) && !t.resizeIfNeeded() {
|
||||
if info {
|
||||
t.printInfo()
|
||||
}
|
||||
if header {
|
||||
t.printHeader()
|
||||
}
|
||||
if footer {
|
||||
t.printFooter()
|
||||
}
|
||||
}
|
||||
t.flush()
|
||||
t.mutex.Unlock()
|
||||
@@ -5670,24 +5685,17 @@ func (t *Terminal) Loop() error {
|
||||
t.cx = len(t.input)
|
||||
case actChangeHeader, actTransformHeader, actBgTransformHeader:
|
||||
capture(false, func(header string) {
|
||||
// When a dedicated header window is not used, we may need to
|
||||
// update other elements as well.
|
||||
if t.changeHeader(header) {
|
||||
if t.headerWindow != nil {
|
||||
// Need to resize header window
|
||||
req(reqRedraw)
|
||||
} else {
|
||||
req(reqHeader, reqList, reqPrompt, reqInfo)
|
||||
}
|
||||
} else {
|
||||
req(reqHeader)
|
||||
req(reqList, reqPrompt, reqInfo)
|
||||
}
|
||||
req(reqHeader)
|
||||
})
|
||||
case actChangeFooter, actTransformFooter, actBgTransformFooter:
|
||||
capture(false, func(footer string) {
|
||||
if t.changeFooter(footer) {
|
||||
req(reqRedraw)
|
||||
} else {
|
||||
req(reqFooter)
|
||||
}
|
||||
t.changeFooter(footer)
|
||||
req(reqFooter)
|
||||
})
|
||||
case actChangeHeaderLabel, actTransformHeaderLabel, actBgTransformHeaderLabel:
|
||||
capture(true, func(label string) {
|
||||
|
@@ -1981,4 +1981,11 @@ class TestCore < TestInteractive
|
||||
refute lines.any_include?('[1]')
|
||||
end
|
||||
end
|
||||
|
||||
def test_render_order
|
||||
tmux.send_keys %(seq 100 | #{FZF} --bind='focus:preview(echo boom)+change-footer(bam)'), :Enter
|
||||
tmux.until { assert_equal 100, it.match_count }
|
||||
tmux.until { assert it.any_include?('boom') }
|
||||
tmux.until { assert it.any_include?('bam') }
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user