diff --git a/README.md b/README.md index 13b7feed52..0b587b448b 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,11 @@ $ which -a pkg-config /usr/bin/pkg-config ``` -To compile and use the REPL, use the following command: +To compile and use the REPL, use the following command to run the repl with suggestions enabled: ``` $ go build ./cmd/flux -$ ./flux repl +$ ./flux --enable-suggestions ``` Alternatively, because the `pkg-config` wrapper may not work in all projects you may not want to add the wrapper `pkg-config` to your `PATH`. In this case you can set `PKG_CONFIG` and Go will use it. Eg, to build and install to ${GOPATH}/bin using `PKG_CONFIG`: diff --git a/cmd/flux/main.go b/cmd/flux/main.go index 9dc5418b6e..8ac1680f2a 100644 --- a/cmd/flux/main.go +++ b/cmd/flux/main.go @@ -21,10 +21,11 @@ import ( ) var flags struct { - ExecScript bool - Trace string - Format string - Features string + ExecScript bool + Trace string + Format string + Features string + EnableSuggestions bool } func runE(cmd *cobra.Command, args []string) error { @@ -63,7 +64,7 @@ func runE(cmd *cobra.Command, args []string) error { ctx = feature.Dependency{Flagger: flagger}.Inject(ctx) if len(args) == 0 { - return replE(ctx) + return replE(ctx, flags.EnableSuggestions) } return executeE(ctx, script, flags.Format) } @@ -115,6 +116,7 @@ func main() { SilenceUsage: true, } fluxCmd.Flags().BoolVarP(&flags.ExecScript, "exec", "e", false, "Interpret file argument as a raw flux script") + fluxCmd.Flags().BoolVarP(&flags.EnableSuggestions, "enable-suggestions", "", false, "enable suggestions in the repl") fluxCmd.Flags().StringVar(&flags.Trace, "trace", "", "Trace query execution") fluxCmd.Flags().StringVarP(&flags.Format, "format", "", "cli", "Output format one of: cli,csv. Defaults to cli") fluxCmd.Flag("trace").NoOptDefVal = "jaeger" diff --git a/cmd/flux/repl.go b/cmd/flux/repl.go index 51d5e9efee..77707fde14 100644 --- a/cmd/flux/repl.go +++ b/cmd/flux/repl.go @@ -6,8 +6,8 @@ import ( "github.com/influxdata/flux/repl" ) -func replE(ctx context.Context) error { - r := repl.New(ctx) +func replE(ctx context.Context, enableSuggestions bool) error { + r := repl.New(ctx, enableSuggestions) r.Run() return nil } diff --git a/interpreter/interpreter_test.go b/interpreter/interpreter_test.go index 5a8111ceda..dccfa6f3ad 100644 --- a/interpreter/interpreter_test.go +++ b/interpreter/interpreter_test.go @@ -658,7 +658,7 @@ func TestInterpreter_MultiPhaseInterpretation(t *testing.T) { ctx, deps := dependency.Inject(context.Background(), dependenciestest.Default()) defer deps.Finish() - r := repl.New(ctx) + r := repl.New(ctx, false) if _, err := r.Eval(prelude); err != nil { t.Fatalf("unable to evaluate prelude: %s", err) } @@ -772,7 +772,7 @@ func TestInterpreter_MultipleEval(t *testing.T) { ctx, deps := dependency.Inject(context.Background(), dependenciestest.Default()) defer deps.Finish() - r := repl.New(ctx) + r := repl.New(ctx, false) if _, err := r.Eval(prelude); err != nil { t.Fatalf("unable to evaluate prelude: %s", err) diff --git a/repl/repl.go b/repl/repl.go index 5faab010c8..11a5a711b9 100644 --- a/repl/repl.go +++ b/repl/repl.go @@ -37,9 +37,11 @@ type REPL struct { cancelMu sync.Mutex cancelFunc context.CancelFunc + + enableSuggestions bool } -func New(ctx context.Context) *REPL { +func New(ctx context.Context, enableSuggestions bool) *REPL { scope := values.NewScope() importer := runtime.StdLib() for _, p := range runtime.PreludeList { @@ -56,11 +58,12 @@ func New(ctx context.Context) *REPL { } return &REPL{ - ctx: ctx, - scope: scope, - itrp: interpreter.NewInterpreter(nil, &lang.ExecOptsConfig{}), - analyzer: analyzer, - importer: importer, + ctx: ctx, + scope: scope, + itrp: interpreter.NewInterpreter(nil, &lang.ExecOptsConfig{}), + analyzer: analyzer, + importer: importer, + enableSuggestions: enableSuggestions, } } @@ -100,35 +103,39 @@ func (r *REPL) clearCancel() { } func (r *REPL) completer(d prompt.Document) []prompt.Suggest { - names := make([]string, 0, r.scope.Size()) - r.scope.Range(func(k string, v values.Value) { - names = append(names, k) - }) - sort.Strings(names) - - s := make([]prompt.Suggest, 0, len(names)) - for _, n := range names { - if n == "_" || !strings.HasPrefix(n, "_") { - s = append(s, prompt.Suggest{Text: n}) - } - } - if d.Text == "" || strings.HasPrefix(d.Text, "@") { - root := "./" + strings.TrimPrefix(d.Text, "@") - fluxFiles, err := getFluxFiles(root) - if err == nil { - for _, fName := range fluxFiles { - s = append(s, prompt.Suggest{Text: "@" + fName}) + if r.enableSuggestions { + names := make([]string, 0, r.scope.Size()) + r.scope.Range(func(k string, v values.Value) { + names = append(names, k) + }) + sort.Strings(names) + + s := make([]prompt.Suggest, 0, len(names)) + for _, n := range names { + if n == "_" || !strings.HasPrefix(n, "_") { + s = append(s, prompt.Suggest{Text: n}) } } - dirs, err := getDirs(root) - if err == nil { - for _, fName := range dirs { - s = append(s, prompt.Suggest{Text: "@" + fName + string(os.PathSeparator)}) + if d.Text == "" || strings.HasPrefix(d.Text, "@") { + root := "./" + strings.TrimPrefix(d.Text, "@") + fluxFiles, err := getFluxFiles(root) + if err == nil { + for _, fName := range fluxFiles { + s = append(s, prompt.Suggest{Text: "@" + fName}) + } + } + dirs, err := getDirs(root) + if err == nil { + for _, fName := range dirs { + s = append(s, prompt.Suggest{Text: "@" + fName + string(os.PathSeparator)}) + } } } + + return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true) } + return nil - return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true) } func (r *REPL) Input(t string) (*libflux.FluxError, error) {