weave: fix %include parsing, add highlighting
Recognize that
%include file -
means "no tag, no caption" instead of "the tag is -, add caption."
Write "go" after backticks, which GitHub will render with syntax
highlighting.
Change-Id: I9e0b3618b5fba8834d7f06b8fc7adf0781574a2d
Reviewed-on: https://go-review.googlesource.com/c/example/+/673875
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/gotypes/README.md b/gotypes/README.md
index 350fbc6..9886a11 100644
--- a/gotypes/README.md
+++ b/gotypes/README.md
@@ -143,7 +143,7 @@
// go get golang.org/x/example/gotypes/pkginfo
-```
+```go
package main
import (
@@ -247,7 +247,7 @@
(The hexadecimal number may vary from one run to the next.)
-```
+```go
$ go build golang.org/x/example/gotypes/pkginfo
$ ./pkginfo
Package "cmd/hello"
@@ -505,7 +505,7 @@
// go get golang.org/x/example/gotypes/defsuses
-```
+```go
func PrintDefsUses(fset *token.FileSet, files ...*ast.File) error {
conf := types.Config{Importer: importer.Default()}
info := &types.Info{
@@ -535,7 +535,7 @@
// go get golang.org/x/example/gotypes/hello
-```
+```go
package main
import "fmt"
@@ -549,7 +549,7 @@
This is what it prints:
-```
+```go
$ go build golang.org/x/example/gotypes/defsuses
$ ./defsuses
hello.go:1:9: "main" defines <nil>
@@ -796,7 +796,7 @@
// go get golang.org/x/example/gotypes/lookup
-```
+```go
func main() {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "hello.go", hello, parser.ParseComments)
@@ -839,7 +839,7 @@
and so on.
-```
+```go
const hello = `
package main
@@ -863,7 +863,7 @@
Here's the output:
-```
+```go
$ go build golang.org/x/example/gotypes/lookup
$ ./lookup
At hello.go:6:1, "append" = builtin append
@@ -1566,7 +1566,7 @@
// go get golang.org/x/example/gotypes/typeandvalue
-```
+```go
// f is a parsed, type-checked *ast.File.
ast.Inspect(f, func(n ast.Node) bool {
if expr, ok := n.(ast.Expr); ok {
@@ -1596,7 +1596,7 @@
Given this input:
-```
+```go
const input = `
package main
@@ -1613,7 +1613,7 @@
the program prints:
-```
+```go
$ go build golang.org/x/example/gotypes/typeandvalue
$ ./typeandvalue
make(map[string]int) mode: value
@@ -1672,7 +1672,7 @@
// go get golang.org/x/example/gotypes/nilfunc
-```
+```go
// CheckNilFuncComparison reports unintended comparisons
// of functions against nil, e.g., "if x.Method == nil {".
func CheckNilFuncComparison(info *types.Info, n ast.Node) {
@@ -1718,7 +1718,7 @@
Given this input,
-```
+```go
const input = `package main
import "bytes"
@@ -1736,7 +1736,7 @@
the program reports these errors:
-```
+```go
$ go build golang.org/x/example/gotypes/nilfunc
$ ./nilfunc
input.go:7:5: comparison of function Bytes == nil is always false
@@ -1969,7 +1969,7 @@
Here's an example:
-```
+```go
$ ./skeleton io ReadWriteCloser buffer
// *buffer implements io.ReadWriteCloser.
type buffer struct{}
@@ -1993,7 +1993,7 @@
// go get golang.org/x/example/gotypes/skeleton
-```
+```go
func PrintSkeleton(pkg *types.Package, ifacename, concname string) error {
obj := pkg.Scope().Lookup(ifacename)
if obj == nil {
@@ -2051,7 +2051,7 @@
Here's another example that illustrates it:
-```
+```go
$ ./skeleton net/http Handler myHandler
// *myHandler implements net/http.Handler.
type myHandler struct{}
@@ -2067,7 +2067,7 @@
// go get golang.org/x/example/gotypes/implements
-```
+```go
// Find all named types at package level.
var allNamed []*types.Named
for _, name := range pkg.Scope().Names() {
@@ -2099,7 +2099,7 @@
// go get golang.org/x/example/gotypes/implements
-```
+```go
const input = `package main
type A struct{}
@@ -2118,7 +2118,7 @@
the program prints:
-```
+```go
$ go build golang.org/x/example/gotypes/implements
$ ./implements
*hello.A satisfies hello.I
@@ -2276,7 +2276,7 @@
// go get golang.org/x/example/gotypes/hugeparam
-```
+```go
var bytesFlag = flag.Int("bytes", 48, "maximum parameter size in bytes")
func PrintHugeParams(fset *token.FileSet, info *types.Info, sizes types.Sizes, files []*ast.File) {
@@ -2324,7 +2324,7 @@
is copied.
-```
+```go
% ./hugeparam encoding/xml
/go/src/encoding/xml/marshal.go:167:50: "start" parameter: encoding/xml.StartElement = 56 bytes
/go/src/encoding/xml/marshal.go:734:97: "" result: encoding/xml.StartElement = 56 bytes
@@ -2408,7 +2408,7 @@
Here's an example:
-```
+```go
$ ./doc net/http File
type net/http.File interface{Readdir(count int) ([]os.FileInfo, error); Seek(offset int64, whence int) (int64, error); Stat() (os.FileInfo, error); io.Closer; io.Reader}
$GOROOT/src/io/io.go:92:2: method (net/http.File) Close() error
@@ -2435,7 +2435,7 @@
// go get golang.org/x/example/gotypes/doc
-```
+```go
pkgpath, name := os.Args[1], os.Args[2]
// Load complete type information for the specified packages,
@@ -2465,7 +2465,7 @@
// go get golang.org/x/example/gotypes/doc
-```
+```go
// Print the object and its methods (incl. location of definition).
fmt.Println(obj)
for _, sel := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
diff --git a/internal/cmd/weave/weave.go b/internal/cmd/weave/weave.go
index d833653..880b415 100644
--- a/internal/cmd/weave/weave.go
+++ b/internal/cmd/weave/weave.go
@@ -27,6 +27,7 @@
import (
"bufio"
"bytes"
+ "flag"
"fmt"
"io"
"log"
@@ -37,13 +38,14 @@
)
func main() {
+ flag.Parse()
log.SetFlags(0)
log.SetPrefix("weave: ")
- if len(os.Args) != 2 {
+ if flag.NArg() != 1 {
log.Fatal("usage: weave input.md\n")
}
- f, err := os.Open(os.Args[1])
+ f, err := os.Open(flag.Arg(0))
if err != nil {
log.Fatal(err)
}
@@ -100,26 +102,38 @@
}
case strings.HasPrefix(line, "%include"):
words := strings.Fields(line)
- if len(words) < 2 {
- log.Fatal(line)
+ var section string
+ caption := true
+ switch len(words) {
+ case 2: // %include filename
+ // Nothing to do.
+ case 3: // %include filename section OR %include filename -
+ if words[2] == "-" {
+ caption = false
+ } else {
+ section = words[2]
+ }
+ case 4: // %include filename section -
+ section = words[2]
+ if words[3] != "-" {
+ log.Fatalf("last word is not '-': %s", line)
+ }
+ caption = false
+ default:
+ log.Fatalf("wrong # words (want 2-4): %s", line)
}
filename := words[1]
- // Show caption unless '-' follows.
- if len(words) < 4 || words[3] != "-" {
+ if caption {
fmt.Printf(" // go get golang.org/x/example/%s/%s\n\n",
curDir, filepath.Dir(filename))
}
- section := ""
- if len(words) > 2 {
- section = words[2]
- }
s, err := include(filename, section)
if err != nil {
log.Fatal(err)
}
- fmt.Println("```")
+ fmt.Println("```go")
fmt.Println(cleanListing(s)) // TODO(adonovan): escape /^```/ in s
fmt.Println("```")
default:
diff --git a/slog-handler-guide/README.md b/slog-handler-guide/README.md
index 01027cc..5342c06 100644
--- a/slog-handler-guide/README.md
+++ b/slog-handler-guide/README.md
@@ -115,7 +115,7 @@
We begin with the `IndentHandler` type
and the `New` function that constructs it from an `io.Writer` and options:
-```
+```go
type IndentHandler struct {
opts Options
// TODO: state for WithGroup and WithAttrs
@@ -186,7 +186,7 @@
Our `IndentHandler` doesn't use the context. It just compares the argument level
with its configured minimum level:
-```
+```go
func (h *IndentHandler) Enabled(ctx context.Context, level slog.Level) bool {
return level >= h.opts.Level.Level()
}
@@ -232,7 +232,7 @@
That is how `IndentHandler.Handle` is structured:
-```
+```go
func (h *IndentHandler) Handle(ctx context.Context, r slog.Record) error {
buf := make([]byte, 0, 1024)
if !r.Time.IsZero() {
@@ -287,7 +287,7 @@
At the heart of the handler is the `appendAttr` method, responsible for
formatting a single attribute:
-```
+```go
func (h *IndentHandler) appendAttr(buf []byte, a slog.Attr, indentLevel int) []byte {
// Resolve the Attr's value before doing anything else.
a.Value = a.Value.Resolve()
@@ -405,7 +405,7 @@
and loop over that slice in `Handle`. We start with a struct that can hold
either a group name or some attributes:
-```
+```go
// groupOrAttrs holds either a group name or a list of slog.Attrs.
type groupOrAttrs struct {
group string // group name if non-empty
@@ -415,7 +415,7 @@
Then we add a slice of `groupOrAttrs` to our handler:
-```
+```go
type IndentHandler struct {
opts Options
goas []groupOrAttrs
@@ -429,7 +429,7 @@
To that end, we define a method that will copy our handler struct
and append one `groupOrAttrs` to the copy:
-```
+```go
func (h *IndentHandler) withGroupOrAttrs(goa groupOrAttrs) *IndentHandler {
h2 := *h
h2.goas = make([]groupOrAttrs, len(h.goas)+1)
@@ -446,7 +446,7 @@
The `With` methods are easy to write using `withGroupOrAttrs`:
-```
+```go
func (h *IndentHandler) WithGroup(name string) slog.Handler {
if name == "" {
return h
@@ -465,7 +465,7 @@
The `Handle` method can now process the groupOrAttrs slice after
the built-in attributes and before the ones in the record:
-```
+```go
func (h *IndentHandler) Handle(ctx context.Context, r slog.Record) error {
buf := make([]byte, 0, 1024)
if !r.Time.IsZero() {
@@ -587,7 +587,7 @@
To pre-format the arguments to `WithAttrs`, we need to keep track of some
additional state in the `IndentHandler` struct.
-```
+```go
type IndentHandler struct {
opts Options
preformatted []byte // data from WithGroup and WithAttrs
@@ -608,7 +608,7 @@
This `WithGroup` is a lot like the previous one: it just remembers the
new group, which is unopened initially.
-```
+```go
func (h *IndentHandler) WithGroup(name string) slog.Handler {
if name == "" {
return h
@@ -624,7 +624,7 @@
`WithAttrs` does all the pre-formatting:
-```
+```go
func (h *IndentHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
if len(attrs) == 0 {
return h
@@ -668,7 +668,7 @@
It's the `Handle` method's job to insert the pre-formatted material in the right
place, which is after the built-in attributes and before the ones in the record:
-```
+```go
func (h *IndentHandler) Handle(ctx context.Context, r slog.Record) error {
buf := make([]byte, 0, 1024)
if !r.Time.IsZero() {
@@ -728,7 +728,7 @@
a function that returns its output formatted as a slice of maps. Here is the test function
for our example handler:
-```
+```go
func TestSlogtest(t *testing.T) {
var buf bytes.Buffer
err := slogtest.TestHandler(New(&buf, nil), func() []map[string]any {
@@ -754,7 +754,7 @@
Our example output is enough like YAML so that we can use the `gopkg.in/yaml.v3`
package to parse it:
-```
+```go
func parseLogEntries(t *testing.T, data []byte) []map[string]any {
entries := bytes.Split(data, []byte("---\n"))
entries = entries[:len(entries)-1] // last one is empty
@@ -985,7 +985,7 @@
Here is our pool and its associated functions:
-```
+```go
var bufPool = sync.Pool{
New: func() any {
b := make([]byte, 0, 1024)