diff options
| author | Junegunn Choi <junegunn.c@gmail.com> | 2024-05-07 01:06:42 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-07 01:06:42 +0900 |
| commit | e8405f40fe2eb3675f1cb4f69e825eff5f13f269 (patch) | |
| tree | c917367f1f0098939f9cdf7376a2a135907024fc /src/core.go | |
| parent | 065b9e6fb2ce3e6e50ff423c3786989afa04ee14 (diff) | |
| download | fzf-e8405f40fe2eb3675f1cb4f69e825eff5f13f269.tar.gz | |
Refactor the code so that fzf can be used as a library (#3769)
Diffstat (limited to 'src/core.go')
| -rw-r--r-- | src/core.go | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/src/core.go b/src/core.go index 14aa781f..dbae6a69 100644 --- a/src/core.go +++ b/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) { - defer util.RunAtExitFuncs() +func Run(opts *Options) (int, error) { + if err := postProcessOptions(opts); err != nil { + return ExitError, err + } - sort := opts.Sort > 0 - sortCriteria = opts.Criteria + defer util.RunAtExitFuncs() - if opts.Version { - if len(revision) > 0 { - fmt.Printf("%s (%s)\n", version, revision) - } else { - fmt.Println(version) + // Output channel given + if opts.Output != nil { + opts.Printer = func(str string) { + opts.Output <- str } - util.Exit(exitOk) } + sort := opts.Sort > 0 + sortCriteria = opts.Criteria + // 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 } |
