mirror of
https://github.com/Llewellynvdm/fzf.git
synced 2024-11-22 04:45:14 +00:00
Improved --sync behavior
When --sync is provided, fzf will not render the interface until the initial filtering and associated actions (bound to any of 'start', 'load', or 'result') are complete.
This commit is contained in:
parent
b8c01af0fc
commit
e0ddb97ab4
18
CHANGELOG.md
18
CHANGELOG.md
@ -3,16 +3,20 @@ CHANGELOG
|
|||||||
|
|
||||||
0.53.1
|
0.53.1
|
||||||
------
|
------
|
||||||
- Bug fixes and minor improvements
|
- Better cache management and improved rendering for `--tail`
|
||||||
- Better cache management and improved rendering for `--tail`
|
- Improved `--sync` behavior
|
||||||
- Fixed crash when using `--tiebreak=end` with very long items
|
- When `--sync` is provided, fzf will not render the interface until the initial filtering and associated actions (bound to any of `start`, `load`, or `result`) are complete.
|
||||||
- Fixed mouse support on Windows
|
```sh
|
||||||
- zsh 5.0 compatibility (thanks to @LangLangBart)
|
(sleep 1; seq 1000000; sleep 1) | fzf --sync --query 5 --listen --bind start:up,load:up,result:up
|
||||||
- Fixed `--walker-skip` to also skip symlinks to directories
|
```
|
||||||
- GET endpoint is now available from `execute` and `transform` actions (it used to timeout due to lock conflict)
|
- GET endpoint is now available from `execute` and `transform` actions (it used to timeout due to lock conflict)
|
||||||
```sh
|
```sh
|
||||||
fzf --listen --bind 'focus:transform-header:curl -s localhost:$FZF_PORT?limit=0 | jq .'
|
fzf --listen --bind 'focus:transform-header:curl -s localhost:$FZF_PORT?limit=0 | jq .'
|
||||||
```
|
```
|
||||||
|
- Fixed crash when using `--tiebreak=end` with very long items
|
||||||
|
- Fixed mouse support on Windows
|
||||||
|
- zsh 5.0 compatibility (thanks to @LangLangBart)
|
||||||
|
- Fixed `--walker-skip` to also skip symlinks to directories
|
||||||
|
|
||||||
0.53.0
|
0.53.0
|
||||||
------
|
------
|
||||||
|
@ -339,9 +339,6 @@ func Run(opts *Options) (int, error) {
|
|||||||
}
|
}
|
||||||
total = count
|
total = count
|
||||||
terminal.UpdateCount(total, !reading, value.(*string))
|
terminal.UpdateCount(total, !reading, value.(*string))
|
||||||
if opts.Sync {
|
|
||||||
terminal.UpdateList(PassMerger(&snapshot, opts.Tac, snapshotRevision), false)
|
|
||||||
}
|
|
||||||
if heightUnknown && !deferred {
|
if heightUnknown && !deferred {
|
||||||
determine(!reading)
|
determine(!reading)
|
||||||
}
|
}
|
||||||
@ -429,7 +426,7 @@ func Run(opts *Options) (int, error) {
|
|||||||
determine(val.final)
|
determine(val.final)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
terminal.UpdateList(val, true)
|
terminal.UpdateList(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
141
src/terminal.go
141
src/terminal.go
@ -286,6 +286,7 @@ type Terminal struct {
|
|||||||
borderWidth int
|
borderWidth int
|
||||||
count int
|
count int
|
||||||
progress int
|
progress int
|
||||||
|
hasStartActions bool
|
||||||
hasResultActions bool
|
hasResultActions bool
|
||||||
hasFocusActions bool
|
hasFocusActions bool
|
||||||
hasLoadActions bool
|
hasLoadActions bool
|
||||||
@ -311,6 +312,7 @@ type Terminal struct {
|
|||||||
previewBox *util.EventBox
|
previewBox *util.EventBox
|
||||||
eventBox *util.EventBox
|
eventBox *util.EventBox
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
|
uiMutex sync.Mutex
|
||||||
initFunc func() error
|
initFunc func() error
|
||||||
prevLines []itemLine
|
prevLines []itemLine
|
||||||
suppress bool
|
suppress bool
|
||||||
@ -318,6 +320,7 @@ type Terminal struct {
|
|||||||
startChan chan fitpad
|
startChan chan fitpad
|
||||||
killChan chan bool
|
killChan chan bool
|
||||||
serverInputChan chan []*action
|
serverInputChan chan []*action
|
||||||
|
keyChan chan tui.Event
|
||||||
eventChan chan tui.Event
|
eventChan chan tui.Event
|
||||||
slab *util.Slab
|
slab *util.Slab
|
||||||
theme *tui.ColorTheme
|
theme *tui.ColorTheme
|
||||||
@ -361,7 +364,7 @@ const (
|
|||||||
reqHeader
|
reqHeader
|
||||||
reqList
|
reqList
|
||||||
reqJump
|
reqJump
|
||||||
reqRefresh
|
reqActivate
|
||||||
reqReinit
|
reqReinit
|
||||||
reqFullRedraw
|
reqFullRedraw
|
||||||
reqResize
|
reqResize
|
||||||
@ -684,7 +687,9 @@ func evaluateHeight(opts *Options, termHeight int) int {
|
|||||||
func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor) (*Terminal, error) {
|
func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor) (*Terminal, error) {
|
||||||
input := trimQuery(opts.Query)
|
input := trimQuery(opts.Query)
|
||||||
var delay time.Duration
|
var delay time.Duration
|
||||||
if opts.Tac {
|
if opts.Sync {
|
||||||
|
delay = 0
|
||||||
|
} else if opts.Tac {
|
||||||
delay = initialDelayTac
|
delay = initialDelayTac
|
||||||
} else {
|
} else {
|
||||||
delay = initialDelay
|
delay = initialDelay
|
||||||
@ -808,6 +813,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
ellipsis: opts.Ellipsis,
|
ellipsis: opts.Ellipsis,
|
||||||
ansi: opts.Ansi,
|
ansi: opts.Ansi,
|
||||||
tabstop: opts.Tabstop,
|
tabstop: opts.Tabstop,
|
||||||
|
hasStartActions: false,
|
||||||
hasResultActions: false,
|
hasResultActions: false,
|
||||||
hasFocusActions: false,
|
hasFocusActions: false,
|
||||||
hasLoadActions: false,
|
hasLoadActions: false,
|
||||||
@ -830,6 +836,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
previewBox: previewBox,
|
previewBox: previewBox,
|
||||||
eventBox: eventBox,
|
eventBox: eventBox,
|
||||||
mutex: sync.Mutex{},
|
mutex: sync.Mutex{},
|
||||||
|
uiMutex: sync.Mutex{},
|
||||||
suppress: true,
|
suppress: true,
|
||||||
sigstop: false,
|
sigstop: false,
|
||||||
slab: util.MakeSlab(slab16Size, slab32Size),
|
slab: util.MakeSlab(slab16Size, slab32Size),
|
||||||
@ -837,7 +844,8 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
startChan: make(chan fitpad, 1),
|
startChan: make(chan fitpad, 1),
|
||||||
killChan: make(chan bool),
|
killChan: make(chan bool),
|
||||||
serverInputChan: make(chan []*action, 100),
|
serverInputChan: make(chan []*action, 100),
|
||||||
eventChan: make(chan tui.Event, 6), // (load + result + zero|one) | (focus) | (resize) | (GetChar)
|
keyChan: make(chan tui.Event),
|
||||||
|
eventChan: make(chan tui.Event, 6), // start | (load + result + zero|one) | (focus) | (resize)
|
||||||
tui: renderer,
|
tui: renderer,
|
||||||
ttyin: ttyin,
|
ttyin: ttyin,
|
||||||
initFunc: func() error { return renderer.Init() },
|
initFunc: func() error { return renderer.Init() },
|
||||||
@ -885,6 +893,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
if t.tui.ShouldEmitResizeEvent() {
|
if t.tui.ShouldEmitResizeEvent() {
|
||||||
t.keymap[tui.Resize.AsEvent()] = append(toActions(actClearScreen), resizeActions...)
|
t.keymap[tui.Resize.AsEvent()] = append(toActions(actClearScreen), resizeActions...)
|
||||||
}
|
}
|
||||||
|
_, t.hasStartActions = t.keymap[tui.Start.AsEvent()]
|
||||||
_, t.hasResultActions = t.keymap[tui.Result.AsEvent()]
|
_, t.hasResultActions = t.keymap[tui.Result.AsEvent()]
|
||||||
_, t.hasFocusActions = t.keymap[tui.Focus.AsEvent()]
|
_, t.hasFocusActions = t.keymap[tui.Focus.AsEvent()]
|
||||||
_, t.hasLoadActions = t.keymap[tui.Load.AsEvent()]
|
_, t.hasLoadActions = t.keymap[tui.Load.AsEvent()]
|
||||||
@ -898,9 +907,17 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
t.listenPort = &port
|
t.listenPort = &port
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if t.hasStartActions {
|
||||||
|
t.eventChan <- tui.Start.AsEvent()
|
||||||
|
}
|
||||||
|
|
||||||
return &t, nil
|
return &t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Terminal) deferActivation() bool {
|
||||||
|
return t.initDelay == 0 && (t.hasStartActions || t.hasLoadActions || t.hasResultActions)
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Terminal) environ() []string {
|
func (t *Terminal) environ() []string {
|
||||||
env := os.Environ()
|
env := os.Environ()
|
||||||
if t.listenPort != nil {
|
if t.listenPort != nil {
|
||||||
@ -1122,10 +1139,14 @@ func (t *Terminal) UpdateCount(cnt int, final bool, failedCommand *string) {
|
|||||||
}
|
}
|
||||||
t.reading = !final
|
t.reading = !final
|
||||||
t.failed = failedCommand
|
t.failed = failedCommand
|
||||||
|
suppressed := t.suppress
|
||||||
t.mutex.Unlock()
|
t.mutex.Unlock()
|
||||||
t.reqBox.Set(reqInfo, nil)
|
t.reqBox.Set(reqInfo, nil)
|
||||||
if final {
|
|
||||||
t.reqBox.Set(reqRefresh, nil)
|
// We want to defer activating the interface when --sync is used and any of
|
||||||
|
// start, load, or result events are bound
|
||||||
|
if suppressed && final && !t.deferActivation() {
|
||||||
|
t.reqBox.Set(reqActivate, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1158,7 +1179,7 @@ func (t *Terminal) UpdateProgress(progress float32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateList updates Merger to display the list
|
// UpdateList updates Merger to display the list
|
||||||
func (t *Terminal) UpdateList(merger *Merger, triggerResultEvent bool) {
|
func (t *Terminal) UpdateList(merger *Merger) {
|
||||||
t.mutex.Lock()
|
t.mutex.Lock()
|
||||||
prevIndex := minItem.Index()
|
prevIndex := minItem.Index()
|
||||||
newRevision := merger.Revision()
|
newRevision := merger.Revision()
|
||||||
@ -1229,7 +1250,7 @@ func (t *Terminal) UpdateList(merger *Merger, triggerResultEvent bool) {
|
|||||||
t.eventChan <- one
|
t.eventChan <- one
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if triggerResultEvent && t.hasResultActions {
|
if t.hasResultActions {
|
||||||
t.eventChan <- tui.Result.AsEvent()
|
t.eventChan <- tui.Result.AsEvent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2645,7 +2666,7 @@ func (t *Terminal) printAll() {
|
|||||||
t.printPreview()
|
t.printPreview()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) refresh() {
|
func (t *Terminal) flush() {
|
||||||
t.placeCursor()
|
t.placeCursor()
|
||||||
if !t.suppress {
|
if !t.suppress {
|
||||||
windows := make([]tui.Window, 0, 4)
|
windows := make([]tui.Window, 0, 4)
|
||||||
@ -2949,7 +2970,7 @@ func replacePlaceholder(params replacePlaceholderParams) (string, []string) {
|
|||||||
return replaced, tempFiles
|
return replaced, tempFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) redraw() {
|
func (t *Terminal) fullRedraw() {
|
||||||
t.tui.Clear()
|
t.tui.Clear()
|
||||||
t.tui.Refresh()
|
t.tui.Refresh()
|
||||||
t.printAll()
|
t.printAll()
|
||||||
@ -2992,15 +3013,18 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t.tui.Pause(true)
|
|
||||||
t.mutex.Unlock()
|
t.mutex.Unlock()
|
||||||
|
t.uiMutex.Lock()
|
||||||
|
t.tui.Pause(true)
|
||||||
cmd.Run()
|
cmd.Run()
|
||||||
t.mutex.Lock()
|
|
||||||
t.tui.Resume(true, false)
|
t.tui.Resume(true, false)
|
||||||
t.redraw()
|
t.mutex.Lock()
|
||||||
t.refresh()
|
t.fullRedraw()
|
||||||
|
t.flush()
|
||||||
|
t.uiMutex.Unlock()
|
||||||
} else {
|
} else {
|
||||||
t.mutex.Unlock()
|
t.mutex.Unlock()
|
||||||
|
t.uiMutex.Lock()
|
||||||
if capture {
|
if capture {
|
||||||
out, _ := cmd.StdoutPipe()
|
out, _ := cmd.StdoutPipe()
|
||||||
reader := bufio.NewReader(out)
|
reader := bufio.NewReader(out)
|
||||||
@ -3017,6 +3041,7 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
|
|||||||
cmd.Run()
|
cmd.Run()
|
||||||
}
|
}
|
||||||
t.mutex.Lock()
|
t.mutex.Lock()
|
||||||
|
t.uiMutex.Unlock()
|
||||||
}
|
}
|
||||||
t.executing.Set(false)
|
t.executing.Set(false)
|
||||||
removeFiles(tempFiles)
|
removeFiles(tempFiles)
|
||||||
@ -3239,13 +3264,15 @@ func (t *Terminal) Loop() error {
|
|||||||
t.printPrompt()
|
t.printPrompt()
|
||||||
t.printInfo()
|
t.printInfo()
|
||||||
t.printHeader()
|
t.printHeader()
|
||||||
t.refresh()
|
t.flush()
|
||||||
t.mutex.Unlock()
|
t.mutex.Unlock()
|
||||||
|
if t.initDelay > 0 {
|
||||||
go func() {
|
go func() {
|
||||||
timer := time.NewTimer(t.initDelay)
|
timer := time.NewTimer(t.initDelay)
|
||||||
<-timer.C
|
<-timer.C
|
||||||
t.reqBox.Set(reqRefresh, nil)
|
t.reqBox.Set(reqActivate, nil)
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
// Keep the spinner spinning
|
// Keep the spinner spinning
|
||||||
go func() {
|
go func() {
|
||||||
@ -3439,7 +3466,7 @@ func (t *Terminal) Loop() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() { // Render loop
|
||||||
var focusedIndex = minItem.Index()
|
var focusedIndex = minItem.Index()
|
||||||
var version int64 = -1
|
var version int64 = -1
|
||||||
running := true
|
running := true
|
||||||
@ -3463,6 +3490,23 @@ func (t *Terminal) Loop() error {
|
|||||||
for running {
|
for running {
|
||||||
t.reqBox.Wait(func(events *util.Events) {
|
t.reqBox.Wait(func(events *util.Events) {
|
||||||
defer events.Clear()
|
defer events.Clear()
|
||||||
|
|
||||||
|
// t.uiMutex must be locked first to avoid deadlock. Execute actions
|
||||||
|
// will 1. unlock t.mutex to allow GET endpoint and 2. lock t.uiMutex
|
||||||
|
// to block rendering during the execution.
|
||||||
|
//
|
||||||
|
// T1 T2 (good) | T1 T2 (bad)
|
||||||
|
// L t.uiMutex |
|
||||||
|
// L t.mutex | L t.mutex
|
||||||
|
// U t.mutex | U t.mutex
|
||||||
|
// L t.mutex | L t.mutex
|
||||||
|
// U t.mutex | L t.uiMutex
|
||||||
|
// U t.uiMutex | L t.uiMutex!!
|
||||||
|
// L t.uiMutex |
|
||||||
|
// | L t.mutex!!
|
||||||
|
// L t.mutex | U t.uiMutex
|
||||||
|
// U t.uiMutex |
|
||||||
|
t.uiMutex.Lock()
|
||||||
t.mutex.Lock()
|
t.mutex.Lock()
|
||||||
for req, value := range *events {
|
for req, value := range *events {
|
||||||
switch req {
|
switch req {
|
||||||
@ -3497,7 +3541,7 @@ func (t *Terminal) Loop() error {
|
|||||||
t.printList()
|
t.printList()
|
||||||
case reqHeader:
|
case reqHeader:
|
||||||
t.printHeader()
|
t.printHeader()
|
||||||
case reqRefresh:
|
case reqActivate:
|
||||||
t.suppress = false
|
t.suppress = false
|
||||||
case reqRedrawBorderLabel:
|
case reqRedrawBorderLabel:
|
||||||
t.printLabel(t.border, t.borderLabel, t.borderLabelOpts, t.borderLabelLen, t.borderShape, true)
|
t.printLabel(t.border, t.borderLabel, t.borderLabelOpts, t.borderLabelLen, t.borderShape, true)
|
||||||
@ -3505,13 +3549,13 @@ func (t *Terminal) Loop() error {
|
|||||||
t.printLabel(t.pborder, t.previewLabel, t.previewLabelOpts, t.previewLabelLen, t.previewOpts.border, true)
|
t.printLabel(t.pborder, t.previewLabel, t.previewLabelOpts, t.previewLabelLen, t.previewOpts.border, true)
|
||||||
case reqReinit:
|
case reqReinit:
|
||||||
t.tui.Resume(t.fullscreen, t.sigstop)
|
t.tui.Resume(t.fullscreen, t.sigstop)
|
||||||
t.redraw()
|
t.fullRedraw()
|
||||||
case reqResize, reqFullRedraw:
|
case reqResize, reqFullRedraw:
|
||||||
if req == reqResize {
|
if req == reqResize {
|
||||||
t.termSize = t.tui.Size()
|
t.termSize = t.tui.Size()
|
||||||
}
|
}
|
||||||
wasHidden := t.pwindow == nil
|
wasHidden := t.pwindow == nil
|
||||||
t.redraw()
|
t.fullRedraw()
|
||||||
if wasHidden && t.hasPreviewWindow() {
|
if wasHidden && t.hasPreviewWindow() {
|
||||||
refreshPreview(t.previewOpts.command)
|
refreshPreview(t.previewOpts.command)
|
||||||
}
|
}
|
||||||
@ -3565,8 +3609,9 @@ func (t *Terminal) Loop() error {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.refresh()
|
t.flush()
|
||||||
t.mutex.Unlock()
|
t.mutex.Unlock()
|
||||||
|
t.uiMutex.Unlock()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3577,9 +3622,6 @@ func (t *Terminal) Loop() error {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
looping := true
|
looping := true
|
||||||
_, startEvent := t.keymap[tui.Start.AsEvent()]
|
|
||||||
|
|
||||||
needBarrier := true
|
|
||||||
barrier := make(chan bool)
|
barrier := make(chan bool)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
@ -3591,7 +3633,7 @@ func (t *Terminal) Loop() error {
|
|||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
case t.eventChan <- t.tui.GetChar():
|
case t.keyChan <- t.tui.GetChar():
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -3599,28 +3641,52 @@ func (t *Terminal) Loop() error {
|
|||||||
barDragging := false
|
barDragging := false
|
||||||
pbarDragging := false
|
pbarDragging := false
|
||||||
wasDown := false
|
wasDown := false
|
||||||
for looping {
|
needBarrier := true
|
||||||
|
|
||||||
|
// If an action is bound to 'start', we're going to process it before reading
|
||||||
|
// user input.
|
||||||
|
if !t.hasStartActions {
|
||||||
|
barrier <- true
|
||||||
|
needBarrier = false
|
||||||
|
}
|
||||||
|
for loopIndex := int64(0); looping; loopIndex++ {
|
||||||
var newCommand *commandSpec
|
var newCommand *commandSpec
|
||||||
var reloadSync bool
|
var reloadSync bool
|
||||||
changed := false
|
changed := false
|
||||||
beof := false
|
beof := false
|
||||||
queryChanged := false
|
queryChanged := false
|
||||||
|
|
||||||
|
// Special handling of --sync. Activate the interface on the second tick.
|
||||||
|
if loopIndex == 1 && t.deferActivation() {
|
||||||
|
t.reqBox.Set(reqActivate, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
if loopIndex > 0 && needBarrier {
|
||||||
|
barrier <- true
|
||||||
|
needBarrier = false
|
||||||
|
}
|
||||||
|
|
||||||
var event tui.Event
|
var event tui.Event
|
||||||
actions := []*action{}
|
actions := []*action{}
|
||||||
if startEvent {
|
select {
|
||||||
event = tui.Start.AsEvent()
|
case event = <-t.keyChan:
|
||||||
startEvent = false
|
needBarrier = true
|
||||||
} else {
|
case event = <-t.eventChan:
|
||||||
if needBarrier {
|
// Drain channel to process all queued events at once without rendering
|
||||||
barrier <- true
|
// the intermediate states
|
||||||
|
Drain:
|
||||||
|
for {
|
||||||
|
if eventActions, prs := t.keymap[event]; prs {
|
||||||
|
actions = append(actions, eventActions...)
|
||||||
}
|
}
|
||||||
|
for {
|
||||||
select {
|
select {
|
||||||
case event = <-t.eventChan:
|
case event = <-t.eventChan:
|
||||||
if t.tui.ShouldEmitResizeEvent() {
|
continue Drain
|
||||||
needBarrier = !event.Is(tui.Load, tui.Result, tui.Focus, tui.One, tui.Zero)
|
default:
|
||||||
} else {
|
break Drain
|
||||||
needBarrier = !event.Is(tui.Load, tui.Result, tui.Focus, tui.One, tui.Zero, tui.Resize)
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case serverActions := <-t.serverInputChan:
|
case serverActions := <-t.serverInputChan:
|
||||||
event = tui.Invalid.AsEvent()
|
event = tui.Invalid.AsEvent()
|
||||||
@ -3633,17 +3699,14 @@ func (t *Terminal) Loop() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
needBarrier = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
t.mutex.Lock()
|
t.mutex.Lock()
|
||||||
for key, ret := range t.expect {
|
for key, ret := range t.expect {
|
||||||
if keyMatch(key, event) {
|
if keyMatch(key, event) {
|
||||||
t.pressed = ret
|
t.pressed = ret
|
||||||
t.reqBox.Set(reqClose, nil)
|
|
||||||
t.mutex.Unlock()
|
t.mutex.Unlock()
|
||||||
|
t.reqBox.Set(reqClose, nil)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,15 +334,6 @@ type Event struct {
|
|||||||
MouseEvent *MouseEvent
|
MouseEvent *MouseEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Event) Is(types ...EventType) bool {
|
|
||||||
for _, t := range types {
|
|
||||||
if e.Type == t {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type MouseEvent struct {
|
type MouseEvent struct {
|
||||||
Y int
|
Y int
|
||||||
X int
|
X int
|
||||||
|
Loading…
Reference in New Issue
Block a user