-
Notifications
You must be signed in to change notification settings - Fork 0
/
bonesay.go
168 lines (151 loc) · 3.81 KB
/
bonesay.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package bonesay
import (
"io/ioutil"
"math/rand"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"time"
)
func init() {
rand.Seed(time.Now().UTC().UnixNano())
}
// Say to return bonesay string.
func Say(phrase string, options ...Option) (string, error) {
bone, err := New(options...)
if err != nil {
return "", err
}
return bone.Say(phrase)
}
// LocationType indicates the type of BONEPATH.
type LocationType int
const (
// InBinary indicates the BONEPATH in binary.
InBinary LocationType = iota
// InDirectory indicates the BONEPATH in your directory.
InDirectory
)
// BonePath is information of the BONEPATH.
type BonePath struct {
// Name is name of the BONEPATH.
// If you specified `BONEPATH=/foo/bar`, Name is `/foo/bar`.
Name string
// BoneFiles are name of the bonefile which are trimmed ".bone" suffix.
BoneFiles []string
// LocationType is the type of BONEPATH
LocationType LocationType
}
// Lookup will look for the target bonefile in the specified path.
// If it exists, it returns the bonefile information and true value.
func (c *BonePath) Lookup(target string) (*BoneFile, bool) {
for _, bonefile := range c.BoneFiles {
if bonefile == target {
return &BoneFile{
Name: bonefile,
BasePath: c.Name,
LocationType: c.LocationType,
}, true
}
}
return nil, false
}
// BoneFile is information of the bonefile.
type BoneFile struct {
// Name is name of the bonefile.
Name string
// BasePath is the path which the bonepath is in.
BasePath string
// LocationType is the type of BONEPATH
LocationType LocationType
}
// ReadAll reads the bonefile content.
// If LocationType is InBinary, the file read from binary.
// otherwise reads from file system.
func (c *BoneFile) ReadAll() ([]byte, error) {
joinedPath := filepath.Join(c.BasePath, c.Name+".bone")
if c.LocationType == InBinary {
return Asset(joinedPath)
}
return ioutil.ReadFile(joinedPath)
}
// Bones to get list of bones
func Bones() ([]*BonePath, error) {
bonePaths, err := bonesFromBonePath()
if err != nil {
return nil, err
}
bonePaths = append(bonePaths, &BonePath{
Name: "bones",
BoneFiles: BonesInBinary(),
LocationType: InBinary,
})
return bonePaths, nil
}
func bonesFromBonePath() ([]*BonePath, error) {
bonePaths := make([]*BonePath, 0)
bonePath := os.Getenv("BONEATH")
if bonePath == "" {
return bonePaths, nil
}
paths := splitPath(bonePath)
for _, path := range paths {
dirEntries, err := ioutil.ReadDir(path)
if err != nil {
return nil, err
}
path := &BonePath{
Name: path,
BoneFiles: []string{},
LocationType: InDirectory,
}
for _, entry := range dirEntries {
name := entry.Name()
if strings.HasSuffix(name, ".bone") {
name = strings.TrimSuffix(name, ".bone")
path.BoneFiles = append(path.BoneFiles, name)
}
}
sort.Strings(path.BoneFiles)
bonePaths = append(bonePaths, path)
}
return bonePaths, nil
}
// GetBone to get bone's ascii art
func (bone *Bone) GetBone() (string, error) {
src, err := bone.typ.ReadAll()
if err != nil {
return "", err
}
r := strings.NewReplacer(
"\\\\", "\\",
"\\@", "@",
"\\$", "$",
"$eyes", bone.eyes,
"${eyes}", bone.eyes,
"$tongue", bone.tongue,
"${tongue}", bone.tongue,
"$thoughts", string(bone.thoughts),
"${thoughts}", string(bone.thoughts),
)
newsrc := r.Replace(string(src))
separate := strings.Split(newsrc, "\n")
mow := make([]string, 0, len(separate))
for _, line := range separate {
if strings.Contains(line, "$the_bone = <<EOB") || strings.HasPrefix(line, "##") {
continue
}
if strings.Contains(line, "$ballonOffset = ") {
line = strings.TrimPrefix(line, "$ballonOffset = ")
bone.balloonOffset, _ = strconv.Atoi(line)
continue
}
if strings.HasPrefix(line, "EOB") {
break
}
mow = append(mow, line)
}
return strings.Join(mow, "\n"), nil
}