]> Cypherpunks repositories - gostls13.git/commitdiff
more work on elastic tabs:
authorRobert Griesemer <gri@golang.org>
Tue, 11 Nov 2008 01:56:46 +0000 (17:56 -0800)
committerRobert Griesemer <gri@golang.org>
Tue, 11 Nov 2008 01:56:46 +0000 (17:56 -0800)
- new code enabled, but no comments printed yet (so the effect
  of the elastic tabs is not seen yet)

TBR=r
DELTA=200  (93 added, 69 deleted, 38 changed)
OCL=18951
CL=18951

usr/gri/pretty/printer.go

index 4c886ad56d43082c1980bf6d9d8b7512a8c06138..ea670eb0c83b2fac6a782e11c62a92bdc8def5e8 100644 (file)
@@ -36,96 +36,117 @@ func PrintBlanks(n int) {
 // (http://nickgravgaard.com/elastictabstops/index.html)
 
 type Buffer struct {
+       segment string;  // current line segment
        lines AST.List;  // a list of lines; and each line is a list of strings
-       widths AST.List;
+}
+
+
+func (b *Buffer) Line(i int) *AST.List {
+       return b.lines.at(i).(*AST.List);
+}
+
+
+func (b *Buffer) Tab() {
+       b.lines.at(b.lines.len() - 1).(*AST.List).Add(b.segment);
+       b.segment = "";
 }
 
 
 func (b *Buffer) Newline() {
+       b.Tab();  // add last segment to current line
        b.lines.Add(AST.NewList());
 }
 
 
+func (b *Buffer) Print(s string) {
+       b.segment += s;
+}
+
+
 func (b *Buffer) Init() {
        b.lines.Init();
-       b.widths.Init();
-       b.Newline();
+       b.lines.Add(AST.NewList());
 }
 
 
-func (b *Buffer) ComputeWidths() {
-       // iterate through all columns j
-       for j := 0; ; j++ {
-               width := -1;  // initial column width
-               
-               // iterate through all lines i
-               for i := 0; i < b.lines.len(); i++ {
-                       line := b.lines.at(i).(*AST.List);
-                       if j < line.len() {
-                               // the j.th column exists in this line
-                               w := len(line.at(j).(string));
-                               if w > width {
-                                       width = w;
+func (b *Buffer) PrintLines(line0, line1 int, widths *AST.List) {
+       for i := line0; i < line1; i++ {
+               nsep := 0;
+               line := b.Line(i);
+               for j := 0; j < line.len(); j++ {
+                       s := line.at(j).(string);
+                       PrintBlanks(nsep);
+                       print(s);
+                       if j < widths.len() {
+                               nsep = widths.at(j).(int) - len(s);
+                               assert(nsep >= 0);
+                               if nsep < int(tabwith.IVal()) {
+                                       nsep = int(tabwith.IVal());
                                }
+                       } else {
+                               nsep = 0;
                        }
                }
-       
-               if width >= 0 {
-                       assert(b.widths.len() == j);
-                       b.widths.Add(width);
-               } else {
-                       // no column j - we are done
-                       return;
-               }
+               println();
        }
 }
 
 
-func (b *Buffer) Flush() {
-       b.ComputeWidths();
-       
-       // print the lines
-       for i := 0; i < b.lines.len(); i++ {
-               line := b.lines.at(i).(*AST.List);
-               for j := 0; j < line.len(); j++ {
-                       s := line.at(j).(string);
-                       d := b.widths.at(j).(int) - len(s);
-                       assert(d >= 0);
-                       if d < int(tabwith.IVal()) {
-                               d = int(tabwith.IVal());
+func (b *Buffer) Format(line0, line1 int, widths *AST.List) {
+       i0, i1 := line0, line0;
+       column := widths.len();
+       width := -1;
+       for i := line0; i < line1; i++ {
+               line := b.Line(i);
+               if column < line.len() - 1 {
+                       if width < 0 {
+                               // column start
+                               i1 = i;
+                               b.PrintLines(i0, i1, widths);
+                       }
+                       w := len(line.at(column).(string));
+                       if w > width {
+                               width = w;
+                       }
+               } else {
+                       if width >= 0 {
+                               // column end
+                               i0 = i;
+                               widths.Add(width);
+                               b.Format(i1, i0, widths);
+                               widths.Pop();
+                               width = -1;
                        }
-                       PrintBlanks(d);  // +1 padding
-                       print(s);
                }
-               println();
        }
-       
-       b.lines.Clear();
-       b.widths.Clear();
-       b.Newline();
+       b.PrintLines(i0, line1, widths);
 }
 
 
-func (b *Buffer) Indent(n int) {
-       line := b.lines.at(b.lines.len() - 1).(*AST.List);
-       for ; n > 0; n-- {
-               line.Add("");
+func (b *Buffer) Dump() {
+       for i := 0; i < b.lines.len(); i++ {
+               line := b.Line(i);
+               print("(", i, ") ");
+               for j := 0; j < line.len(); j++ {
+                       print("[", line.at(j).(string), "]");
+               }
+               print("\n");
        }
+       print("\n");
 }
 
 
-func (b *Buffer) Print(s string) {
-       i := b.lines.len() - 1;
-       line := b.lines.at(i).(*AST.List);
-       j := line.len() - 1;
-       if j < 0 {
-               line.Add(s);
-       } else {
-               line.set(j, line.at(j).(string) + s);
-       }
+func (b *Buffer) Flush() {
+       b.Tab();  // add last segment to current line
+       b.Format(0, b.lines.len(), AST.NewList());
+       b.lines.Clear();
+       b.lines.Add(AST.NewList());
 }
 
 
+// ----------------------------------------------------------------------------
+// Printer
+
 export type Printer struct {
        buf Buffer;
        
@@ -142,28 +163,42 @@ export type Printer struct {
 }
 
 
-const NEW_CODE = false;
+func CountNewlinesAndTabs(s string) (int, int, string) {
+       nls, tabs := 0, 0;
+       for i := 0; i < len(s); i++ {
+               switch ch := s[i]; ch {
+               case '\n': nls++;
+               case '\t': tabs++;
+               case ' ':
+               default:
+                       // non-whitespace char
+                       assert(ch == '/');
+                       return nls, tabs, s[i : len(s)];
+               }
+       }
+       return nls, tabs, "";
+}
+
 
 func (P *Printer) String(pos int, s string) {
        if P.semi && P.level > 0 {  // no semicolons at level 0
-               if NEW_CODE {
-                       P.buf.Print(";");
-               } else {
-                       print(";");
-               }
+               P.buf.Print(";");
        }
 
        /*
        for pos > P.cpos {
                // we have a comment
-               c := P.clist.at(P.cindex).(*AST.Comment);
-               if len(c.text) > 1 && c.text[1] == '/' {
-                       print("  " + c.text);
+               comment := P.clist.at(P.cindex).(*AST.Comment);
+               nls, tabs, text := CountNewlinesAndTabs(comment.text);
+               
+               if nls == 0 && len(text) > 1 && text[1] == '/' {
+                       P.buf.Tab();
+                       P.buf.Print(text);
                        if P.newl <= 0 {
-                               P.newl = 1;  // line comments must have a newline
+                               //P.newl = 1;  // line comments must have a newline
                        }
                } else {
-                       print(c.text);
+                       P.buf.Print(text);
                }
                P.cindex++;
                if P.cindex < P.clist.len() {
@@ -175,30 +210,19 @@ func (P *Printer) String(pos int, s string) {
        */
 
        if P.newl > 0 {
-               if NEW_CODE {
-                       P.buf.Flush();
-               }
-               for i := P.newl; i > 0; i-- {
-                       if NEW_CODE {
+               P.buf.Newline();
+               if P.newl > 1 {
+                       for i := P.newl; i > 1; i-- {
+                               //P.buf.Flush();
                                P.buf.Newline();
-                       } else {
-                               print("\n");
                        }
                }
-               if NEW_CODE {
-                       P.buf.Indent(P.indent);
-               } else {
-                       for i := P.indent; i > 0; i-- {
-                               print("\t");
-                       }
+               for i := P.indent; i > 0; i-- {
+                       P.buf.Tab();
                }
        }
 
-       if NEW_CODE {
-               P.buf.Print(s);
-       } else {
-               print(s);
-       }
+       P.buf.Print(s);
 
        P.semi, P.newl = false, 0;
 }
@@ -668,5 +692,5 @@ func (P *Printer) Program(p *AST.Program) {
        }
        P.newl = 1;
 
-       P.String(0, "");  // flush
+       P.buf.Flush();  // TODO should not access P.buf directly here
 }