diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0abb881b17a87b45acfbe5287446a18b3a32f6e2 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,11 @@ +# Copyright 2009 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. + +include $(GOROOT)/src/Make.$(GOARCH) + +TARG=htmlgen +GOFILES=\ + htmlgen.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/doc/go_tutorial.head b/doc/go_tutorial.head deleted file mode 100644 index a15e53683bfaa301ef77b15f325849373aadc1a3..0000000000000000000000000000000000000000 --- a/doc/go_tutorial.head +++ /dev/null @@ -1,3 +0,0 @@ -<!-- Let's Go --> - -<h2>Introduction</h2> diff --git a/doc/go_tutorial.html b/doc/go_tutorial.html index f966ef936a4e7ba50e6e8f8e0d7055bc85f1e31e..27710ed268c5669b13a09475d34cbc22c987e55c 100644 --- a/doc/go_tutorial.html +++ b/doc/go_tutorial.html @@ -1,15 +1,14 @@ <!-- Let's Go --> - <h2>Introduction</h2> <p> This document is a tutorial introduction to the basics of the Go systems programming language, intended for programmers familiar with C or C++. It is not a comprehensive guide to the language; at the moment the document closest to that is the -<a href=/doc/go_spec.html>language specification.</a> +<a href='/doc/go_spec.html'>language specification.</a> <p> The presentation proceeds through a series of modest programs to illustrate key features of the language. All the programs work (at time of writing) and are -checked into the repository in the directory <a href=/doc/progs><code>/doc/progs</code></a>. +checked into the repository in the directory <a href='/doc/progs'><code>/doc/progs/</code></a>. <p> Program snippets are annotated with the line number in the original file; for cleanliness, blank lines remain blank. @@ -45,8 +44,8 @@ The comment convention is the same as in C++: <pre> /* ... */ // ... - </pre> +<p> Later we'll have much more to say about printing. <p> <h2>Echo</h2> @@ -94,8 +93,8 @@ But it's not necessary to do so; we could have said <pre> const Space = " " const Newline = "\n" - </pre> +<p> Semicolons aren't needed here; in fact, semicolons are unnecessary after any top-level declaration, even though they are needed as separators <i>within</i> a parenthesized list of declarations. @@ -128,8 +127,8 @@ The declaration statement has the form <p> <pre> var s string = ""; - </pre> +<p> This is the <code>var</code> keyword, followed by the name of the variable, followed by its type, followed by an equals sign and an initial value for the variable. <p> @@ -139,14 +138,14 @@ We could write <p> <pre> var s = ""; - </pre> +<p> or we could go even shorter and write the idiom <p> <pre> s := ""; - </pre> +<p> The <code>:=</code> operator is used a lot in Go to represent an initializing declaration. (For those who know Sawzall, its <code>:=</code> construct is the same, but notice that Go has no colon after the name in a full <code>var</code> declaration. @@ -177,8 +176,8 @@ It's defined that way. Falling off the end of <code>main.main</code> means <p> <pre> os.Exit(1) - </pre> +<p> The <code>os</code> package contains other essentials for getting started; for instance, <code>os.Args</code> is an array used by the <code>flag</code> package to access the command-line arguments. @@ -213,8 +212,8 @@ a <code>string</code> value: <pre> s[0] = 'x'; (*p)[1] = 'y'; - </pre> +<p> In C++ terms, Go strings are a bit like <code>const strings</code>, while pointers to strings are analogous to <code>const string</code> references. <p> @@ -225,8 +224,8 @@ Arrays are declared like this: <p> <pre> var array_of_int [10]int; - </pre> +<p> Arrays, like strings, are values, but they are mutable. This differs from C, in which <code>array_of_int</code> would be usable as a pointer to <code>int</code>. In Go, since arrays are values, it's meaningful (and useful) to talk @@ -286,21 +285,21 @@ elements for you, use <code>...</code> as the array size: <p> <pre> s := sum(&[...]int{1,2,3}); - </pre> +<p> In practice, though, unless you're meticulous about storage layout within a data structure, a slice itself - using empty brackets and no <code>&</code> - is all you need: <p> <pre> s := sum([]int{1,2,3}); - </pre> +<p> There are also maps, which you can initialize like this: <p> <pre> m := map[string] int {"one":1 , "two":2} - </pre> +<p> The built-in function <code>len()</code>, which returns number of elements, makes its first appearance in <code>sum</code>. It works on strings, arrays, slices, and maps. @@ -317,14 +316,14 @@ returns a pointer to the allocated storage. <pre> type T struct { a, b int } var t *T = new(T); - </pre> +<p> or the more idiomatic <p> <pre> t := new(T); - </pre> +<p> Some types - maps, slices, and channels (see below) - have reference semantics. If you're holding a slice or a map and you modify its contents, other variables referencing the same underlying data will see the modification. For these three @@ -332,15 +331,15 @@ types you want to use the built-in function <code>make()</code>: <p> <pre> m := make(map[string] int); - </pre> +<p> This statement initializes a new map ready to store entries. If you just declare the map, as in <p> <pre> var m map[string] int; - </pre> +<p> it creates a <code>nil</code> reference that cannot hold anything. To use the map, you must first initialize the reference using <code>make()</code> or by assignment to an existing map. @@ -360,8 +359,8 @@ too little precision to represent the value. <p> <pre> const hard_eight = (1 << 100) >> 97 // legal - </pre> +<p> There are nuances that deserve redirection to the legalese of the language specification but here are some illustrative examples: <p> @@ -373,8 +372,8 @@ language specification but here are some illustrative examples: x := 1.5 // a float i3div2 := 3/2 // integer division - result is 1 f3div2 := 3./2. // floating point division - result is 1.5 - </pre> +<p> Conversions only work for simple cases such as converting <code>ints</code> of one sign or size to another, and between <code>ints</code> and <code>floats</code>, plus a few other simple cases. There are no automatic numeric conversions of any kind in Go, @@ -446,8 +445,8 @@ object. We could write n.fd = fd; n.name = name; return n - </pre> +<p> but for simple structures like <code>File</code> it's easier to return the address of a nonce composite literal, as is done here on line 21. <p> @@ -585,8 +584,8 @@ Finally we can run the program: hello, world can't open file; err=No such file or directory % - </pre> +<p> <h2>Rotting cats</h2> <p> Building on the <code>file</code> package, here's a simple version of the Unix utility <code>cat(1)</code>, @@ -864,8 +863,8 @@ Within the <code>fmt</code> package, <code>Printf</code> is declared with this s <p> <pre> Printf(format string, v ...) (n int, errno os.Error) - </pre> +<p> That <code>...</code> represents the variadic argument list that in C would be handled using the <code>stdarg.h</code> macros, but in Go is passed using an empty interface variable (<code>interface {}</code>) that is then unpacked @@ -888,8 +887,8 @@ prints <p> <pre> 18446744073709551615 -1 - </pre> +<p> In fact, if you're lazy the format <code>%v</code> will print, in a simple appropriate style, any value, even an array or structure. The output of <p> @@ -904,8 +903,8 @@ is <p> <pre> 18446744073709551615 {77 Sunset Strip} [1 2 3 4] - </pre> +<p> You can drop the formatting altogether if you use <code>Print</code> or <code>Println</code> instead of <code>Printf</code>. Those routines do fully automatic formatting. The <code>Print</code> function just prints its elements out using the equivalent @@ -946,8 +945,8 @@ default formatter for that type will use it and produce the output <p> <pre> 77 Sunset Strip - </pre> +<p> Observe that the <code>String()</code> method calls <code>Sprint</code> (the obvious Go variant that returns a string) to do its formatting; special formatters can use the <code>fmt</code> library recursively. @@ -970,15 +969,17 @@ Schematically, given a value <code>v</code>, it does this: type Stringer interface { String() string } - +</pre> +<p> +<pre> s, ok := v.(Stringer); // Test whether v implements "String()" if ok { result = s.String() } else { result = default_output(v) } - </pre> +<p> The code uses a ``type assertion'' (<code>v.(Stringer)</code>) to test if the value stored in <code>v</code> satisfies the <code>Stringer</code> interface; if it does, <code>s</code> will become an interface variable implementing the method and <code>ok</code> will @@ -1000,8 +1001,8 @@ interface type defined in the <code>io</code> library: type Writer interface { Write(p []byte) (n int, err os.Error); } - </pre> +<p> (This interface is another conventional name, this time for <code>Write</code>; there are also <code>io.Reader</code>, <code>io.ReadWriter</code>, and so on.) Thus you can call <code>Fprintf</code> on any type that implements a standard <code>Write()</code> @@ -1081,8 +1082,8 @@ computation but in the same address space: <p> <pre> go sum(huge_array); // calculate sum in the background - </pre> +<p> If you want to know when the calculation is done, pass a channel on which it can report back: <p> @@ -1091,8 +1092,8 @@ on which it can report back: go sum(huge_array, ch); // ... do something else for a while result := <-ch; // wait for, and retrieve, result - </pre> +<p> Back to our prime sieve. Here's how the sieve pipeline is stitched together: <p> diff --git a/doc/go_tutorial.txt b/doc/go_tutorial.txt index 15e29281b58ae38c1352a75c43c58fdcf561c11d..dd7cd9fd87809c1b40b57f4fd9b64a260ca7a852 100644 --- a/doc/go_tutorial.txt +++ b/doc/go_tutorial.txt @@ -1,14 +1,15 @@ -Let's Go +<!-- Let's Go --> +Introduction ---- This document is a tutorial introduction to the basics of the Go systems programming language, intended for programmers familiar with C or C++. It is not a comprehensive guide to the language; at the moment the document closest to that is the -<a href=/doc/go_spec.html>language specification.</a> +<a href='/doc/go_spec.html'>language specification.</a> The presentation proceeds through a series of modest programs to illustrate key features of the language. All the programs work (at time of writing) and are -checked into the repository in the directory <a href=/doc/progs>"/doc/progs"</a>. +checked into the repository in the directory <a href='/doc/progs'>"/doc/progs/"</a>. Program snippets are annotated with the line number in the original file; for cleanliness, blank lines remain blank. @@ -215,7 +216,7 @@ pointer to "sum()" by (automatically) promoting it to a slice. If you are creating a regular array but want the compiler to count the elements for you, use "..." as the array size: - s := sum(&[...]int{1,2,3}); + s := sum(&[...]int{1,2,3}); In practice, though, unless you're meticulous about storage layout within a data structure, a slice itself - using empty brackets and no "&" - is all you need: @@ -277,7 +278,7 @@ constants are evaluated as large-precision values that can overflow only when they are assigned to an integer variable with too little precision to represent the value. - const hard_eight = (1 << 100) >> 97 // legal + const hard_eight = (1 << 100) >> 97 // legal There are nuances that deserve redirection to the legalese of the language specification but here are some illustrative examples: @@ -542,7 +543,7 @@ to implement the three methods for that type, like this: Printing ---- +---- The examples of formatted printing so far have been modest. In this section we'll talk about how formatted I/O can be done well in Go. @@ -721,7 +722,7 @@ on which it can report back: ch := make(chan int); go sum(huge_array, ch); // ... do something else for a while - result := <-ch; // wait for, and retrieve, result + result := <-ch; // wait for, and retrieve, result Back to our prime sieve. Here's how the sieve pipeline is stitched together: @@ -824,3 +825,6 @@ at the end of main: There's a lot more to Go programming and concurrent programming in general but this quick tour should give you some of the basics. +</table> +</body> +</html> diff --git a/doc/htmlgen.go b/doc/htmlgen.go new file mode 100644 index 0000000000000000000000000000000000000000..8d44fc0787b0e7119479c4588f464c458f9d1ed5 --- /dev/null +++ b/doc/htmlgen.go @@ -0,0 +1,192 @@ +// Copyright 2009 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. + +// Process plain text into HTML. +// - h2's are made from lines followed by a line "----\n" +// - tab-indented blocks become <pre> blocks +// - blank lines become <p> marks +// - "quoted strings" become <code>quoted strings</code> + +package main + +import ( + "bufio"; + "bytes"; + "log"; + "os"; + "strings"; +) + +var ( + lines = make([][]byte, 0, 10000); // assume big enough + linebuf = make([]byte, 10000); // assume big enough + + empty = strings.Bytes(""); + newline = strings.Bytes("\n"); + tab = strings.Bytes("\t"); + quote = strings.Bytes(`"`); + + sectionMarker = strings.Bytes("----\n"); + preStart = strings.Bytes("<pre>"); + preEnd = strings.Bytes("</pre>\n"); + pp = strings.Bytes("<p>\n"); +); + +func main() { + read(); + headings(); + paragraphs(); + coalesce(preStart, foldPre); + coalesce(tab, foldTabs); + quotes(); + write(); +} + +func read() { + b := bufio.NewReader(os.Stdin); + for { + line, err := b.ReadBytes('\n'); + if err == os.EOF { + break; + } + if err != nil { + log.Exit(err) + } + n := len(lines); + lines = lines[0:n+1]; + lines[n] = line; + } +} + +func write() { + b := bufio.NewWriter(os.Stdout); + for _, line := range lines { + b.Write(expandTabs(line)); + } + b.Flush(); +} + +// each time prefix is found on a line, call fold and replace +// line with return value from fold. +func coalesce(prefix []byte, fold func(i int) (n int, line []byte)) { + j := 0; // output line number; goes up by one each loop + for i := 0; i < len(lines); { + if bytes.HasPrefix(lines[i], prefix) { + nlines, block := fold(i); + lines[j] = block; + i += nlines; + } else { + lines[j] = lines[i]; + i++; + } + j++; + } + lines = lines[0:j]; +} + +// return the <pre> block as a single slice +func foldPre(i int) (n int, line []byte) { + buf := new(bytes.Buffer); + for i < len(lines) { + buf.Write(lines[i]); + n++; + if bytes.Equal(lines[i], preEnd) { + break + } + i++; + } + return n, buf.Bytes(); +} + +// return the tab-indented block as a single <pre>-bounded slice +func foldTabs(i int) (n int, line []byte) { + buf := new(bytes.Buffer); + buf.WriteString("<pre>\n"); + for i < len(lines) { + if !bytes.HasPrefix(lines[i], tab) { + break; + } + buf.Write(lines[i]); + n++; + i++; + } + buf.WriteString("</pre>\n"); + return n, buf.Bytes(); +} + +func headings() { + b := bufio.NewWriter(os.Stdout); + for i, l := range lines { + if i > 0 && bytes.Equal(l, sectionMarker) { + lines[i-1] = strings.Bytes("<h2>" + string(trim(lines[i-1])) + "</h2>\n"); + lines[i] = empty; + } + } + b.Flush(); +} + +func paragraphs() { + for i, l := range lines { + if bytes.Equal(l, newline) { + lines[i] = pp; + } + } +} + +func quotes() { + for i, l := range lines { + lines[i] = codeQuotes(l); + } +} + +func codeQuotes(l []byte) []byte { + if bytes.HasPrefix(l, preStart) { + return l + } + n := bytes.Index(l, quote); + if n < 0 { + return l + } + buf := new(bytes.Buffer); + inQuote := false; + for _, c := range l { + if c == '"' { + if inQuote { + buf.WriteString("</code>") + } else { + buf.WriteString("<code>") + } + inQuote = !inQuote + } else { + buf.WriteByte(c) + } + } + return buf.Bytes(); +} + +// drop trailing newline +func trim(l []byte) []byte { + n := len(l); + if n > 0 && l[n-1] == '\n' { + return l[0:n-1] + } + return l +} + +// expand tabs to 4 spaces. don't worry about columns. +func expandTabs(l []byte) []byte { + j := 0; // position in linebuf. + for _, c := range l { + if c == '\t' { + for k := 0; k < 4; k++ { + linebuf[j] = ' '; + j++; + } + } else { + linebuf[j] = c; + j++; + } + } + return linebuf[0:j]; +} diff --git a/doc/makehtml b/doc/makehtml new file mode 100755 index 0000000000000000000000000000000000000000..c9ac0c8e8ddaaced645e904052662d549fa46d41 --- /dev/null +++ b/doc/makehtml @@ -0,0 +1,31 @@ +#!/bin/sh +# Copyright 2009 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. + +set -e + +TXT=${1:-go_tutorial.txt} # input file +HTML=$(basename $TXT .txt).html # output file (basename) +TMP=TEMP.txt # input to htmlgen + +if ! test -w $HTML +then + echo 1>&2 makehtml: cannot open $HTML for write + exit 1 +fi + +if grep -q '^--PROG' $TXT +then + echo >&2 makehtml: processing PROG sections + <$TXT >$TMP awk ' + /^--PROG/ { system("sh ./prog.sh "$2" "$3" "$4" "); getline } + /^/ {print} + ' +else + cp $TXT $TMP +fi + +make htmlgen && ./htmlgen < $TMP > $HTML + +rm -f $TMP