-
Notifications
You must be signed in to change notification settings - Fork 1
/
heredoc.go
86 lines (73 loc) · 1.86 KB
/
heredoc.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
package internal
// Migrate from https://github.com/makenowjust/heredoc/blob/main/heredoc.go
import (
"fmt"
"strings"
)
const maxInt = int(^uint(0) >> 1)
// HereDoc returns un-indented string as here-document.
func HereDoc(raw string) string {
skipFirstLine := false
if len(raw) > 0 && raw[0] == '\n' {
raw = raw[1:]
} else {
skipFirstLine = true
}
rawLines := strings.Split(raw, "\n")
lines := rawLines
if skipFirstLine {
lines = lines[1:]
}
minIndentSize := getMinIndent(lines)
lines = removeIndentation(lines, minIndentSize)
return strings.Join(rawLines, "\n")
}
// isSpace checks whether the rune represents space or not.
// Only white spcaes (U+0020) and horizontal tabs are treated as space character.
// It is the same as Go.
//
// See https://github.com/MakeNowJust/heredoc/issues/6#issuecomment-524231625.
func isSpace(r rune) bool {
switch r {
case ' ', '\t':
return true
default:
return false
}
}
// getMinIndent calculates the minimum indentation in lines, excluding empty lines.
func getMinIndent(lines []string) int {
minIndentSize := maxInt
for i, line := range lines {
indentSize := 0
for _, r := range line {
if isSpace(r) {
indentSize++
} else {
break
}
}
if len(line) == indentSize {
if i == len(lines)-1 && indentSize < minIndentSize {
lines[i] = ""
}
} else if indentSize < minIndentSize {
minIndentSize = indentSize
}
}
return minIndentSize
}
// removeIndentation removes n characters from the front of each line in lines.
func removeIndentation(lines []string, n int) []string {
for i, line := range lines {
if len(lines[i]) >= n {
lines[i] = line[n:]
}
}
return lines
}
// HereDocf returns unindented and formatted string as here-document.
// Formatting is done as for fmt.Printf().
func HereDocf(raw string, args ...interface{}) string {
return fmt.Sprintf(HereDoc(raw), args...)
}