Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 12, 18:15 UTC
caddyfile: Add heredoc support to `fmt` command (#6056)
bbaa committed
Jan 22, 2024 at 10:24 UTC
c0273f1f049aa66e4426023d8e43d68fbdbccbb6
3 files changed
+145
-1
caddyconfig/caddyfile/formatter.go
+74
@@ -31,6 +31,14 @@ func Format(input []byte) []byte {
31
out := new(bytes.Buffer)
32
rdr := bytes.NewReader(input)
33
34
+ type heredocState int
35
+
36
+ const (
37
+ heredocClosed heredocState = 0
38
+ heredocOpening heredocState = 1
39
+ heredocOpened heredocState = 2
40
+ )
41
+
42
var (
43
last rune // the last character that was written to the result
44
@@ -47,6 +55,11 @@ func Format(input []byte) []byte {
55
quoted bool // whether we're in a quoted segment
56
escaped bool // whether current char is escaped
57
58
+ heredoc heredocState // whether we're in a heredoc
59
+ heredocEscaped bool // whether heredoc is escaped
60
+ heredocMarker []rune
61
+ heredocClosingMarker []rune
62
+
63
nesting int // indentation level
64
)
65
@@ -75,6 +88,58 @@ func Format(input []byte) []byte {
88
panic(err)
89
}
90
91
+ // detect whether we have the start of a heredoc
92
+ if !quoted && !(heredoc != heredocClosed || heredocEscaped) &&
93
+ space && last == '<' && ch == '<' {
94
+ write(ch)
95
+ heredoc = heredocOpening
96
+ space = false
97
+ continue
98
+ }
99
+
100
+ if heredoc == heredocOpening {
101
+ if ch == '\n' {
102
+ if len(heredocMarker) > 0 && heredocMarkerRegexp.MatchString(string(heredocMarker)) {
103
+ heredoc = heredocOpened
104
+ } else {
105
+ heredocMarker = nil
106
+ heredoc = heredocClosed
107
+ nextLine()
108
+ continue
109
+ }
110
+ write(ch)
111
+ continue
112
+ }
113
+ if unicode.IsSpace(ch) {
114
+ // a space means it's just a regular token and not a heredoc
115
+ heredocMarker = nil
116
+ heredoc = heredocClosed
117
+ } else {
118
+ heredocMarker = append(heredocMarker, ch)
119
+ write(ch)
120
+ continue
121
+ }
122
+ }
123
+ // if we're in a heredoc, all characters are read&write as-is
124
+ if heredoc == heredocOpened {
125
+ write(ch)
126
+ heredocClosingMarker = append(heredocClosingMarker, ch)
127
+ if len(heredocClosingMarker) > len(heredocMarker) {
128
+ heredocClosingMarker = heredocClosingMarker[1:]
129
+ }
130
+ // check if we're done
131
+ if string(heredocClosingMarker) == string(heredocMarker) {
132
+ heredocMarker = nil
133
+ heredocClosingMarker = nil
134
+ heredoc = heredocClosed
135
+ }
136
+ continue
137
+ }
138
+
139
+ if last == '<' && space {
140
+ space = false
141
+ }
142
+
143
if comment {
144
if ch == '\n' {
145
comment = false
@@ -98,6 +163,9 @@ func Format(input []byte) []byte {
163
}
164
165
if escaped {
166
+ if ch == '<' {
167
+ heredocEscaped = true
168
+ }
169
write(ch)
170
escaped = false
171
continue
@@ -117,6 +185,7 @@ func Format(input []byte) []byte {
185
186
if unicode.IsSpace(ch) {
187
space = true
188
+ heredocEscaped = false
189
if ch == '\n' {
190
newLines++
191
}
@@ -205,6 +274,11 @@ func Format(input []byte) []byte {
274
write('{')
275
openBraceWritten = true
276
}
277
+
278
+ if spacePrior && ch == '<' {
279
+ space = true
280
+ }
281
+
282
write(ch)
283
284
beginningOfLine = false
caddyconfig/caddyfile/formatter_test.go
+70
@@ -362,6 +362,76 @@ block {
362
363
block {
364
}
365
+`,
366
+ },
367
+ {
368
+ description: "keep heredoc as-is",
369
+ input: `block {
370
+ heredoc <<HEREDOC
371
+ Here's more than one space Here's more than one space
372
+ HEREDOC
373
+}
374
+`,
375
+ expect: `block {
376
+ heredoc <<HEREDOC
377
+ Here's more than one space Here's more than one space
378
+ HEREDOC
379
+}
380
+`,
381
+ },
382
+ {
383
+ description: "Mixing heredoc with regular part",
384
+ input: `block {
385
+ heredoc <<HEREDOC
386
+ Here's more than one space Here's more than one space
387
+ HEREDOC
388
+ respond "More than one space will be eaten" 200
389
+}
390
+
391
+block2 {
392
+ heredoc <<HEREDOC
393
+ Here's more than one space Here's more than one space
394
+ HEREDOC
395
+ respond "More than one space will be eaten" 200
396
+}
397
+`,
398
+ expect: `block {
399
+ heredoc <<HEREDOC
400
+ Here's more than one space Here's more than one space
401
+ HEREDOC
402
+ respond "More than one space will be eaten" 200
403
+}
404
+
405
+block2 {
406
+ heredoc <<HEREDOC
407
+ Here's more than one space Here's more than one space
408
+ HEREDOC
409
+ respond "More than one space will be eaten" 200
410
+}
411
+`,
412
+ },
413
+ {
414
+ description: "Heredoc as regular token",
415
+ input: `block {
416
+ heredoc <<HEREDOC "More than one space will be eaten"
417
+}
418
+`,
419
+ expect: `block {
420
+ heredoc <<HEREDOC "More than one space will be eaten"
421
+}
422
+`,
423
+ },
424
+ {
425
+ description: "Escape heredoc",
426
+ input: `block {
427
+ heredoc \<<HEREDOC
428
+ respond "More than one space will be eaten" 200
429
+}
430
+`,
431
+ expect: `block {
432
+ heredoc \<<HEREDOC
433
+ respond "More than one space will be eaten" 200
434
+}
435
`,
436
},
437
} {
caddyconfig/caddyfile/lexer.go
+1
-1
@@ -313,7 +313,7 @@ func (l *lexer) finalizeHeredoc(val []rune, marker string) ([]rune, error) {
313
// iterate over each line and strip the whitespace from the front
314
var out string
315
for lineNum, lineText := range lines[:len(lines)-1] {
316
- if lineText == "" {
316
+ if lineText == "" || lineText == "\r" {
317
out += "\n"
318
continue
319
}