Refactor the code so that fzf can be used as a library (#3769)

This commit is contained in:
Junegunn Choi
2024-05-07 01:06:42 +09:00
committed by GitHub
parent 065b9e6fb2
commit e8405f40fe
32 changed files with 1152 additions and 893 deletions

View File

@@ -2,7 +2,6 @@
package fzf
import (
"fmt"
"sync"
"time"
"unsafe"
@@ -27,22 +26,29 @@ func sbytes(data string) []byte {
return unsafe.Slice(unsafe.StringData(data), len(data))
}
type quitSignal struct {
code int
err error
}
// Run starts fzf
func Run(opts *Options, version string, revision string) {
func Run(opts *Options) (int, error) {
if err := postProcessOptions(opts); err != nil {
return ExitError, err
}
defer util.RunAtExitFuncs()
// Output channel given
if opts.Output != nil {
opts.Printer = func(str string) {
opts.Output <- str
}
}
sort := opts.Sort > 0
sortCriteria = opts.Criteria
if opts.Version {
if len(revision) > 0 {
fmt.Printf("%s (%s)\n", version, revision)
} else {
fmt.Println(version)
}
util.Exit(exitOk)
}
// Event channel
eventBox := util.NewEventBox()
@@ -131,7 +137,7 @@ func Run(opts *Options, version string, revision string) {
reader = NewReader(func(data []byte) bool {
return chunkList.Push(data)
}, eventBox, executor, opts.ReadZero, opts.Filter == nil)
go reader.ReadSource(opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip)
go reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip)
}
// Matcher
@@ -147,14 +153,16 @@ func Run(opts *Options, version string, revision string) {
forward = true
}
}
cache := NewChunkCache()
patternCache := make(map[string]*Pattern)
patternBuilder := func(runes []rune) *Pattern {
return BuildPattern(
return BuildPattern(cache, patternCache,
opts.Fuzzy, opts.FuzzyAlgo, opts.Extended, opts.Case, opts.Normalize, forward, withPos,
opts.Filter == nil, opts.Nth, opts.Delimiter, runes)
}
inputRevision := 0
snapshotRevision := 0
matcher := NewMatcher(patternBuilder, sort, opts.Tac, eventBox, inputRevision)
matcher := NewMatcher(cache, patternBuilder, sort, opts.Tac, eventBox, inputRevision)
// Filtering mode
if opts.Filter != nil {
@@ -182,7 +190,7 @@ func Run(opts *Options, version string, revision string) {
}
return false
}, eventBox, executor, opts.ReadZero, false)
reader.ReadSource(opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip)
reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip)
} else {
eventBox.Unwatch(EvtReadNew)
eventBox.WaitFor(EvtReadFin)
@@ -197,9 +205,9 @@ func Run(opts *Options, version string, revision string) {
}
}
if found {
util.Exit(exitOk)
return ExitOk, nil
}
util.Exit(exitNoMatch)
return ExitNoMatch, nil
}
// Synchronous search
@@ -210,9 +218,13 @@ func Run(opts *Options, version string, revision string) {
// Go interactive
go matcher.Loop()
defer matcher.Stop()
// Terminal I/O
terminal := NewTerminal(opts, eventBox, executor)
terminal, err := NewTerminal(opts, eventBox, executor)
if err != nil {
return ExitError, err
}
maxFit := 0 // Maximum number of items that can fit on screen
padHeight := 0
heightUnknown := opts.Height.auto
@@ -258,6 +270,9 @@ func Run(opts *Options, version string, revision string) {
header = make([]string, 0, opts.HeaderLines)
go reader.restart(command, environ)
}
exitCode := ExitOk
stop := false
for {
delay := true
ticks++
@@ -278,7 +293,11 @@ func Run(opts *Options, version string, revision string) {
if reading {
reader.terminate()
}
util.Exit(value.(int))
quitSignal := value.(quitSignal)
exitCode = quitSignal.code
err = quitSignal.err
stop = true
return
case EvtReadNew, EvtReadFin:
if evt == EvtReadFin && nextCommand != nil {
restart(*nextCommand, nextEnviron)
@@ -378,10 +397,11 @@ func Run(opts *Options, version string, revision string) {
for i := 0; i < count; i++ {
opts.Printer(val.Get(i).item.AsString(opts.Ansi))
}
if count > 0 {
util.Exit(exitOk)
if count == 0 {
exitCode = ExitNoMatch
}
util.Exit(exitNoMatch)
stop = true
return
}
determine(val.final)
}
@@ -392,6 +412,9 @@ func Run(opts *Options, version string, revision string) {
}
events.Clear()
})
if stop {
break
}
if delay && reading {
dur := util.DurWithin(
time.Duration(ticks)*coordinatorDelayStep,
@@ -399,4 +422,5 @@ func Run(opts *Options, version string, revision string) {
time.Sleep(dur)
}
}
return exitCode, err
}