-
Notifications
You must be signed in to change notification settings - Fork 156
/
Copy pathsuggestion.go
150 lines (129 loc) · 2.87 KB
/
suggestion.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package jid
import (
"regexp"
"sort"
"strings"
simplejson "github.com/bitly/go-simplejson"
)
type SuggestionInterface interface {
Get(json *simplejson.Json, keyword string) []string
GetCandidateKeys(json *simplejson.Json, keyword string) []string
}
type SuggestionDataType int
const (
UNKNOWN SuggestionDataType = iota
ARRAY
MAP
NUMBER
STRING
BOOL
)
type Suggestion struct {
}
func NewSuggestion() *Suggestion {
return &Suggestion{}
}
func (s *Suggestion) Get(json *simplejson.Json, keyword string) []string {
var completion string
var suggestion string
if a, err := json.Array(); err == nil {
if len(a) > 1 {
kw := regexp.MustCompile(`\[([0-9]+)?\]?`).FindString(keyword)
if kw == "" {
return []string{"[", "["}
} else if kw == "[" {
return []string{"", "["}
}
return []string{strings.Replace(kw+"]", kw, "", -1), kw + "]"}
}
return []string{strings.Replace(`[0]`, keyword, "", -1), `[0]`}
}
candidateKeys := s.GetCandidateKeys(json, keyword)
if keyword == "" {
if l := len(candidateKeys); l > 1 {
return []string{"", ""}
} else if l == 1 {
return []string{candidateKeys[0], candidateKeys[0]}
}
}
for _, key := range candidateKeys {
// first
if suggestion == "" && key != "" {
suggestion = key
} else {
axis := suggestion
if len(suggestion) > len(key) {
axis = key
}
max := 0
for i, _ := range axis {
if suggestion[i] != key[i] {
break
}
max = i
}
if max == 0 {
suggestion = ""
break
}
suggestion = suggestion[0 : max+1]
}
}
if reg, err := regexp.Compile("(?i)^" + keyword); err == nil {
completion = reg.ReplaceAllString(suggestion, "")
}
return []string{completion, suggestion}
}
func (s *Suggestion) GetCandidateKeys(json *simplejson.Json, keyword string) []string {
candidates := []string{}
if _, err := json.Array(); err == nil {
return []string{}
}
if keyword == "" {
return getCurrentKeys(json)
}
reg, err := regexp.Compile(`(?i)^(\\")?` + keyword + `(\\")?`)
if err != nil {
return []string{}
}
for _, key := range getCurrentKeys(json) {
if reg.MatchString(key) {
candidates = append(candidates, key)
}
}
return candidates
}
func getCurrentKeys(json *simplejson.Json) []string {
kk := []string{}
m, err := json.Map()
if err != nil {
return kk
}
for k := range m {
kk = append(kk, k)
}
sort.Strings(kk)
keys := []string{}
for _, k := range kk {
if strings.Contains(k, ".") {
var sb strings.Builder
sb.Grow(len(k) + 4)
sb.WriteString(`\"`)
sb.WriteString(k)
sb.WriteString(`\"`)
k = sb.String()
}
keys = append(keys, k)
}
return keys
}
func (s *Suggestion) GetCurrentType(json *simplejson.Json) SuggestionDataType {
if _, err := json.Array(); err == nil {
return ARRAY
} else if _, err = json.Map(); err == nil {
return MAP
} else if _, err = json.String(); err == nil {
return STRING
}
return UNKNOWN
}