From f340baa9492812622efdc18d7e84d9a1c09ef13b Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Tue, 13 Oct 2009 22:10:16 -0700 Subject: bye-bye to old makehtml. go can do the job just fine. R=rsc DELTA=290 (209 added, 13 deleted, 68 changed) OCL=35699 CL=35699 --- doc/htmlgen.go | 192 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 doc/htmlgen.go (limited to 'doc/htmlgen.go') diff --git a/doc/htmlgen.go b/doc/htmlgen.go new file mode 100644 index 000000000..8d44fc078 --- /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
 blocks
+//	- blank lines become 

marks +// - "quoted strings" become quoted strings + +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("

");
+	preEnd = strings.Bytes("
\n"); + pp = strings.Bytes("

\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

 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 
-bounded slice
+func foldTabs(i int) (n int, line []byte) {
+	buf := new(bytes.Buffer);
+	buf.WriteString("
\n");
+	for i < len(lines) {
+		if !bytes.HasPrefix(lines[i], tab) {
+			break;
+		}
+		buf.Write(lines[i]);
+		n++;
+		i++;
+	}
+	buf.WriteString("
\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("

" + string(trim(lines[i-1])) + "

\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("") + } else { + buf.WriteString("") + } + 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]; +} -- cgit v1.2.3