package textfmt import ( "io" "time" ) const ( invalid = iota title paragraph list numberedList definitions numberedDefinitions table code syntax ) type Txt struct { text string link string bold, italic bool cat []Txt } type ListItem struct { text Txt } type DefinitionItem struct { name, value Txt } type TableCell struct { text Txt } type TableRow struct { cells []TableCell header bool } type SyntaxItem struct { symbol string multiple bool required bool optional bool sequence []SyntaxItem choice []SyntaxItem topLevel bool delimited bool } type Entry struct { typ int text Txt titleLevel int items []ListItem definitions []DefinitionItem rows []TableRow syntax SyntaxItem wrapWidth int indent int indentFirst int man struct{ section int date time.Time version string category string } } type TitleInfo struct { section int date time.Time version string category string } type Document struct { entries []Entry } func Text(text string) Txt { return Txt{text: text} } func Link(label, uri string) Txt { return Txt{text: label, link: uri} } func Bold(t Txt) Txt { t.bold = true return t } func Italic(t Txt) Txt { t.italic = true return t } func Cat(t ...Txt) Txt { return Txt{cat: t} } func Title(level int, text string, manInfo ...TitleInfo) Entry { if level != 0 { return Entry{ typ: title, titleLevel: level, text: Text(text), } } e := Entry{ typ: title, titleLevel: level, text: Text(text), } for _, m := range manInfo { if m.section != 0 { e.man.section = m.section } if !m.date.IsZero() { e.man.date = m.date } if m.version != "" { e.man.version = m.version } if m.category != "" { e.man.category = m.category } } return e } func ManSection(s int) TitleInfo { return TitleInfo{section: s} } func ReleaseDate(d time.Time) TitleInfo { return TitleInfo{date: d} } func ReleaseVersion(v string) TitleInfo { return TitleInfo{version: v} } func ManCategory(c string) TitleInfo { return TitleInfo{category: c} } func Paragraph(t Txt) Entry { return Entry{typ: paragraph, text: t} } func Item(text Txt) ListItem { return ListItem{text: text} } func List(items ...ListItem) Entry { return Entry{typ: list, items: items} } func NumberedList(items ...ListItem) Entry { return Entry{typ: numberedList, items: items} } func Definition(name, value Txt) DefinitionItem { return DefinitionItem{name: name, value: value} } func DefinitionList(items ...DefinitionItem) Entry { return Entry{typ: definitions, definitions: items} } func NumberedDefinitionList(items ...DefinitionItem) Entry { return Entry{typ: numberedDefinitions, definitions: items} } func Cell(text Txt) TableCell { return TableCell{text: text} } func Header(cells ...TableCell) TableRow { return TableRow{cells: cells, header: true} } func Row(cells ...TableCell) TableRow { return TableRow{cells: cells} } func Table(rows ...TableRow) Entry { return Entry{typ: table, rows: rows} } func CodeBlock(codeBlock string) Entry { return Entry{typ: code, text: Text(codeBlock)} } func Symbol(text string) SyntaxItem { return SyntaxItem{symbol: text} } func OneOrMore(item SyntaxItem) SyntaxItem { item.required = true item.optional = false item.multiple = true return item } func ZeroOrMore(item SyntaxItem) SyntaxItem { item.required = false item.optional = true item.multiple = true return item } func Required(item SyntaxItem) SyntaxItem { item.required = true item.optional = false return item } func Optional(item SyntaxItem) SyntaxItem { item.required = false item.optional = true return item } func Sequence(items ...SyntaxItem) SyntaxItem { return SyntaxItem{sequence: items} } func Choice(items ...SyntaxItem) SyntaxItem { return SyntaxItem{choice: items} } func Syntax(items ...SyntaxItem) Entry { if len(items) == 1 { return Entry{typ: syntax, syntax: items[0]} } return Entry{typ: syntax, syntax: Sequence(items...)} } func Wrap(e Entry, width int) Entry { e.wrapWidth = width return e } // indentFirst is relative to indent func Indent(e Entry, indent, indentFirst int) Entry { e.indent, e.indentFirst = indent, indentFirst return e } func Doc(e ...Entry) Document { return Document{entries: e} } func Teletype(out io.Writer, d Document) error { return renderTeletype(out, d) } // Runoff is an attempt to render roff format. It is primarily targeting man pages. While it may be possible to // use for other purposes, the man macro will likely be required to render the output. // // Text is always wrapped, or as controlled by the roff processor, except for tables. The Wrap instrunction has // no effect, except for tables. func Runoff(out io.Writer, d Document) error { return renderRoff(out, d) } func Markdown(io.Writer, Document) error { return nil } func HTML(io.Writer, Document) error { // with the won HTML library return nil } func HTMLFragment(io.Writer, Document) error { // with the won HTML library return nil }