]> Cypherpunks repositories - gostls13.git/commitdiff
- filter trailing whitespace
authorRobert Griesemer <gri@golang.org>
Sat, 19 Sep 2009 18:52:40 +0000 (11:52 -0700)
committerRobert Griesemer <gri@golang.org>
Sat, 19 Sep 2009 18:52:40 +0000 (11:52 -0700)
- removed some unused code

R=rsc
DELTA=103  (84 added, 15 deleted, 4 changed)
OCL=34816
CL=34829

src/pkg/go/printer/printer.go
src/pkg/go/printer/testdata/declarations.golden
src/pkg/go/printer/testdata/expressions.golden
src/pkg/go/printer/testdata/linebreaks.golden

index c34b21e52755cead18241f1230475dcbdc80aff3..37bdc2349f1ead4a26ae447f09fea0aea874e6f1 100644 (file)
@@ -6,6 +6,7 @@
 package printer
 
 import (
+       "bytes";
        "container/vector";
        "fmt";
        "go/ast";
@@ -74,7 +75,6 @@ type printer struct {
 
        // current state (changes during printing)
        written int;  // number of bytes written
-       level int;  // function nesting level; 0 = package scope, 1 = top-level function scope, etc.
        indent int;  // current indentation
        last token.Position;  // (possibly estimated) position immediately after the last item; in AST space
        pos token.Position;  // (possibly estimated) position; in AST space
@@ -97,8 +97,8 @@ func (p *printer) init(output io.Writer, mode uint) {
 }
 
 
-// Writing to p.output is done with write0 which also handles errors.
-// Does not indent after newlines, or HTML-escape, or update p.pos.
+// write0 writes raw (uninterpreted) data to p.output and handles errors.
+// write0 does not indent after newlines, and does not HTML-escape or update p.pos.
 //
 func (p *printer) write0(data []byte) {
        n, err := p.output.Write(data);
@@ -109,23 +109,19 @@ func (p *printer) write0(data []byte) {
 }
 
 
+// write interprets data and writes it to p.output. It inserts indentation
+// after newline or formfeed, converts formfeed characters into newlines if
+// RawFormat is set, and HTML-escapes data if GenHTML is set.
+//
 func (p *printer) write(data []byte) {
        i0 := 0;
        for i, b := range data {
                switch b {
                case '\n', '\f':
                        // write segment ending in b followed by indentation
-                       if p.mode & RawFormat != 0 && b == '\f' {
-                               // no tabwriter - convert last byte into a newline
-                               p.write0(data[i0 : i]);
-                               p.write0(newlines[0 : 1]);
-                       } else {
-                               p.write0(data[i0 : i+1]);
-                       }
+                       p.write0(data[i0 : i+1]);
 
                        // write indentation
-                       // TODO(gri) should not write indentation if there is nothing else
-                       //           on the line
                        j := p.indent;
                        for ; j > len(tabs); j -= len(tabs) {
                                p.write0(&tabs);
@@ -532,19 +528,17 @@ func (p *printer) exprList(list []ast.Expr, mode exprListMode) {
 func (p *printer) parameters(list []*ast.Field) {
        p.print(token.LPAREN);
        if len(list) > 0 {
-               p.level++;  // adjust nesting level for parameters
                for i, par := range list {
                        if i > 0 {
                                p.print(token.COMMA, blank);
                        }
-                       p.identList(par.Names);  // p.level > 0; all identifiers will be printed
+                       p.identList(par.Names);
                        if len(par.Names) > 0 {
                                // at least one identifier
                                p.print(blank);
                        };
                        p.expr(par.Type);
                }
-               p.level--;
        }
        p.print(token.RPAREN);
 }
@@ -760,9 +754,7 @@ func (p *printer) expr1(expr ast.Expr, prec1 int) (optSemi bool) {
        case *ast.FuncLit:
                p.expr(x.Type);
                p.print(blank);
-               p.level++;  // adjust nesting level for function body
                p.stmt(x.Body);
-               p.level--;
 
        case *ast.ParenExpr:
                p.print(token.LPAREN);
@@ -1255,9 +1247,7 @@ func (p *printer) decl(decl ast.Decl) (comment *ast.CommentGroup, optSemi bool)
                p.signature(d.Type.Params, d.Type.Results);
                if d.Body != nil {
                        p.print(blank);
-                       p.level++;  // adjust nesting level for function body
                        p.stmt(d.Body);
-                       p.level--;
                }
 
        default:
@@ -1286,6 +1276,79 @@ func (p *printer) file(src *ast.File) {
 }
 
 
+// ----------------------------------------------------------------------------
+// Trimmer
+
+// A trimmer is an io.Writer filter for stripping trailing blanks
+// and tabs, and for converting formfeed characters into newlines.
+//
+type trimmer struct {
+       output io.Writer;
+       buf bytes.Buffer;
+}
+
+
+func (p *trimmer) Write(data []byte) (n int, err os.Error) {
+       // m < 0: no unwritten data except for whitespace
+       // m >= 0: data[m:n] unwritten and no whitespace
+       m := 0;
+       if p.buf.Len() > 0 {
+               m = -1;
+       }
+
+       var b byte;
+       for n, b = range data {
+               switch b {
+               default:
+                       // write any pending whitespace
+                       if m < 0 {
+                               if _, err = p.output.Write(p.buf.Bytes()); err != nil {
+                                       return;
+                               }
+                               p.buf.Reset();
+                               m = n;
+                       }
+
+               case '\t', ' ':
+                       // write any pending (non-whitespace) data
+                       if m >= 0 {
+                               if _, err = p.output.Write(data[m:n]); err != nil {
+                                       return;
+                               }
+                               m = -1;
+                       }
+                       // collect whitespace
+                       p.buf.WriteByte(b);  // WriteByte returns no errors
+
+               case '\f', '\n':
+                       // discard whitespace
+                       p.buf.Reset();
+                       // write any pending (non-whitespace) data
+                       if m >= 0 {
+                               if _, err = p.output.Write(data[m:n]); err != nil {
+                                       return;
+                               }
+                               m = -1;
+                       }
+                       // convert formfeed into newline
+                       if _, err = p.output.Write(newlines[0:1]); err != nil {
+                               return;
+                       }
+               }
+       }
+       n = len(data);
+
+       // write any pending non-whitespace
+       if m >= 0 {
+               if _, err = p.output.Write(data[m:n]); err != nil {
+                       return;
+               }
+       }
+
+       return;
+}
+
+
 // ----------------------------------------------------------------------------
 // Public interface
 
@@ -1298,6 +1361,12 @@ var inf = token.Position{Offset: 1<<30, Line: 1<<30}
 // is controlled by the mode and tabwidth parameters.
 //
 func Fprint(output io.Writer, node interface{}, mode uint, tabwidth int) (int, os.Error) {
+       // redirect output through a trimmer to eliminate trailing whitespace
+       // (Input to a tabwriter must be untrimmed since trailing tabs provide
+       // formatting information. The tabwriter could provide trimming
+       // functionality but no tabwriter is used when RawFormat is set.)
+       output = &trimmer{output: output};
+
        // setup tabwriter if needed and redirect output
        var tw *tabwriter.Writer;
        if mode & RawFormat == 0 {
index 8da17307f4bc2bf1ee1007123efdb26fd470738e..6ab45db745c4a20752b5277f1c1952eef6b2191c 100644 (file)
@@ -39,7 +39,7 @@ func _() {
        var _ map[string]int;
        var _ chan int;
        var _ func() int;
-       
+
        // the following decls don't need a semicolon at the end
        type _ struct{}
        type _ *struct{}
index a8b9928c96b57f752d80a2a5035643b4f667b897..1bd3c6e3c325b1d90260116cc15090e924a3ceec 100644 (file)
@@ -32,7 +32,7 @@ func main() {
        _ = s[1:2];
        _ = s[a:b];
        _ = s[0:len(s)];
-       
+
        // spaces around expressions of different precedence or expressions containing spaces
        _ = a + -b;
        _ = a - ^b;
@@ -47,7 +47,7 @@ func main() {
        _ = s[a+b : len(s)];
        _ = s[len(s) : -a];
        _ = s[a : len(s)+1];
-       
+
        // spaces around operators with equal or lower precedence than comparisons
        _ = a == b;
        _ = a != b;
@@ -57,13 +57,13 @@ func main() {
        _ = a <= b;
        _ = a < b && c > d;
        _ = a < b || c > d;
-       
+
        // spaces around "long" operands
        _ = a + longIdentifier1;
        _ = longIdentifier1 + a;
        _ = longIdentifier1 + longIdentifier2 * longIdentifier3;
        _ = s + "a longer string";
-       
+
        // some selected cases
        _ = a + t0.x;
        _ = a + t0.x + t1.x * t2.x;
index 1700492c16dae8f6f1120663fe12c96310449c78..0aa1c92d83b45dba696c5ce582e3ef97baa26170 100644 (file)
@@ -109,7 +109,7 @@ var facts = map[int]string{
        2: "2",
        10: "3628800",
        20: "2432902008176640000",
-       100: 
+       100:
                "933262154439441526816992388562667004907159682643816214685929"
                "638952175999932299156089414639761565182862536979208272237582"
                "51185210916864000000000000000000000000"
@@ -118,7 +118,7 @@ var facts = map[int]string{
 
 func TestReader(t *testing.T) {
 
-testLoop:      
+testLoop:
        for i, test := range untarTests {
                f, err := os.Open(test.file, os.O_RDONLY, 0444);
                if err != nil {