-
Notifications
You must be signed in to change notification settings - Fork 205
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
examples: derive examples from the examples directory
With the gotip playground we may want to swap out examples with greater frequency, to demonstrate new features at Go tip. Make this easier by deriving examples directly from the examples directory via a new examplesHandler type. This also enables having dynamic content for hello.txt, which depends on the value of runtime.GoVersion(). This will impact the non-tip playground in a few ways: - We will now pre-load examples at server start up. - Examples will be sorted by their title (with the exception of Hello, playground, which is always first). - We will set a CORS header for examples. This was added for consistency with other handlers, and seems harmless. Generalize TestShare to TestServer, and use it to test the examples handler. Add a single gotip example demonstrating generics. Updates golang/go#48517 Change-Id: I7ab58eb391829d581f7aeae95c291666be5718b9 Reviewed-on: https://go-review.googlesource.com/c/playground/+/364374 Trust: Robert Findley <[email protected]> Run-TryBot: Robert Findley <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Alexander Rakoczy <[email protected]>
- Loading branch information
Showing
15 changed files
with
242 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
// Copyright 2021 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package main | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"os" | ||
"path/filepath" | ||
"runtime" | ||
"sort" | ||
"strings" | ||
"time" | ||
) | ||
|
||
// examplesHandler serves example content out of the examples directory. | ||
type examplesHandler struct { | ||
modtime time.Time | ||
examples []example | ||
} | ||
|
||
type example struct { | ||
Title string | ||
Path string | ||
Content string | ||
} | ||
|
||
func (h *examplesHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||
w.Header().Set("Access-Control-Allow-Origin", "*") | ||
for _, e := range h.examples { | ||
if e.Path == req.URL.Path { | ||
http.ServeContent(w, req, e.Path, h.modtime, strings.NewReader(e.Content)) | ||
return | ||
} | ||
} | ||
http.NotFound(w, req) | ||
} | ||
|
||
// hello returns the hello text for this instance, which depends on the Go | ||
// version and whether or not we are serving Gotip examples. | ||
func (h *examplesHandler) hello() string { | ||
return h.examples[0].Content | ||
} | ||
|
||
// newExamplesHandler reads from the examples directory, returning a handler to | ||
// serve their content. | ||
// | ||
// If gotip is set, all files ending in .txt will be included in the set of | ||
// examples. If gotip is not set, files ending in .gotip.txt are excluded. | ||
// Examples must start with a line beginning "// Title:" that sets their title. | ||
// | ||
// modtime is used for content caching headers. | ||
func newExamplesHandler(gotip bool, modtime time.Time) (*examplesHandler, error) { | ||
const dir = "examples" | ||
entries, err := os.ReadDir(dir) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var examples []example | ||
for _, entry := range entries { | ||
name := entry.Name() | ||
|
||
// Read examples ending in .txt, skipping those ending in .gotip.txt if | ||
// gotip is not set. | ||
prefix := "" // if non-empty, this is a relevant example file | ||
if strings.HasSuffix(name, ".gotip.txt") { | ||
if gotip { | ||
prefix = strings.TrimSuffix(name, ".gotip.txt") | ||
} | ||
} else if strings.HasSuffix(name, ".txt") { | ||
prefix = strings.TrimSuffix(name, ".txt") | ||
} | ||
|
||
if prefix == "" { | ||
continue | ||
} | ||
|
||
data, err := os.ReadFile(filepath.Join(dir, name)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
content := string(data) | ||
|
||
// Extract the magic "// Title:" comment specifying the example's title. | ||
nl := strings.IndexByte(content, '\n') | ||
const titlePrefix = "// Title:" | ||
if nl == -1 || !strings.HasPrefix(content, titlePrefix) { | ||
return nil, fmt.Errorf("malformed example for %q: must start with a title line beginning %q", name, titlePrefix) | ||
} | ||
title := strings.TrimPrefix(content[:nl], titlePrefix) | ||
title = strings.TrimSpace(title) | ||
|
||
examples = append(examples, example{ | ||
Title: title, | ||
Path: name, | ||
Content: content[nl+1:], | ||
}) | ||
} | ||
|
||
// Sort by title, before prepending the hello example (we always want Hello | ||
// to be first). | ||
sort.Slice(examples, func(i, j int) bool { | ||
return examples[i].Title < examples[j].Title | ||
}) | ||
|
||
// For Gotip, serve hello content that includes the Go version. | ||
hi := hello | ||
if gotip { | ||
hi = helloGotip | ||
} | ||
|
||
examples = append([]example{ | ||
{"Hello, playground", "hello.txt", hi}, | ||
}, examples...) | ||
return &examplesHandler{ | ||
modtime: modtime, | ||
examples: examples, | ||
}, nil | ||
} | ||
|
||
const hello = `package main | ||
import ( | ||
"fmt" | ||
) | ||
func main() { | ||
fmt.Println("Hello, playground") | ||
} | ||
` | ||
|
||
var helloGotip = fmt.Sprintf(`package main | ||
import ( | ||
"fmt" | ||
) | ||
// This playground uses a development build of Go: | ||
// %s | ||
func Print[T any](s ...T) { | ||
for _, v := range s { | ||
fmt.Print(v) | ||
} | ||
} | ||
func main() { | ||
Print("Hello, ", "playground\n") | ||
} | ||
`, runtime.Version()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Playground Examples | ||
|
||
Add examples to the playground by adding files to this directory with the | ||
`.txt` file extension. Examples with file names ending in `.gotip.txt` are only | ||
displayed on the gotip playground. | ||
|
||
Each example must start with a line beginning with "// Title:", specifying the | ||
title of the example in the selection menu. This title line will be stripped | ||
from the example before serving. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
// Title: Clear | ||
package main | ||
|
||
import ( | ||
|
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
// Title: HTTP server | ||
package main | ||
|
||
import ( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
// Title: Display image | ||
package main | ||
|
||
import ( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// Title: Generic min | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"constraints" | ||
) | ||
|
||
func min[P constraints.Ordered](x, y P) P { | ||
if x < y { | ||
return x | ||
} else { | ||
return y | ||
} | ||
} | ||
|
||
func main() { | ||
fmt.Println(min(42, 24)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
// Title: Multiple files | ||
package main | ||
|
||
import ( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
// Title: Sleep | ||
package main | ||
|
||
import ( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
// Title: Test | ||
package main | ||
|
||
import ( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.