-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
docparse.go
77 lines (66 loc) · 1.55 KB
/
docparse.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
package testdoc
import (
"bufio"
"bytes"
"strings"
)
// Doc represents an documentation block.
type Doc struct {
Description string
Fields map[string]string
}
// ParseDoc parses an documentation block and returns an instance to Doc.
// It will parse Sections separated by a colon and populate them in the Doc.Fields field.
// Example:
// Take following input:
// Lorem ipsum dolor sit amet, consectetur adipiscing elit.
//
// Field1:
// Hello World
//
// Field2:
// Good Bye World
// Will return
// Doc{
// Description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
// Fields: map[string]string{
// "Field1": "Hello World",
// "Field2": "Good Bye World",
// },
// }.
func ParseDoc(s string) (*Doc, error) {
var d Doc
setField := func(fieldName, value string) {
if fieldName == "" {
d.Description = strings.TrimSpace(value)
return
}
if d.Fields == nil {
d.Fields = make(map[string]string)
}
d.Fields[fieldName] = strings.TrimSpace(value)
}
scanner := bufio.NewScanner(bytes.NewReader([]byte(s)))
var previousText string
var sb strings.Builder
var currentField string
for scanner.Scan() {
txt := scanner.Text()
if strings.HasSuffix(txt, ":") && previousText == "" {
setField(currentField, sb.String())
sb.Reset()
currentField = txt[:len(txt)-1]
continue
}
sb.WriteString(strings.TrimSpace(txt))
sb.WriteRune('\n')
previousText = txt
}
if err := scanner.Err(); err != nil {
return nil, err
}
if sb.Len() > 0 {
setField(currentField, sb.String())
}
return &d, nil
}