-
Notifications
You must be signed in to change notification settings - Fork 0
/
fmt.go
138 lines (115 loc) · 2.61 KB
/
fmt.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
package balafon
import (
"bufio"
"bytes"
"io"
"os"
"github.com/mgnsk/balafon/internal/ast"
"github.com/mgnsk/balafon/internal/parser/lexer"
"github.com/mgnsk/balafon/internal/parser/parser"
)
var lf = []byte("\n")
// FormatFile formats a file.
func FormatFile(filename string) error {
f, err := os.Open(filename)
if err != nil {
return err
}
defer f.Close()
stat, err := f.Stat()
if err != nil {
return err
}
b, err := io.ReadAll(f)
if err != nil {
return err
}
if err := f.Close(); err != nil {
return err
}
result, err := Format(b)
if err != nil {
return err
}
return os.WriteFile(filename, result, stat.Mode())
}
// Format a balafon script.
func Format(input []byte) ([]byte, error) {
scanner := bufio.NewScanner(bytes.NewReader(input))
p := parser.NewParser()
var (
isBar bool
barBuffer bytes.Buffer
output bytes.Buffer
isEmptyLine bool
)
for scanner.Scan() {
line := scanner.Bytes()
line = bytes.TrimSpace(line)
if len(line) == 0 {
if isEmptyLine {
continue
}
isEmptyLine = true
} else {
isEmptyLine = false
}
if isBar && bytes.HasPrefix(line, []byte(":end")) {
barBuffer.Write(line)
barBuffer.Write(lf)
isBar = false
barBuffer.WriteTo(&output)
barBuffer.Reset()
} else if pref := []byte(":bar"); bytes.HasPrefix(line, pref) {
isBar = true
barName := bytes.TrimPrefix(line, pref)
barName = bytes.TrimSpace(barName)
barBuffer.Write(pref)
barBuffer.WriteString(" ")
barBuffer.Write(barName)
barBuffer.Write(lf)
} else if pref := []byte(":play"); bytes.HasPrefix(line, pref) {
barName := bytes.TrimPrefix(line, pref)
barName = bytes.TrimSpace(barName)
output.Write(pref)
output.WriteString(" ")
output.Write(barName)
output.Write(lf)
} else if isBar {
if len(line) > 0 {
barBuffer.WriteString("\t")
}
if bytes.HasPrefix(line, []byte(":")) {
// Parse the command line and print.
node, err := p.Parse(lexer.NewLexer(line))
if err != nil {
return nil, err
}
node.(ast.NodeList).WriteTo(&barBuffer)
} else {
// Print note list raw.
barBuffer.Write(line)
}
barBuffer.Write(lf)
} else {
if bytes.HasPrefix(line, []byte(":")) {
// Parse the command line and print.
node, err := p.Parse(lexer.NewLexer(line))
if err != nil {
return nil, err
}
node.(ast.NodeList).WriteTo(&output)
} else {
// Print note list raw.
output.Write(line)
}
output.Write(lf)
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
out := bytes.TrimSpace(output.Bytes())
out = append(out, lf...)
return out, nil
}