github.com/aergoio/aergo@v1.3.1/cmd/brick/brick.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "os" 6 "sort" 7 "strings" 8 9 "github.com/aergoio/aergo-lib/log" 10 "github.com/aergoio/aergo/cmd/brick/context" 11 "github.com/aergoio/aergo/cmd/brick/exec" 12 prompt "github.com/c-bata/go-prompt" 13 ) 14 15 var logger = log.NewLogger("brick") 16 17 func completerBroker(d prompt.Document) []prompt.Suggest { 18 var s []prompt.Suggest 19 // parse first word. it is represent a command 20 cmd, args := context.ParseFirstWord(d.Lines()[0]) 21 22 // find number of word before a current cursor location 23 chunks := context.SplitSpaceAndAccent(args, true) 24 chunkNum := len(chunks) 25 26 // if there is nothing typed text or it is a first word 27 if cmd == "" || (cmd != "" && chunkNum == 0 && !strings.HasSuffix(d.TextBeforeCursor(), " ")) { 28 // suggest all commands available 29 for _, executor := range exec.AllExecutors() { 30 s = append(s, prompt.Suggest{Text: executor.Command(), Description: executor.Describe()}) 31 } 32 33 return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true) 34 } else if cmd == context.Comment { 35 // ignore a special char; comment 36 s = append(s, prompt.Suggest{Text: "<comment>"}) 37 38 return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true) 39 } 40 41 // suggest consequence word using a syntax of command 42 executor := exec.GetExecutor(cmd) 43 if executor == nil { 44 s = append(s, prompt.Suggest{Text: "<error>", Description: fmt.Sprintf("command not found: %s", cmd)}) 45 } else { 46 syntax := executor.Syntax() 47 syntaxSplit := strings.Fields(syntax) 48 syntaxNum := len(syntaxSplit) 49 var symbol string 50 var current int 51 52 // there exist a syntax 53 if syntaxNum != 0 { 54 // from the syntax, try to find a matched symbol of a current field 55 if syntaxNum >= chunkNum { 56 // when last char is a space, then skip to next symbol 57 takeNextSymbol := strings.HasSuffix(d.TextBeforeCursor(), " ") 58 if takeNextSymbol && syntaxNum != chunkNum { 59 current = chunkNum 60 symbol = syntaxSplit[current] 61 } else if !takeNextSymbol { 62 current = chunkNum - 1 63 symbol = syntaxSplit[current] 64 } 65 } 66 67 // search from index using symbol 68 for text, descr := range exec.Candidates(cmd, chunks, current, symbol) { 69 s = append(s, prompt.Suggest{Text: text, Description: descr}) 70 } 71 } 72 } 73 74 // sort suggestions by text in ascending order 75 sort.Slice(s, func(i, j int) bool { 76 return strings.Compare(s[i].Text, s[j].Text) < 0 77 }) 78 79 return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true) 80 } 81 82 func main() { 83 if len(os.Args) <= 1 { 84 // cli mode 85 p := prompt.New( 86 exec.Broker, 87 completerBroker, 88 prompt.OptionPrefix(">"), 89 prompt.OptionLivePrefix(context.LivePrefix), 90 prompt.OptionTitle("Aergo Brick: Dummy Virtual Machine"), 91 ) 92 p.Run() 93 } else { 94 // call batch executor 95 cmd := "batch" 96 args := os.Args[1] 97 98 // set user-defined log level 99 if len(os.Args) > 2 { 100 if os.Args[2] == "-v" { 101 exec.EnableVerbose() 102 } else if os.Args[2] == "-w" { 103 exec.EnableWatch() 104 } else { 105 fmt.Println("Invalid Parameter. Usage: brick filename [-v|-w]\n\t-v\tverbose mode\n\t-w\twatch mode") 106 os.Exit(1) 107 } 108 } 109 110 exec.Execute(cmd, args) 111 } 112 }