this repo has no description
at master 102 lines 2.5 kB view raw
1// Copyright 2019 CUE Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package cli 16 17import ( 18 "bufio" 19 "fmt" 20 "io" 21 "strings" 22 23 "cuelang.org/go/cue" 24 "cuelang.org/go/internal/task" 25) 26 27func init() { 28 task.Register("tool/cli.Print", newPrintCmd) 29 task.Register("tool/cli.Ask", newAskCmd) 30 31 // For backwards compatibility. 32 task.Register("print", newPrintCmd) 33} 34 35type printCmd struct{} 36 37func newPrintCmd(v cue.Value) (task.Runner, error) { 38 return &printCmd{}, nil 39} 40 41func (c *printCmd) Run(ctx *task.Context) (res interface{}, err error) { 42 str := ctx.String("text") 43 if ctx.Err != nil { 44 return nil, ctx.Err 45 } 46 fmt.Fprintln(ctx.Stdout, str) 47 return nil, nil 48} 49 50type askCmd struct{} 51 52func newAskCmd(v cue.Value) (task.Runner, error) { 53 return &askCmd{}, nil 54} 55 56type oneByteReader struct { 57 r io.Reader 58} 59 60func (r *oneByteReader) Read(p []byte) (int, error) { 61 if len(p) == 0 { 62 return 0, nil 63 } 64 return r.r.Read(p[:1]) 65} 66 67func (c *askCmd) Run(ctx *task.Context) (res interface{}, err error) { 68 str := ctx.String("prompt") 69 if ctx.Err != nil { 70 return nil, ctx.Err 71 } 72 if str != "" { 73 fmt.Fprint(ctx.Stdout, str+" ") 74 } 75 76 // Roger is convinced that bufio.Scanner will only issue as many reads 77 // as it needs, so that limiting it to one-byte reads should be enough 78 // to not read any bytes after a newline. 79 // This behavior is true today but technically not documented, 80 // so Roger will send a CL to properly document it. 81 // 82 // TODO(mvdan): come back to remove this notice once Roger's CL is 83 // approved, or to rewrite the code if it is rejected. 84 scanner := bufio.NewScanner(&oneByteReader{ctx.Stdin}) 85 var response string 86 if scanner.Scan() { 87 response = scanner.Text() 88 } 89 if err := scanner.Err(); err != nil { 90 return nil, err 91 } 92 93 update := map[string]interface{}{"response": response} 94 95 switch v := ctx.Lookup("response"); v.IncompleteKind() { 96 case cue.BoolKind: 97 update["response"] = strings.ToLower(response) == "yes" 98 case cue.StringKind: 99 // already set above 100 } 101 return update, nil 102}