Commit add4e167 authored by Andrew Gerrand's avatar Andrew Gerrand

doc/codelab/wiki: update to work with template changes, add to run.bash

Fixes #1444.

R=rsc, r
CC=golang-dev
https://golang.org/cl/3979045
parent b7949035
<h1>Editing {title}</h1> <h1>Editing {Title}</h1>
<form action="/save/{title}" method="POST"> <form action="/save/{Title}" method="POST">
<div><textarea name="body" rows="20" cols="80">{body|html}</textarea></div> <div><textarea name="Body" rows="20" cols="80">{Body|html}</textarea></div>
<div><input type="submit" value="Save"></div> <div><input type="submit" value="Save"></div>
</form> </form>
...@@ -8,23 +8,23 @@ import ( ...@@ -8,23 +8,23 @@ import (
"template" "template"
) )
type page struct { type Page struct {
title string Title string
body []byte Body []byte
} }
func (p *page) save() os.Error { func (p *Page) save() os.Error {
filename := p.title + ".txt" filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.body, 0600) return ioutil.WriteFile(filename, p.Body, 0600)
} }
func loadPage(title string) (*page, os.Error) { func loadPage(title string) (*Page, os.Error) {
filename := title + ".txt" filename := title + ".txt"
body, err := ioutil.ReadFile(filename) body, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &page{title: title, body: body}, nil return &Page{Title: title, Body: body}, nil
} }
func viewHandler(w http.ResponseWriter, r *http.Request) { func viewHandler(w http.ResponseWriter, r *http.Request) {
...@@ -47,7 +47,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) { ...@@ -47,7 +47,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
} }
p, err := loadPage(title) p, err := loadPage(title)
if err != nil { if err != nil {
p = &page{title: title} p = &Page{Title: title}
} }
renderTemplate(w, "edit", p) renderTemplate(w, "edit", p)
} }
...@@ -58,7 +58,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { ...@@ -58,7 +58,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
body := r.FormValue("body") body := r.FormValue("body")
p := &page{title: title, body: []byte(body)} p := &Page{Title: title, Body: []byte(body)}
err = p.save() err = p.save()
if err != nil { if err != nil {
http.Error(w, err.String(), http.StatusInternalServerError) http.Error(w, err.String(), http.StatusInternalServerError)
...@@ -67,7 +67,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { ...@@ -67,7 +67,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/view/"+title, http.StatusFound) http.Redirect(w, r, "/view/"+title, http.StatusFound)
} }
func renderTemplate(w http.ResponseWriter, tmpl string, p *page) { func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
t, err := template.ParseFile(tmpl+".html", nil) t, err := template.ParseFile(tmpl+".html", nil)
if err != nil { if err != nil {
http.Error(w, err.String(), http.StatusInternalServerError) http.Error(w, err.String(), http.StatusInternalServerError)
......
...@@ -7,23 +7,23 @@ import ( ...@@ -7,23 +7,23 @@ import (
"template" "template"
) )
type page struct { type Page struct {
title string Title string
body []byte Body []byte
} }
func (p *page) save() os.Error { func (p *Page) save() os.Error {
filename := p.title + ".txt" filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.body, 0600) return ioutil.WriteFile(filename, p.Body, 0600)
} }
func loadPage(title string) (*page, os.Error) { func loadPage(title string) (*Page, os.Error) {
filename := title + ".txt" filename := title + ".txt"
body, err := ioutil.ReadFile(filename) body, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &page{title: title, body: body}, nil return &Page{Title: title, Body: body}, nil
} }
const lenPath = len("/view/") const lenPath = len("/view/")
...@@ -32,7 +32,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) { ...@@ -32,7 +32,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[lenPath:] title := r.URL.Path[lenPath:]
p, err := loadPage(title) p, err := loadPage(title)
if err != nil { if err != nil {
p = &page{title: title} p = &Page{Title: title}
} }
t, _ := template.ParseFile("edit.html", nil) t, _ := template.ParseFile("edit.html", nil)
t.Execute(p, w) t.Execute(p, w)
......
...@@ -8,23 +8,23 @@ import ( ...@@ -8,23 +8,23 @@ import (
"template" "template"
) )
type page struct { type Page struct {
title string Title string
body []byte Body []byte
} }
func (p *page) save() os.Error { func (p *Page) save() os.Error {
filename := p.title + ".txt" filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.body, 0600) return ioutil.WriteFile(filename, p.Body, 0600)
} }
func loadPage(title string) (*page, os.Error) { func loadPage(title string) (*Page, os.Error) {
filename := title + ".txt" filename := title + ".txt"
body, err := ioutil.ReadFile(filename) body, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &page{title: title, body: body}, nil return &Page{Title: title, Body: body}, nil
} }
func viewHandler(w http.ResponseWriter, r *http.Request, title string) { func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
...@@ -39,14 +39,14 @@ func viewHandler(w http.ResponseWriter, r *http.Request, title string) { ...@@ -39,14 +39,14 @@ func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
func editHandler(w http.ResponseWriter, r *http.Request, title string) { func editHandler(w http.ResponseWriter, r *http.Request, title string) {
p, err := loadPage(title) p, err := loadPage(title)
if err != nil { if err != nil {
p = &page{title: title} p = &Page{Title: title}
} }
renderTemplate(w, "edit", p) renderTemplate(w, "edit", p)
} }
func saveHandler(w http.ResponseWriter, r *http.Request, title string) { func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
body := r.FormValue("body") body := r.FormValue("body")
p := &page{title: title, body: []byte(body)} p := &Page{Title: title, Body: []byte(body)}
err := p.save() err := p.save()
if err != nil { if err != nil {
http.Error(w, err.String(), http.StatusInternalServerError) http.Error(w, err.String(), http.StatusInternalServerError)
...@@ -55,7 +55,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request, title string) { ...@@ -55,7 +55,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
http.Redirect(w, r, "/view/"+title, http.StatusFound) http.Redirect(w, r, "/view/"+title, http.StatusFound)
} }
func renderTemplate(w http.ResponseWriter, tmpl string, p *page) { func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
t, err := template.ParseFile(tmpl+".html", nil) t, err := template.ParseFile(tmpl+".html", nil)
if err != nil { if err != nil {
http.Error(w, err.String(), http.StatusInternalServerError) http.Error(w, err.String(), http.StatusInternalServerError)
......
...@@ -7,23 +7,23 @@ import ( ...@@ -7,23 +7,23 @@ import (
"template" "template"
) )
type page struct { type Page struct {
title string Title string
body []byte Body []byte
} }
func (p *page) save() os.Error { func (p *Page) save() os.Error {
filename := p.title + ".txt" filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.body, 0600) return ioutil.WriteFile(filename, p.Body, 0600)
} }
func loadPage(title string) (*page, os.Error) { func loadPage(title string) (*Page, os.Error) {
filename := title + ".txt" filename := title + ".txt"
body, err := ioutil.ReadFile(filename) body, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &page{title: title, body: body}, nil return &Page{Title: title, Body: body}, nil
} }
const lenPath = len("/view/") const lenPath = len("/view/")
...@@ -32,7 +32,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) { ...@@ -32,7 +32,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[lenPath:] title := r.URL.Path[lenPath:]
p, err := loadPage(title) p, err := loadPage(title)
if err != nil { if err != nil {
p = &page{title: title} p = &Page{Title: title}
} }
renderTemplate(w, "edit", p) renderTemplate(w, "edit", p)
} }
...@@ -46,12 +46,12 @@ func viewHandler(w http.ResponseWriter, r *http.Request) { ...@@ -46,12 +46,12 @@ func viewHandler(w http.ResponseWriter, r *http.Request) {
func saveHandler(w http.ResponseWriter, r *http.Request) { func saveHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[lenPath:] title := r.URL.Path[lenPath:]
body := r.FormValue("body") body := r.FormValue("body")
p := &page{title: title, body: []byte(body)} p := &Page{Title: title, Body: []byte(body)}
p.save() p.save()
http.Redirect(w, r, "/view/"+title, http.StatusFound) http.Redirect(w, r, "/view/"+title, http.StatusFound)
} }
func renderTemplate(w http.ResponseWriter, tmpl string, p *page) { func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
t, _ := template.ParseFile(tmpl+".html", nil) t, _ := template.ParseFile(tmpl+".html", nil)
t.Execute(p, w) t.Execute(p, w)
} }
......
...@@ -8,23 +8,23 @@ import ( ...@@ -8,23 +8,23 @@ import (
"template" "template"
) )
type page struct { type Page struct {
title string Title string
body []byte Body []byte
} }
func (p *page) save() os.Error { func (p *Page) save() os.Error {
filename := p.title + ".txt" filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.body, 0600) return ioutil.WriteFile(filename, p.Body, 0600)
} }
func loadPage(title string) (*page, os.Error) { func loadPage(title string) (*Page, os.Error) {
filename := title + ".txt" filename := title + ".txt"
body, err := ioutil.ReadFile(filename) body, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &page{title: title, body: body}, nil return &Page{Title: title, Body: body}, nil
} }
func viewHandler(w http.ResponseWriter, r *http.Request, title string) { func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
...@@ -39,14 +39,14 @@ func viewHandler(w http.ResponseWriter, r *http.Request, title string) { ...@@ -39,14 +39,14 @@ func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
func editHandler(w http.ResponseWriter, r *http.Request, title string) { func editHandler(w http.ResponseWriter, r *http.Request, title string) {
p, err := loadPage(title) p, err := loadPage(title)
if err != nil { if err != nil {
p = &page{title: title} p = &Page{Title: title}
} }
renderTemplate(w, "edit", p) renderTemplate(w, "edit", p)
} }
func saveHandler(w http.ResponseWriter, r *http.Request, title string) { func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
body := r.FormValue("body") body := r.FormValue("body")
p := &page{title: title, body: []byte(body)} p := &Page{Title: title, Body: []byte(body)}
err := p.save() err := p.save()
if err != nil { if err != nil {
http.Error(w, err.String(), http.StatusInternalServerError) http.Error(w, err.String(), http.StatusInternalServerError)
...@@ -63,7 +63,7 @@ func init() { ...@@ -63,7 +63,7 @@ func init() {
} }
} }
func renderTemplate(w http.ResponseWriter, tmpl string, p *page) { func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
err := templates[tmpl].Execute(p, w) err := templates[tmpl].Execute(p, w)
if err != nil { if err != nil {
http.Error(w, err.String(), http.StatusInternalServerError) http.Error(w, err.String(), http.StatusInternalServerError)
......
...@@ -8,5 +8,5 @@ import ( ...@@ -8,5 +8,5 @@ import (
func main() { func main() {
b, _ := ioutil.ReadAll(os.Stdin) b, _ := ioutil.ReadAll(os.Stdin)
template.HTMLFormatter(os.Stdout, b, "") template.HTMLFormatter(os.Stdout, "", b)
} }
This diff is collapsed.
...@@ -7,23 +7,23 @@ import ( ...@@ -7,23 +7,23 @@ import (
"os" "os"
) )
type page struct { type Page struct {
title string Title string
body []byte Body []byte
} }
func (p *page) save() os.Error { func (p *Page) save() os.Error {
filename := p.title + ".txt" filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.body, 0600) return ioutil.WriteFile(filename, p.Body, 0600)
} }
func loadPage(title string) (*page, os.Error) { func loadPage(title string) (*Page, os.Error) {
filename := title + ".txt" filename := title + ".txt"
body, err := ioutil.ReadFile(filename) body, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &page{title: title, body: body}, nil return &Page{Title: title, Body: body}, nil
} }
const lenPath = len("/view/") const lenPath = len("/view/")
...@@ -31,21 +31,21 @@ const lenPath = len("/view/") ...@@ -31,21 +31,21 @@ const lenPath = len("/view/")
func viewHandler(w http.ResponseWriter, r *http.Request) { func viewHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[lenPath:] title := r.URL.Path[lenPath:]
p, _ := loadPage(title) p, _ := loadPage(title)
fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.title, p.body) fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.Title, p.Body)
} }
func editHandler(w http.ResponseWriter, r *http.Request) { func editHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[lenPath:] title := r.URL.Path[lenPath:]
p, err := loadPage(title) p, err := loadPage(title)
if err != nil { if err != nil {
p = &page{title: title} p = &Page{Title: title}
} }
fmt.Fprintf(w, "<h1>Editing %s</h1>"+ fmt.Fprintf(w, "<h1>Editing %s</h1>"+
"<form action=\"/save/%s\" method=\"POST\">"+ "<form action=\"/save/%s\" method=\"POST\">"+
"<textarea name=\"body\">%s</textarea><br>"+ "<textarea name=\"body\">%s</textarea><br>"+
"<input type=\"submit\" value=\"Save\">"+ "<input type=\"submit\" value=\"Save\">"+
"</form>", "</form>",
p.title, p.title, p.body) p.Title, p.Title, p.Body)
} }
func main() { func main() {
......
...@@ -6,25 +6,25 @@ import ( ...@@ -6,25 +6,25 @@ import (
"os" "os"
) )
type page struct { type Page struct {
title string Title string
body []byte Body []byte
} }
func (p *page) save() os.Error { func (p *Page) save() os.Error {
filename := p.title + ".txt" filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.body, 0600) return ioutil.WriteFile(filename, p.Body, 0600)
} }
func loadPage(title string) *page { func loadPage(title string) *Page {
filename := title + ".txt" filename := title + ".txt"
body, _ := ioutil.ReadFile(filename) body, _ := ioutil.ReadFile(filename)
return &page{title: title, body: body} return &Page{Title: title, Body: body}
} }
func main() { func main() {
p1 := &page{title: "TestPage", body: []byte("This is a sample page.")} p1 := &Page{Title: "TestPage", Body: []byte("This is a sample page.")}
p1.save() p1.save()
p2 := loadPage("TestPage") p2 := loadPage("TestPage")
fmt.Println(string(p2.body)) fmt.Println(string(p2.Body))
} }
...@@ -6,28 +6,28 @@ import ( ...@@ -6,28 +6,28 @@ import (
"os" "os"
) )
type page struct { type Page struct {
title string Title string
body []byte Body []byte
} }
func (p *page) save() os.Error { func (p *Page) save() os.Error {
filename := p.title + ".txt" filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.body, 0600) return ioutil.WriteFile(filename, p.Body, 0600)
} }
func loadPage(title string) (*page, os.Error) { func loadPage(title string) (*Page, os.Error) {
filename := title + ".txt" filename := title + ".txt"
body, err := ioutil.ReadFile(filename) body, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &page{title: title, body: body}, nil return &Page{Title: title, Body: body}, nil
} }
func main() { func main() {
p1 := &page{title: "TestPage", body: []byte("This is a sample page.")} p1 := &Page{Title: "TestPage", Body: []byte("This is a sample Page.")}
p1.save() p1.save()
p2, _ := loadPage("TestPage") p2, _ := loadPage("TestPage")
fmt.Println(string(p2.body)) fmt.Println(string(p2.Body))
} }
...@@ -7,23 +7,23 @@ import ( ...@@ -7,23 +7,23 @@ import (
"os" "os"
) )
type page struct { type Page struct {
title string Title string
body []byte Body []byte
} }
func (p *page) save() os.Error { func (p *Page) save() os.Error {
filename := p.title + ".txt" filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.body, 0600) return ioutil.WriteFile(filename, p.Body, 0600)
} }
func loadPage(title string) (*page, os.Error) { func loadPage(title string) (*Page, os.Error) {
filename := title + ".txt" filename := title + ".txt"
body, err := ioutil.ReadFile(filename) body, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &page{title: title, body: body}, nil return &Page{Title: title, Body: body}, nil
} }
const lenPath = len("/view/") const lenPath = len("/view/")
...@@ -31,7 +31,7 @@ const lenPath = len("/view/") ...@@ -31,7 +31,7 @@ const lenPath = len("/view/")
func viewHandler(w http.ResponseWriter, r *http.Request) { func viewHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[lenPath:] title := r.URL.Path[lenPath:]
p, _ := loadPage(title) p, _ := loadPage(title)
fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.title, p.body) fmt.Fprintf(w, "<h1>%s</h1><div>%s</div>", p.Title, p.Body)
} }
func main() { func main() {
......
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"go/parser" "go/parser"
"go/printer" "go/printer"
"go/ast" "go/ast"
"go/token"
"log" "log"
"os" "os"
) )
...@@ -25,7 +26,8 @@ func main() { ...@@ -25,7 +26,8 @@ func main() {
os.Exit(2) os.Exit(2)
} }
// load file // load file
file, err := parser.ParseFile(*srcFn, nil, 0) fs := token.NewFileSet()
file, err := parser.ParseFile(fs, *srcFn, nil, 0)
if err != nil { if err != nil {
log.Exit(err) log.Exit(err)
} }
...@@ -47,7 +49,7 @@ func main() { ...@@ -47,7 +49,7 @@ func main() {
os.Exit(1) os.Exit(1)
} }
b := new(bytes.Buffer) b := new(bytes.Buffer)
p.Fprint(b, file) p.Fprint(b, fs, file)
// drop package declaration // drop package declaration
if !*showPkg { if !*showPkg {
for { for {
......
<h1>Editing Test</h1> <h1>Editing Test</h1>
<form action="/save/Test" method="POST"> <form action="/save/Test" method="POST">
<div><textarea name="body" rows="20" cols="80"></textarea></div> <div><textarea name="Body" rows="20" cols="80"></textarea></div>
<div><input type="submit" value="Save"></div> <div><input type="submit" value="Save"></div>
</form> </form>
<h1>{title}</h1> <h1>{Title}</h1>
<p>[<a href="/edit/{title}">edit</a>]</p> <p>[<a href="/edit/{Title}">edit</a>]</p>
<div>{body}</div> <div>{Body}</div>
...@@ -71,27 +71,27 @@ declaration. ...@@ -71,27 +71,27 @@ declaration.
<p> <p>
Let's start by defining the data structures. A wiki consists of a series of Let's start by defining the data structures. A wiki consists of a series of
interconnected pages, each of which has a title and a body (the page content). interconnected pages, each of which has a title and a body (the page content).
Here, we define <code>page</code> as a struct with two fields representing Here, we define <code>Page</code> as a struct with two fields representing
the title and body. the title and body.
</p> </p>
<pre> <pre>
!./srcextract.bin -src=part1.go -name=page !./srcextract.bin -src=part1.go -name=Page
</pre> </pre>
<p> <p>
The type <code>[]byte</code> means "a <code>byte</code> slice". The type <code>[]byte</code> means "a <code>byte</code> slice".
(See <a href="http://golang.org/doc/effective_go.html#slices">Effective Go</a> (See <a href="http://golang.org/doc/effective_go.html#slices">Effective Go</a>
for more on slices.) for more on slices.)
The <code>body</code> element is a <code>[]byte</code> rather than The <code>Body</code> element is a <code>[]byte</code> rather than
<code>string</code> because that is the type expected by the <code>io</code> <code>string</code> because that is the type expected by the <code>io</code>
libraries we will use, as you'll see below. libraries we will use, as you'll see below.
</p> </p>
<p> <p>
The <code>page</code> struct describes how page data will be stored in memory. The <code>Page</code> struct describes how page data will be stored in memory.
But what about persistent storage? We can address that by creating a But what about persistent storage? We can address that by creating a
<code>save</code> method on <code>page</code>: <code>save</code> method on <code>Page</code>:
</p> </p>
<pre> <pre>
...@@ -100,13 +100,13 @@ But what about persistent storage? We can address that by creating a ...@@ -100,13 +100,13 @@ But what about persistent storage? We can address that by creating a
<p> <p>
This method's signature reads: "This is a method named <code>save</code> that This method's signature reads: "This is a method named <code>save</code> that
takes as its receiver <code>p</code>, a pointer to <code>page</code> . It takes takes as its receiver <code>p</code>, a pointer to <code>Page</code> . It takes
no parameters, and returns a value of type <code>os.Error</code>." no parameters, and returns a value of type <code>os.Error</code>."
</p> </p>
<p> <p>
This method will save the <code>page</code>'s <code>body</code> to a text This method will save the <code>Page</code>'s <code>Body</code> to a text
file. For simplicity, we will use the <code>title</code> as the file name. file. For simplicity, we will use the <code>Title</code> as the file name.
</p> </p>
<p> <p>
...@@ -114,7 +114,7 @@ The <code>save</code> method returns an <code>os.Error</code> value because ...@@ -114,7 +114,7 @@ The <code>save</code> method returns an <code>os.Error</code> value because
that is the return type of <code>WriteFile</code> (a standard library function that is the return type of <code>WriteFile</code> (a standard library function
that writes a byte slice to a file). The <code>save</code> method returns the that writes a byte slice to a file). The <code>save</code> method returns the
error value, to let the application handle it should anything go wrong while error value, to let the application handle it should anything go wrong while
writing the file. If all goes well, <code>page.save()</code> will return writing the file. If all goes well, <code>Page.save()</code> will return
<code>nil</code> (the zero-value for pointers, interfaces, and some other <code>nil</code> (the zero-value for pointers, interfaces, and some other
types). types).
</p> </p>
...@@ -136,8 +136,8 @@ We will want to load pages, too: ...@@ -136,8 +136,8 @@ We will want to load pages, too:
<p> <p>
The function <code>loadPage</code> constructs the file name from The function <code>loadPage</code> constructs the file name from
<code>title</code>, reads the file's contents into a new <code>Title</code>, reads the file's contents into a new
<code>page</code>, and returns a pointer to that new <code>page</code>. <code>Page</code>, and returns a pointer to that new <code>page</code>.
</p> </p>
<p> <p>
...@@ -151,7 +151,7 @@ error return value (in essence, assigning the value to nothing). ...@@ -151,7 +151,7 @@ error return value (in essence, assigning the value to nothing).
<p> <p>
But what happens if <code>ReadFile</code> encounters an error? For example, But what happens if <code>ReadFile</code> encounters an error? For example,
the file might not exist. We should not ignore such errors. Let's modify the the file might not exist. We should not ignore such errors. Let's modify the
function to return <code>*page</code> and <code>os.Error</code>. function to return <code>*Page</code> and <code>os.Error</code>.
</p> </p>
<pre> <pre>
...@@ -160,7 +160,7 @@ function to return <code>*page</code> and <code>os.Error</code>. ...@@ -160,7 +160,7 @@ function to return <code>*page</code> and <code>os.Error</code>.
<p> <p>
Callers of this function can now check the second parameter; if it is Callers of this function can now check the second parameter; if it is
<code>nil</code> then it has successfully loaded a page. If not, it will be an <code>nil</code> then it has successfully loaded a Page. If not, it will be an
<code>os.Error</code> that can be handled by the caller (see the <a <code>os.Error</code> that can be handled by the caller (see the <a
href="http://golang.org/pkg/os/#Error">os package documentation</a> for href="http://golang.org/pkg/os/#Error">os package documentation</a> for
details). details).
...@@ -179,7 +179,7 @@ written: ...@@ -179,7 +179,7 @@ written:
<p> <p>
After compiling and executing this code, a file named <code>TestPage.txt</code> After compiling and executing this code, a file named <code>TestPage.txt</code>
would be created, containing the contents of <code>p1</code>. The file would would be created, containing the contents of <code>p1</code>. The file would
then be read into the struct <code>p2</code>, and its <code>body</code> element then be read into the struct <code>p2</code>, and its <code>Body</code> element
printed to the screen. printed to the screen.
</p> </p>
...@@ -334,7 +334,7 @@ href="http://localhost:8080/view/test">http://localhost:8080/view/test</a></code ...@@ -334,7 +334,7 @@ href="http://localhost:8080/view/test">http://localhost:8080/view/test</a></code
should show a page titled "test" containing the words "Hello world". should show a page titled "test" containing the words "Hello world".
</p> </p>
<h2>Editing pages</h2> <h2>Editing Pages</h2>
<p> <p>
A wiki is not a wiki without the ability to edit pages. Let's create two new A wiki is not a wiki without the ability to edit pages. Let's create two new
...@@ -353,7 +353,7 @@ First, we add them to <code>main()</code>: ...@@ -353,7 +353,7 @@ First, we add them to <code>main()</code>:
<p> <p>
The function <code>editHandler</code> loads the page The function <code>editHandler</code> loads the page
(or, if it doesn't exist, create an empty <code>page</code> struct), (or, if it doesn't exist, create an empty <code>Page</code> struct),
and displays an HTML form. and displays an HTML form.
</p> </p>
...@@ -413,15 +413,15 @@ The function <code>template.ParseFile</code> will read the contents of ...@@ -413,15 +413,15 @@ The function <code>template.ParseFile</code> will read the contents of
<p> <p>
The method <code>t.Execute</code> replaces all occurrences of The method <code>t.Execute</code> replaces all occurrences of
<code>{title}</code> and <code>{body}</code> with the values of <code>{Title}</code> and <code>{Body}</code> with the values of
<code>p.title</code> and <code>p.body</code>, and writes the resultant <code>p.Title</code> and <code>p.Body</code>, and writes the resultant
HTML to the <code>http.ResponseWriter</code>. HTML to the <code>http.ResponseWriter</code>.
</p> </p>
<p> <p>
Note that we've used <code>{body|html}</code> in the above template. Note that we've used <code>{Body|html}</code> in the above template.
The <code>|html</code> part asks the template engine to pass the value The <code>|html</code> part asks the template engine to pass the value
<code>body</code> through the <code>html</code> formatter before outputting it, <code>Body</code> through the <code>html</code> formatter before outputting it,
which escapes HTML characters (such as replacing <code>&gt;</code> with which escapes HTML characters (such as replacing <code>&gt;</code> with
<code>&amp;gt;</code>). <code>&amp;gt;</code>).
This will prevent user data from corrupting the form HTML. This will prevent user data from corrupting the form HTML.
...@@ -472,8 +472,8 @@ The handlers are now shorter and simpler. ...@@ -472,8 +472,8 @@ The handlers are now shorter and simpler.
<p> <p>
What if you visit <code>/view/APageThatDoesntExist</code>? The program will What if you visit <code>/view/APageThatDoesntExist</code>? The program will
crash. This is because it ignores the error return value from crash. This is because it ignores the error return value from
<code>loadPage</code>. Instead, if the requested page doesn't exist, it should <code>loadPage</code>. Instead, if the requested Page doesn't exist, it should
redirect the client to the edit page so the content may be created: redirect the client to the edit Page so the content may be created:
</p> </p>
<pre> <pre>
...@@ -486,7 +486,7 @@ The <code>http.Redirect</code> function adds an HTTP status code of ...@@ -486,7 +486,7 @@ The <code>http.Redirect</code> function adds an HTTP status code of
header to the HTTP response. header to the HTTP response.
</p> </p>
<h2>Saving pages</h2> <h2>Saving Pages</h2>
<p> <p>
The function <code>saveHandler</code> will handle the form submission. The function <code>saveHandler</code> will handle the form submission.
...@@ -498,7 +498,7 @@ The function <code>saveHandler</code> will handle the form submission. ...@@ -498,7 +498,7 @@ The function <code>saveHandler</code> will handle the form submission.
<p> <p>
The page title (provided in the URL) and the form's only field, The page title (provided in the URL) and the form's only field,
<code>body</code>, are stored in a new <code>page</code>. <code>Body</code>, are stored in a new <code>Page</code>.
The <code>save()</code> method is then called to write the data to a file, The <code>save()</code> method is then called to write the data to a file,
and the client is redirected to the <code>/view/</code> page. and the client is redirected to the <code>/view/</code> page.
</p> </p>
...@@ -506,7 +506,7 @@ and the client is redirected to the <code>/view/</code> page. ...@@ -506,7 +506,7 @@ and the client is redirected to the <code>/view/</code> page.
<p> <p>
The value returned by <code>FormValue</code> is of type <code>string</code>. The value returned by <code>FormValue</code> is of type <code>string</code>.
We must convert that value to <code>[]byte</code> before it will fit into We must convert that value to <code>[]byte</code> before it will fit into
the <code>page</code> struct. We use <code>[]byte(body)</code> to perform the <code>Page</code> struct. We use <code>[]byte(body)</code> to perform
the conversion. the conversion.
</p> </p>
...@@ -610,7 +610,7 @@ Then we can create a global variable to store our validation regexp: ...@@ -610,7 +610,7 @@ Then we can create a global variable to store our validation regexp:
</p> </p>
<pre> <pre>
!./srcextract.bin -src=final-noclosure.go -name=titleValidator !./srcextract.bin -src=final-noclosure.go -name=TitleValidator
</pre> </pre>
<p> <p>
...@@ -624,7 +624,7 @@ the expression compilation fails, while <code>Compile</code> returns an ...@@ -624,7 +624,7 @@ the expression compilation fails, while <code>Compile</code> returns an
<p> <p>
Now, let's write a function that extracts the title string from the request Now, let's write a function that extracts the title string from the request
URL, and tests it against our <code>titleValidator</code> expression: URL, and tests it against our <code>TitleValidator</code> expression:
</p> </p>
<pre> <pre>
...@@ -708,7 +708,7 @@ The closure returned by <code>makeHandler</code> is a function that takes ...@@ -708,7 +708,7 @@ The closure returned by <code>makeHandler</code> is a function that takes
an <code>http.ResponseWriter</code> and <code>http.Request</code> (in other an <code>http.ResponseWriter</code> and <code>http.Request</code> (in other
words, an <code>http.HandlerFunc</code>). words, an <code>http.HandlerFunc</code>).
The closure extracts the <code>title</code> from the request path, and The closure extracts the <code>title</code> from the request path, and
validates it with the <code>titleValidator</code> regexp. If the validates it with the <code>TitleValidator</code> regexp. If the
<code>title</code> is invalid, an error will be written to the <code>title</code> is invalid, an error will be written to the
<code>ResponseWriter</code> using the <code>http.NotFound</code> function. <code>ResponseWriter</code> using the <code>http.NotFound</code> function.
If the <code>title</code> is valid, the enclosed handler function If the <code>title</code> is valid, the enclosed handler function
......
...@@ -103,6 +103,9 @@ if [[ $(uname | tr A-Z a-z | sed 's/mingw/windows/') != *windows* ]]; then ...@@ -103,6 +103,9 @@ if [[ $(uname | tr A-Z a-z | sed 's/mingw/windows/') != *windows* ]]; then
fi fi
) || exit $? ) || exit $?
(xcd ../doc/codelab/wiki
gomake test) || exit $?
for i in ../misc/dashboard/builder ../misc/goplay for i in ../misc/dashboard/builder ../misc/goplay
do do
(xcd $i (xcd $i
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment