/
print.go
99 lines (83 loc) · 2 KB
/
print.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
package main
import (
"fmt"
"io"
"os"
"sort"
"strconv"
"strings"
"unicode/utf8"
"arp242.net/uni/isatty"
"arp242.net/uni/terminal"
"arp242.net/uni/unidata"
)
var (
isTerm = isatty.IsTerminal(os.Stdout.Fd())
termWidth = func() int {
if !isTerm {
return 0
}
w, _, err := terminal.GetSize(int(os.Stdout.Fd()))
if err != nil || w < 50 {
return 0
}
return w
}()
)
type printer []unidata.Codepoint
func (p printer) Print(fp io.Writer, quiet, raw bool) {
if len(p) == 0 {
return
}
var b strings.Builder
if !quiet {
b.WriteString(" cpoint dec utf-8 html name\n")
}
for _, c := range p {
p.fmtChar(&b, c, raw)
}
fmt.Fprint(fp, b.String())
}
func (p *printer) PrintSorted(fp io.Writer, quiet, raw bool) {
s := []unidata.Codepoint(*p)
sort.Slice(s, func(i int, j int) bool { return s[i].Codepoint < s[j].Codepoint })
p.Print(fp, quiet, raw)
}
func (p printer) fmtChar(b *strings.Builder, info unidata.Codepoint, raw bool) {
c := rune(info.Codepoint)
size := 44
b.WriteString(fmt.Sprintf("'%v' ", fmtChar(c, raw)))
if info.Width != unidata.WidthFullWidth && info.Width != unidata.WidthWide {
size++
b.WriteString(" ")
}
name := fmt.Sprintf("%s (%s)", info.Name, unidata.Catnames[info.Cat])
if isTerm && termWidth > 0 && utf8.RuneCountInString(name) > termWidth-size {
name = name[:termWidth-size] + "…"
}
b.WriteString(fmt.Sprintf("U+%s %s %s %s %s\n",
fill(fmt.Sprintf("%04X", info.Codepoint), 5),
fill(strconv.FormatUint(uint64(info.Codepoint), 10), 6),
fill(p.utf8(c), 11),
fill(p.entity(c, info.Codepoint), 10),
name))
}
func (p printer) entity(c rune, cp uint32) string {
html := unidata.Entities[c]
if html == "" {
html = fmt.Sprintf("#x%x", cp)
}
return "&" + html + ";"
}
func (p printer) utf8(r rune) string {
buf := make([]byte, 4)
n := utf8.EncodeRune(buf, r)
return fmt.Sprintf("% x", buf[:n])
}
func fill(s string, n int) string {
l := utf8.RuneCountInString(s)
if l >= n {
return s
}
return s + strings.Repeat(" ", n-l)
}