/
section.go
144 lines (114 loc) · 3.07 KB
/
section.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
package main
import (
"bufio"
"bytes"
"fmt"
"strings"
)
type Section struct {
Title string
Body string
}
// This method returns the line in the body denoted by 'i'.
// Lines are sections of the string delimited by newlines.
// Empty lines are excluded from the set of lines.
// If the line does not exist, the boolean is returned as false.
func (this Section) Line(i int) (string, bool) {
lines := this.Lines()
if i >= len(lines) {
return "", false
}
return lines[i], true
}
func (this Section) Lines() []string {
in := strings.Split(this.Body, "\n")
out := make([]string, 0)
for _, line := range in {
line = strings.TrimSpace(line)
if line != "" {
out = append(out, line)
}
}
return out
}
func (this Section) String() string {
b := bytes.NewBuffer(nil)
fmt.Fprintln(b, this.Title+":")
s := bufio.NewScanner(strings.NewReader(this.Body))
for s.Scan() {
t := s.Text()
fmt.Fprintln(b, "|"+t)
}
return b.String()
}
func parseSections(commentBlock string) []Section {
var (
sections []Section = make([]Section, 0)
section *Section // Leave nil until a new section is identified.
body *bytes.Buffer = bytes.NewBuffer(nil)
)
scnr := bufio.NewScanner(strings.NewReader(commentBlock))
for scnr.Scan() {
line := scnr.Text()
line = strings.TrimSpace(line)
line_ := strings.ToLower(line)
// The most basic criteria for finding a section.
if strings.HasPrefix(line_, "openapi") && strings.HasSuffix(line_, ":") {
// A new tag means the start of a new section.
// A new section means the end of a previous section.
if section != nil {
// A new section was previously detected.
// Build it up and spit it out.
section.Body = body.String()
sections = append(sections, cleanupSection(*section))
}
section = new(Section)
section.Title = strings.TrimSuffix(line, ":")
body = bytes.NewBuffer(nil)
} else {
fmt.Fprintln(body, line)
}
}
// capture the last section.
if section != nil {
section.Body = body.String()
sections = append(sections, cleanupSection(*section))
}
return sections
}
func cleanupSection(section Section) Section {
var (
spacesRemoved bool = true // gotta get the loop going.
tabsRemoved bool
)
for spacesRemoved || tabsRemoved {
// Remove uniform spaces.
body := trimPrefixMultiline(section.Body, " ")
spacesRemoved = len(body) != len(section.Body)
section.Body = body
// Remove uniform tabs.
body = trimPrefixMultiline(section.Body, "\t")
tabsRemoved = len(body) != len(section.Body)
section.Body = body
}
return section
}
func trimPrefixMultiline(s string, prefix string) string {
scnr := bufio.NewScanner(strings.NewReader(s))
out := bytes.NewBuffer(nil)
for scnr.Scan() {
line := scnr.Text()
// Empty lines get a pass.
if len(strings.TrimSpace(line)) == 0 {
fmt.Fprintln(out)
continue
}
// Every line must have the same prefix.
if strings.Index(line, prefix) != 0 {
return s
}
// If everything went well, write the trimmed line to the output buffer.
fmt.Fprintln(out, strings.TrimPrefix(s, prefix))
}
return out.String()
}