-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmandoc.go
169 lines (140 loc) · 4.07 KB
/
mandoc.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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package style
import (
"strconv"
"strings"
)
var (
_ Styler = (*ManSyntax)(nil) //Makes sure that Man implements Styler
)
//NewMan is a predefined style.ManSyntax to write manpages.
func NewMan() *ManSyntax {
return &ManSyntax{&TextSyntax{
TabWidth: 4,
ListBullets: []string{"\u2043 ", "\u2022 ", "\u25E6 "},
}}
}
//ManSyntax is a Styler that provides a sub-set of roff markup featuring common
//used macros for building man pages
type ManSyntax struct {
*TextSyntax
}
//Bold changes a string case to bold.
func (stx *ManSyntax) Bold(s string) string {
return "\\fB" + s + "\\fP"
}
//Italic changes a string case to italic.
func (stx *ManSyntax) Italic(s string) string {
return "\\fI" + s + "\\fP"
}
//Header returns text as a chapter's header
func (stx *ManSyntax) Header(lvl int) func(s string) string {
switch {
case lvl <= 0:
return func(s string) string { return "" }
case lvl == 1:
return func(s string) string { return "\n.SH " + s + "\n" }
default:
return func(s string) string { return "\n.SS " + s + "\n" }
}
}
//Metadata returns formatted metadata information.
//Used metadata are: "title", "date" and "mansection"
func (stx *ManSyntax) Metadata(mdata map[string]string) string {
return ".TH " + stx.Upper(mdata["title"]) + " " + mdata["mansection"] + " " + mdata["date"] + "\n"
}
//Paragraph returns text as a new paragraph.
func (stx *ManSyntax) Paragraph(s string) string {
return stx.tab(".PP\n" + s + "\n")
}
//BulletedList returns a new bulleted-list (each list item has a leading
//bullet).
//It automatically indents each item.
func (stx *ManSyntax) BulletedList() func(items ...string) string {
stx.indentLvl++
bullet := stx.ListBullets[stx.indentLvl%len(stx.ListBullets)]
return func(items ...string) string {
var s string
for _, item := range items {
s = s + "\n.TP " + strconv.Itoa(len(bullet)) + "\n" + bullet + "\n" + item
if !strings.HasSuffix(s, "\n") {
s += "\n"
}
}
stx.indentLvl--
return stx.tab(s)
}
}
//OrderedList returns a new ordered-list (each list item has a leading
//auto-incrementing enumerator).
//It automatically indents each item.
func (stx *ManSyntax) OrderedList() func(items ...string) string {
stx.indentLvl++
return func(items ...string) string {
var s string
for i, item := range items {
enum := strconv.Itoa(i+1) + ". "
s = s + "\n.TP " + strconv.Itoa(len(enum)) + "\n" + enum + "\n" + item
if !strings.HasSuffix(s, "\n") {
s += "\n"
}
}
stx.indentLvl--
return stx.tab(s)
}
}
//Define returns a term definition
func (stx *ManSyntax) Define(term string, desc string) string {
def := ".TP\n" + stx.Bold(term) + "\n" + desc + "\n"
return stx.tab(def)
}
//Table draws a table out of the provided rows (using tbl).
func (stx *ManSyntax) Table(rows ...[]string) string {
if len(rows) == 0 {
return ""
}
var r []string
for _, row := range rows {
for i, c := range row {
row[i] = "T{\n" + c + "\nT}"
}
r = append(r, strings.Join(row, "\t"))
}
var layout []string
for range rows[0] {
layout = append(layout, "lx")
}
table := ".TS\nallbox;\n" + strings.Join(layout, " ") + ".\n" + strings.Join(r, "\n") + "\n.TE\n"
return stx.tab(table)
}
//Link is not supported in this style.
func (stx *ManSyntax) Link(txt string, url string) string {
return stx.Italic(url)
}
//Img is not supported in this style.
func (stx *ManSyntax) Img(txt string, url string) string {
return stx.Link(txt, url)
}
//Escape escapes the provided text.
func (stx *ManSyntax) Escape(s string) string {
var toEsc = [...]string{"-", "_", "&", "~"}
//Assume that if supplied string contains already escaped char, it was
//already escaped (chaining of styling's functions)
for _, e := range toEsc {
if strings.Contains(s, "\\"+e) {
return s
}
}
for _, e := range toEsc {
s = strings.ReplaceAll(s, e, "\\"+e)
}
return s
}
func (stx *ManSyntax) tab(s string) string {
if stx.indentLvl > 0 {
if strings.HasSuffix(s, "\n") {
return ".RS " + strconv.Itoa(stx.indentLvl*stx.TabWidth) + "\n" + s + ".RE\n"
}
return ".RS " + strconv.Itoa(stx.indentLvl*stx.TabWidth) + "\n" + s + "\n.RE\n"
}
return s
}