~emersion/gyosu

ref: bcc2eda9ba1b7292700f6ac32190f9ab6f89c05a gyosu/template.go -rw-r--r-- 2.7 KiB
bcc2eda9Simon Ser ci: add .build.yml 4 months ago
                                                                                
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
145
146
147
148
149
150
151
152
153
154
155
package main

import (
	"fmt"
	"strings"
)

const (
	// nbsp is a non-breaking space.
	nbsp = "\u00A0"
	// zwsp is a zero-width space, used to insert line break suggestions.
	zwsp = "\u200B"
)

type declKind string

const (
	declFunc   declKind = "func"
	declVar    declKind = "var"
	declStruct declKind = "struct"
	declUnion  declKind = "union"
	declEnum   declKind = "enum"
)

type inlineType int

const (
	inlineText inlineType = iota
	inlineSymbol
)

func (t inlineType) String() string {
	switch t {
	case inlineText:
		return "text"
	case inlineSymbol:
		return "symbol"
	}
	panic(fmt.Sprintf("invalid inline type %d", t))
}

type inline struct {
	Type  inlineType
	Value string
	Kind  declKind // only if inlineSymbol
}

func (inline inline) String() string {
	switch inline.Type {
	case inlineSymbol:
		decl := declData{Kind: inline.Kind, Name: inline.Value}
		return decl.Title()
	default:
		return inline.Value
	}
}

type paragraph []inline

type declData struct {
	Kind        declKind
	Name        string
	Prototype   []token
	Description []paragraph
	Filename    string
}

func (decl *declData) key() declKey {
	return declKey{Name: decl.Name, Kind: decl.Kind}
}

func (decl *declData) Title() string {
	switch decl.Kind {
	case declFunc:
		return decl.Name + "()"
	case declVar:
		return decl.Name
	default:
		return string(decl.Kind) + " " + decl.Name
	}
}

type unitData struct {
	Title     string
	Decls     []declData
	IndexHref string
}

type indexData struct {
	Title     string
	Filenames []string
	Decls     []declData
}

type declKey struct {
	Name string
	Kind declKind
}

type prototype []token

func (proto *prototype) Add(other ...token) *prototype {
	*proto = append(*proto, other...)
	return proto
}

func (proto *prototype) Raw(format string, v ...interface{}) *prototype {
	return proto.Add(token{Type: tokenRaw, Value: fmt.Sprintf(format, v...)})
}

func (proto *prototype) Keyword(s string) *prototype {
	return proto.Add(token{Type: tokenKeyword, Value: s})
}

func (proto *prototype) Symbol(kind declKind, name string) *prototype {
	switch kind {
	case "enum", "struct", "union":
		proto.Keyword(string(kind)).Raw(nbsp)
	}
	return proto.Add(token{Type: tokenSymbol, Value: name, Kind: kind})
}

func (proto prototype) String() string {
	var sb strings.Builder
	for _, tok := range proto {
		sb.WriteString(tok.Value)
	}
	return sb.String()
}

type tokenType int

const (
	tokenRaw tokenType = iota
	tokenKeyword
	tokenSymbol
)

func (t tokenType) String() string {
	switch t {
	case tokenRaw:
		return "raw"
	case tokenKeyword:
		return "keyword"
	case tokenSymbol:
		return "symbol"
	}
	panic(fmt.Sprintf("invalid token type %d", t))
}

type token struct {
	Type  tokenType
	Value string
	Kind  declKind // only if tokenSymbol
}