wand/format.go
2025-08-26 03:21:35 +02:00

202 lines
3.4 KiB
Go

package wand
import (
"fmt"
"io"
"sort"
"strings"
)
func printer(out io.Writer) (printf func(f string, args ...any), println func(args ...any), finish func() error) {
var err error
printf = func(f string, args ...any) {
if err != nil {
return
}
_, err = fmt.Fprintf(out, f, args...)
}
println = func(args ...any) {
if err != nil {
return
}
_, err = fmt.Fprintln(out, args...)
}
finish = func() error {
return err
}
return
}
func paragraphs(s string) string {
var (
paragraph []string
paragraphs [][]string
)
l := strings.Split(s, "\n")
for i := range l {
l[i] = strings.TrimSpace(l[i])
if l[i] == "" {
if len(paragraph) > 0 {
paragraphs, paragraph = append(paragraphs, paragraph), nil
}
continue
}
paragraph = append(paragraph, l[i])
}
if len(paragraph) > 0 {
paragraphs = append(paragraphs, paragraph)
}
var cparagraphs []string
for _, p := range paragraphs {
cparagraphs = append(cparagraphs, strings.Join(p, " "))
}
return strings.Join(cparagraphs, "\n\n")
}
func lines(s string) string {
p := paragraphs(s)
pp := strings.Split(p, "\n\n")
return strings.Join(pp, "\n")
}
func escapeTeletype(s string) string {
r := []rune(s)
for i := range r {
if r[i] >= 0x00 && r[i] <= 0x1f && r[i] != '\n' && r[i] != '\t' {
r[i] = 0xb7
}
if r[i] >= 0x7f && r[i] <= 0x9f {
r[i] = 0xb7
}
}
return string(r)
}
func manParagraphs(s string) string {
p := paragraphs(s)
pp := strings.Split(p, "\n\n")
for i := range pp {
pp[i] = fmt.Sprintf(".PP\n%s", pp[i])
}
return strings.Join(pp, "\n")
}
func manLines(s string) string {
l := lines(s)
ll := strings.Split(l, "\n")
for i := range ll {
ll[i] = fmt.Sprintf(".br\n%s", ll[i])
}
return strings.Join(ll, "\n")
}
func escapeRoff(s string) string {
var (
rr []rune
lastNewline bool
)
r := []rune(s)
for _, ri := range r {
switch ri {
case '\\', '-', '"':
rr = append(rr, '\\', ri)
case '.', '\'':
if lastNewline {
rr = append(rr, '\\')
}
rr = append(rr, ri)
case 0x2013:
rr = append(rr, []rune("\\(en")...)
case 0x2014:
rr = append(rr, []rune("\\(em")...)
case 0x201c:
rr = append(rr, []rune("\\(lq")...)
case 0x201d:
rr = append(rr, []rune("\\(rq")...)
case 0x2018:
rr = append(rr, []rune("\\(oq")...)
case 0x2019:
rr = append(rr, []rune("\\(cq")...)
default:
rr = append(rr, ri)
}
lastNewline = ri == '\n'
}
return string(rr)
}
func escapeMD(s string) string {
var (
rr []rune
lastDigit bool
)
r := []rune(s)
for _, ri := range r {
switch ri {
case '*', '_', '#', '-', '+', '[', ']', '`', '<', '>', '|', '\\':
rr = append(rr, '\\', ri)
case '.':
if lastDigit {
rr = append(rr, '\\')
}
rr = append(rr, ri)
default:
rr = append(rr, ri)
lastDigit = ri >= 0 && ri <= 9
}
}
return string(rr)
}
func prepareOptions(o []docOption) (names []string, descriptions map[string]string) {
for _, oi := range o {
ons := []string{fmt.Sprintf("--%s", oi.name)}
for _, sn := range oi.shortNames {
ons = append(ons, fmt.Sprintf("-%s", sn))
}
n := strings.Join(ons, ", ")
if oi.isBool {
n = fmt.Sprintf("%s [b]", n)
} else {
n = fmt.Sprintf("%s %s", n, oi.typ)
}
if oi.acceptsMultiple {
n = fmt.Sprintf("%s [*]", n)
}
names = append(names, n)
if descriptions == nil {
descriptions = make(map[string]string)
}
descriptions[n] = oi.description
}
sort.Strings(names)
return
}