mirror of
https://github.com/golang/go
synced 2024-11-24 09:20:02 -07:00
go/doc/comment: parse and print code
[This CL is part of a sequence implementing the proposal #51082. The design doc is at https://go.dev/s/godocfmt-design.] Implement indented code blocks. For #51082. Change-Id: I0eacbf56e101424a875386cb6f26174b239561f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/397285 Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: Jonathan Amsterdam <jba@google.com> Reviewed-by: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
6eceabf119
commit
3f5d099663
@ -51,6 +51,11 @@ func (p *htmlPrinter) block(out *bytes.Buffer, x Block) {
|
|||||||
out.WriteString("</h")
|
out.WriteString("</h")
|
||||||
out.WriteString(h)
|
out.WriteString(h)
|
||||||
out.WriteString(">\n")
|
out.WriteString(">\n")
|
||||||
|
|
||||||
|
case *Code:
|
||||||
|
out.WriteString("<pre>")
|
||||||
|
p.escape(out, x.Text)
|
||||||
|
out.WriteString("</pre>\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +54,18 @@ func (p *mdPrinter) block(out *bytes.Buffer, x Block) {
|
|||||||
out.WriteString("}")
|
out.WriteString("}")
|
||||||
}
|
}
|
||||||
out.WriteString("\n")
|
out.WriteString("\n")
|
||||||
|
|
||||||
|
case *Code:
|
||||||
|
md := x.Text
|
||||||
|
for md != "" {
|
||||||
|
var line string
|
||||||
|
line, md, _ = strings.Cut(md, "\n")
|
||||||
|
if line != "" {
|
||||||
|
out.WriteString("\t")
|
||||||
|
out.WriteString(line)
|
||||||
|
}
|
||||||
|
out.WriteString("\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,6 +309,9 @@ func (p *Parser) Parse(text string) *Doc {
|
|||||||
case line == "":
|
case line == "":
|
||||||
// emit nothing
|
// emit nothing
|
||||||
|
|
||||||
|
case isIndented(line):
|
||||||
|
b, lines = d.code(lines)
|
||||||
|
|
||||||
case (len(lines) == 1 || lines[1] == "") && !didHeading && isOldHeading(line, all, len(all)-n):
|
case (len(lines) == 1 || lines[1] == "") && !didHeading && isOldHeading(line, all, len(all)-n):
|
||||||
b = d.oldHeading(line)
|
b = d.oldHeading(line)
|
||||||
didHeading = true
|
didHeading = true
|
||||||
@ -473,17 +476,51 @@ func (d *parseDoc) heading(line string) Block {
|
|||||||
return &Heading{Text: []Text{Plain(strings.TrimSpace(line[1:]))}}
|
return &Heading{Text: []Text{Plain(strings.TrimSpace(line[1:]))}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// code returns a code block built from the indented text
|
||||||
|
// at the start of lines, along with the remainder of the lines.
|
||||||
|
// If there is no indented text at the start, or if the indented
|
||||||
|
// text consists only of empty lines, code returns a nil Block.
|
||||||
|
func (d *parseDoc) code(lines []string) (b Block, rest []string) {
|
||||||
|
lines, rest = indented(lines)
|
||||||
|
body := unindent(lines)
|
||||||
|
if len(body) == 0 {
|
||||||
|
return nil, rest
|
||||||
|
}
|
||||||
|
body = append(body, "") // to get final \n from Join
|
||||||
|
return &Code{Text: strings.Join(body, "\n")}, rest
|
||||||
|
}
|
||||||
|
|
||||||
|
// isIndented reports whether the line is indented,
|
||||||
|
// meaning it starts with a space or tab.
|
||||||
|
func isIndented(line string) bool {
|
||||||
|
return line != "" && (line[0] == ' ' || line[0] == '\t')
|
||||||
|
}
|
||||||
|
|
||||||
|
// indented splits lines into an initial indented section
|
||||||
|
// and the remaining lines, returning the two halves.
|
||||||
|
func indented(lines []string) (indented, rest []string) {
|
||||||
|
// Blank lines mid-run are OK, but not at the end.
|
||||||
|
i := 0
|
||||||
|
for i < len(lines) && (isIndented(lines[i]) || lines[i] == "") {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
for i > 0 && lines[i-1] == "" {
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
return lines[:i], lines[i:]
|
||||||
|
}
|
||||||
|
|
||||||
// paragraph returns a paragraph block built from the
|
// paragraph returns a paragraph block built from the
|
||||||
// unindented text at the start of lines, along with the remainder of the lines.
|
// unindented text at the start of lines, along with the remainder of the lines.
|
||||||
// If there is no unindented text at the start of lines,
|
// If there is no unindented text at the start of lines,
|
||||||
// then paragraph returns a nil Block.
|
// then paragraph returns a nil Block.
|
||||||
func (d *parseDoc) paragraph(lines []string) (b Block, rest []string) {
|
func (d *parseDoc) paragraph(lines []string) (b Block, rest []string) {
|
||||||
// TODO: Paragraph should be interrupted by any indented line,
|
// Paragraph is interrupted by any indented line,
|
||||||
// which is either a list or a code block,
|
// which is either a list or a code block,
|
||||||
// and of course by a blank line.
|
// and of course by a blank line.
|
||||||
// It should not be interrupted by a # line - headings must stand alone.
|
// It is not interrupted by a # line - headings must stand alone.
|
||||||
i := 0
|
i := 0
|
||||||
for i < len(lines) && lines[i] != "" {
|
for i < len(lines) && lines[i] != "" && !isIndented(lines[i]) {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
lines, rest = lines[:i], lines[i:]
|
lines, rest = lines[:i], lines[i:]
|
||||||
|
@ -213,6 +213,18 @@ func (p *commentPrinter) block(out *bytes.Buffer, x Block) {
|
|||||||
out.WriteString("# ")
|
out.WriteString("# ")
|
||||||
p.text(out, "", x.Text)
|
p.text(out, "", x.Text)
|
||||||
out.WriteString("\n")
|
out.WriteString("\n")
|
||||||
|
|
||||||
|
case *Code:
|
||||||
|
md := x.Text
|
||||||
|
for md != "" {
|
||||||
|
var line string
|
||||||
|
line, md, _ = strings.Cut(md, "\n")
|
||||||
|
if line != "" {
|
||||||
|
out.WriteString("\t")
|
||||||
|
out.WriteString(line)
|
||||||
|
}
|
||||||
|
out.WriteString("\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
94
src/go/doc/comment/testdata/code.txt
vendored
Normal file
94
src/go/doc/comment/testdata/code.txt
vendored
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
-- input --
|
||||||
|
Text.
|
||||||
|
A tab-indented
|
||||||
|
(no, not eight-space indented)
|
||||||
|
code block and haiku.
|
||||||
|
More text.
|
||||||
|
One space
|
||||||
|
is
|
||||||
|
enough
|
||||||
|
to
|
||||||
|
start
|
||||||
|
a
|
||||||
|
block.
|
||||||
|
More text.
|
||||||
|
|
||||||
|
Blocks
|
||||||
|
can
|
||||||
|
|
||||||
|
have
|
||||||
|
blank
|
||||||
|
lines.
|
||||||
|
-- gofmt --
|
||||||
|
Text.
|
||||||
|
|
||||||
|
A tab-indented
|
||||||
|
(no, not eight-space indented)
|
||||||
|
code block and haiku.
|
||||||
|
|
||||||
|
More text.
|
||||||
|
|
||||||
|
One space
|
||||||
|
is
|
||||||
|
enough
|
||||||
|
to
|
||||||
|
start
|
||||||
|
a
|
||||||
|
block.
|
||||||
|
|
||||||
|
More text.
|
||||||
|
|
||||||
|
Blocks
|
||||||
|
can
|
||||||
|
|
||||||
|
have
|
||||||
|
blank
|
||||||
|
lines.
|
||||||
|
-- markdown --
|
||||||
|
Text.
|
||||||
|
|
||||||
|
A tab-indented
|
||||||
|
(no, not eight-space indented)
|
||||||
|
code block and haiku.
|
||||||
|
|
||||||
|
More text.
|
||||||
|
|
||||||
|
One space
|
||||||
|
is
|
||||||
|
enough
|
||||||
|
to
|
||||||
|
start
|
||||||
|
a
|
||||||
|
block.
|
||||||
|
|
||||||
|
More text.
|
||||||
|
|
||||||
|
Blocks
|
||||||
|
can
|
||||||
|
|
||||||
|
have
|
||||||
|
blank
|
||||||
|
lines.
|
||||||
|
-- html --
|
||||||
|
<p>Text.
|
||||||
|
<pre>A tab-indented
|
||||||
|
(no, not eight-space indented)
|
||||||
|
code block and haiku.
|
||||||
|
</pre>
|
||||||
|
<p>More text.
|
||||||
|
<pre>One space
|
||||||
|
is
|
||||||
|
enough
|
||||||
|
to
|
||||||
|
start
|
||||||
|
a
|
||||||
|
block.
|
||||||
|
</pre>
|
||||||
|
<p>More text.
|
||||||
|
<pre> Blocks
|
||||||
|
can
|
||||||
|
|
||||||
|
have
|
||||||
|
blank
|
||||||
|
lines.
|
||||||
|
</pre>
|
31
src/go/doc/comment/testdata/code2.txt
vendored
Normal file
31
src/go/doc/comment/testdata/code2.txt
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
-- input --
|
||||||
|
Text.
|
||||||
|
|
||||||
|
A tab-indented
|
||||||
|
(no, not eight-space indented)
|
||||||
|
code block and haiku.
|
||||||
|
|
||||||
|
More text.
|
||||||
|
-- gofmt --
|
||||||
|
Text.
|
||||||
|
|
||||||
|
A tab-indented
|
||||||
|
(no, not eight-space indented)
|
||||||
|
code block and haiku.
|
||||||
|
|
||||||
|
More text.
|
||||||
|
-- markdown --
|
||||||
|
Text.
|
||||||
|
|
||||||
|
A tab-indented
|
||||||
|
(no, not eight-space indented)
|
||||||
|
code block and haiku.
|
||||||
|
|
||||||
|
More text.
|
||||||
|
-- html --
|
||||||
|
<p>Text.
|
||||||
|
<pre>A tab-indented
|
||||||
|
(no, not eight-space indented)
|
||||||
|
code block and haiku.
|
||||||
|
</pre>
|
||||||
|
<p>More text.
|
33
src/go/doc/comment/testdata/code3.txt
vendored
Normal file
33
src/go/doc/comment/testdata/code3.txt
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
-- input --
|
||||||
|
Text.
|
||||||
|
|
||||||
|
$
|
||||||
|
A tab-indented
|
||||||
|
(surrounded by more blank lines)
|
||||||
|
code block and haiku.
|
||||||
|
$
|
||||||
|
|
||||||
|
More text.
|
||||||
|
-- gofmt --
|
||||||
|
Text.
|
||||||
|
|
||||||
|
A tab-indented
|
||||||
|
(surrounded by more blank lines)
|
||||||
|
code block and haiku.
|
||||||
|
|
||||||
|
More text.
|
||||||
|
-- markdown --
|
||||||
|
Text.
|
||||||
|
|
||||||
|
A tab-indented
|
||||||
|
(surrounded by more blank lines)
|
||||||
|
code block and haiku.
|
||||||
|
|
||||||
|
More text.
|
||||||
|
-- html --
|
||||||
|
<p>Text.
|
||||||
|
<pre>A tab-indented
|
||||||
|
(surrounded by more blank lines)
|
||||||
|
code block and haiku.
|
||||||
|
</pre>
|
||||||
|
<p>More text.
|
12
src/go/doc/comment/testdata/text9.txt
vendored
Normal file
12
src/go/doc/comment/testdata/text9.txt
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{"TextPrefix":"|", "TextCodePrefix": "@"}
|
||||||
|
-- input --
|
||||||
|
Hello, world
|
||||||
|
Code block here.
|
||||||
|
-- gofmt --
|
||||||
|
Hello, world
|
||||||
|
|
||||||
|
Code block here.
|
||||||
|
-- text --
|
||||||
|
|Hello, world
|
||||||
|
|
|
||||||
|
@Code block here.
|
@ -15,18 +15,23 @@ import (
|
|||||||
// A textPrinter holds the state needed for printing a Doc as plain text.
|
// A textPrinter holds the state needed for printing a Doc as plain text.
|
||||||
type textPrinter struct {
|
type textPrinter struct {
|
||||||
*Printer
|
*Printer
|
||||||
long strings.Builder
|
long strings.Builder
|
||||||
prefix string
|
prefix string
|
||||||
width int
|
codePrefix string
|
||||||
|
width int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text returns a textual formatting of the Doc.
|
// Text returns a textual formatting of the Doc.
|
||||||
// See the [Printer] documentation for ways to customize the text output.
|
// See the [Printer] documentation for ways to customize the text output.
|
||||||
func (p *Printer) Text(d *Doc) []byte {
|
func (p *Printer) Text(d *Doc) []byte {
|
||||||
tp := &textPrinter{
|
tp := &textPrinter{
|
||||||
Printer: p,
|
Printer: p,
|
||||||
prefix: p.TextPrefix,
|
prefix: p.TextPrefix,
|
||||||
width: p.TextWidth,
|
codePrefix: p.TextCodePrefix,
|
||||||
|
width: p.TextWidth,
|
||||||
|
}
|
||||||
|
if tp.codePrefix == "" {
|
||||||
|
tp.codePrefix = p.TextPrefix + "\t"
|
||||||
}
|
}
|
||||||
if tp.width == 0 {
|
if tp.width == 0 {
|
||||||
tp.width = 80 - utf8.RuneCountInString(tp.prefix)
|
tp.width = 80 - utf8.RuneCountInString(tp.prefix)
|
||||||
@ -35,6 +40,7 @@ func (p *Printer) Text(d *Doc) []byte {
|
|||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
for i, x := range d.Content {
|
for i, x := range d.Content {
|
||||||
if i > 0 && blankBefore(x) {
|
if i > 0 && blankBefore(x) {
|
||||||
|
out.WriteString(tp.prefix)
|
||||||
writeNL(&out)
|
writeNL(&out)
|
||||||
}
|
}
|
||||||
tp.block(&out, x)
|
tp.block(&out, x)
|
||||||
@ -86,6 +92,18 @@ func (p *textPrinter) block(out *bytes.Buffer, x Block) {
|
|||||||
out.WriteString(p.prefix)
|
out.WriteString(p.prefix)
|
||||||
out.WriteString("# ")
|
out.WriteString("# ")
|
||||||
p.text(out, x.Text)
|
p.text(out, x.Text)
|
||||||
|
|
||||||
|
case *Code:
|
||||||
|
text := x.Text
|
||||||
|
for text != "" {
|
||||||
|
var line string
|
||||||
|
line, text, _ = strings.Cut(text, "\n")
|
||||||
|
if line != "" {
|
||||||
|
out.WriteString(p.codePrefix)
|
||||||
|
out.WriteString(line)
|
||||||
|
}
|
||||||
|
writeNL(out)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user