");
-}
-
-
-func (P *Printer) importSpec(d *ast.ImportSpec) {
- if d.Name != nil {
- P.Expr(d.Name);
- } else {
- P.String(d.Path[0].Pos(), ""); // flush pending ';' separator/newlines
- }
- P.separator = tab;
- // TODO fix for longer package names
- P.HtmlPackageName(d.Path[0].Pos(), string(d.Path[0].Value));
- P.newlines = 2;
-}
-
-
-func (P *Printer) valueSpec(d *ast.ValueSpec) {
- P.Idents(d.Names, P.full);
- if d.Type != nil {
- P.separator = blank; // TODO switch to tab? (indentation problem with structs)
- P.Expr(d.Type);
- }
- if d.Values != nil {
- P.separator = tab;
- P.Token(noPos, token.ASSIGN);
- P.separator = blank;
- P.Exprs(d.Values);
- }
- P.newlines = 2;
-}
-
-
-func (P *Printer) typeSpec(d *ast.TypeSpec) {
- P.Expr(d.Name);
- P.separator = blank; // TODO switch to tab? (but indentation problem with structs)
- P.Expr(d.Type);
- P.newlines = 2;
-}
-
-
-func (P *Printer) spec(d ast.Spec) {
- switch s := d.(type) {
- case *ast.ImportSpec: P.importSpec(s);
- case *ast.ValueSpec: P.valueSpec(s);
- case *ast.TypeSpec: P.typeSpec(s);
- default: panic("unreachable");
- }
-}
-
-
-func (P *Printer) DoGenDecl(d *ast.GenDecl) {
- P.Token(d.Pos(), d.Tok);
- P.separator = blank;
-
- if d.Lparen.Line > 0 {
- // group of parenthesized declarations
- P.state = opening_scope;
- P.Token(d.Lparen, token.LPAREN);
- if len(d.Specs) > 0 {
- P.newlines = 1;
- for i := 0; i < len(d.Specs); i++ {
- if i > 0 {
- P.separator = semicolon;
- }
- P.spec(d.Specs[i]);
- P.newlines = 1;
- }
- }
- P.state = closing_scope;
- P.Token(d.Rparen, token.RPAREN);
- P.opt_semi = true;
- P.newlines = 2;
-
- } else {
- // single declaration
- P.spec(d.Specs[0]);
- }
-}
-
-
-func (P *Printer) DoFuncDecl(d *ast.FuncDecl) {
- P.Token(d.Pos(), token.FUNC);
- P.separator = blank;
- if recv := d.Recv; recv != nil {
- // method: print receiver
- P.Token(noPos, token.LPAREN);
- if len(recv.Names) > 0 {
- P.Expr(recv.Names[0]);
- P.separator = blank;
- }
- P.Expr(recv.Type);
- P.Token(noPos, token.RPAREN);
- P.separator = blank;
- }
- P.Expr(d.Name);
- P.Signature(d.Type.Params, d.Type.Results);
- if P.full && d.Body != nil {
- P.separator = blank;
- P.Stmt(d.Body);
- }
- P.newlines = 3;
-}
-
-
-func (P *Printer) Decl(d ast.Decl) {
- d.Visit(P);
-}
-
-
-// ----------------------------------------------------------------------------
-// Program
-
-func (P *Printer) DoProgram(p *ast.Program) {
- P.full = true;
- P.Token(p.Pos(), token.PACKAGE);
- P.separator = blank;
- P.Expr(p.Name);
- P.newlines = 1;
- for i := 0; i < len(p.Decls); i++ {
- P.Decl(p.Decls[i]);
- }
- P.newlines = 1;
-}
diff --git a/usr/gri/pretty/godoc.go b/usr/gri/pretty/godoc.go
index f2d66079a4..c4bc6d7e21 100644
--- a/usr/gri/pretty/godoc.go
+++ b/usr/gri/pretty/godoc.go
@@ -33,6 +33,7 @@ import (
"go/ast";
"go/doc";
"go/parser";
+ "go/printer";
"go/token";
"http";
"io";
@@ -47,8 +48,6 @@ import (
"tabwriter";
"template";
"time";
-
- "astprinter"; // TODO remove eventually in favor of ast.Fprint
)
@@ -90,7 +89,6 @@ var (
// layout control
tabwidth = flag.Int("tabwidth", 4, "tab width");
- usetabs = flag.Bool("tabs", false, "align with tabs instead of spaces");
html = flag.Bool("html", false, "print HTML in command-line mode");
// server control
@@ -129,11 +127,7 @@ func isPkgDir(dir *os.Dir) bool {
func makeTabwriter(writer io.Writer) *tabwriter.Writer {
- padchar := byte(' ');
- if *usetabs {
- padchar = '\t';
- }
- return tabwriter.NewWriter(writer, *tabwidth, 1, padchar, tabwriter.FilterHTML);
+ return tabwriter.NewWriter(writer, *tabwidth, 1, byte(' '), 0);
}
@@ -203,22 +197,12 @@ func parse(path string, mode uint) (*ast.Program, *parseErrors) {
// ----------------------------------------------------------------------------
// Templates
-// Return text for decl.
-func DeclText(d ast.Decl) []byte {
+// Return text for an AST node.
+func nodeText(node interface{}, mode uint) []byte {
var buf io.ByteBuffer;
- var p astPrinter.Printer;
- p.Init(&buf, nil, nil, false);
- d.Visit(&p);
- return buf.Data();
-}
-
-
-// Return text for expr.
-func ExprText(d ast.Expr) []byte {
- var buf io.ByteBuffer;
- var p astPrinter.Printer;
- p.Init(&buf, nil, nil, false);
- d.Visit(&p);
+ tw := makeTabwriter(&buf);
+ printer.Fprint(tw, node, mode);
+ tw.Flush();
return buf.Data();
}
@@ -235,9 +219,9 @@ func toText(x interface{}) []byte {
case String:
return io.StringBytes(v.String());
case ast.Decl:
- return DeclText(v);
+ return nodeText(v, printer.ExportsOnly);
case ast.Expr:
- return ExprText(v);
+ return nodeText(v, printer.ExportsOnly);
}
var buf io.ByteBuffer;
fmt.Fprint(&buf, x);
@@ -247,23 +231,7 @@ func toText(x interface{}) []byte {
// Template formatter for "html" format.
func htmlFmt(w io.Writer, x interface{}, format string) {
- // Can do better than text in some cases.
- switch v := x.(type) {
- case ast.Decl:
- var p astPrinter.Printer;
- tw := makeTabwriter(w);
- p.Init(tw, nil, nil, true);
- v.Visit(&p);
- tw.Flush();
- case ast.Expr:
- var p astPrinter.Printer;
- tw := makeTabwriter(w);
- p.Init(tw, nil, nil, true);
- v.Visit(&p);
- tw.Flush();
- default:
- template.HtmlEscape(w, toText(x));
- }
+ template.HtmlEscape(w, toText(x));
}
@@ -363,11 +331,7 @@ func serveGoSource(c *http.Conn, name string) {
var buf io.ByteBuffer;
fmt.Fprintln(&buf, "");
- var p astPrinter.Printer;
- writer := makeTabwriter(&buf); // for nicely formatted output
- p.Init(writer, nil, nil, true);
- p.DoProgram(prog);
- writer.Flush(); // ignore errors
+ template.HtmlEscape(&buf, nodeText(prog, printer.DocComments));
fmt.Fprintln(&buf, "
");
servePage(c, name + " - Go source", buf.Data());
diff --git a/usr/gri/pretty/gofmt.go b/usr/gri/pretty/gofmt.go
new file mode 100644
index 0000000000..73f9d8e23c
--- /dev/null
+++ b/usr/gri/pretty/gofmt.go
@@ -0,0 +1,107 @@
+// 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.
+
+package main
+
+import (
+ "flag";
+ "fmt";
+ "go/parser";
+ "go/printer";
+ "io";
+ "os";
+ "sort";
+ "tabwriter";
+)
+
+
+var (
+ // operation modes
+ silent = flag.Bool("s", false, "silent mode: parsing only");
+ verbose = flag.Bool("v", false, "verbose mode: trace parsing");
+ exports = flag.Bool("x", false, "show exports only");
+
+ // layout control
+ tabwidth = flag.Int("tabwidth", 4, "tab width");
+ usetabs = flag.Bool("tabs", false, "align with tabs instead of blanks");
+ optcommas = flag.Bool("optcommas", false, "print optional commas");
+ optsemis = flag.Bool("optsemis", false, "print optional semicolons");
+)
+
+
+func usage() {
+ fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [file.go]\n");
+ flag.PrintDefaults();
+ os.Exit(1);
+}
+
+
+func parserMode() uint {
+ mode := parser.ParseComments;
+ if *verbose {
+ mode |= parser.Trace;
+ }
+ return mode;
+}
+
+
+func printerMode() uint {
+ mode := uint(0);
+ if *exports {
+ mode |= printer.ExportsOnly;
+ }
+ if *optcommas {
+ mode |= printer.OptCommas;
+ }
+ if *optsemis {
+ mode |= printer.OptSemis;
+ }
+ return mode;
+}
+
+
+func makeTabwriter(writer io.Writer) *tabwriter.Writer {
+ padchar := byte(' ');
+ if *usetabs {
+ padchar = '\t';
+ }
+ return tabwriter.NewWriter(writer, *tabwidth, 1, padchar, 0);
+}
+
+
+func main() {
+ flag.Parse();
+
+ var filename string;
+ switch flag.NArg() {
+ case 0: filename = "/dev/stdin";
+ case 1: filename = flag.Arg(0);
+ default: usage();
+ }
+
+ src, err := io.ReadFile(filename);
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s: %v\n", filename, err);
+ os.Exit(1);
+ }
+
+ prog, err := parser.Parse(src, parserMode());
+ if err != nil {
+ if errors, ok := err.(parser.ErrorList); ok {
+ sort.Sort(errors);
+ for _, e := range errors {
+ fmt.Fprintf(os.Stderr, "%s:%v\n", filename, e);
+ }
+ } else {
+ fmt.Fprintf(os.Stderr, "%s: %v\n", filename, err);
+ }
+ os.Exit(1);
+ }
+
+ if !*silent {
+ w := makeTabwriter(os.Stdout);
+ printer.Fprint(w, prog, printerMode());
+ w.Flush();
+ }
+}
diff --git a/usr/gri/pretty/pretty.go b/usr/gri/pretty/pretty.go
deleted file mode 100644
index 82fc16b3c2..0000000000
--- a/usr/gri/pretty/pretty.go
+++ /dev/null
@@ -1,123 +0,0 @@
-// 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.
-
-package main
-
-import (
- "astprinter"; // TODO remove once go/printer is fully functional
- "flag";
- "fmt";
- "go/ast";
- "go/parser";
- "go/token";
- "io";
- "os";
- "sort";
- "tabwriter";
-)
-
-
-var (
- // operation modes
- columns bool;
- // TODO remove silent flag eventually, can achieve same by proving no format file
- silent = flag.Bool("s", false, "silent mode: no pretty print output");
- verbose = flag.Bool("v", false, "verbose mode: trace parsing");
-
- // layout control
- format = flag.String("format", "", "format file");
- tabwidth = flag.Int("tabwidth", 4, "tab width");
- usetabs = flag.Bool("tabs", false, "align with tabs instead of blanks");
-)
-
-
-func init() {
- user, err := os.Getenv("USER");
- flag.BoolVar(&columns, "columns", user == "gri", "print column no. in error messages");
-}
-
-
-func usage() {
- fmt.Fprintf(os.Stderr, "usage: pretty { flags } { files }\n");
- flag.PrintDefaults();
- os.Exit(1);
-}
-
-
-// TODO(gri) move this function into tabwriter.go? (also used in godoc)
-func makeTabwriter(writer io.Writer) *tabwriter.Writer {
- padchar := byte(' ');
- if *usetabs {
- padchar = '\t';
- }
- return tabwriter.NewWriter(writer, *tabwidth, 1, padchar, 0);
-}
-
-
-func main() {
- // handle flags
- flag.Parse();
- if flag.NFlag() == 0 && flag.NArg() == 0 {
- usage();
- }
-
- // initialize astFormat
- astFormat, err := ast.NewFormat(*format);
- if *format != "" && err != nil { // ignore error if no format file given
- fmt.Fprintf(os.Stderr, "ast.NewFormat(%s): %v\n", *format, err);
- os.Exit(1);
- }
-
- // determine parsing mode
- mode := parser.ParseComments;
- if *verbose {
- mode |= parser.Trace;
- }
-
- // process files
- exitcode := 0;
- for i := 0; i < flag.NArg(); i++ {
- filename := flag.Arg(i);
-
- src, err := io.ReadFile(filename);
- if err != nil {
- fmt.Fprintf(os.Stderr, "%s: %v\n", filename, err);
- exitcode = 1;
- continue; // proceed with next file
- }
-
- prog, err := parser.Parse(src, mode);
- if err != nil {
- if errors, ok := err.(parser.ErrorList); ok {
- sort.Sort(errors);
- for _, e := range errors {
- fmt.Fprintf(os.Stderr, "%s:%v\n", filename, e);
- }
- } else {
- fmt.Fprintf(os.Stderr, "%s: %v\n", filename, err);
- }
- exitcode = 1;
- continue; // proceed with next file
- }
-
- if !*silent {
- tw := makeTabwriter(os.Stdout);
- if *format != "" {
- _, err := astFormat.Fprint(tw, prog);
- if err != nil {
- fmt.Fprintf(os.Stderr, "format error: %v\n", err);
- exitcode = 1;
- continue; // proceed with next file
- }
- } else {
- var p astPrinter.Printer;
- p.Init(tw, nil, nil /*prog.Comments*/, false);
- p.DoProgram(prog);
- }
- tw.Flush();
- }
- }
-
- os.Exit(exitcode);
-}
diff --git a/usr/gri/pretty/test.sh b/usr/gri/pretty/test.sh
index c330821155..4015b0c8ed 100755
--- a/usr/gri/pretty/test.sh
+++ b/usr/gri/pretty/test.sh
@@ -10,7 +10,7 @@ if [ -z "$O" ]; then
exit 1
fi
-CMD="./pretty -format=ast.txt"
+CMD="./gofmt"
TMP1=test_tmp1.go
TMP2=test_tmp2.go
TMP3=test_tmp3.go
@@ -34,7 +34,7 @@ apply1() {
# the following have semantic errors: bug039.go | bug040.go
test_errors.go | calc.go | method1.go | selftest1.go | func3.go | const2.go | \
bug014.go | bug025.go | bug029.go | bug032.go | bug039.go | bug040.go | bug050.go | bug068.go | \
- bug088.go | bug083.go | bug106.go | bug121.go | bug125.go | bug126.go | bug132.go | bug133.go | bug134.go ) ;;
+ bug088.go | bug083.go | bug106.go | bug121.go | bug125.go | bug126.go | bug132.go | bug133.go | bug134.go | bug160.go ) ;;
* ) $1 $2; count $F;;
esac
}
diff --git a/usr/gri/pretty/untab.go b/usr/gri/pretty/untab.go
deleted file mode 100644
index b18e08f8b7..0000000000
--- a/usr/gri/pretty/untab.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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.
-
-package main
-
-import (
- "flag";
- "fmt";
- "io";
- "os";
- "tabwriter";
-)
-
-
-var (
- tabwidth = flag.Int("tabwidth", 4, "tab width");
- usetabs = flag.Bool("usetabs", false, "align with tabs instead of blanks");
-)
-
-
-func error(format string, params ...) {
- fmt.Printf(format, params);
- os.Exit(1);
-}
-
-
-func untab(name string, src *os.File, dst *tabwriter.Writer) {
- n, err := io.Copy(src, dst);
- if err != nil {
- error("error while processing %s (%v)", name, err);
- }
- //dst.Flush();
-}
-
-
-func main() {
- flag.Parse();
- padchar := byte(' ');
- if *usetabs {
- padchar = '\t';
- }
- dst := tabwriter.NewWriter(os.Stdout, *tabwidth, 1, padchar, 0);
- if flag.NArg() > 0 {
- for i := 0; i < flag.NArg(); i++ {
- name := flag.Arg(i);
- src, err := os.Open(name, os.O_RDONLY, 0);
- if err != nil {
- error("could not open %s (%v)\n", name, err);
- }
- untab(name, src, dst);
- src.Close(); // ignore errors
- }
- } else {
- // no files => use stdin
- untab("/dev/stdin", os.Stdin, dst);
- }
-}