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
170
171
172
173
174
|
package main
import (
"fmt"
"io"
"log"
"os"
"golang.org/x/text/transform"
)
// 输出索引
type OutputIndex struct {
groups []IndexGroup
style *OutputStyle
option *OutputOptions
}
func NewOutputIndex(input *InputIndex, option *OutputOptions, style *OutputStyle) *OutputIndex {
sorter := NewIndexSorter(option.sort)
outindex := sorter.SortIndex(input, style, option)
outindex.style = style
outindex.option = option
return outindex
}
// 按格式输出索引项
// suffix_2p, suffix_3p, suffix_mp 暂未实现
// line_max, indent_space, indent_length 未实现
func (o *OutputIndex) Output(option *OutputOptions) {
var writer io.WriteCloser
if o.option.output == "" {
writer = os.Stdout
} else {
var err error
writer, err = os.Create(o.option.output)
if err != nil {
log.Fatalln(err)
}
defer writer.Close()
}
writer = transform.NewWriter(writer, option.encoder)
fmt.Fprint(writer, o.style.preamble)
first_group := true
for _, group := range o.groups {
if group.items == nil {
continue
}
if first_group {
first_group = false
} else {
fmt.Fprint(writer, o.style.group_skip)
}
if o.style.headings_flag != 0 {
fmt.Fprintf(writer, "%s%s%s", o.style.heading_prefix, group.name, o.style.heading_suffix)
}
for i, item := range group.items {
// debug.Println(i, item)
// 如果修改一下 OutputStyle 的数据结构,容易改成任意层的索引
switch item.level {
case 0:
fmt.Fprintf(writer, "%s%s", o.style.item_0, item.text)
writePage(writer, 0, item.page, o.style)
case 1:
if last := group.items[i-1]; last.level == 0 {
if last.page != nil {
fmt.Fprint(writer, o.style.item_01)
} else {
fmt.Fprint(writer, o.style.item_x1)
}
} else {
fmt.Fprint(writer, o.style.item_1)
}
fmt.Fprint(writer, item.text)
writePage(writer, 1, item.page, o.style)
case 2:
if last := group.items[i-1]; last.level == 1 {
if last.page != nil {
fmt.Fprint(writer, o.style.item_12)
} else {
fmt.Fprint(writer, o.style.item_x2)
}
} else {
fmt.Fprint(writer, o.style.item_2)
}
fmt.Fprint(writer, item.text)
writePage(writer, 2, item.page, o.style)
default:
log.Printf("索引项“%s”层次数过深,忽略此项\n", item.text)
}
}
}
fmt.Fprint(writer, o.style.postamble)
}
func writePage(out io.Writer, level int, pageranges []PageRange, style *OutputStyle) {
if pageranges == nil {
return
}
switch level {
case 0:
fmt.Fprint(out, style.delim_0)
case 1:
fmt.Fprint(out, style.delim_1)
case 2:
fmt.Fprint(out, style.delim_2)
}
for i, p := range pageranges {
if i > 0 {
fmt.Fprint(out, style.delim_n)
}
p.Write(out, style)
}
if len(pageranges) != 0 {
fmt.Fprint(out, style.delim_t)
}
}
// 一个输出项目组
type IndexGroup struct {
name string
items []IndexItem
}
// 一个输出项,包括级别、文字、一系列页码区间
type IndexItem struct {
level int
text string
page []PageRange
}
// 用于输出的页码区间
type PageRange struct {
begin *Page
end *Page
}
func (p *PageRange) Diff() int {
return p.end.Diff(p.begin)
}
// 输出页码区间
func (p *PageRange) Write(out io.Writer, style *OutputStyle) {
var rangestr string
switch {
// 单页
case p.Diff() == 0:
rangestr = p.begin.String()
// 由单页合并得到的两页的区间,且未设置 suffix_2p,视为独立的两页
case p.begin.rangetype == PAGE_NORMAL && p.end.rangetype == PAGE_NORMAL &&
p.Diff() == 1 && style.suffix_2p == "":
rangestr = p.begin.String() + style.delim_n + p.end.String()
// 两页的区间,设置了 suffix_2p
case p.Diff() == 1 && style.suffix_2p != "":
rangestr = p.begin.String() + style.suffix_2p
// 三页的区间,设置了 suffix_3p
case p.Diff() == 2 && style.suffix_3p != "":
rangestr = p.begin.String() + style.suffix_3p
// 三页或更长的区间,设置了 suffix_mp
case p.Diff() >= 2 && style.suffix_mp != "":
rangestr = p.begin.String() + style.suffix_mp
// 普通的区间
default:
rangestr = p.begin.String() + style.delim_r + p.end.String()
}
// encap 只看区间头,对不完全区间可能不总正确
if p.begin.encap == "" {
fmt.Fprint(out, rangestr)
} else {
fmt.Fprint(out, style.encap_prefix, p.begin.encap,
style.encap_infix, rangestr, style.encap_suffix)
}
}
|