2718 lines
56 KiB
Go
2718 lines
56 KiB
Go
package textfmt_test
|
|
|
|
import (
|
|
"bytes"
|
|
"code.squareroundforest.org/arpio/textfmt"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestRoff(t *testing.T) {
|
|
t.Run("invalid", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, textfmt.Doc(textfmt.Entry{})); err == nil {
|
|
t.Fatal("failed to fail")
|
|
}
|
|
})
|
|
|
|
t.Run("empty", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, textfmt.Doc()); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != "" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("example", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Title(0, "Example Text"),
|
|
|
|
textfmt.Indent(
|
|
textfmt.Paragraph(textfmt.Text("Below you can find some test text, with various text items.")),
|
|
0,
|
|
8,
|
|
),
|
|
|
|
textfmt.Title(1, "Document syntax:"),
|
|
|
|
textfmt.Indent(
|
|
textfmt.Syntax(
|
|
textfmt.Symbol("textfmt.Doc"),
|
|
textfmt.Symbol("("),
|
|
textfmt.ZeroOrMore(textfmt.Symbol("Entry")),
|
|
textfmt.Symbol(")"),
|
|
),
|
|
8,
|
|
0,
|
|
),
|
|
|
|
textfmt.Title(1, "Entries:"),
|
|
|
|
textfmt.Paragraph(textfmt.Text("textfmt supports the following entries:")),
|
|
|
|
textfmt.List(
|
|
textfmt.Item(textfmt.Text("CodeBlock")),
|
|
textfmt.Item(textfmt.Text("DefinitionList")),
|
|
textfmt.Item(textfmt.Text("List")),
|
|
textfmt.Item(textfmt.Text("NumberedDefinitionList")),
|
|
textfmt.Item(textfmt.Text("NumberedList")),
|
|
textfmt.Item(textfmt.Text("Paragraph")),
|
|
textfmt.Item(textfmt.Text("Syntax")),
|
|
textfmt.Item(textfmt.Text("Table")),
|
|
textfmt.Item(textfmt.Text("Title")),
|
|
),
|
|
|
|
textfmt.Title(1, "Entry explanations:"),
|
|
|
|
textfmt.DefinitionList(
|
|
textfmt.Definition(
|
|
textfmt.Text("CodeBlock"),
|
|
textfmt.Text("a multiline block of code"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("DefinitionList"),
|
|
textfmt.Text("a list of definitions like this one"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("List"),
|
|
textfmt.Text("a list of items"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("NumberedDefinitionList"),
|
|
textfmt.Text("numbered definitions"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("NumberedList"),
|
|
textfmt.Text("numbered list"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("Paragraph"),
|
|
textfmt.Text("paragraph of text"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("Syntax"),
|
|
textfmt.Text("a syntax expression"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("Table"),
|
|
textfmt.Text("a table"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("Title"),
|
|
textfmt.Text("a title"),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 0
|
|
.ti 0
|
|
\fBExample Text\fR
|
|
.br
|
|
.sp 1v
|
|
.in 0
|
|
.ti 8
|
|
Below you can find some test text, with various text items.
|
|
.br
|
|
.sp 1v
|
|
.in 0
|
|
.ti 0
|
|
\fBDocument syntax:\fR
|
|
.br
|
|
.sp 1v
|
|
.nf
|
|
textfmt.Doc ( [Entry]... )
|
|
.fi
|
|
.br
|
|
.sp 1v
|
|
.in 0
|
|
.ti 0
|
|
\fBEntries:\fR
|
|
.br
|
|
.sp 1v
|
|
.in 0
|
|
.ti 0
|
|
textfmt supports the following entries:
|
|
.br
|
|
.sp 1v
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~CodeBlock
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~DefinitionList
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~List
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~NumberedDefinitionList
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~NumberedList
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~Paragraph
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~Syntax
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~Table
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~Title
|
|
.br
|
|
.sp 1v
|
|
.in 0
|
|
.ti 0
|
|
\fBEntry explanations:\fR
|
|
.br
|
|
.sp 1v
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~CodeBlock:\~\~\~\~\~\~\~\~\~\~\~\~\~\~a multiline block of code
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~DefinitionList:\~\~\~\~\~\~\~\~\~a list of definitions like this one
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~List:\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~a list of items
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~NumberedDefinitionList:\~numbered definitions
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~NumberedList:\~\~\~\~\~\~\~\~\~\~\~numbered list
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~Paragraph:\~\~\~\~\~\~\~\~\~\~\~\~\~\~paragraph of text
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~Syntax:\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~a syntax expression
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~Table:\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~a table
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~Title:\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~a title
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Log(b.String())
|
|
t.Log(expect)
|
|
logBytes(t, b.String())
|
|
logBytes(t, expect)
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("example man", func(t *testing.T) {
|
|
releaseDate := time.Date(2025, 11, 2, 15, 36, 18, 0, time.FixedZone("CET", 3600))
|
|
doc := textfmt.Doc(
|
|
textfmt.Title(
|
|
0,
|
|
"Example Text",
|
|
textfmt.ManSection(1),
|
|
textfmt.ManCategory("User Command"),
|
|
textfmt.ReleaseDate(releaseDate),
|
|
textfmt.ReleaseVersion("v1"),
|
|
),
|
|
|
|
textfmt.Indent(
|
|
textfmt.Paragraph(textfmt.Text("Below you can find some test text, with various text items.")),
|
|
0,
|
|
8,
|
|
),
|
|
|
|
textfmt.Title(1, "Document syntax:"),
|
|
|
|
textfmt.Indent(
|
|
textfmt.Syntax(
|
|
textfmt.Symbol("textfmt.Doc"),
|
|
textfmt.Symbol("("),
|
|
textfmt.ZeroOrMore(textfmt.Symbol("Entry")),
|
|
textfmt.Symbol(")"),
|
|
),
|
|
8,
|
|
0,
|
|
),
|
|
|
|
textfmt.Title(1, "Entries:"),
|
|
|
|
textfmt.Paragraph(textfmt.Text("textfmt supports the following entries:")),
|
|
|
|
textfmt.List(
|
|
textfmt.Item(textfmt.Text("CodeBlock")),
|
|
textfmt.Item(textfmt.Text("DefinitionList")),
|
|
textfmt.Item(textfmt.Text("List")),
|
|
textfmt.Item(textfmt.Text("NumberedDefinitionList")),
|
|
textfmt.Item(textfmt.Text("NumberedList")),
|
|
textfmt.Item(textfmt.Text("Paragraph")),
|
|
textfmt.Item(textfmt.Text("Syntax")),
|
|
textfmt.Item(textfmt.Text("Table")),
|
|
textfmt.Item(textfmt.Text("Title")),
|
|
),
|
|
|
|
textfmt.Title(1, "Entry explanations:"),
|
|
|
|
textfmt.DefinitionList(
|
|
textfmt.Definition(
|
|
textfmt.Text("CodeBlock"),
|
|
textfmt.Text("a multiline block of code"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("DefinitionList"),
|
|
textfmt.Text("a list of definitions like this one"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("List"),
|
|
textfmt.Text("a list of items"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("NumberedDefinitionList"),
|
|
textfmt.Text("numbered definitions"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("NumberedList"),
|
|
textfmt.Text("numbered list"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("Paragraph"),
|
|
textfmt.Text("paragraph of text"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("Syntax"),
|
|
textfmt.Text("a syntax expression"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("Table"),
|
|
textfmt.Text("a table"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("Title"),
|
|
textfmt.Text("a title"),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.TH "Example Text" 1 "November 2025" "v1" "User Command"
|
|
.br
|
|
.sp 1v
|
|
.in 0
|
|
.ti 8
|
|
Below you can find some test text, with various text items.
|
|
.br
|
|
.sp 1v
|
|
.in 0
|
|
.ti 0
|
|
\fBDocument syntax:\fR
|
|
.br
|
|
.sp 1v
|
|
.nf
|
|
textfmt.Doc ( [Entry]... )
|
|
.fi
|
|
.br
|
|
.sp 1v
|
|
.in 0
|
|
.ti 0
|
|
\fBEntries:\fR
|
|
.br
|
|
.sp 1v
|
|
.in 0
|
|
.ti 0
|
|
textfmt supports the following entries:
|
|
.br
|
|
.sp 1v
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~CodeBlock
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~DefinitionList
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~List
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~NumberedDefinitionList
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~NumberedList
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~Paragraph
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~Syntax
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~Table
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~Title
|
|
.br
|
|
.sp 1v
|
|
.in 0
|
|
.ti 0
|
|
\fBEntry explanations:\fR
|
|
.br
|
|
.sp 1v
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~CodeBlock:\~\~\~\~\~\~\~\~\~\~\~\~\~\~a multiline block of code
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~DefinitionList:\~\~\~\~\~\~\~\~\~a list of definitions like this one
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~List:\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~a list of items
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~NumberedDefinitionList:\~numbered definitions
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~NumberedList:\~\~\~\~\~\~\~\~\~\~\~numbered list
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~Paragraph:\~\~\~\~\~\~\~\~\~\~\~\~\~\~paragraph of text
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~Syntax:\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~a syntax expression
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~Table:\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~a table
|
|
.br
|
|
.in 26
|
|
.ti 0
|
|
\(bu\~Title:\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~a title
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Log(b.String())
|
|
t.Log(expect)
|
|
logBytes(t, b.String())
|
|
logBytes(t, expect)
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("escape", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(textfmt.Paragraph(textfmt.Text("...some sample text...\x00\n...with invalid chars.")))
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = ".in 0\n.ti 0\n\\&...some sample text...\x00 ...with invalid chars.\n"
|
|
if b.String() != expect {
|
|
logBytes(t, b.String())
|
|
logBytes(t, expect)
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("styling", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Paragraph(
|
|
textfmt.Cat(
|
|
textfmt.Italic(textfmt.Text("Some sample text... with")),
|
|
textfmt.Bold(textfmt.Text("some")),
|
|
textfmt.Italic(textfmt.Text("styling.")),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 0
|
|
.ti 0
|
|
\fISome sample text... with\fR \fBsome\fR \fIstyling.\fR
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("single line by default", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(textfmt.Paragraph(textfmt.Text("Some sample text...\n\non multiple lines.")))
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 0
|
|
.ti 0
|
|
Some sample text... on multiple lines.
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent", func(t *testing.T) {
|
|
t.Run("indent uniform", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.Paragraph(textfmt.Text("Some sample text...\non multiple lines.")),
|
|
2,
|
|
0,
|
|
),
|
|
)
|
|
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 2
|
|
.ti 2
|
|
Some sample text... on multiple lines.
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent first in", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.Paragraph(textfmt.Text("Some sample text...\non multiple lines.")),
|
|
2,
|
|
2,
|
|
),
|
|
)
|
|
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 2
|
|
.ti 4
|
|
Some sample text... on multiple lines.
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent first out", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.Paragraph(textfmt.Text("Some sample text...\non multiple lines.")),
|
|
2,
|
|
-2,
|
|
),
|
|
)
|
|
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 2
|
|
.ti 0
|
|
Some sample text... on multiple lines.
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("failing writer", func(t *testing.T) {
|
|
w := &failingWriter{failAfter: 15}
|
|
doc := textfmt.Doc(
|
|
textfmt.Paragraph(textfmt.Text("Some sample text...\non multiple lines.")),
|
|
)
|
|
|
|
if err := textfmt.Runoff(w, doc); err == nil {
|
|
t.Fatal("failed to fail")
|
|
}
|
|
})
|
|
|
|
t.Run("concatenate", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Paragraph(
|
|
textfmt.Cat(
|
|
textfmt.Text("Text from"),
|
|
textfmt.Text("multiple"),
|
|
textfmt.Text("pieces."),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".in 0\n.ti 0\nText from multiple pieces.\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("link", func(t *testing.T) {
|
|
t.Run("without label", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(textfmt.Paragraph(textfmt.Link("", "https://sqrndfst.org")))
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".in 0\n.ti 0\nhttps://sqrndfst.org\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("with label", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(textfmt.Paragraph(textfmt.Link("a link", "https://sqrndfst.org")))
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".in 0\n.ti 0\na link (https://sqrndfst.org)\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("newline in link", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(textfmt.Paragraph(textfmt.Link("a\nlink", "https://sqrndfst.org\n/foo")))
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".in 0\n.ti 0\na link (https://sqrndfst.org /foo)\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("title", func(t *testing.T) {
|
|
t.Run("basic", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(textfmt.Title(0, "This is a title"))
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 0
|
|
.ti 0
|
|
\fBThis is a title\fR
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("escaped man", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(textfmt.Title(0, "This is a title \"\\\"", textfmt.ManSection(1)))
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.TH "This is a title \(dq\\\(dq" 1 "" "" ""
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("paragraph", func(t *testing.T) {
|
|
t.Run("unwrapped", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(textfmt.Paragraph(textfmt.Text("This is a paragraph.")))
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 0
|
|
.ti 0
|
|
This is a paragraph.
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("wrap ignored", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(
|
|
textfmt.Wrap(textfmt.Paragraph(textfmt.Text("This is a paragraph.")), 8),
|
|
)
|
|
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 0
|
|
.ti 0
|
|
This is a paragraph.
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent in", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.Paragraph(textfmt.Text("This is a paragraph.")),
|
|
0,
|
|
4,
|
|
),
|
|
)
|
|
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 0
|
|
.ti 4
|
|
This is a paragraph.
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent out", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.Paragraph(textfmt.Text("This is a paragraph.")),
|
|
4,
|
|
-4,
|
|
),
|
|
)
|
|
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 4
|
|
.ti 0
|
|
This is a paragraph.
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("list", func(t *testing.T) {
|
|
t.Run("simple", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.List(
|
|
textfmt.Item(textfmt.Text("this is an item")),
|
|
textfmt.Item(textfmt.Text("this is another item")),
|
|
textfmt.Item(textfmt.Text("this is a third item")),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 2
|
|
.ti 0
|
|
\(bu\~this is an item
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~this is another item
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
\(bu\~this is a third item
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.List(
|
|
textfmt.Item(textfmt.Text("this is an item")),
|
|
textfmt.Item(textfmt.Text("this is another item")),
|
|
textfmt.Item(textfmt.Text("this is a third item")),
|
|
),
|
|
4,
|
|
0,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 6
|
|
.ti 4
|
|
\(bu\~this is an item
|
|
.br
|
|
.in 6
|
|
.ti 4
|
|
\(bu\~this is another item
|
|
.br
|
|
.in 6
|
|
.ti 4
|
|
\(bu\~this is a third item
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent in", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.List(
|
|
textfmt.Item(textfmt.Text("this is an item")),
|
|
textfmt.Item(textfmt.Text("this is another item")),
|
|
textfmt.Item(textfmt.Text("this is a third item")),
|
|
),
|
|
-2,
|
|
6,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 0
|
|
.ti 4
|
|
\(bu\~this is an item
|
|
.br
|
|
.in 0
|
|
.ti 4
|
|
\(bu\~this is another item
|
|
.br
|
|
.in 0
|
|
.ti 4
|
|
\(bu\~this is a third item
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent out", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.List(
|
|
textfmt.Item(textfmt.Text("this is an item")),
|
|
textfmt.Item(textfmt.Text("this is another item")),
|
|
textfmt.Item(textfmt.Text("this is a third item")),
|
|
),
|
|
2,
|
|
-2,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 4
|
|
.ti 0
|
|
\(bu\~this is an item
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
\(bu\~this is another item
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
\(bu\~this is a third item
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("custom bullet", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.List(
|
|
textfmt.Item(textfmt.Text("foo bar baz"), textfmt.Bullet("*")),
|
|
textfmt.Item(textfmt.Text("qux"), textfmt.Bullet("*")),
|
|
textfmt.Item(textfmt.Text("quux"), textfmt.Bullet("*")),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 2
|
|
.ti 0
|
|
*\~foo bar baz
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
*\~qux
|
|
.br
|
|
.in 2
|
|
.ti 0
|
|
*\~quux
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("custom bullet longer", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.List(
|
|
textfmt.Item(textfmt.Text("foo bar baz"), textfmt.Bullet("=>")),
|
|
textfmt.Item(textfmt.Text("qux"), textfmt.Bullet("=>")),
|
|
textfmt.Item(textfmt.Text("quux"), textfmt.Bullet("=>")),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 3
|
|
.ti 0
|
|
=>\~foo bar baz
|
|
.br
|
|
.in 3
|
|
.ti 0
|
|
=>\~qux
|
|
.br
|
|
.in 3
|
|
.ti 0
|
|
=>\~quux
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("no bullet", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.List(
|
|
textfmt.Item(textfmt.Text("foo bar baz"), textfmt.NoBullet()),
|
|
textfmt.Item(textfmt.Text("qux"), textfmt.NoBullet()),
|
|
textfmt.Item(textfmt.Text("quux"), textfmt.NoBullet()),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 0
|
|
.ti 0
|
|
foo bar baz
|
|
.br
|
|
.in 0
|
|
.ti 0
|
|
qux
|
|
.br
|
|
.in 0
|
|
.ti 0
|
|
quux
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("varying bullet length", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.List(
|
|
textfmt.Item(textfmt.Text("foo bar baz"), textfmt.Bullet("=>")),
|
|
textfmt.Item(textfmt.Text("qux"), textfmt.Bullet("==>")),
|
|
textfmt.Item(textfmt.Text("quux"), textfmt.Bullet("=>")),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 4
|
|
.ti 0
|
|
=>\~\~foo bar baz
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
==>\~qux
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
=>\~\~quux
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("escape custom bullet", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.List(
|
|
textfmt.Item(textfmt.Text("foo bar baz"), textfmt.Bullet(".>")),
|
|
textfmt.Item(textfmt.Text("qux"), textfmt.Bullet("=>")),
|
|
textfmt.Item(textfmt.Text("quux"), textfmt.Bullet("=>")),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 3
|
|
.ti 0
|
|
\&.>\~foo bar baz
|
|
.br
|
|
.in 3
|
|
.ti 0
|
|
=>\~qux
|
|
.br
|
|
.in 3
|
|
.ti 0
|
|
=>\~quux
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("numbered list", func(t *testing.T) {
|
|
t.Run("simple", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.NumberedList(
|
|
textfmt.Item(textfmt.Text("this is an item")),
|
|
textfmt.Item(textfmt.Text("this is another item")),
|
|
textfmt.Item(textfmt.Text("this is a third item")),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 3
|
|
.ti 0
|
|
1.\~this is an item
|
|
.br
|
|
.in 3
|
|
.ti 0
|
|
2.\~this is another item
|
|
.br
|
|
.in 3
|
|
.ti 0
|
|
3.\~this is a third item
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.NumberedList(
|
|
textfmt.Item(textfmt.Text("this is an item")),
|
|
textfmt.Item(textfmt.Text("this is another item")),
|
|
textfmt.Item(textfmt.Text("this is a third item")),
|
|
),
|
|
4,
|
|
0,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 7
|
|
.ti 4
|
|
1.\~this is an item
|
|
.br
|
|
.in 7
|
|
.ti 4
|
|
2.\~this is another item
|
|
.br
|
|
.in 7
|
|
.ti 4
|
|
3.\~this is a third item
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent in", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.NumberedList(
|
|
textfmt.Item(textfmt.Text("this is an item")),
|
|
textfmt.Item(textfmt.Text("this is another item")),
|
|
textfmt.Item(textfmt.Text("this is a third item")),
|
|
),
|
|
-3,
|
|
7,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 0
|
|
.ti 4
|
|
1.\~this is an item
|
|
.br
|
|
.in 0
|
|
.ti 4
|
|
2.\~this is another item
|
|
.br
|
|
.in 0
|
|
.ti 4
|
|
3.\~this is a third item
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent out", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.NumberedList(
|
|
textfmt.Item(textfmt.Text("this is an item")),
|
|
textfmt.Item(textfmt.Text("this is another item")),
|
|
textfmt.Item(textfmt.Text("this is a third item")),
|
|
),
|
|
3,
|
|
-3,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 6
|
|
.ti 0
|
|
1.\~this is an item
|
|
.br
|
|
.in 6
|
|
.ti 0
|
|
2.\~this is another item
|
|
.br
|
|
.in 6
|
|
.ti 0
|
|
3.\~this is a third item
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("long numbered list", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.NumberedList(
|
|
textfmt.Item(textfmt.Text("this is an item")),
|
|
textfmt.Item(textfmt.Text("this is another item")),
|
|
textfmt.Item(textfmt.Text("this is the third item")),
|
|
textfmt.Item(textfmt.Text("this is the fourth item")),
|
|
textfmt.Item(textfmt.Text("this is the fifth item")),
|
|
textfmt.Item(textfmt.Text("this is the sixth item")),
|
|
textfmt.Item(textfmt.Text("this is the seventh item")),
|
|
textfmt.Item(textfmt.Text("this is the eighth item")),
|
|
textfmt.Item(textfmt.Text("this is the nineth item")),
|
|
textfmt.Item(textfmt.Text("this is the tenth item")),
|
|
textfmt.Item(textfmt.Text("this is the eleventh item")),
|
|
textfmt.Item(textfmt.Text("this is the twelfth item")),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 4
|
|
.ti 0
|
|
1.\~\~this is an item
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
2.\~\~this is another item
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
3.\~\~this is the third item
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
4.\~\~this is the fourth item
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
5.\~\~this is the fifth item
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
6.\~\~this is the sixth item
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
7.\~\~this is the seventh item
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
8.\~\~this is the eighth item
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
9.\~\~this is the nineth item
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
10.\~this is the tenth item
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
11.\~this is the eleventh item
|
|
.br
|
|
.in 4
|
|
.ti 0
|
|
12.\~this is the twelfth item
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("definition list", func(t *testing.T) {
|
|
t.Run("simple", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.DefinitionList(
|
|
textfmt.Definition(textfmt.Text("red"), textfmt.Text("looks like strawberry")),
|
|
textfmt.Definition(textfmt.Text("green"), textfmt.Text("looks like grass")),
|
|
textfmt.Definition(textfmt.Text("blue"), textfmt.Text("looks like sky")),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 9
|
|
.ti 0
|
|
\(bu\~red:\~\~\~looks like strawberry
|
|
.br
|
|
.in 9
|
|
.ti 0
|
|
\(bu\~green:\~looks like grass
|
|
.br
|
|
.in 9
|
|
.ti 0
|
|
\(bu\~blue:\~\~looks like sky
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.DefinitionList(
|
|
textfmt.Definition(textfmt.Text("red"), textfmt.Text("looks like strawberry")),
|
|
textfmt.Definition(textfmt.Text("green"), textfmt.Text("looks like grass")),
|
|
textfmt.Definition(textfmt.Text("blue"), textfmt.Text("looks like sky")),
|
|
),
|
|
4,
|
|
0,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 13
|
|
.ti 4
|
|
\(bu\~red:\~\~\~looks like strawberry
|
|
.br
|
|
.in 13
|
|
.ti 4
|
|
\(bu\~green:\~looks like grass
|
|
.br
|
|
.in 13
|
|
.ti 4
|
|
\(bu\~blue:\~\~looks like sky
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent in", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.DefinitionList(
|
|
textfmt.Definition(textfmt.Text("red"), textfmt.Text("looks like strawberry")),
|
|
textfmt.Definition(textfmt.Text("green"), textfmt.Text("looks like grass")),
|
|
textfmt.Definition(textfmt.Text("blue"), textfmt.Text("looks like sky")),
|
|
),
|
|
-6,
|
|
9,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 3
|
|
.ti 3
|
|
\(bu\~red:\~\~\~looks like strawberry
|
|
.br
|
|
.in 3
|
|
.ti 3
|
|
\(bu\~green:\~looks like grass
|
|
.br
|
|
.in 3
|
|
.ti 3
|
|
\(bu\~blue:\~\~looks like sky
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent out", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.DefinitionList(
|
|
textfmt.Definition(textfmt.Text("red"), textfmt.Text("looks like strawberry")),
|
|
textfmt.Definition(textfmt.Text("green"), textfmt.Text("looks like grass")),
|
|
textfmt.Definition(textfmt.Text("blue"), textfmt.Text("looks like sky")),
|
|
),
|
|
4,
|
|
-4,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 13
|
|
.ti 0
|
|
\(bu\~red:\~\~\~looks like strawberry
|
|
.br
|
|
.in 13
|
|
.ti 0
|
|
\(bu\~green:\~looks like grass
|
|
.br
|
|
.in 13
|
|
.ti 0
|
|
\(bu\~blue:\~\~looks like sky
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("custom bullet", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.DefinitionList(
|
|
textfmt.Definition(
|
|
textfmt.Text("one"),
|
|
textfmt.Text("foo bar baz"),
|
|
textfmt.Bullet("*"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("two"),
|
|
textfmt.Text("qux"),
|
|
textfmt.Bullet("*"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("three"),
|
|
textfmt.Text("quux"),
|
|
textfmt.Bullet("*"),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 9
|
|
.ti 0
|
|
*\~one:\~\~\~foo bar baz
|
|
.br
|
|
.in 9
|
|
.ti 0
|
|
*\~two:\~\~\~qux
|
|
.br
|
|
.in 9
|
|
.ti 0
|
|
*\~three:\~quux
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("custom bullet longer", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.DefinitionList(
|
|
textfmt.Definition(
|
|
textfmt.Text("one"),
|
|
textfmt.Text("foo bar baz"),
|
|
textfmt.Bullet("=>"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("two"),
|
|
textfmt.Text("qux"),
|
|
textfmt.Bullet("=>"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("three"),
|
|
textfmt.Text("quux"),
|
|
textfmt.Bullet("=>"),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 10
|
|
.ti 0
|
|
=>\~one:\~\~\~foo bar baz
|
|
.br
|
|
.in 10
|
|
.ti 0
|
|
=>\~two:\~\~\~qux
|
|
.br
|
|
.in 10
|
|
.ti 0
|
|
=>\~three:\~quux
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("no bullet", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.DefinitionList(
|
|
textfmt.Definition(
|
|
textfmt.Text("one"),
|
|
textfmt.Text("foo bar baz"),
|
|
textfmt.NoBullet(),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("two"),
|
|
textfmt.Text("qux"),
|
|
textfmt.NoBullet(),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("three"),
|
|
textfmt.Text("quux"),
|
|
textfmt.NoBullet(),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 7
|
|
.ti 0
|
|
one:\~\~\~foo bar baz
|
|
.br
|
|
.in 7
|
|
.ti 0
|
|
two:\~\~\~qux
|
|
.br
|
|
.in 7
|
|
.ti 0
|
|
three:\~quux
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("varying bullet length", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.DefinitionList(
|
|
textfmt.Definition(
|
|
textfmt.Text("one"),
|
|
textfmt.Text("foo bar baz"),
|
|
textfmt.Bullet("=>"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("two"),
|
|
textfmt.Text("qux"),
|
|
textfmt.Bullet("==>"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("three"),
|
|
textfmt.Text("quux"),
|
|
textfmt.Bullet("=>"),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 11
|
|
.ti 0
|
|
=>\~\~one:\~\~\~foo bar baz
|
|
.br
|
|
.in 11
|
|
.ti 0
|
|
==>\~two:\~\~\~qux
|
|
.br
|
|
.in 11
|
|
.ti 0
|
|
=>\~\~three:\~quux
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("escape custom bullet", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.DefinitionList(
|
|
textfmt.Definition(
|
|
textfmt.Text("one"),
|
|
textfmt.Text("foo bar baz"),
|
|
textfmt.Bullet(".>"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("two"),
|
|
textfmt.Text("qux"),
|
|
textfmt.Bullet("=>"),
|
|
),
|
|
textfmt.Definition(
|
|
textfmt.Text("three"),
|
|
textfmt.Text("quux"),
|
|
textfmt.Bullet("=>"),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 10
|
|
.ti 0
|
|
\&.>\~one:\~\~\~foo bar baz
|
|
.br
|
|
.in 10
|
|
.ti 0
|
|
=>\~two:\~\~\~qux
|
|
.br
|
|
.in 10
|
|
.ti 0
|
|
=>\~three:\~quux
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("numbered definition list", func(t *testing.T) {
|
|
t.Run("simple", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.NumberedDefinitionList(
|
|
textfmt.Definition(textfmt.Text("red"), textfmt.Text("looks like strawberry")),
|
|
textfmt.Definition(textfmt.Text("green"), textfmt.Text("looks like grass")),
|
|
textfmt.Definition(textfmt.Text("blue"), textfmt.Text("looks like sky")),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 10
|
|
.ti 0
|
|
1.\~red:\~\~\~looks like strawberry
|
|
.br
|
|
.in 10
|
|
.ti 0
|
|
2.\~green:\~looks like grass
|
|
.br
|
|
.in 10
|
|
.ti 0
|
|
3.\~blue:\~\~looks like sky
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.NumberedDefinitionList(
|
|
textfmt.Definition(textfmt.Text("red"), textfmt.Text("looks like strawberry")),
|
|
textfmt.Definition(textfmt.Text("green"), textfmt.Text("looks like grass")),
|
|
textfmt.Definition(textfmt.Text("blue"), textfmt.Text("looks like sky")),
|
|
),
|
|
0,
|
|
4,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 10
|
|
.ti 4
|
|
1.\~red:\~\~\~looks like strawberry
|
|
.br
|
|
.in 10
|
|
.ti 4
|
|
2.\~green:\~looks like grass
|
|
.br
|
|
.in 10
|
|
.ti 4
|
|
3.\~blue:\~\~looks like sky
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent in", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.NumberedDefinitionList(
|
|
textfmt.Definition(textfmt.Text("red"), textfmt.Text("looks like strawberry")),
|
|
textfmt.Definition(textfmt.Text("green"), textfmt.Text("looks like grass")),
|
|
textfmt.Definition(textfmt.Text("blue"), textfmt.Text("looks like sky")),
|
|
),
|
|
-6,
|
|
9,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 4
|
|
.ti 3
|
|
1.\~red:\~\~\~looks like strawberry
|
|
.br
|
|
.in 4
|
|
.ti 3
|
|
2.\~green:\~looks like grass
|
|
.br
|
|
.in 4
|
|
.ti 3
|
|
3.\~blue:\~\~looks like sky
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent out", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.NumberedDefinitionList(
|
|
textfmt.Definition(textfmt.Text("red"), textfmt.Text("looks like strawberry")),
|
|
textfmt.Definition(textfmt.Text("green"), textfmt.Text("looks like grass")),
|
|
textfmt.Definition(textfmt.Text("blue"), textfmt.Text("looks like sky")),
|
|
),
|
|
4,
|
|
-4,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `
|
|
.in 14
|
|
.ti 0
|
|
1.\~red:\~\~\~looks like strawberry
|
|
.br
|
|
.in 14
|
|
.ti 0
|
|
2.\~green:\~looks like grass
|
|
.br
|
|
.in 14
|
|
.ti 0
|
|
3.\~blue:\~\~looks like sky
|
|
`
|
|
|
|
if "\n"+b.String() != expect {
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("long numbered definition list", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.NumberedDefinitionList(
|
|
textfmt.Definition(textfmt.Text("one"), textfmt.Text("this is an item")),
|
|
textfmt.Definition(textfmt.Text("two"), textfmt.Text("this is another item")),
|
|
textfmt.Definition(textfmt.Text("three"), textfmt.Text("this is the third item")),
|
|
textfmt.Definition(textfmt.Text("four"), textfmt.Text("this is the fourth item")),
|
|
textfmt.Definition(textfmt.Text("five"), textfmt.Text("this is the fifth item")),
|
|
textfmt.Definition(textfmt.Text("six"), textfmt.Text("this is the sixth item")),
|
|
textfmt.Definition(textfmt.Text("seven"), textfmt.Text("this is the seventh item")),
|
|
textfmt.Definition(textfmt.Text("eight"), textfmt.Text("this is the eighth item")),
|
|
textfmt.Definition(textfmt.Text("nine"), textfmt.Text("this is the nineth item")),
|
|
textfmt.Definition(textfmt.Text("ten"), textfmt.Text("this is the tenth item")),
|
|
textfmt.Definition(textfmt.Text("eleven"), textfmt.Text("this is the eleventh item")),
|
|
textfmt.Definition(textfmt.Text("twelve"), textfmt.Text("this is the twelfth item")),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.in 12
|
|
.ti 0
|
|
1.\~\~one:\~\~\~\~this is an item
|
|
.br
|
|
.in 12
|
|
.ti 0
|
|
2.\~\~two:\~\~\~\~this is another item
|
|
.br
|
|
.in 12
|
|
.ti 0
|
|
3.\~\~three:\~\~this is the third item
|
|
.br
|
|
.in 12
|
|
.ti 0
|
|
4.\~\~four:\~\~\~this is the fourth item
|
|
.br
|
|
.in 12
|
|
.ti 0
|
|
5.\~\~five:\~\~\~this is the fifth item
|
|
.br
|
|
.in 12
|
|
.ti 0
|
|
6.\~\~six:\~\~\~\~this is the sixth item
|
|
.br
|
|
.in 12
|
|
.ti 0
|
|
7.\~\~seven:\~\~this is the seventh item
|
|
.br
|
|
.in 12
|
|
.ti 0
|
|
8.\~\~eight:\~\~this is the eighth item
|
|
.br
|
|
.in 12
|
|
.ti 0
|
|
9.\~\~nine:\~\~\~this is the nineth item
|
|
.br
|
|
.in 12
|
|
.ti 0
|
|
10.\~ten:\~\~\~\~this is the tenth item
|
|
.br
|
|
.in 12
|
|
.ti 0
|
|
11.\~eleven:\~this is the eleventh item
|
|
.br
|
|
.in 12
|
|
.ti 0
|
|
12.\~twelve:\~this is the twelfth item
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("table", func(t *testing.T) {
|
|
t.Run("now rows", func(t *testing.T) {
|
|
var b bytes.Buffer
|
|
doc := textfmt.Doc(textfmt.Table())
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != "\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("no columns", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Table(
|
|
textfmt.Row(),
|
|
textfmt.Row(),
|
|
textfmt.Row(),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != "\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("basic", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Table(
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("1")), textfmt.Cell(textfmt.Text("2")), textfmt.Cell(textfmt.Text("3")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("4")), textfmt.Cell(textfmt.Text("5")), textfmt.Cell(textfmt.Text("6")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("7")), textfmt.Cell(textfmt.Text("8")), textfmt.Cell(textfmt.Text("9")),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.nf
|
|
1 | 2 | 3
|
|
---------
|
|
4 | 5 | 6
|
|
---------
|
|
7 | 8 | 9
|
|
.fi
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("basic with header", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Table(
|
|
textfmt.Header(
|
|
textfmt.Cell(textfmt.Text("1")), textfmt.Cell(textfmt.Text("-1")), textfmt.Cell(textfmt.Text("0")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("1")), textfmt.Cell(textfmt.Text("2")), textfmt.Cell(textfmt.Text("3")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("4")), textfmt.Cell(textfmt.Text("5")), textfmt.Cell(textfmt.Text("6")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("7")), textfmt.Cell(textfmt.Text("8")), textfmt.Cell(textfmt.Text("9")),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.nf
|
|
1 | -1 | 0
|
|
==========
|
|
1 | 2\~ | 3
|
|
----------
|
|
4 | 5\~ | 6
|
|
----------
|
|
7 | 8\~ | 9
|
|
.fi
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("header without rows", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Table(
|
|
textfmt.Header(
|
|
textfmt.Cell(textfmt.Text("foo")),
|
|
textfmt.Cell(textfmt.Text("bar")),
|
|
textfmt.Cell(textfmt.Text("baz")),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\nfoo | bar | baz\n===============\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("single row", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Table(
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("1")),
|
|
textfmt.Cell(textfmt.Text("2")),
|
|
textfmt.Cell(textfmt.Text("3")),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\n1 | 2 | 3\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("single row with header", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Table(
|
|
textfmt.Header(
|
|
textfmt.Cell(textfmt.Text("foo")),
|
|
textfmt.Cell(textfmt.Text("bar")),
|
|
textfmt.Cell(textfmt.Text("baz")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("1")),
|
|
textfmt.Cell(textfmt.Text("2")),
|
|
textfmt.Cell(textfmt.Text("3")),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\nfoo | bar | baz\n===============\n1\\~\\~ | 2\\~\\~ | 3\\~\\~\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("single column", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Table(
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("1")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("4")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("7")),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\n1\n-\n4\n-\n7\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("single column with header", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Table(
|
|
textfmt.Header(
|
|
textfmt.Cell(textfmt.Text("foo")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("1")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("4")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("7")),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\nfoo\n===\n1\\~\\~\n---\n4\\~\\~\n---\n7\\~\\~\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("single row and single column", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Table(
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("1")),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\n1\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("single row and single column with header", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Table(
|
|
textfmt.Header(
|
|
textfmt.Cell(textfmt.Text("foo")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("1")),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\nfoo\n===\n1\\~\\~\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("unequal number of row cells", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Table(
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("1")), textfmt.Cell(textfmt.Text("2")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("4")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("7")), textfmt.Cell(textfmt.Text("8")), textfmt.Cell(textfmt.Text("9")),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.nf
|
|
1 | 2 | \~
|
|
---------
|
|
4 | \~ | \~
|
|
---------
|
|
7 | 8 | 9
|
|
.fi
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("unequal number of row cells with header", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Table(
|
|
textfmt.Header(
|
|
textfmt.Cell(textfmt.Text("1")), textfmt.Cell(textfmt.Text("-1")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("1")), textfmt.Cell(textfmt.Text("2")), textfmt.Cell(textfmt.Text("3")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("4")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("")), textfmt.Cell(textfmt.Text("8")), textfmt.Cell(textfmt.Text("9")),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.nf
|
|
1 | -1 | \~
|
|
==========
|
|
1 | 2\~ | 3
|
|
----------
|
|
4 | \~\~ | \~
|
|
----------
|
|
\~ | 8\~ | 9
|
|
.fi
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("all empty cells", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Wrap(
|
|
textfmt.Table(
|
|
textfmt.Header(textfmt.Cell(textfmt.Text("")), textfmt.Cell(textfmt.Text(""))),
|
|
textfmt.Row(textfmt.Cell(textfmt.Text("")), textfmt.Cell(textfmt.Text(""))),
|
|
textfmt.Row(textfmt.Cell(textfmt.Text("")), textfmt.Cell(textfmt.Text(""))),
|
|
),
|
|
72,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\n | \n===\n | \n---\n | \n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("no new lines by default", func(t *testing.T) {
|
|
const txt = `
|
|
Walking through the mixed forests of Brandenburg in early autumn,
|
|
one notices the dominant presence of Scots pine (Pinus sylvestris).
|
|
`
|
|
|
|
doc := textfmt.Doc(
|
|
textfmt.Table(
|
|
textfmt.Header(textfmt.Cell(textfmt.Text("Forest"))),
|
|
textfmt.Row(textfmt.Cell(textfmt.Text(txt))),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal()
|
|
}
|
|
|
|
// <<
|
|
const expect = `.nf
|
|
Forest\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~
|
|
=====================================================================================================================================
|
|
Walking through the mixed forests of Brandenburg in early autumn, one notices the dominant presence of Scots pine (Pinus sylvestris).
|
|
.fi
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.Table(
|
|
textfmt.Header(
|
|
textfmt.Cell(textfmt.Text("one")),
|
|
textfmt.Cell(textfmt.Text("two")),
|
|
textfmt.Cell(textfmt.Text("three")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("Walking through the mixed forests of Brandenburg in early autumn")),
|
|
textfmt.Cell(textfmt.Text("one notices the dominant presence of Scots pine (Pinus sylvestris)")),
|
|
textfmt.Cell(textfmt.Text("interspersed with sessile oak (Quercus petraea)")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("and silver birch (Betula pendula)")),
|
|
textfmt.Cell(textfmt.Text("their canopies creating a mosaic of light")),
|
|
textfmt.Cell(textfmt.Text("and shadow on the forest floor")),
|
|
),
|
|
),
|
|
4,
|
|
0,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.nf
|
|
one\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~ | two\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~ | three\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~
|
|
=======================================================================================================================================================================================
|
|
Walking through the mixed forests of Brandenburg in early autumn | one notices the dominant presence of Scots pine (Pinus sylvestris) | interspersed with sessile oak (Quercus petraea)
|
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
and silver birch (Betula pendula)\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~ | their canopies creating a mosaic of light\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~ | and shadow on the forest floor\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~
|
|
.fi
|
|
`
|
|
|
|
if b.String() != expect {
|
|
logBytes(t, expect)
|
|
logBytes(t, b.String())
|
|
t.Log("\n" + expect)
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("wrap without indent", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Wrap(
|
|
textfmt.Table(
|
|
textfmt.Header(
|
|
textfmt.Cell(textfmt.Text("one")),
|
|
textfmt.Cell(textfmt.Text("two")),
|
|
textfmt.Cell(textfmt.Text("three")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("Walking through the mixed forests of Brandenburg in early autumn")),
|
|
textfmt.Cell(textfmt.Text("one notices the dominant presence of Scots pine (Pinus sylvestris)")),
|
|
textfmt.Cell(textfmt.Text("interspersed with sessile oak (Quercus petraea)")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("and silver birch (Betula pendula)")),
|
|
textfmt.Cell(textfmt.Text("their canopies creating a mosaic of light")),
|
|
textfmt.Cell(textfmt.Text("and shadow on the forest floor")),
|
|
),
|
|
),
|
|
72,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.nf
|
|
one\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~ | two\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~ | three\~\~\~\~\~\~\~\~\~\~\~\~
|
|
===================================================================
|
|
Walking through the\~ | one notices the dominant | interspersed with
|
|
mixed forests of\~\~\~\~ | presence of Scots pine\~\~ | sessile oak\~\~\~\~\~\~
|
|
Brandenburg in early | (Pinus sylvestris)\~\~\~\~\~\~ | (Quercus petraea)
|
|
autumn\~\~\~\~\~\~\~\~\~\~\~\~\~\~ | \~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~ | \~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~
|
|
-------------------------------------------------------------------
|
|
and silver birch\~\~\~\~ | their canopies creating\~ | and shadow on the
|
|
(Betula pendula)\~\~\~\~ | a mosaic of light\~\~\~\~\~\~\~ | forest floor\~\~\~\~\~
|
|
.fi
|
|
`
|
|
|
|
if b.String() != expect {
|
|
logBytes(t, expect)
|
|
logBytes(t, b.String())
|
|
t.Log("\n" + expect)
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indent and wrap", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.Wrap(
|
|
textfmt.Table(
|
|
textfmt.Header(
|
|
textfmt.Cell(textfmt.Text("one")),
|
|
textfmt.Cell(textfmt.Text("two")),
|
|
textfmt.Cell(textfmt.Text("three")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("Walking through the mixed forests of Brandenburg in early autumn")),
|
|
textfmt.Cell(textfmt.Text("one notices the dominant presence of Scots pine (Pinus sylvestris)")),
|
|
textfmt.Cell(textfmt.Text("interspersed with sessile oak (Quercus petraea)")),
|
|
),
|
|
textfmt.Row(
|
|
textfmt.Cell(textfmt.Text("and silver birch (Betula pendula)")),
|
|
textfmt.Cell(textfmt.Text("their canopies creating a mosaic of light")),
|
|
textfmt.Cell(textfmt.Text("and shadow on the forest floor")),
|
|
),
|
|
),
|
|
72,
|
|
),
|
|
4,
|
|
0,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.nf
|
|
one\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~ | two\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~ | three\~\~\~\~\~\~\~\~\~\~\~\~
|
|
==================================================================
|
|
Walking through the\~ | one notices the\~\~\~\~\~\~\~\~ | interspersed with
|
|
mixed forests of\~\~\~\~ | dominant presence of\~\~\~ | sessile oak\~\~\~\~\~\~
|
|
Brandenburg in early | Scots pine (Pinus\~\~\~\~\~\~ | (Quercus petraea)
|
|
autumn\~\~\~\~\~\~\~\~\~\~\~\~\~\~ | sylvestris)\~\~\~\~\~\~\~\~\~\~\~\~ | \~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~
|
|
------------------------------------------------------------------
|
|
and silver birch\~\~\~\~ | their canopies creating | and shadow on the
|
|
(Betula pendula)\~\~\~\~ | a mosaic of light\~\~\~\~\~\~ | forest floor\~\~\~\~\~
|
|
.fi
|
|
`
|
|
|
|
if b.String() != expect {
|
|
logBytes(t, expect)
|
|
logBytes(t, b.String())
|
|
t.Log("\n" + expect)
|
|
t.Fatal("\n" + b.String())
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("code", func(t *testing.T) {
|
|
t.Run("unindented", func(t *testing.T) {
|
|
const code = `func() textfmt.Document {
|
|
return textfmt.Document(
|
|
textfmt.Paragraph(textfmt.Text("Hello, world!")),
|
|
)
|
|
}`
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, textfmt.Doc(textfmt.CodeBlock(code))); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\n"+code+"\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("indented", func(t *testing.T) {
|
|
const code = `func() textfmt.Document {
|
|
return textfmt.Document(
|
|
textfmt.Paragraph(textfmt.Text("Hello, world!")),
|
|
)
|
|
}`
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, textfmt.Doc(textfmt.Indent(textfmt.CodeBlock(code), 4, 0))); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
const expect = `.nf
|
|
func() textfmt.Document {
|
|
return textfmt.Document(
|
|
textfmt.Paragraph(textfmt.Text("Hello, world!")),
|
|
)
|
|
}
|
|
.fi
|
|
`
|
|
|
|
if b.String() != expect {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("wrap has no effect", func(t *testing.T) {
|
|
const code = `func() textfmt.Document {
|
|
return textfmt.Document(
|
|
textfmt.Paragraph(textfmt.Text("Hello, world!")),
|
|
)
|
|
}`
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, textfmt.Doc(textfmt.Wrap(textfmt.CodeBlock(code), 12))); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\n"+code+"\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("syntax", func(t *testing.T) {
|
|
t.Run("symbol", func(t *testing.T) {
|
|
doc := textfmt.Doc(textfmt.Syntax(textfmt.Symbol("foo")))
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\nfoo\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("zero or more symbols", func(t *testing.T) {
|
|
doc := textfmt.Doc(textfmt.Syntax(textfmt.ZeroOrMore(textfmt.Symbol("foo"))))
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\n[foo]...\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("one or more", func(t *testing.T) {
|
|
doc := textfmt.Doc(textfmt.Syntax(textfmt.OneOrMore(textfmt.Symbol("foo"))))
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\n<foo>...\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("required symbol", func(t *testing.T) {
|
|
doc := textfmt.Doc(textfmt.Syntax(textfmt.Required(textfmt.Symbol("foo"))))
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\n<foo>\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("optional symbol", func(t *testing.T) {
|
|
doc := textfmt.Doc(textfmt.Syntax(textfmt.Optional(textfmt.Symbol("foo"))))
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\n[foo]\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("sequence implicit", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Syntax(
|
|
textfmt.Symbol("foo"),
|
|
textfmt.Symbol("bar"),
|
|
textfmt.Symbol("baz"),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\nfoo bar baz\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("sequence", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Syntax(
|
|
textfmt.Sequence(
|
|
textfmt.Symbol("foo"),
|
|
textfmt.Symbol("bar"),
|
|
textfmt.Symbol("baz"),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\nfoo bar baz\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("subsequence", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Syntax(
|
|
textfmt.Symbol("corge"),
|
|
textfmt.Sequence(
|
|
textfmt.Symbol("foo"),
|
|
textfmt.Symbol("bar"),
|
|
textfmt.Symbol("baz"),
|
|
),
|
|
textfmt.Symbol("garply"),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\ncorge (foo bar baz) garply\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("top level choice", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Syntax(
|
|
textfmt.Choice(
|
|
textfmt.Symbol("foo"),
|
|
textfmt.Symbol("bar"),
|
|
textfmt.Symbol("baz"),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\nfoo\nbar\nbaz\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("choice", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Syntax(
|
|
textfmt.Symbol("corge"),
|
|
textfmt.Choice(
|
|
textfmt.Symbol("foo"),
|
|
textfmt.Symbol("bar"),
|
|
textfmt.Symbol("baz"),
|
|
),
|
|
textfmt.Symbol("garply"),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\ncorge (foo|bar|baz) garply\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("example", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Syntax(
|
|
textfmt.Symbol("foo"),
|
|
textfmt.ZeroOrMore(textfmt.Symbol("options")),
|
|
textfmt.Required(textfmt.Symbol("filename")),
|
|
textfmt.ZeroOrMore(
|
|
textfmt.Choice(
|
|
textfmt.Symbol("string"),
|
|
textfmt.Symbol("number"),
|
|
),
|
|
),
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\nfoo [options]... <filename> [string|number]...\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
|
|
t.Run("example indented", func(t *testing.T) {
|
|
doc := textfmt.Doc(
|
|
textfmt.Indent(
|
|
textfmt.Syntax(
|
|
textfmt.Symbol("foo"),
|
|
textfmt.ZeroOrMore(textfmt.Symbol("options")),
|
|
textfmt.Required(textfmt.Symbol("filename")),
|
|
textfmt.ZeroOrMore(
|
|
textfmt.Choice(
|
|
textfmt.Symbol("string"),
|
|
textfmt.Symbol("number"),
|
|
),
|
|
),
|
|
),
|
|
4,
|
|
0,
|
|
),
|
|
)
|
|
|
|
var b bytes.Buffer
|
|
if err := textfmt.Runoff(&b, doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if b.String() != ".nf\n foo [options]... <filename> [string|number]...\n.fi\n" {
|
|
t.Fatal(b.String())
|
|
}
|
|
})
|
|
})
|
|
}
|