From 07b98cb91243293e26564058a78f28b83aa81cd4 Mon Sep 17 00:00:00 2001 From: Eyal Posener Date: Sat, 6 May 2017 19:08:47 +0300 Subject: [PATCH] Use pointers to predicates --- command.go | 10 ++++------ gocomplete/complete.go | 12 ++++++------ gocomplete/tests.go | 4 ++-- predicate.go | 34 ++++++++++++++++------------------ run_test.go | 6 +++--- 5 files changed, 31 insertions(+), 35 deletions(-) diff --git a/command.go b/command.go index 253f8e7..7bc0fc5 100644 --- a/command.go +++ b/command.go @@ -2,13 +2,13 @@ package complete type Commands map[string]Command -type Flags map[string]Predicate +type Flags map[string]*Predicate type Command struct { Name string Sub Commands Flags Flags - Args Predicate + Args *Predicate } // options returns all available complete options for the given command @@ -20,7 +20,7 @@ func (c *Command) options(args []string) (options []Option, only bool) { // if prev has something that needs to follow it, // it is the most relevant completion - if predicate, ok := c.Flags[last(args)]; ok && !predicate.ExpectsNothing { + if predicate, ok := c.Flags[last(args)]; ok && predicate != nil { return predicate.predict(), true } @@ -41,9 +41,7 @@ func (c *Command) options(args []string) (options []Option, only bool) { } // add additional expected argument of the command - if !c.Args.ExpectsNothing { - options = append(options, c.Args.predict()...) - } + options = append(options, c.Args.predict()...) return } diff --git a/gocomplete/complete.go b/gocomplete/complete.go index 7dc1694..60a9835 100644 --- a/gocomplete/complete.go +++ b/gocomplete/complete.go @@ -4,13 +4,13 @@ import ( "github.com/posener/complete" ) -var predictEllipsis = complete.Predicate{ - Predictor: func() []complete.Option { return []complete.Option{complete.Arg("./...")} }, -} +var ( + predictEllipsis = complete.PredictSet("./...") -var goFilesOrPackages = complete.PredictFiles("**.go"). - Or(complete.PredictDirs("./")). - Or(predictEllipsis) + goFilesOrPackages = complete.PredictFiles("**.go"). + Or(complete.PredictDirs("./")). + Or(predictEllipsis) +) func main() { build := complete.Command{ diff --git a/gocomplete/tests.go b/gocomplete/tests.go index 388b7b7..0ab99ec 100644 --- a/gocomplete/tests.go +++ b/gocomplete/tests.go @@ -11,8 +11,8 @@ import ( "github.com/posener/complete" ) -func predictTest(testType string) complete.Predicate { - return complete.Predicate{ +func predictTest(testType string) *complete.Predicate { + return &complete.Predicate{ Predictor: func() []complete.Option { tests := testNames(testType) options := make([]complete.Option, len(tests)) diff --git a/predicate.go b/predicate.go index bcf48b8..0740cfb 100644 --- a/predicate.go +++ b/predicate.go @@ -7,10 +7,6 @@ import ( // Predicate determines what terms can follow a command or a flag type Predicate struct { - // ExpectsNothing determine if the predicate expects something after. - // flags/commands that do not expect any specific argument should - // leave it on false - ExpectsNothing bool // Predictor is function that returns list of arguments that can // come after the flag/command Predictor func() []Option @@ -18,27 +14,29 @@ type Predicate struct { // Or unions two predicate struct, so that the result predicate // returns the union of their predication -func (p Predicate) Or(other Predicate) Predicate { - return Predicate{ - ExpectsNothing: p.ExpectsNothing && other.ExpectsNothing, - Predictor: func() []Option { return append(p.predict(), other.predict()...) }, +func (p *Predicate) Or(other *Predicate) *Predicate { + if p == nil || other == nil { + return nil + } + return &Predicate{ + Predictor: func() []Option { return append(p.predict(), other.predict()...) }, } } -func (p Predicate) predict() []Option { - if p.Predictor == nil { +func (p *Predicate) predict() []Option { + if p == nil || p.Predictor == nil { return nil } return p.Predictor() } var ( - PredictNothing = Predicate{ExpectsNothing: true} - PredictAnything = Predicate{} + PredictNothing *Predicate = nil + PredictAnything = &Predicate{} ) -func PredictSet(options ...string) Predicate { - return Predicate{ +func PredictSet(options ...string) *Predicate { + return &Predicate{ Predictor: func() []Option { ret := make([]Option, len(options)) for i := range options { @@ -49,12 +47,12 @@ func PredictSet(options ...string) Predicate { } } -func PredictFiles(pattern string) Predicate { - return Predicate{Predictor: glob(pattern)} +func PredictFiles(pattern string) *Predicate { + return &Predicate{Predictor: glob(pattern)} } -func PredictDirs(path string) Predicate { - return Predicate{Predictor: dirs(path)} +func PredictDirs(path string) *Predicate { + return &Predicate{Predictor: dirs(path)} } func dirs(path string) func() []Option { diff --git a/run_test.go b/run_test.go index 0e18850..9800b6a 100644 --- a/run_test.go +++ b/run_test.go @@ -16,20 +16,20 @@ func TestCompleter_Complete(t *testing.T) { c := Command{ Sub: map[string]Command{ "sub1": { - Flags: map[string]Predicate{ + Flags: map[string]*Predicate{ "-flag1": PredictAnything, "-flag2": PredictNothing, }, }, "sub2": { - Flags: map[string]Predicate{ + Flags: map[string]*Predicate{ "-flag2": PredictNothing, "-flag3": PredictSet("opt1", "opt2", "opt12"), }, Args: PredictDirs("./tests/").Or(PredictFiles("./tests/*.md")), }, }, - Flags: map[string]Predicate{ + Flags: map[string]*Predicate{ "-h": PredictNothing, "-global1": PredictAnything, "-o": PredictFiles("./tests/*.txt"),