| package main |
| |
| import ( |
| "fmt" |
| "io" |
| "os" |
| "strings" |
| |
| isatty "github.com/mattn/go-isatty" |
| |
| "v.io/v23/context" |
| wire "v.io/v23/services/syncbase" |
| "v.io/v23/syncbase" |
| "v.io/x/lib/cmdline" |
| "v.io/x/ref/cmd/sb/sb2/commands" |
| "v.io/x/ref/cmd/sb/internal/reader" |
| "v.io/x/ref/lib/v23cmd" |
| ) |
| |
| var cmdSbShell = &cmdline.Command{ |
| Runner: v23cmd.RunnerFunc(runSbShell), |
| Name: "sh", |
| Short: "Start a syncQL shell", |
| Long: ` |
| Connect to a database on the Syncbase service and start a syncQL shell. |
| `, |
| } |
| |
| // Runs the shell. |
| // Takes commands as input, executes them, and spits out output. |
| func runSbShell(ctx *context.T, env *cmdline.Env, args []string) error { |
| if len(args) != 0 { |
| return env.UsageErrorf("no arguments expected") |
| } |
| |
| // open a connection to syncbase |
| sbService := syncbase.NewService(flagService) |
| dbId := wire.Id{Blessing: flagBlessing, Name: flagDBName} |
| db, err := openDB(ctx, sbService, dbId, flagCreateIfAbsent) |
| if err != nil { |
| return err |
| } |
| |
| // test if input is interactive and get reader |
| var input *reader.T |
| stdinFile, ok := env.Stdin.(*os.File) |
| isTerminal := ok && isatty.IsTerminal(stdinFile.Fd()) |
| if isTerminal { |
| input = reader.NewInteractive() |
| } else { |
| input = reader.NewNonInteractive() |
| } |
| defer input.Close() |
| |
| // read-exec loop |
| for true { |
| // read command |
| query, err := input.GetQueryWithTerminator('\n') |
| if err != nil { |
| if err == io.EOF && isTerminal { |
| // ctrl-d |
| fmt.Println() |
| } |
| break |
| } |
| |
| // exec command |
| fields := strings.Fields(query) |
| if len(fields) > 0 { |
| if err := runCommand(ctx, env, db, fields[0], fields[1:], isTerminal); |
| err != nil { |
| return err |
| } |
| } |
| } |
| |
| return nil |
| } |
| |
| func runCommand(ctx *context.T, env *cmdline.Env, db syncbase.Database, |
| command string, args []string, isTerminal bool) error { |
| cmd, err := commands.GetCommand(command) |
| if err != nil { |
| // command not found, inform the user |
| if isTerminal { |
| fmt.Printf("no command %q\n", command) |
| return nil |
| } else { |
| return err |
| } |
| } |
| |
| // command was found, run it |
| commands.SetCtx(context.WithValue(ctx, "database", db)) |
| if err := cmd.Runner.Run(env, args); err != nil { |
| if isTerminal { |
| fmt.Fprintln(env.Stderr, "Error:", err) |
| //printUsage(cmd) |
| } else { |
| // if running non-interactively, errors halt execution |
| return err |
| } |
| } |
| return nil |
| } |