mirror of
https://github.com/junegunn/fzf.git
synced 2025-08-15 12:13:52 -07:00
Refactor the code so that fzf can be used as a library (#3769)
This commit is contained in:
68
src/core.go
68
src/core.go
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user