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