Commit 2a58e7d7 authored by Robert Griesemer's avatar Robert Griesemer

more work on elastic tabs:

- 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
parent 600ee088
......@@ -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
}
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