bash - format.go
1 package bash
2
3 import (
4 "fmt"
5 "io"
6 )
7
8 var indent = []byte{'\t'}
9
10 type indentPrinter struct {
11 io.Writer
12 }
13
14 func (i *indentPrinter) Write(p []byte) (int, error) {
15 var (
16 total int
17 last int
18 )
19
20 for n, c := range p {
21 if c == '\n' {
22 m, err := i.Writer.Write(p[last : n+1])
23 total += m
24
25 if err != nil {
26 return total, err
27 }
28
29 _, err = i.Writer.Write(indent)
30 if err != nil {
31 return total, err
32 }
33
34 last = n + 1
35 }
36 }
37
38 if last != len(p) {
39 m, err := i.Writer.Write(p[last:])
40 total += m
41
42 if err != nil {
43 return total, err
44 }
45 }
46
47 return total, nil
48 }
49
50 func (i *indentPrinter) Print(args ...interface{}) {
51 fmt.Fprint(i, args...)
52 }
53
54 func (i *indentPrinter) Printf(format string, args ...interface{}) {
55 fmt.Fprintf(i, format, args...)
56 }
57
58 func (i *indentPrinter) WriteString(s string) (int, error) {
59 return i.Write([]byte(s))
60 }
61
62 func (t Token) printType(w io.Writer, v bool) {
63 var typ string
64
65 switch t.Type {
66 case TokenWhitespace:
67 typ = "TokenWhitespace"
68 case TokenLineTerminator:
69 typ = "TokenLineTerminator"
70 case TokenComment:
71 typ = "TokenComment"
72 case TokenIdentifier:
73 typ = "TokenIdentifier"
74 case TokenIdentifierAssign:
75 typ = "TokenIdentifierAssign"
76 case TokenKeyword:
77 typ = "TokenKeyword"
78 case TokenWord:
79 typ = "TokenWord"
80 case TokenNumberLiteral:
81 typ = "TokenNumberLiteral"
82 case TokenString:
83 typ = "TokenString"
84 case TokenStringStart:
85 typ = "TokenStringStart"
86 case TokenStringMid:
87 typ = "TokenStringMid"
88 case TokenStringEnd:
89 typ = "TokenStringEnd"
90 case TokenBraceExpansion:
91 typ = "TokenBraceExpansion"
92 case TokenBraceWord:
93 typ = "TokenBraceWord"
94 case TokenPunctuator:
95 typ = "TokenPunctuator"
96 case TokenHeredoc:
97 typ = "TokenHeredoc"
98 case TokenHeredocEnd:
99 typ = "TokenHeredocEnd"
100 case TokenOpenBacktick:
101 typ = "TokenOpenBacktick"
102 case TokenCloseBacktick:
103 typ = "TokenCloseBacktick"
104 case TokenCloseParen:
105 typ = "TokenCloseParen"
106 case TokenPattern:
107 typ = "TokenPattern"
108 default:
109 typ = "Unknown"
110 }
111
112 fmt.Fprintf(w, "Type: %s - Data: %q", typ, t.Data)
113
114 if v {
115 fmt.Fprintf(w, " - Position: %d (%d: %d)", t.Pos, t.Line, t.LinePos)
116 }
117 }
118
119 func (t Tokens) printType(w io.Writer, v bool) {
120 if t == nil {
121 io.WriteString(w, "nil")
122
123 return
124 }
125
126 if len(t) == 0 {
127 io.WriteString(w, "[]")
128
129 return
130 }
131
132 io.WriteString(w, "[")
133
134 ipp := indentPrinter{w}
135
136 for n, t := range t {
137 ipp.Printf("\n%d: ", n)
138 t.printType(w, v)
139 }
140
141 io.WriteString(w, "\n]")
142 }
143
144 func (a AssignmentType) String() string {
145 switch a {
146 case AssignmentAssign:
147 return "AssignmentAssign"
148 case AssignmentAppend:
149 return "AssignmentAppend"
150 default:
151 return "Unknown"
152 }
153 }
154
155 func (a AssignmentType) printSource(w io.Writer, v bool) {
156 switch a {
157 case AssignmentAssign:
158 io.WriteString(w, "=")
159 case AssignmentAppend:
160 io.WriteString(w, "+=")
161 }
162 }
163
164 func (a AssignmentType) printType(w io.Writer, v bool) {
165 io.WriteString(w, a.String())
166 }
167
168 func (s SubstitutionType) String() string {
169 switch s {
170 case SubstitutionNew:
171 return "SubstitutionNew"
172 case SubstitutionBacktick:
173 return "SubstitutionBacktick"
174 default:
175 return "Unknown"
176 }
177 }
178
179 func (s SubstitutionType) printType(w io.Writer, v bool) {
180 io.WriteString(w, s.String())
181 }
182
183 func (p PipelineTime) String() string {
184 switch p {
185 case PipelineTimeNone:
186 return "PipelineTimeNone"
187 case PipelineTimeBash:
188 return "PipelineTimeBash"
189 case PipelineTimePosix:
190 return "PipelineTimePosix"
191 default:
192 return "Unknown"
193 }
194 }
195
196 func (p PipelineTime) printSource(w io.Writer, v bool) {
197 switch p {
198 case PipelineTimeBash:
199 io.WriteString(w, "time ")
200 case PipelineTimePosix:
201 io.WriteString(w, "time -p ")
202 }
203 }
204
205 func (p PipelineTime) printType(w io.Writer, v bool) {
206 io.WriteString(w, p.String())
207 }
208
209 func (l LogicalOperator) String() string {
210 switch l {
211 case LogicalOperatorNone:
212 return "LogicalOperatorNone"
213 case LogicalOperatorAnd:
214 return "LogicalOperatorAnd"
215 case LogicalOperatorOr:
216 return "LogicalOperatorOr"
217 default:
218 return "Unknown"
219 }
220 }
221
222 func (l LogicalOperator) printSource(w io.Writer, v bool) {
223 switch l {
224 case LogicalOperatorAnd:
225 io.WriteString(w, " && ")
226 case LogicalOperatorOr:
227 io.WriteString(w, " || ")
228 }
229 }
230
231 func (l LogicalOperator) printType(w io.Writer, v bool) {
232 io.WriteString(w, l.String())
233 }
234
235 func (j JobControl) String() string {
236 switch j {
237 case JobControlForeground:
238 return "JobControlForeground"
239 case JobControlBackground:
240 return "JobControlBackground"
241 default:
242 return "Unknown"
243 }
244 }
245
246 func (j JobControl) printType(w io.Writer, v bool) {
247 io.WriteString(w, j.String())
248 }
249
250 func (p ParameterType) String() string {
251 switch p {
252 case ParameterValue:
253 return "ParameterValue"
254 case ParameterLength:
255 return "ParameterLength"
256 case ParameterSubstitution:
257 return "ParameterSubstitution"
258 case ParameterAssignment:
259 return "ParameterAssignment"
260 case ParameterMessage:
261 return "ParameterMessage"
262 case ParameterSetAssign:
263 return "ParameterSetAssign"
264 case ParameterSubstring:
265 return "ParameterSubstring"
266 case ParameterPrefix:
267 return "ParameterPrefix"
268 case ParameterPrefixSeperate:
269 return "ParameterPrefixSeperate"
270 case ParameterRemoveStartShortest:
271 return "ParameterRemoveStartShortest"
272 case ParameterRemoveStartLongest:
273 return "ParameterRemoveStartLongest"
274 case ParameterRemoveEndShortest:
275 return "ParameterRemoveEndShortest"
276 case ParameterRemoveEndLongest:
277 return "ParameterRemoveEndLongest"
278 case ParameterReplace:
279 return "ParameterReplace"
280 case ParameterReplaceAll:
281 return "ParameterReplaceAll"
282 case ParameterReplaceStart:
283 return "ParameterReplaceStart"
284 case ParameterReplaceEnd:
285 return "ParameterReplaceEnd"
286 case ParameterLowercaseFirstMatch:
287 return "ParameterLowercaseFirstMatch"
288 case ParameterLowercaseAllMatches:
289 return "ParameterLowercaseAllMatches"
290 case ParameterUppercaseFirstMatch:
291 return "ParameterUppercaseFirstMatch"
292 case ParameterUppercaseAllMatches:
293 return "ParameterUppercaseAllMatches"
294 case ParameterUppercase:
295 return "ParameterUppercase"
296 case ParameterUppercaseFirst:
297 return "ParameterUppercaseFirst"
298 case ParameterLowercase:
299 return "ParameterLowercase"
300 case ParameterQuoted:
301 return "ParameterQuoted"
302 case ParameterEscaped:
303 return "ParameterEscaped"
304 case ParameterPrompt:
305 return "ParameterPrompt"
306 case ParameterDeclare:
307 return "ParameterDeclare"
308 case ParameterQuotedArrays:
309 return "ParameterQuotedArrays"
310 case ParameterQuotedArraysSeperate:
311 return ""
312 case ParameterAttributes:
313 return "ParameterAttributes"
314 default:
315 return ""
316 }
317 }
318
319 func (p ParameterType) printType(w io.Writer, v bool) {
320 io.WriteString(w, p.String())
321 }
322
323 type formatter interface {
324 printType(io.Writer, bool)
325 printSource(io.Writer, bool)
326 }
327
328 func format(f formatter, s fmt.State, v rune) {
329 switch v {
330 case 'v':
331 f.printType(s, s.Flag('+'))
332 case 's':
333 f.printSource(s, s.Flag('+'))
334 }
335 }
336