2022-08-12 13:11:15 +00:00
|
|
|
// Package fzf implements fzf, a command-line fuzzy finder.
|
2015-01-01 19:49:30 +00:00
|
|
|
package fzf
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"time"
|
2015-01-12 03:56:17 +00:00
|
|
|
|
|
|
|
"github.com/junegunn/fzf/src/util"
|
2015-01-01 19:49:30 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
/*
|
2015-01-11 18:01:24 +00:00
|
|
|
Reader -> EvtReadFin
|
|
|
|
Reader -> EvtReadNew -> Matcher (restart)
|
2015-03-31 13:05:02 +00:00
|
|
|
Terminal -> EvtSearchNew:bool -> Matcher (restart)
|
2015-01-11 18:01:24 +00:00
|
|
|
Matcher -> EvtSearchProgress -> Terminal (update info)
|
|
|
|
Matcher -> EvtSearchFin -> Terminal (update list)
|
2015-07-21 18:21:20 +00:00
|
|
|
Matcher -> EvtHeader -> Terminal (update header)
|
2015-01-01 19:49:30 +00:00
|
|
|
*/
|
|
|
|
|
2015-01-11 18:01:24 +00:00
|
|
|
// Run starts fzf
|
2020-10-26 16:46:43 +00:00
|
|
|
func Run(opts *Options, version string, revision string) {
|
2015-03-31 13:05:02 +00:00
|
|
|
sort := opts.Sort > 0
|
2016-01-12 18:07:42 +00:00
|
|
|
sortCriteria = opts.Criteria
|
2015-01-01 19:49:30 +00:00
|
|
|
|
|
|
|
if opts.Version {
|
2017-06-02 08:57:28 +00:00
|
|
|
if len(revision) > 0 {
|
|
|
|
fmt.Printf("%s (%s)\n", version, revision)
|
|
|
|
} else {
|
|
|
|
fmt.Println(version)
|
|
|
|
}
|
2015-09-15 04:21:51 +00:00
|
|
|
os.Exit(exitOk)
|
2015-01-01 19:49:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Event channel
|
2015-01-12 03:56:17 +00:00
|
|
|
eventBox := util.NewEventBox()
|
2015-01-01 19:49:30 +00:00
|
|
|
|
2015-03-18 16:59:14 +00:00
|
|
|
// ANSI code processor
|
2016-08-18 17:39:32 +00:00
|
|
|
ansiProcessor := func(data []byte) (util.Chars, *[]ansiOffset) {
|
2016-08-13 15:39:44 +00:00
|
|
|
return util.ToChars(data), nil
|
2015-08-02 05:25:57 +00:00
|
|
|
}
|
2019-03-06 10:05:05 +00:00
|
|
|
|
|
|
|
var lineAnsiState, prevLineAnsiState *ansiState
|
2015-03-18 16:59:14 +00:00
|
|
|
if opts.Ansi {
|
2020-10-25 10:29:37 +00:00
|
|
|
if opts.Theme.Colored {
|
2016-08-18 17:39:32 +00:00
|
|
|
ansiProcessor = func(data []byte) (util.Chars, *[]ansiOffset) {
|
2019-03-06 10:05:05 +00:00
|
|
|
prevLineAnsiState = lineAnsiState
|
|
|
|
trimmed, offsets, newState := extractColor(string(data), lineAnsiState, nil)
|
|
|
|
lineAnsiState = newState
|
2017-07-21 08:29:14 +00:00
|
|
|
return util.ToChars([]byte(trimmed)), offsets
|
2015-03-18 16:59:14 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// When color is disabled but ansi option is given,
|
|
|
|
// we simply strip out ANSI codes from the input
|
2016-08-18 17:39:32 +00:00
|
|
|
ansiProcessor = func(data []byte) (util.Chars, *[]ansiOffset) {
|
2016-06-14 12:52:47 +00:00
|
|
|
trimmed, _, _ := extractColor(string(data), nil, nil)
|
2017-07-21 08:29:14 +00:00
|
|
|
return util.ToChars([]byte(trimmed)), nil
|
2015-03-18 16:59:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-01 19:49:30 +00:00
|
|
|
// Chunk list
|
|
|
|
var chunkList *ChunkList
|
2017-08-16 03:26:06 +00:00
|
|
|
var itemIndex int32
|
2015-07-21 18:21:20 +00:00
|
|
|
header := make([]string, 0, opts.HeaderLines)
|
2015-01-01 19:49:30 +00:00
|
|
|
if len(opts.WithNth) == 0 {
|
2017-08-16 03:26:06 +00:00
|
|
|
chunkList = NewChunkList(func(item *Item, data []byte) bool {
|
2015-07-21 18:21:20 +00:00
|
|
|
if len(header) < opts.HeaderLines {
|
2015-08-02 05:00:18 +00:00
|
|
|
header = append(header, string(data))
|
2015-07-21 18:21:20 +00:00
|
|
|
eventBox.Set(EvtHeader, header)
|
2017-08-14 16:10:41 +00:00
|
|
|
return false
|
2015-07-21 18:21:20 +00:00
|
|
|
}
|
2017-08-14 16:10:41 +00:00
|
|
|
item.text, item.colors = ansiProcessor(data)
|
2017-08-16 03:26:06 +00:00
|
|
|
item.text.Index = itemIndex
|
|
|
|
itemIndex++
|
2017-08-14 16:10:41 +00:00
|
|
|
return true
|
2015-01-01 19:49:30 +00:00
|
|
|
})
|
|
|
|
} else {
|
2017-08-16 03:26:06 +00:00
|
|
|
chunkList = NewChunkList(func(item *Item, data []byte) bool {
|
2017-07-19 17:44:30 +00:00
|
|
|
tokens := Tokenize(string(data), opts.Delimiter)
|
2020-10-25 10:29:37 +00:00
|
|
|
if opts.Ansi && opts.Theme.Colored && len(tokens) > 1 {
|
2019-03-06 10:05:05 +00:00
|
|
|
var ansiState *ansiState
|
|
|
|
if prevLineAnsiState != nil {
|
|
|
|
ansiStateDup := *prevLineAnsiState
|
|
|
|
ansiState = &ansiStateDup
|
|
|
|
}
|
|
|
|
for _, token := range tokens {
|
|
|
|
prevAnsiState := ansiState
|
|
|
|
_, _, ansiState = extractColor(token.text.ToString(), ansiState, nil)
|
|
|
|
if prevAnsiState != nil {
|
2019-03-07 01:47:09 +00:00
|
|
|
token.text.Prepend("\x1b[m" + prevAnsiState.ToString())
|
|
|
|
} else {
|
|
|
|
token.text.Prepend("\x1b[m")
|
2019-03-06 10:05:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-07-22 12:24:02 +00:00
|
|
|
trans := Transform(tokens, opts.WithNth)
|
2017-07-19 17:44:30 +00:00
|
|
|
transformed := joinTokens(trans)
|
2015-07-21 18:21:20 +00:00
|
|
|
if len(header) < opts.HeaderLines {
|
2017-07-19 17:44:30 +00:00
|
|
|
header = append(header, transformed)
|
2015-07-21 18:21:20 +00:00
|
|
|
eventBox.Set(EvtHeader, header)
|
2017-08-14 16:10:41 +00:00
|
|
|
return false
|
2015-07-21 18:21:20 +00:00
|
|
|
}
|
2017-08-14 16:10:41 +00:00
|
|
|
item.text, item.colors = ansiProcessor([]byte(transformed))
|
2019-11-12 13:45:25 +00:00
|
|
|
item.text.TrimTrailingWhitespaces()
|
2017-08-16 03:26:06 +00:00
|
|
|
item.text.Index = itemIndex
|
2017-08-14 16:10:41 +00:00
|
|
|
item.origText = &data
|
2017-08-16 03:26:06 +00:00
|
|
|
itemIndex++
|
2017-08-14 16:10:41 +00:00
|
|
|
return true
|
2015-01-01 19:49:30 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reader
|
2015-03-31 13:05:02 +00:00
|
|
|
streamingFilter := opts.Filter != nil && !sort && !opts.Tac && !opts.Sync
|
2019-11-10 02:36:22 +00:00
|
|
|
var reader *Reader
|
2015-03-01 02:16:38 +00:00
|
|
|
if !streamingFilter {
|
2019-11-10 02:36:22 +00:00
|
|
|
reader = NewReader(func(data []byte) bool {
|
2015-08-02 05:00:18 +00:00
|
|
|
return chunkList.Push(data)
|
2019-11-11 03:53:03 +00:00
|
|
|
}, eventBox, opts.ReadZero, opts.Filter == nil)
|
2015-03-01 02:16:38 +00:00
|
|
|
go reader.ReadSource()
|
|
|
|
}
|
2015-01-01 19:49:30 +00:00
|
|
|
|
|
|
|
// Matcher
|
2016-01-12 18:07:42 +00:00
|
|
|
forward := true
|
2022-08-03 13:18:26 +00:00
|
|
|
withPos := false
|
|
|
|
for idx := len(opts.Criteria) - 1; idx > 0; idx-- {
|
|
|
|
switch opts.Criteria[idx] {
|
|
|
|
case byChunk:
|
|
|
|
withPos = true
|
|
|
|
case byEnd:
|
2016-01-12 18:07:42 +00:00
|
|
|
forward = false
|
2022-08-03 13:18:26 +00:00
|
|
|
case byBegin:
|
|
|
|
forward = true
|
2016-01-12 18:07:42 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-01 19:49:30 +00:00
|
|
|
patternBuilder := func(runes []rune) *Pattern {
|
|
|
|
return BuildPattern(
|
2022-08-03 13:18:26 +00:00
|
|
|
opts.Fuzzy, opts.FuzzyAlgo, opts.Extended, opts.Case, opts.Normalize, forward, withPos,
|
2016-09-07 00:58:18 +00:00
|
|
|
opts.Filter == nil, opts.Nth, opts.Delimiter, runes)
|
2015-01-01 19:49:30 +00:00
|
|
|
}
|
2015-03-31 13:05:02 +00:00
|
|
|
matcher := NewMatcher(patternBuilder, sort, opts.Tac, eventBox)
|
2015-01-01 19:49:30 +00:00
|
|
|
|
2015-02-17 15:08:17 +00:00
|
|
|
// Filtering mode
|
|
|
|
if opts.Filter != nil {
|
|
|
|
if opts.PrintQuery {
|
2016-09-17 19:52:47 +00:00
|
|
|
opts.Printer(*opts.Filter)
|
2015-01-01 19:49:30 +00:00
|
|
|
}
|
2015-03-01 02:16:38 +00:00
|
|
|
|
|
|
|
pattern := patternBuilder([]rune(*opts.Filter))
|
2018-12-19 14:05:29 +00:00
|
|
|
matcher.sort = pattern.sortable
|
2015-03-01 02:16:38 +00:00
|
|
|
|
2015-09-15 04:21:51 +00:00
|
|
|
found := false
|
2015-03-01 02:16:38 +00:00
|
|
|
if streamingFilter {
|
2016-09-07 00:58:18 +00:00
|
|
|
slab := util.MakeSlab(slab16Size, slab32Size)
|
2017-08-15 18:24:23 +00:00
|
|
|
reader := NewReader(
|
2015-08-02 05:25:57 +00:00
|
|
|
func(runes []byte) bool {
|
2017-08-14 16:10:41 +00:00
|
|
|
item := Item{}
|
2017-08-16 03:26:06 +00:00
|
|
|
if chunkList.trans(&item, runes) {
|
2017-07-15 03:28:29 +00:00
|
|
|
if result, _, _ := pattern.MatchItem(&item, false, slab); result != nil {
|
2016-09-17 19:52:47 +00:00
|
|
|
opts.Printer(item.text.ToString())
|
2016-08-19 16:46:54 +00:00
|
|
|
found = true
|
|
|
|
}
|
2015-03-01 02:16:38 +00:00
|
|
|
}
|
2015-07-21 18:21:20 +00:00
|
|
|
return false
|
2019-11-11 03:53:03 +00:00
|
|
|
}, eventBox, opts.ReadZero, false)
|
2015-03-01 02:16:38 +00:00
|
|
|
reader.ReadSource()
|
|
|
|
} else {
|
|
|
|
eventBox.Unwatch(EvtReadNew)
|
|
|
|
eventBox.WaitFor(EvtReadFin)
|
|
|
|
|
|
|
|
snapshot, _ := chunkList.Snapshot()
|
|
|
|
merger, _ := matcher.scan(MatchRequest{
|
|
|
|
chunks: snapshot,
|
|
|
|
pattern: pattern})
|
|
|
|
for i := 0; i < merger.Length(); i++ {
|
2016-09-17 19:52:47 +00:00
|
|
|
opts.Printer(merger.Get(i).item.AsString(opts.Ansi))
|
2015-09-15 04:21:51 +00:00
|
|
|
found = true
|
2015-03-01 02:16:38 +00:00
|
|
|
}
|
2015-02-17 15:08:17 +00:00
|
|
|
}
|
2015-09-15 04:21:51 +00:00
|
|
|
if found {
|
|
|
|
os.Exit(exitOk)
|
|
|
|
}
|
|
|
|
os.Exit(exitNoMatch)
|
2015-01-01 19:49:30 +00:00
|
|
|
}
|
|
|
|
|
2015-02-13 03:25:19 +00:00
|
|
|
// Synchronous search
|
|
|
|
if opts.Sync {
|
|
|
|
eventBox.Unwatch(EvtReadNew)
|
|
|
|
eventBox.WaitFor(EvtReadFin)
|
|
|
|
}
|
|
|
|
|
2015-01-01 19:49:30 +00:00
|
|
|
// Go interactive
|
|
|
|
go matcher.Loop()
|
|
|
|
|
|
|
|
// Terminal I/O
|
|
|
|
terminal := NewTerminal(opts, eventBox)
|
2022-09-07 16:01:22 +00:00
|
|
|
maxFit := 0 // Maximum number of items that can fit on screen
|
|
|
|
padHeight := 0
|
|
|
|
heightUnknown := opts.Height.auto
|
|
|
|
if heightUnknown {
|
|
|
|
maxFit, padHeight = terminal.MaxFitAndPad(opts)
|
|
|
|
}
|
2015-02-17 15:08:17 +00:00
|
|
|
deferred := opts.Select1 || opts.Exit0
|
2015-01-01 19:49:30 +00:00
|
|
|
go terminal.Loop()
|
2022-09-07 16:01:22 +00:00
|
|
|
if !deferred && !heightUnknown {
|
|
|
|
// Start right away
|
|
|
|
terminal.startChan <- fitpad{-1, -1}
|
2015-02-17 15:08:17 +00:00
|
|
|
}
|
2015-01-01 19:49:30 +00:00
|
|
|
|
|
|
|
// Event coordination
|
|
|
|
reading := true
|
2019-12-09 12:32:58 +00:00
|
|
|
clearCache := util.Once(false)
|
|
|
|
clearSelection := util.Once(false)
|
2015-01-01 19:49:30 +00:00
|
|
|
ticks := 0
|
2019-11-10 02:36:22 +00:00
|
|
|
var nextCommand *string
|
2015-01-11 18:01:24 +00:00
|
|
|
eventBox.Watch(EvtReadNew)
|
2022-09-07 16:01:22 +00:00
|
|
|
total := 0
|
2021-01-02 15:00:40 +00:00
|
|
|
query := []rune{}
|
2022-09-07 16:01:22 +00:00
|
|
|
determine := func(final bool) {
|
|
|
|
if heightUnknown {
|
|
|
|
if total >= maxFit || final {
|
2023-04-02 14:26:13 +00:00
|
|
|
deferred = false
|
2022-09-07 16:01:22 +00:00
|
|
|
heightUnknown = false
|
|
|
|
terminal.startChan <- fitpad{util.Min(total, maxFit), padHeight}
|
|
|
|
}
|
|
|
|
} else if deferred {
|
|
|
|
deferred = false
|
|
|
|
terminal.startChan <- fitpad{-1, -1}
|
|
|
|
}
|
|
|
|
}
|
2022-12-29 11:03:51 +00:00
|
|
|
|
|
|
|
useSnapshot := false
|
|
|
|
var snapshot []*Chunk
|
|
|
|
var prevSnapshot []*Chunk
|
|
|
|
var count int
|
|
|
|
restart := func(command string) {
|
|
|
|
reading = true
|
|
|
|
clearCache = util.Once(true)
|
|
|
|
clearSelection = util.Once(true)
|
|
|
|
// We should not update snapshot if reload is triggered again while
|
|
|
|
// the previous reload is in progress
|
|
|
|
if useSnapshot && prevSnapshot != nil {
|
|
|
|
snapshot, count = chunkList.Snapshot()
|
|
|
|
}
|
|
|
|
chunkList.Clear()
|
|
|
|
itemIndex = 0
|
|
|
|
header = make([]string, 0, opts.HeaderLines)
|
|
|
|
go reader.restart(command)
|
|
|
|
}
|
2015-01-01 19:49:30 +00:00
|
|
|
for {
|
|
|
|
delay := true
|
2015-01-11 18:01:24 +00:00
|
|
|
ticks++
|
2022-04-04 12:54:22 +00:00
|
|
|
input := func(reloaded bool) []rune {
|
2021-01-02 15:00:40 +00:00
|
|
|
paused, input := terminal.Input()
|
2022-04-04 12:54:22 +00:00
|
|
|
if reloaded && paused {
|
|
|
|
query = []rune{}
|
|
|
|
} else if !paused {
|
2021-01-02 15:00:40 +00:00
|
|
|
query = input
|
2019-11-09 13:54:48 +00:00
|
|
|
}
|
2021-01-02 15:00:40 +00:00
|
|
|
return query
|
2019-11-09 13:54:48 +00:00
|
|
|
}
|
2015-01-12 03:56:17 +00:00
|
|
|
eventBox.Wait(func(events *util.Events) {
|
2017-08-20 05:29:50 +00:00
|
|
|
if _, fin := (*events)[EvtReadFin]; fin {
|
|
|
|
delete(*events, EvtReadNew)
|
|
|
|
}
|
2015-01-01 19:49:30 +00:00
|
|
|
for evt, value := range *events {
|
|
|
|
switch evt {
|
2021-03-07 02:30:26 +00:00
|
|
|
case EvtQuit:
|
|
|
|
if reading {
|
|
|
|
reader.terminate()
|
|
|
|
}
|
|
|
|
os.Exit(value.(int))
|
2015-01-11 18:01:24 +00:00
|
|
|
case EvtReadNew, EvtReadFin:
|
2019-11-10 02:36:22 +00:00
|
|
|
if evt == EvtReadFin && nextCommand != nil {
|
2019-11-11 15:10:24 +00:00
|
|
|
restart(*nextCommand)
|
2019-11-10 02:36:22 +00:00
|
|
|
nextCommand = nil
|
2019-12-05 13:25:43 +00:00
|
|
|
break
|
2019-11-10 02:36:22 +00:00
|
|
|
} else {
|
|
|
|
reading = reading && evt == EvtReadNew
|
|
|
|
}
|
2022-12-29 11:03:51 +00:00
|
|
|
if useSnapshot && evt == EvtReadFin {
|
|
|
|
useSnapshot = false
|
|
|
|
prevSnapshot = nil
|
|
|
|
}
|
|
|
|
if !useSnapshot {
|
|
|
|
snapshot, count = chunkList.Snapshot()
|
|
|
|
}
|
2022-09-07 16:01:22 +00:00
|
|
|
total = count
|
|
|
|
terminal.UpdateCount(total, !reading, value.(*string))
|
2017-08-19 16:58:51 +00:00
|
|
|
if opts.Sync {
|
2019-12-09 12:32:58 +00:00
|
|
|
opts.Sync = false
|
|
|
|
terminal.UpdateList(PassMerger(&snapshot, opts.Tac), false)
|
2017-08-19 16:58:51 +00:00
|
|
|
}
|
2022-09-07 16:01:22 +00:00
|
|
|
if heightUnknown && !deferred {
|
|
|
|
determine(!reading)
|
|
|
|
}
|
2022-12-31 00:33:23 +00:00
|
|
|
reset := !useSnapshot && clearCache()
|
2022-04-04 12:54:22 +00:00
|
|
|
matcher.Reset(snapshot, input(reset), false, !reading, sort, reset)
|
2015-01-01 19:49:30 +00:00
|
|
|
|
2015-01-11 18:01:24 +00:00
|
|
|
case EvtSearchNew:
|
2019-11-10 02:36:22 +00:00
|
|
|
var command *string
|
2015-04-16 05:44:41 +00:00
|
|
|
switch val := value.(type) {
|
2019-11-10 02:36:22 +00:00
|
|
|
case searchRequest:
|
|
|
|
sort = val.sort
|
|
|
|
command = val.command
|
2022-12-29 11:03:51 +00:00
|
|
|
if command != nil {
|
|
|
|
useSnapshot = val.sync
|
|
|
|
}
|
2019-11-10 02:36:22 +00:00
|
|
|
}
|
|
|
|
if command != nil {
|
|
|
|
if reading {
|
|
|
|
reader.terminate()
|
|
|
|
nextCommand = command
|
|
|
|
} else {
|
2019-11-11 15:10:24 +00:00
|
|
|
restart(*command)
|
2019-11-10 02:36:22 +00:00
|
|
|
}
|
2019-12-05 13:25:43 +00:00
|
|
|
break
|
2015-03-31 13:05:02 +00:00
|
|
|
}
|
2022-12-29 11:03:51 +00:00
|
|
|
if !useSnapshot {
|
|
|
|
snapshot, _ = chunkList.Snapshot()
|
|
|
|
}
|
2022-12-31 00:33:23 +00:00
|
|
|
reset := !useSnapshot && clearCache()
|
2022-04-04 12:54:22 +00:00
|
|
|
matcher.Reset(snapshot, input(reset), true, !reading, sort, reset)
|
2015-01-01 19:49:30 +00:00
|
|
|
delay = false
|
|
|
|
|
2015-01-11 18:01:24 +00:00
|
|
|
case EvtSearchProgress:
|
2015-01-01 19:49:30 +00:00
|
|
|
switch val := value.(type) {
|
|
|
|
case float32:
|
|
|
|
terminal.UpdateProgress(val)
|
|
|
|
}
|
|
|
|
|
2015-07-21 18:21:20 +00:00
|
|
|
case EvtHeader:
|
2019-12-16 09:47:05 +00:00
|
|
|
headerPadded := make([]string, opts.HeaderLines)
|
|
|
|
copy(headerPadded, value.([]string))
|
|
|
|
terminal.UpdateHeader(headerPadded)
|
2015-07-21 18:21:20 +00:00
|
|
|
|
2015-01-11 18:01:24 +00:00
|
|
|
case EvtSearchFin:
|
2015-01-01 19:49:30 +00:00
|
|
|
switch val := value.(type) {
|
2015-01-09 16:06:08 +00:00
|
|
|
case *Merger:
|
2015-02-17 15:08:17 +00:00
|
|
|
if deferred {
|
|
|
|
count := val.Length()
|
|
|
|
if opts.Select1 && count > 1 || opts.Exit0 && !opts.Select1 && count > 0 {
|
2022-09-07 16:01:22 +00:00
|
|
|
determine(val.final)
|
2015-02-17 15:51:44 +00:00
|
|
|
} else if val.final {
|
2015-02-17 15:08:17 +00:00
|
|
|
if opts.Exit0 && count == 0 || opts.Select1 && count == 1 {
|
|
|
|
if opts.PrintQuery {
|
2016-09-17 19:52:47 +00:00
|
|
|
opts.Printer(opts.Query)
|
2015-02-17 15:08:17 +00:00
|
|
|
}
|
2015-03-31 11:52:16 +00:00
|
|
|
if len(opts.Expect) > 0 {
|
2016-09-17 19:52:47 +00:00
|
|
|
opts.Printer("")
|
2015-03-31 11:52:16 +00:00
|
|
|
}
|
2015-02-17 15:08:17 +00:00
|
|
|
for i := 0; i < count; i++ {
|
2016-09-17 19:52:47 +00:00
|
|
|
opts.Printer(val.Get(i).item.AsString(opts.Ansi))
|
2015-02-17 15:08:17 +00:00
|
|
|
}
|
2015-09-15 04:21:51 +00:00
|
|
|
if count > 0 {
|
|
|
|
os.Exit(exitOk)
|
|
|
|
}
|
|
|
|
os.Exit(exitNoMatch)
|
2015-02-17 15:08:17 +00:00
|
|
|
}
|
2022-09-07 16:01:22 +00:00
|
|
|
determine(val.final)
|
2015-02-17 15:08:17 +00:00
|
|
|
}
|
|
|
|
}
|
2019-12-09 12:32:58 +00:00
|
|
|
terminal.UpdateList(val, clearSelection())
|
2015-01-01 19:49:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-07-31 18:39:57 +00:00
|
|
|
events.Clear()
|
2015-01-01 19:49:30 +00:00
|
|
|
})
|
2015-01-08 13:07:04 +00:00
|
|
|
if delay && reading {
|
2015-01-12 03:56:17 +00:00
|
|
|
dur := util.DurWithin(
|
2015-01-11 18:01:24 +00:00
|
|
|
time.Duration(ticks)*coordinatorDelayStep,
|
|
|
|
0, coordinatorDelayMax)
|
2015-01-08 13:07:04 +00:00
|
|
|
time.Sleep(dur)
|
2015-01-01 19:49:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|