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 }