Parcourir la source

cmd/geth, jsre: restore command line editing on windows

PR #856 broke command line editing by wrapping stdout with a filter that
interprets ANSI escape sequences to fix colored printing on windows.
Implement the printer in Go instead so it can do its own
platform-dependent coloring.

As a nice side effect, the JS console is now noticeably more responsive
when printing results.

Fixes #1608
Fixes #1612
Felix Lange il y a 10 ans
Parent
commit
0ef80bb3d0
27 fichiers modifiés avec 1941 ajouts et 872 suppressions
  1. 11 7
      Godeps/Godeps.json
  2. 3 0
      Godeps/_workspace/src/github.com/fatih/color/.travis.yml
  3. 20 0
      Godeps/_workspace/src/github.com/fatih/color/LICENSE.md
  4. 151 0
      Godeps/_workspace/src/github.com/fatih/color/README.md
  5. 353 0
      Godeps/_workspace/src/github.com/fatih/color/color.go
  6. 176 0
      Godeps/_workspace/src/github.com/fatih/color/color_test.go
  7. 114 0
      Godeps/_workspace/src/github.com/fatih/color/doc.go
  8. 0 42
      Godeps/_workspace/src/github.com/mattn/go-colorable/README.md
  9. 0 16
      Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_others.go
  10. 0 594
      Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_windows.go
  11. 27 0
      Godeps/_workspace/src/github.com/shiena/ansicolor/.gitignore
  12. 21 0
      Godeps/_workspace/src/github.com/shiena/ansicolor/LICENSE
  13. 100 0
      Godeps/_workspace/src/github.com/shiena/ansicolor/README.md
  14. 20 0
      Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor.go
  15. 27 0
      Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor/main.go
  16. 17 0
      Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_ansi.go
  17. 25 0
      Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_test.go
  18. 351 0
      Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows.go
  19. 236 0
      Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows_test.go
  20. 24 0
      Godeps/_workspace/src/github.com/shiena/ansicolor/example_test.go
  21. 19 0
      Godeps/_workspace/src/github.com/shiena/ansicolor/export_test.go
  22. 15 24
      cmd/geth/js.go
  23. 0 19
      cmd/geth/main.go
  24. 8 25
      jsre/jsre.go
  25. 3 8
      jsre/jsre_test.go
  26. 0 137
      jsre/pp_js.go
  27. 220 0
      jsre/pretty.go

+ 11 - 7
Godeps/Godeps.json

@@ -24,14 +24,18 @@
 			"Comment": "v23.1-227-g8f6ccaa",
 			"Rev": "8f6ccaaef9b418553807a73a95cb5f49cd3ea39f"
 		},
+		{
+			"ImportPath": "github.com/fatih/color",
+			"Comment": "v0.1-5-gf773d4c",
+			"Rev": "f773d4c806cc8e4a5749d6a35e2a4bbcd71443d6"
+		},
 		{
 			"ImportPath": "github.com/gizak/termui",
 			"Rev": "bab8dce01c193d82bc04888a0a9a7814d505f532"
 		},
 		{
-			"ImportPath": "github.com/howeyc/fsnotify",
-			"Comment": "v0.9.0-11-g6b1ef89",
-			"Rev": "6b1ef893dc11e0447abda6da20a5203481878dda"
+			"ImportPath": "github.com/hashicorp/golang-lru",
+			"Rev": "7f9ef20a0256f494e24126014135cf893ab71e9e"
 		},
 		{
 			"ImportPath": "github.com/huin/goupnp",
@@ -45,10 +49,6 @@
 			"ImportPath": "github.com/kardianos/osext",
 			"Rev": "ccfcd0245381f0c94c68f50626665eed3c6b726a"
 		},
-		{
-			"ImportPath": "github.com/mattn/go-colorable",
-			"Rev": "043ae16291351db8465272edf465c9f388161627"
-		},
 		{
 			"ImportPath": "github.com/mattn/go-isatty",
 			"Rev": "fdbe02a1b44e75977b2690062b83cf507d70c013"
@@ -78,6 +78,10 @@
 			"ImportPath": "github.com/rs/cors",
 			"Rev": "6e0c3cb65fc0fdb064c743d176a620e3ca446dfb"
 		},
+		{
+			"ImportPath": "github.com/shiena/ansicolor",
+			"Rev": "a5e2b567a4dd6cc74545b8a4f27c9d63b9e7735b"
+		},
 		{
 			"ImportPath": "github.com/syndtr/goleveldb/leveldb",
 			"Rev": "4875955338b0a434238a31165cb87255ab6e9e4a"

+ 3 - 0
Godeps/_workspace/src/github.com/fatih/color/.travis.yml

@@ -0,0 +1,3 @@
+language: go
+go: 1.3
+

+ 20 - 0
Godeps/_workspace/src/github.com/fatih/color/LICENSE.md

@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Fatih Arslan
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 151 - 0
Godeps/_workspace/src/github.com/fatih/color/README.md

@@ -0,0 +1,151 @@
+# Color [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/fatih/color) [![Build Status](http://img.shields.io/travis/fatih/color.svg?style=flat-square)](https://travis-ci.org/fatih/color)
+
+
+
+Color lets you use colorized outputs in terms of [ANSI Escape Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It has support for Windows too! The API can be used in several ways, pick one that suits you.
+
+
+
+![Color](http://i.imgur.com/c1JI0lA.png)
+
+
+## Install
+
+```bash
+go get github.com/fatih/color
+```
+
+## Examples
+
+### Standard colors
+
+```go
+// Print with default helper functions
+color.Cyan("Prints text in cyan.")
+
+// A newline will be appended automatically
+color.Blue("Prints %s in blue.", "text")
+
+// These are using the default foreground colors
+color.Red("We have red")
+color.Magenta("And many others ..")
+
+```
+
+### Mix and reuse colors
+
+```go
+// Create a new color object
+c := color.New(color.FgCyan).Add(color.Underline)
+c.Println("Prints cyan text with an underline.")
+
+// Or just add them to New()
+d := color.New(color.FgCyan, color.Bold)
+d.Printf("This prints bold cyan %s\n", "too!.")
+
+// Mix up foreground and background colors, create new mixes!
+red := color.New(color.FgRed)
+
+boldRed := red.Add(color.Bold)
+boldRed.Println("This will print text in bold red.")
+
+whiteBackground := red.Add(color.BgWhite)
+whiteBackground.Println("Red text with white background.")
+```
+
+### Custom print functions (PrintFunc)
+
+```go
+// Create a custom print function for convenience
+red := color.New(color.FgRed).PrintfFunc()
+red("Warning")
+red("Error: %s", err)
+
+// Mix up multiple attributes
+notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
+notice("Don't forget this...")
+```
+
+### Insert into noncolor strings (SprintFunc)
+
+```go
+// Create SprintXxx functions to mix strings with other non-colorized strings:
+yellow := color.New(color.FgYellow).SprintFunc()
+red := color.New(color.FgRed).SprintFunc()
+fmt.Printf("This is a %s and this is %s.\n", yellow("warning"), red("error"))
+
+info := color.New(color.FgWhite, color.BgGreen).SprintFunc()
+fmt.Printf("This %s rocks!\n", info("package"))
+
+// Use helper functions
+fmt.Printf("This", color.RedString("warning"), "should be not neglected.")
+fmt.Printf(color.GreenString("Info:"), "an important message." )
+
+// Windows supported too! Just don't forget to change the output to color.Output
+fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))
+```
+
+### Plug into existing code
+
+```go
+// Use handy standard colors
+color.Set(color.FgYellow)
+
+fmt.Println("Existing text will now be in yellow")
+fmt.Printf("This one %s\n", "too")
+
+color.Unset() // Don't forget to unset
+
+// You can mix up parameters
+color.Set(color.FgMagenta, color.Bold)
+defer color.Unset() // Use it in your function
+
+fmt.Println("All text will now be bold magenta.")
+```
+
+### Disable color
+
+There might be a case where you want to disable color output (for example to
+pipe the standard output of your app to somewhere else). `Color` has support to
+disable colors both globally and for single color definition. For example
+suppose you have a CLI app and a `--no-color` bool flag. You can easily disable
+the color output with:
+
+```go
+
+var flagNoColor = flag.Bool("no-color", false, "Disable color output")
+
+if *flagNoColor {
+	color.NoColor = true // disables colorized output
+}
+```
+
+It also has support for single color definitions (local). You can
+disable/enable color output on the fly:
+
+```go
+c := color.New(color.FgCyan)
+c.Println("Prints cyan text")
+
+c.DisableColor()
+c.Println("This is printed without any color")
+
+c.EnableColor()
+c.Println("This prints again cyan...")
+```
+
+## Todo
+
+* Save/Return previous values
+* Evaluate fmt.Formatter interface
+
+
+## Credits
+
+ * [Fatih Arslan](https://github.com/fatih)
+ * Windows support via @shiena: [ansicolor](https://github.com/shiena/ansicolor)
+
+## License
+
+The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details
+

+ 353 - 0
Godeps/_workspace/src/github.com/fatih/color/color.go

@@ -0,0 +1,353 @@
+package color
+
+import (
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+
+	"github.com/mattn/go-isatty"
+	"github.com/shiena/ansicolor"
+)
+
+// NoColor defines if the output is colorized or not. It's dynamically set to
+// false or true based on the stdout's file descriptor referring to a terminal
+// or not. This is a global option and affects all colors. For more control
+// over each color block use the methods DisableColor() individually.
+var NoColor = !isatty.IsTerminal(os.Stdout.Fd())
+
+// Color defines a custom color object which is defined by SGR parameters.
+type Color struct {
+	params  []Attribute
+	noColor *bool
+}
+
+// Attribute defines a single SGR Code
+type Attribute int
+
+const escape = "\x1b"
+
+// Base attributes
+const (
+	Reset Attribute = iota
+	Bold
+	Faint
+	Italic
+	Underline
+	BlinkSlow
+	BlinkRapid
+	ReverseVideo
+	Concealed
+	CrossedOut
+)
+
+// Foreground text colors
+const (
+	FgBlack Attribute = iota + 30
+	FgRed
+	FgGreen
+	FgYellow
+	FgBlue
+	FgMagenta
+	FgCyan
+	FgWhite
+)
+
+// Background text colors
+const (
+	BgBlack Attribute = iota + 40
+	BgRed
+	BgGreen
+	BgYellow
+	BgBlue
+	BgMagenta
+	BgCyan
+	BgWhite
+)
+
+// New returns a newly created color object.
+func New(value ...Attribute) *Color {
+	c := &Color{params: make([]Attribute, 0)}
+	c.Add(value...)
+	return c
+}
+
+// Set sets the given parameters immediately. It will change the color of
+// output with the given SGR parameters until color.Unset() is called.
+func Set(p ...Attribute) *Color {
+	c := New(p...)
+	c.Set()
+	return c
+}
+
+// Unset resets all escape attributes and clears the output. Usually should
+// be called after Set().
+func Unset() {
+	if NoColor {
+		return
+	}
+
+	fmt.Fprintf(Output, "%s[%dm", escape, Reset)
+}
+
+// Set sets the SGR sequence.
+func (c *Color) Set() *Color {
+	if c.isNoColorSet() {
+		return c
+	}
+
+	fmt.Fprintf(Output, c.format())
+	return c
+}
+
+func (c *Color) unset() {
+	if c.isNoColorSet() {
+		return
+	}
+
+	Unset()
+}
+
+// Add is used to chain SGR parameters. Use as many as parameters to combine
+// and create custom color objects. Example: Add(color.FgRed, color.Underline).
+func (c *Color) Add(value ...Attribute) *Color {
+	c.params = append(c.params, value...)
+	return c
+}
+
+func (c *Color) prepend(value Attribute) {
+	c.params = append(c.params, 0)
+	copy(c.params[1:], c.params[0:])
+	c.params[0] = value
+}
+
+// Output defines the standard output of the print functions. By default
+// os.Stdout is used.
+var Output = ansicolor.NewAnsiColorWriter(os.Stdout)
+
+// Print formats using the default formats for its operands and writes to
+// standard output. Spaces are added between operands when neither is a
+// string. It returns the number of bytes written and any write error
+// encountered. This is the standard fmt.Print() method wrapped with the given
+// color.
+func (c *Color) Print(a ...interface{}) (n int, err error) {
+	c.Set()
+	defer c.unset()
+
+	return fmt.Fprint(Output, a...)
+}
+
+// Printf formats according to a format specifier and writes to standard output.
+// It returns the number of bytes written and any write error encountered.
+// This is the standard fmt.Printf() method wrapped with the given color.
+func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
+	c.Set()
+	defer c.unset()
+
+	return fmt.Fprintf(Output, format, a...)
+}
+
+// Println formats using the default formats for its operands and writes to
+// standard output. Spaces are always added between operands and a newline is
+// appended. It returns the number of bytes written and any write error
+// encountered. This is the standard fmt.Print() method wrapped with the given
+// color.
+func (c *Color) Println(a ...interface{}) (n int, err error) {
+	c.Set()
+	defer c.unset()
+
+	return fmt.Fprintln(Output, a...)
+}
+
+// PrintFunc returns a new function that prints the passed arguments as
+// colorized with color.Print().
+func (c *Color) PrintFunc() func(a ...interface{}) {
+	return func(a ...interface{}) { c.Print(a...) }
+}
+
+// PrintfFunc returns a new function that prints the passed arguments as
+// colorized with color.Printf().
+func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
+	return func(format string, a ...interface{}) { c.Printf(format, a...) }
+}
+
+// PrintlnFunc returns a new function that prints the passed arguments as
+// colorized with color.Println().
+func (c *Color) PrintlnFunc() func(a ...interface{}) {
+	return func(a ...interface{}) { c.Println(a...) }
+}
+
+// SprintFunc returns a new function that returns colorized strings for the
+// given arguments with fmt.Sprint(). Useful to put into or mix into other
+// string. Windows users should use this in conjuction with color.Output, example:
+//
+//	put := New(FgYellow).SprintFunc()
+//	fmt.Fprintf(color.Output, "This is a %s", put("warning"))
+func (c *Color) SprintFunc() func(a ...interface{}) string {
+	return func(a ...interface{}) string {
+		return c.wrap(fmt.Sprint(a...))
+	}
+}
+
+// SprintfFunc returns a new function that returns colorized strings for the
+// given arguments with fmt.Sprintf(). Useful to put into or mix into other
+// string. Windows users should use this in conjuction with color.Output.
+func (c *Color) SprintfFunc() func(format string, a ...interface{}) string {
+	return func(format string, a ...interface{}) string {
+		return c.wrap(fmt.Sprintf(format, a...))
+	}
+}
+
+// SprintlnFunc returns a new function that returns colorized strings for the
+// given arguments with fmt.Sprintln(). Useful to put into or mix into other
+// string. Windows users should use this in conjuction with color.Output.
+func (c *Color) SprintlnFunc() func(a ...interface{}) string {
+	return func(a ...interface{}) string {
+		return c.wrap(fmt.Sprintln(a...))
+	}
+}
+
+// sequence returns a formated SGR sequence to be plugged into a "\x1b[...m"
+// an example output might be: "1;36" -> bold cyan
+func (c *Color) sequence() string {
+	format := make([]string, len(c.params))
+	for i, v := range c.params {
+		format[i] = strconv.Itoa(int(v))
+	}
+
+	return strings.Join(format, ";")
+}
+
+// wrap wraps the s string with the colors attributes. The string is ready to
+// be printed.
+func (c *Color) wrap(s string) string {
+	if c.isNoColorSet() {
+		return s
+	}
+
+	return c.format() + s + c.unformat()
+}
+
+func (c *Color) format() string {
+	return fmt.Sprintf("%s[%sm", escape, c.sequence())
+}
+
+func (c *Color) unformat() string {
+	return fmt.Sprintf("%s[%dm", escape, Reset)
+}
+
+// DisableColor disables the color output. Useful to not change any existing
+// code and still being able to output. Can be used for flags like
+// "--no-color". To enable back use EnableColor() method.
+func (c *Color) DisableColor() {
+	c.noColor = boolPtr(true)
+}
+
+// EnableColor enables the color output. Use it in conjuction with
+// DisableColor(). Otherwise this method has no side effects.
+func (c *Color) EnableColor() {
+	c.noColor = boolPtr(false)
+}
+
+func (c *Color) isNoColorSet() bool {
+	// check first if we have user setted action
+	if c.noColor != nil {
+		return *c.noColor
+	}
+
+	// if not return the global option, which is disabled by default
+	return NoColor
+}
+
+func boolPtr(v bool) *bool {
+	return &v
+}
+
+// Black is an convenient helper function to print with black foreground. A
+// newline is appended to format by default.
+func Black(format string, a ...interface{}) { printColor(format, FgBlack, a...) }
+
+// Red is an convenient helper function to print with red foreground. A
+// newline is appended to format by default.
+func Red(format string, a ...interface{}) { printColor(format, FgRed, a...) }
+
+// Green is an convenient helper function to print with green foreground. A
+// newline is appended to format by default.
+func Green(format string, a ...interface{}) { printColor(format, FgGreen, a...) }
+
+// Yellow is an convenient helper function to print with yellow foreground.
+// A newline is appended to format by default.
+func Yellow(format string, a ...interface{}) { printColor(format, FgYellow, a...) }
+
+// Blue is an convenient helper function to print with blue foreground. A
+// newline is appended to format by default.
+func Blue(format string, a ...interface{}) { printColor(format, FgBlue, a...) }
+
+// Magenta is an convenient helper function to print with magenta foreground.
+// A newline is appended to format by default.
+func Magenta(format string, a ...interface{}) { printColor(format, FgMagenta, a...) }
+
+// Cyan is an convenient helper function to print with cyan foreground. A
+// newline is appended to format by default.
+func Cyan(format string, a ...interface{}) { printColor(format, FgCyan, a...) }
+
+// White is an convenient helper function to print with white foreground. A
+// newline is appended to format by default.
+func White(format string, a ...interface{}) { printColor(format, FgWhite, a...) }
+
+func printColor(format string, p Attribute, a ...interface{}) {
+	if !strings.HasSuffix(format, "\n") {
+		format += "\n"
+	}
+
+	c := &Color{params: []Attribute{p}}
+	c.Printf(format, a...)
+}
+
+// BlackString is an convenient helper function to return a string with black
+// foreground.
+func BlackString(format string, a ...interface{}) string {
+	return New(FgBlack).SprintfFunc()(format, a...)
+}
+
+// RedString is an convenient helper function to return a string with red
+// foreground.
+func RedString(format string, a ...interface{}) string {
+	return New(FgRed).SprintfFunc()(format, a...)
+}
+
+// GreenString is an convenient helper function to return a string with green
+// foreground.
+func GreenString(format string, a ...interface{}) string {
+	return New(FgGreen).SprintfFunc()(format, a...)
+}
+
+// YellowString is an convenient helper function to return a string with yellow
+// foreground.
+func YellowString(format string, a ...interface{}) string {
+	return New(FgYellow).SprintfFunc()(format, a...)
+}
+
+// BlueString is an convenient helper function to return a string with blue
+// foreground.
+func BlueString(format string, a ...interface{}) string {
+	return New(FgBlue).SprintfFunc()(format, a...)
+}
+
+// MagentaString is an convenient helper function to return a string with magenta
+// foreground.
+func MagentaString(format string, a ...interface{}) string {
+	return New(FgMagenta).SprintfFunc()(format, a...)
+}
+
+// CyanString is an convenient helper function to return a string with cyan
+// foreground.
+func CyanString(format string, a ...interface{}) string {
+	return New(FgCyan).SprintfFunc()(format, a...)
+}
+
+// WhiteString is an convenient helper function to return a string with white
+// foreground.
+func WhiteString(format string, a ...interface{}) string {
+	return New(FgWhite).SprintfFunc()(format, a...)
+}

+ 176 - 0
Godeps/_workspace/src/github.com/fatih/color/color_test.go

@@ -0,0 +1,176 @@
+package color
+
+import (
+	"bytes"
+	"fmt"
+	"os"
+	"testing"
+
+	"github.com/shiena/ansicolor"
+)
+
+// Testing colors is kinda different. First we test for given colors and their
+// escaped formatted results. Next we create some visual tests to be tested.
+// Each visual test includes the color name to be compared.
+func TestColor(t *testing.T) {
+	rb := new(bytes.Buffer)
+	Output = rb
+
+	testColors := []struct {
+		text string
+		code Attribute
+	}{
+		{text: "black", code: FgBlack},
+		{text: "red", code: FgRed},
+		{text: "green", code: FgGreen},
+		{text: "yellow", code: FgYellow},
+		{text: "blue", code: FgBlue},
+		{text: "magent", code: FgMagenta},
+		{text: "cyan", code: FgCyan},
+		{text: "white", code: FgWhite},
+	}
+
+	for _, c := range testColors {
+		New(c.code).Print(c.text)
+
+		line, _ := rb.ReadString('\n')
+		scannedLine := fmt.Sprintf("%q", line)
+		colored := fmt.Sprintf("\x1b[%dm%s\x1b[0m", c.code, c.text)
+		escapedForm := fmt.Sprintf("%q", colored)
+
+		fmt.Printf("%s\t: %s\n", c.text, line)
+
+		if scannedLine != escapedForm {
+			t.Errorf("Expecting %s, got '%s'\n", escapedForm, scannedLine)
+		}
+	}
+}
+
+func TestNoColor(t *testing.T) {
+	rb := new(bytes.Buffer)
+	Output = rb
+
+	testColors := []struct {
+		text string
+		code Attribute
+	}{
+		{text: "black", code: FgBlack},
+		{text: "red", code: FgRed},
+		{text: "green", code: FgGreen},
+		{text: "yellow", code: FgYellow},
+		{text: "blue", code: FgBlue},
+		{text: "magent", code: FgMagenta},
+		{text: "cyan", code: FgCyan},
+		{text: "white", code: FgWhite},
+	}
+
+	for _, c := range testColors {
+		p := New(c.code)
+		p.DisableColor()
+		p.Print(c.text)
+
+		line, _ := rb.ReadString('\n')
+		if line != c.text {
+			t.Errorf("Expecting %s, got '%s'\n", c.text, line)
+		}
+	}
+
+	// global check
+	NoColor = true
+	defer func() {
+		NoColor = false
+	}()
+	for _, c := range testColors {
+		p := New(c.code)
+		p.Print(c.text)
+
+		line, _ := rb.ReadString('\n')
+		if line != c.text {
+			t.Errorf("Expecting %s, got '%s'\n", c.text, line)
+		}
+	}
+
+}
+
+func TestColorVisual(t *testing.T) {
+	// First Visual Test
+	fmt.Println("")
+	Output = ansicolor.NewAnsiColorWriter(os.Stdout)
+
+	New(FgRed).Printf("red\t")
+	New(BgRed).Print("         ")
+	New(FgRed, Bold).Println(" red")
+
+	New(FgGreen).Printf("green\t")
+	New(BgGreen).Print("         ")
+	New(FgGreen, Bold).Println(" green")
+
+	New(FgYellow).Printf("yellow\t")
+	New(BgYellow).Print("         ")
+	New(FgYellow, Bold).Println(" yellow")
+
+	New(FgBlue).Printf("blue\t")
+	New(BgBlue).Print("         ")
+	New(FgBlue, Bold).Println(" blue")
+
+	New(FgMagenta).Printf("magenta\t")
+	New(BgMagenta).Print("         ")
+	New(FgMagenta, Bold).Println(" magenta")
+
+	New(FgCyan).Printf("cyan\t")
+	New(BgCyan).Print("         ")
+	New(FgCyan, Bold).Println(" cyan")
+
+	New(FgWhite).Printf("white\t")
+	New(BgWhite).Print("         ")
+	New(FgWhite, Bold).Println(" white")
+	fmt.Println("")
+
+	// Second Visual test
+	Black("black")
+	Red("red")
+	Green("green")
+	Yellow("yellow")
+	Blue("blue")
+	Magenta("magenta")
+	Cyan("cyan")
+	White("white")
+
+	// Third visual test
+	fmt.Println()
+	Set(FgBlue)
+	fmt.Println("is this blue?")
+	Unset()
+
+	Set(FgMagenta)
+	fmt.Println("and this magenta?")
+	Unset()
+
+	// Fourth Visual test
+	fmt.Println()
+	blue := New(FgBlue).PrintlnFunc()
+	blue("blue text with custom print func")
+
+	red := New(FgRed).PrintfFunc()
+	red("red text with a printf func: %d\n", 123)
+
+	put := New(FgYellow).SprintFunc()
+	warn := New(FgRed).SprintFunc()
+
+	fmt.Fprintf(Output, "this is a %s and this is %s.\n", put("warning"), warn("error"))
+
+	info := New(FgWhite, BgGreen).SprintFunc()
+	fmt.Fprintf(Output, "this %s rocks!\n", info("package"))
+
+	// Fifth Visual Test
+	fmt.Println()
+
+	fmt.Fprintln(Output, BlackString("black"))
+	fmt.Fprintln(Output, RedString("red"))
+	fmt.Fprintln(Output, GreenString("green"))
+	fmt.Fprintln(Output, YellowString("yellow"))
+	fmt.Fprintln(Output, BlueString("blue"))
+	fmt.Fprintln(Output, MagentaString("magenta"))
+	fmt.Fprintln(Output, CyanString("cyan"))
+	fmt.Fprintln(Output, WhiteString("white"))
+}

+ 114 - 0
Godeps/_workspace/src/github.com/fatih/color/doc.go

@@ -0,0 +1,114 @@
+/*
+Package color is an ANSI color package to output colorized or SGR defined
+output to the standard output. The API can be used in several way, pick one
+that suits you.
+
+Use simple and default helper functions with predefined foreground colors:
+
+    color.Cyan("Prints text in cyan.")
+
+    // a newline will be appended automatically
+    color.Blue("Prints %s in blue.", "text")
+
+    // More default foreground colors..
+    color.Red("We have red")
+    color.Yellow("Yellow color too!")
+    color.Magenta("And many others ..")
+
+However there are times where custom color mixes are required. Below are some
+examples to create custom color objects and use the print functions of each
+separate color object.
+
+    // Create a new color object
+    c := color.New(color.FgCyan).Add(color.Underline)
+    c.Println("Prints cyan text with an underline.")
+
+    // Or just add them to New()
+    d := color.New(color.FgCyan, color.Bold)
+    d.Printf("This prints bold cyan %s\n", "too!.")
+
+
+    // Mix up foreground and background colors, create new mixes!
+    red := color.New(color.FgRed)
+
+    boldRed := red.Add(color.Bold)
+    boldRed.Println("This will print text in bold red.")
+
+    whiteBackground := red.Add(color.BgWhite)
+    whiteBackground.Println("Red text with White background.")
+
+
+You can create PrintXxx functions to simplify even more:
+
+    // Create a custom print function for convenient
+    red := color.New(color.FgRed).PrintfFunc()
+    red("warning")
+    red("error: %s", err)
+
+    // Mix up multiple attributes
+    notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
+    notice("don't forget this...")
+
+
+Or create SprintXxx functions to mix strings with other non-colorized strings:
+
+    yellow := New(FgYellow).SprintFunc()
+    red := New(FgRed).SprintFunc()
+
+    fmt.Printf("this is a %s and this is %s.\n", yellow("warning"), red("error"))
+
+    info := New(FgWhite, BgGreen).SprintFunc()
+    fmt.Printf("this %s rocks!\n", info("package"))
+
+Windows support is enabled by default. All Print functions works as intended.
+However only for color.SprintXXX functions, user should use fmt.FprintXXX and
+set the output to color.Output:
+
+    fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))
+
+    info := New(FgWhite, BgGreen).SprintFunc()
+    fmt.Fprintf(color.Output, "this %s rocks!\n", info("package"))
+
+Using with existing code is possible. Just use the Set() method to set the
+standard output to the given parameters. That way a rewrite of an existing
+code is not required.
+
+    // Use handy standard colors.
+    color.Set(color.FgYellow)
+
+    fmt.Println("Existing text will be now in Yellow")
+    fmt.Printf("This one %s\n", "too")
+
+    color.Unset() // don't forget to unset
+
+    // You can mix up parameters
+    color.Set(color.FgMagenta, color.Bold)
+    defer color.Unset() // use it in your function
+
+    fmt.Println("All text will be now bold magenta.")
+
+There might be a case where you want to disable color output (for example to
+pipe the standard output of your app to somewhere else). `Color` has support to
+disable colors both globally and for single color definition. For example
+suppose you have a CLI app and a `--no-color` bool flag. You can easily disable
+the color output with:
+
+    var flagNoColor = flag.Bool("no-color", false, "Disable color output")
+
+    if *flagNoColor {
+    	color.NoColor = true // disables colorized output
+    }
+
+It also has support for single color definitions (local). You can
+disable/enable color output on the fly:
+
+     c := color.New(color.FgCyan)
+     c.Println("Prints cyan text")
+
+     c.DisableColor()
+     c.Println("This is printed without any color")
+
+     c.EnableColor()
+     c.Println("This prints again cyan...")
+*/
+package color

+ 0 - 42
Godeps/_workspace/src/github.com/mattn/go-colorable/README.md

@@ -1,42 +0,0 @@
-# go-colorable
-
-Colorable writer for windows.
-
-For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.)
-This package is possible to handle escape sequence for ansi color on windows.
-
-## Too Bad!
-
-![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png)
-
-
-## So Good!
-
-![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png)
-
-## Usage
-
-```go
-logrus.SetOutput(colorable.NewColorableStdout())
-
-logrus.Info("succeeded")
-logrus.Warn("not correct")
-logrus.Error("something error")
-logrus.Fatal("panic")
-```
-
-You can compile above code on non-windows OSs.
-
-## Installation
-
-```
-$ go get github.com/mattn/go-colorable
-```
-
-# License
-
-MIT
-
-# Author
-
-Yasuhiro Matsumoto (a.k.a mattn)

+ 0 - 16
Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_others.go

@@ -1,16 +0,0 @@
-// +build !windows
-
-package colorable
-
-import (
-	"io"
-	"os"
-)
-
-func NewColorableStdout() io.Writer {
-	return os.Stdout
-}
-
-func NewColorableStderr() io.Writer {
-	return os.Stderr
-}

+ 0 - 594
Godeps/_workspace/src/github.com/mattn/go-colorable/colorable_windows.go

@@ -1,594 +0,0 @@
-package colorable
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"os"
-	"strconv"
-	"strings"
-	"syscall"
-	"unsafe"
-
-	"github.com/mattn/go-isatty"
-)
-
-const (
-	foregroundBlue      = 0x1
-	foregroundGreen     = 0x2
-	foregroundRed       = 0x4
-	foregroundIntensity = 0x8
-	foregroundMask      = (foregroundRed | foregroundBlue | foregroundGreen | foregroundIntensity)
-	backgroundBlue      = 0x10
-	backgroundGreen     = 0x20
-	backgroundRed       = 0x40
-	backgroundIntensity = 0x80
-	backgroundMask      = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
-)
-
-type wchar uint16
-type short int16
-type dword uint32
-type word uint16
-
-type coord struct {
-	x short
-	y short
-}
-
-type smallRect struct {
-	left   short
-	top    short
-	right  short
-	bottom short
-}
-
-type consoleScreenBufferInfo struct {
-	size              coord
-	cursorPosition    coord
-	attributes        word
-	window            smallRect
-	maximumWindowSize coord
-}
-
-var (
-	kernel32                       = syscall.NewLazyDLL("kernel32.dll")
-	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
-	procSetConsoleTextAttribute    = kernel32.NewProc("SetConsoleTextAttribute")
-)
-
-type Writer struct {
-	out     io.Writer
-	handle  syscall.Handle
-	lastbuf bytes.Buffer
-	oldattr word
-}
-
-func NewColorableStdout() io.Writer {
-	var csbi consoleScreenBufferInfo
-	out := os.Stdout
-	if !isatty.IsTerminal(out.Fd()) {
-		return out
-	}
-	handle := syscall.Handle(out.Fd())
-	procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
-	return &Writer{out: out, handle: handle, oldattr: csbi.attributes}
-}
-
-func NewColorableStderr() io.Writer {
-	var csbi consoleScreenBufferInfo
-	out := os.Stderr
-	if !isatty.IsTerminal(out.Fd()) {
-		return out
-	}
-	handle := syscall.Handle(out.Fd())
-	procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
-	return &Writer{out: out, handle: handle, oldattr: csbi.attributes}
-}
-
-var color256 = map[int]int{
-	0:   0x000000,
-	1:   0x800000,
-	2:   0x008000,
-	3:   0x808000,
-	4:   0x000080,
-	5:   0x800080,
-	6:   0x008080,
-	7:   0xc0c0c0,
-	8:   0x808080,
-	9:   0xff0000,
-	10:  0x00ff00,
-	11:  0xffff00,
-	12:  0x0000ff,
-	13:  0xff00ff,
-	14:  0x00ffff,
-	15:  0xffffff,
-	16:  0x000000,
-	17:  0x00005f,
-	18:  0x000087,
-	19:  0x0000af,
-	20:  0x0000d7,
-	21:  0x0000ff,
-	22:  0x005f00,
-	23:  0x005f5f,
-	24:  0x005f87,
-	25:  0x005faf,
-	26:  0x005fd7,
-	27:  0x005fff,
-	28:  0x008700,
-	29:  0x00875f,
-	30:  0x008787,
-	31:  0x0087af,
-	32:  0x0087d7,
-	33:  0x0087ff,
-	34:  0x00af00,
-	35:  0x00af5f,
-	36:  0x00af87,
-	37:  0x00afaf,
-	38:  0x00afd7,
-	39:  0x00afff,
-	40:  0x00d700,
-	41:  0x00d75f,
-	42:  0x00d787,
-	43:  0x00d7af,
-	44:  0x00d7d7,
-	45:  0x00d7ff,
-	46:  0x00ff00,
-	47:  0x00ff5f,
-	48:  0x00ff87,
-	49:  0x00ffaf,
-	50:  0x00ffd7,
-	51:  0x00ffff,
-	52:  0x5f0000,
-	53:  0x5f005f,
-	54:  0x5f0087,
-	55:  0x5f00af,
-	56:  0x5f00d7,
-	57:  0x5f00ff,
-	58:  0x5f5f00,
-	59:  0x5f5f5f,
-	60:  0x5f5f87,
-	61:  0x5f5faf,
-	62:  0x5f5fd7,
-	63:  0x5f5fff,
-	64:  0x5f8700,
-	65:  0x5f875f,
-	66:  0x5f8787,
-	67:  0x5f87af,
-	68:  0x5f87d7,
-	69:  0x5f87ff,
-	70:  0x5faf00,
-	71:  0x5faf5f,
-	72:  0x5faf87,
-	73:  0x5fafaf,
-	74:  0x5fafd7,
-	75:  0x5fafff,
-	76:  0x5fd700,
-	77:  0x5fd75f,
-	78:  0x5fd787,
-	79:  0x5fd7af,
-	80:  0x5fd7d7,
-	81:  0x5fd7ff,
-	82:  0x5fff00,
-	83:  0x5fff5f,
-	84:  0x5fff87,
-	85:  0x5fffaf,
-	86:  0x5fffd7,
-	87:  0x5fffff,
-	88:  0x870000,
-	89:  0x87005f,
-	90:  0x870087,
-	91:  0x8700af,
-	92:  0x8700d7,
-	93:  0x8700ff,
-	94:  0x875f00,
-	95:  0x875f5f,
-	96:  0x875f87,
-	97:  0x875faf,
-	98:  0x875fd7,
-	99:  0x875fff,
-	100: 0x878700,
-	101: 0x87875f,
-	102: 0x878787,
-	103: 0x8787af,
-	104: 0x8787d7,
-	105: 0x8787ff,
-	106: 0x87af00,
-	107: 0x87af5f,
-	108: 0x87af87,
-	109: 0x87afaf,
-	110: 0x87afd7,
-	111: 0x87afff,
-	112: 0x87d700,
-	113: 0x87d75f,
-	114: 0x87d787,
-	115: 0x87d7af,
-	116: 0x87d7d7,
-	117: 0x87d7ff,
-	118: 0x87ff00,
-	119: 0x87ff5f,
-	120: 0x87ff87,
-	121: 0x87ffaf,
-	122: 0x87ffd7,
-	123: 0x87ffff,
-	124: 0xaf0000,
-	125: 0xaf005f,
-	126: 0xaf0087,
-	127: 0xaf00af,
-	128: 0xaf00d7,
-	129: 0xaf00ff,
-	130: 0xaf5f00,
-	131: 0xaf5f5f,
-	132: 0xaf5f87,
-	133: 0xaf5faf,
-	134: 0xaf5fd7,
-	135: 0xaf5fff,
-	136: 0xaf8700,
-	137: 0xaf875f,
-	138: 0xaf8787,
-	139: 0xaf87af,
-	140: 0xaf87d7,
-	141: 0xaf87ff,
-	142: 0xafaf00,
-	143: 0xafaf5f,
-	144: 0xafaf87,
-	145: 0xafafaf,
-	146: 0xafafd7,
-	147: 0xafafff,
-	148: 0xafd700,
-	149: 0xafd75f,
-	150: 0xafd787,
-	151: 0xafd7af,
-	152: 0xafd7d7,
-	153: 0xafd7ff,
-	154: 0xafff00,
-	155: 0xafff5f,
-	156: 0xafff87,
-	157: 0xafffaf,
-	158: 0xafffd7,
-	159: 0xafffff,
-	160: 0xd70000,
-	161: 0xd7005f,
-	162: 0xd70087,
-	163: 0xd700af,
-	164: 0xd700d7,
-	165: 0xd700ff,
-	166: 0xd75f00,
-	167: 0xd75f5f,
-	168: 0xd75f87,
-	169: 0xd75faf,
-	170: 0xd75fd7,
-	171: 0xd75fff,
-	172: 0xd78700,
-	173: 0xd7875f,
-	174: 0xd78787,
-	175: 0xd787af,
-	176: 0xd787d7,
-	177: 0xd787ff,
-	178: 0xd7af00,
-	179: 0xd7af5f,
-	180: 0xd7af87,
-	181: 0xd7afaf,
-	182: 0xd7afd7,
-	183: 0xd7afff,
-	184: 0xd7d700,
-	185: 0xd7d75f,
-	186: 0xd7d787,
-	187: 0xd7d7af,
-	188: 0xd7d7d7,
-	189: 0xd7d7ff,
-	190: 0xd7ff00,
-	191: 0xd7ff5f,
-	192: 0xd7ff87,
-	193: 0xd7ffaf,
-	194: 0xd7ffd7,
-	195: 0xd7ffff,
-	196: 0xff0000,
-	197: 0xff005f,
-	198: 0xff0087,
-	199: 0xff00af,
-	200: 0xff00d7,
-	201: 0xff00ff,
-	202: 0xff5f00,
-	203: 0xff5f5f,
-	204: 0xff5f87,
-	205: 0xff5faf,
-	206: 0xff5fd7,
-	207: 0xff5fff,
-	208: 0xff8700,
-	209: 0xff875f,
-	210: 0xff8787,
-	211: 0xff87af,
-	212: 0xff87d7,
-	213: 0xff87ff,
-	214: 0xffaf00,
-	215: 0xffaf5f,
-	216: 0xffaf87,
-	217: 0xffafaf,
-	218: 0xffafd7,
-	219: 0xffafff,
-	220: 0xffd700,
-	221: 0xffd75f,
-	222: 0xffd787,
-	223: 0xffd7af,
-	224: 0xffd7d7,
-	225: 0xffd7ff,
-	226: 0xffff00,
-	227: 0xffff5f,
-	228: 0xffff87,
-	229: 0xffffaf,
-	230: 0xffffd7,
-	231: 0xffffff,
-	232: 0x080808,
-	233: 0x121212,
-	234: 0x1c1c1c,
-	235: 0x262626,
-	236: 0x303030,
-	237: 0x3a3a3a,
-	238: 0x444444,
-	239: 0x4e4e4e,
-	240: 0x585858,
-	241: 0x626262,
-	242: 0x6c6c6c,
-	243: 0x767676,
-	244: 0x808080,
-	245: 0x8a8a8a,
-	246: 0x949494,
-	247: 0x9e9e9e,
-	248: 0xa8a8a8,
-	249: 0xb2b2b2,
-	250: 0xbcbcbc,
-	251: 0xc6c6c6,
-	252: 0xd0d0d0,
-	253: 0xdadada,
-	254: 0xe4e4e4,
-	255: 0xeeeeee,
-}
-
-func (w *Writer) Write(data []byte) (n int, err error) {
-	var csbi consoleScreenBufferInfo
-	procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
-
-	er := bytes.NewBuffer(data)
-loop:
-	for {
-		r1, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
-		if r1 == 0 {
-			break loop
-		}
-
-		c1, _, err := er.ReadRune()
-		if err != nil {
-			break loop
-		}
-		if c1 != 0x1b {
-			fmt.Fprint(w.out, string(c1))
-			continue
-		}
-		c2, _, err := er.ReadRune()
-		if err != nil {
-			w.lastbuf.WriteRune(c1)
-			break loop
-		}
-		if c2 != 0x5b {
-			w.lastbuf.WriteRune(c1)
-			w.lastbuf.WriteRune(c2)
-			continue
-		}
-
-		var buf bytes.Buffer
-		var m rune
-		for {
-			c, _, err := er.ReadRune()
-			if err != nil {
-				w.lastbuf.WriteRune(c1)
-				w.lastbuf.WriteRune(c2)
-				w.lastbuf.Write(buf.Bytes())
-				break loop
-			}
-			if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
-				m = c
-				break
-			}
-			buf.Write([]byte(string(c)))
-		}
-
-		switch m {
-		case 'm':
-			attr := csbi.attributes
-			cs := buf.String()
-			if cs == "" {
-				procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.oldattr))
-				continue
-			}
-			token := strings.Split(cs, ";")
-			for i, ns := range token {
-				if n, err = strconv.Atoi(ns); err == nil {
-					switch {
-					case n == 0 || n == 100:
-						attr = w.oldattr
-					case 1 <= n && n <= 5:
-						attr |= foregroundIntensity
-					case n == 7:
-						attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
-					case 22 == n || n == 25 || n == 25:
-						attr |= foregroundIntensity
-					case n == 27:
-						attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
-					case 30 <= n && n <= 37:
-						attr = (attr & backgroundMask)
-						if (n-30)&1 != 0 {
-							attr |= foregroundRed
-						}
-						if (n-30)&2 != 0 {
-							attr |= foregroundGreen
-						}
-						if (n-30)&4 != 0 {
-							attr |= foregroundBlue
-						}
-					case n == 38: // set foreground color.
-						if i < len(token)-2 && token[i+1] == "5" {
-							if n256, err := strconv.Atoi(token[i+2]); err == nil {
-								if n256foreAttr == nil {
-									n256setup()
-								}
-								attr &= backgroundMask
-								attr |= n256foreAttr[n256]
-								i += 2
-							}
-						} else {
-							attr = attr & (w.oldattr & backgroundMask)
-						}
-					case n == 39: // reset foreground color.
-						attr &= backgroundMask
-						attr |= w.oldattr & foregroundMask
-					case 40 <= n && n <= 47:
-						attr = (attr & foregroundMask)
-						if (n-40)&1 != 0 {
-							attr |= backgroundRed
-						}
-						if (n-40)&2 != 0 {
-							attr |= backgroundGreen
-						}
-						if (n-40)&4 != 0 {
-							attr |= backgroundBlue
-						}
-					case n == 48: // set background color.
-						if i < len(token)-2 && token[i+1] == "5" {
-							if n256, err := strconv.Atoi(token[i+2]); err == nil {
-								if n256backAttr == nil {
-									n256setup()
-								}
-								attr &= foregroundMask
-								attr |= n256backAttr[n256]
-								i += 2
-							}
-						} else {
-							attr = attr & (w.oldattr & foregroundMask)
-						}
-					case n == 49: // reset foreground color.
-						attr &= foregroundMask
-						attr |= w.oldattr & backgroundMask
-					}
-					procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr))
-				}
-			}
-		}
-	}
-	return len(data) - w.lastbuf.Len(), nil
-}
-
-type consoleColor struct {
-	red       bool
-	green     bool
-	blue      bool
-	intensity bool
-}
-
-func minmax3(a, b, c int) (min, max int) {
-	if a < b {
-		if b < c {
-			return a, c
-		} else if a < c {
-			return a, b
-		} else {
-			return c, b
-		}
-	} else {
-		if a < c {
-			return b, c
-		} else if b < c {
-			return b, a
-		} else {
-			return c, a
-		}
-	}
-}
-
-func toConsoleColor(rgb int) (c consoleColor) {
-	r, g, b := (rgb&0xFF0000)>>16, (rgb&0x00FF00)>>8, rgb&0x0000FF
-	min, max := minmax3(r, g, b)
-	a := (min + max) / 2
-	if r < 128 && g < 128 && b < 128 {
-		if r >= a {
-			c.red = true
-		}
-		if g >= a {
-			c.green = true
-		}
-		if b >= a {
-			c.blue = true
-		}
-		// non-intensed white is lighter than intensed black, so swap those.
-		if c.red && c.green && c.blue {
-			c.red, c.green, c.blue = false, false, false
-			c.intensity = true
-		}
-	} else {
-		if min < 128 {
-			min = 128
-			a = (min + max) / 2
-		}
-		if r >= a {
-			c.red = true
-		}
-		if g >= a {
-			c.green = true
-		}
-		if b >= a {
-			c.blue = true
-		}
-		c.intensity = true
-		// intensed black is darker than non-intensed white, so swap those.
-		if !c.red && !c.green && !c.blue {
-			c.red, c.green, c.blue = true, true, true
-			c.intensity = false
-		}
-	}
-	return c
-}
-
-func (c consoleColor) foregroundAttr() (attr word) {
-	if c.red {
-		attr |= foregroundRed
-	}
-	if c.green {
-		attr |= foregroundGreen
-	}
-	if c.blue {
-		attr |= foregroundBlue
-	}
-	if c.intensity {
-		attr |= foregroundIntensity
-	}
-	return
-}
-
-func (c consoleColor) backgroundAttr() (attr word) {
-	if c.red {
-		attr |= backgroundRed
-	}
-	if c.green {
-		attr |= backgroundGreen
-	}
-	if c.blue {
-		attr |= backgroundBlue
-	}
-	if c.intensity {
-		attr |= backgroundIntensity
-	}
-	return
-}
-
-var n256foreAttr []word
-var n256backAttr []word
-
-func n256setup() {
-	n256foreAttr = make([]word, 256)
-	n256backAttr = make([]word, 256)
-	for i, rgb := range color256 {
-		c := toConsoleColor(rgb)
-		n256foreAttr[i] = c.foregroundAttr()
-		n256backAttr[i] = c.backgroundAttr()
-	}
-}

+ 27 - 0
Godeps/_workspace/src/github.com/shiena/ansicolor/.gitignore

@@ -0,0 +1,27 @@
+# Created by http://www.gitignore.io
+
+### Go ###
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+

+ 21 - 0
Godeps/_workspace/src/github.com/shiena/ansicolor/LICENSE

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) [2014] [shiena]
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 100 - 0
Godeps/_workspace/src/github.com/shiena/ansicolor/README.md

@@ -0,0 +1,100 @@
+[![GoDoc](https://godoc.org/github.com/shiena/ansicolor?status.svg)](https://godoc.org/github.com/shiena/ansicolor)
+
+# ansicolor
+
+Ansicolor library provides color console in Windows as ANSICON for Golang.
+
+## Features
+
+|Escape sequence|Text attributes|
+|---------------|----|
+|\x1b[0m|All attributes off(color at startup)|
+|\x1b[1m|Bold on(enable foreground intensity)|
+|\x1b[4m|Underline on|
+|\x1b[5m|Blink on(enable background intensity)|
+|\x1b[21m|Bold off(disable foreground intensity)|
+|\x1b[24m|Underline off|
+|\x1b[25m|Blink off(disable background intensity)|
+
+|Escape sequence|Foreground colors|
+|---------------|----|
+|\x1b[30m|Black|
+|\x1b[31m|Red|
+|\x1b[32m|Green|
+|\x1b[33m|Yellow|
+|\x1b[34m|Blue|
+|\x1b[35m|Magenta|
+|\x1b[36m|Cyan|
+|\x1b[37m|White|
+|\x1b[39m|Default(foreground color at startup)|
+|\x1b[90m|Light Gray|
+|\x1b[91m|Light Red|
+|\x1b[92m|Light Green|
+|\x1b[93m|Light Yellow|
+|\x1b[94m|Light Blue|
+|\x1b[95m|Light Magenta|
+|\x1b[96m|Light Cyan|
+|\x1b[97m|Light White|
+
+|Escape sequence|Background colors|
+|---------------|----|
+|\x1b[40m|Black|
+|\x1b[41m|Red|
+|\x1b[42m|Green|
+|\x1b[43m|Yellow|
+|\x1b[44m|Blue|
+|\x1b[45m|Magenta|
+|\x1b[46m|Cyan|
+|\x1b[47m|White|
+|\x1b[49m|Default(background color at startup)|
+|\x1b[100m|Light Gray|
+|\x1b[101m|Light Red|
+|\x1b[102m|Light Green|
+|\x1b[103m|Light Yellow|
+|\x1b[104m|Light Blue|
+|\x1b[105m|Light Magenta|
+|\x1b[106m|Light Cyan|
+|\x1b[107m|Light White|
+
+## Example
+
+```go
+package main
+
+import (
+	"fmt"
+	"os"
+
+	"github.com/shiena/ansicolor"
+)
+
+func main() {
+	w := ansicolor.NewAnsiColorWriter(os.Stdout)
+	text := "%sforeground %sbold%s %sbackground%s\n"
+	fmt.Fprintf(w, text, "\x1b[31m", "\x1b[1m", "\x1b[21m", "\x1b[41;32m", "\x1b[0m")
+	fmt.Fprintf(w, text, "\x1b[32m", "\x1b[1m", "\x1b[21m", "\x1b[42;31m", "\x1b[0m")
+	fmt.Fprintf(w, text, "\x1b[33m", "\x1b[1m", "\x1b[21m", "\x1b[43;34m", "\x1b[0m")
+	fmt.Fprintf(w, text, "\x1b[34m", "\x1b[1m", "\x1b[21m", "\x1b[44;33m", "\x1b[0m")
+	fmt.Fprintf(w, text, "\x1b[35m", "\x1b[1m", "\x1b[21m", "\x1b[45;36m", "\x1b[0m")
+	fmt.Fprintf(w, text, "\x1b[36m", "\x1b[1m", "\x1b[21m", "\x1b[46;35m", "\x1b[0m")
+	fmt.Fprintf(w, text, "\x1b[37m", "\x1b[1m", "\x1b[21m", "\x1b[47;30m", "\x1b[0m")
+}
+```
+
+![screenshot](https://gist.githubusercontent.com/shiena/a1bada24b525314a7d5e/raw/c763aa7cda6e4fefaccf831e2617adc40b6151c7/main.png)
+
+## See also:
+
+- https://github.com/daviddengcn/go-colortext
+- https://github.com/adoxa/ansicon
+- https://github.com/aslakhellesoy/wac
+- https://github.com/wsxiaoys/terminal
+
+## Contributing
+
+1. Fork it
+2. Create your feature branch (`git checkout -b my-new-feature`)
+3. Commit your changes (`git commit -am 'Add some feature'`)
+4. Push to the branch (`git push origin my-new-feature`)
+5. Create new Pull Request
+

+ 20 - 0
Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor.go

@@ -0,0 +1,20 @@
+// Copyright 2014 shiena Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+// Package ansicolor provides color console in Windows as ANSICON.
+package ansicolor
+
+import "io"
+
+// NewAnsiColorWriter creates and initializes a new ansiColorWriter
+// using io.Writer w as its initial contents.
+// In the console of Windows, which change the foreground and background
+// colors of the text by the escape sequence.
+// In the console of other systems, which writes to w all text.
+func NewAnsiColorWriter(w io.Writer) io.Writer {
+	if _, ok := w.(*ansiColorWriter); !ok {
+		return &ansiColorWriter{w: w}
+	}
+	return w
+}

+ 27 - 0
Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor/main.go

@@ -0,0 +1,27 @@
+// Copyright 2014 shiena Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+/*
+
+The ansicolor command colors a console text by ANSI escape sequence like wac.
+
+    $ go get github.com/shiena/ansicolor/ansicolor
+
+See also:
+    https://github.com/aslakhellesoy/wac
+
+*/
+package main
+
+import (
+	"io"
+	"os"
+
+	"github.com/shiena/ansicolor"
+)
+
+func main() {
+	w := ansicolor.NewAnsiColorWriter(os.Stdout)
+	io.Copy(w, os.Stdin)
+}

+ 17 - 0
Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_ansi.go

@@ -0,0 +1,17 @@
+// Copyright 2014 shiena Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+// +build !windows
+
+package ansicolor
+
+import "io"
+
+type ansiColorWriter struct {
+	w io.Writer
+}
+
+func (cw *ansiColorWriter) Write(p []byte) (int, error) {
+	return cw.w.Write(p)
+}

+ 25 - 0
Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_test.go

@@ -0,0 +1,25 @@
+package ansicolor_test
+
+import (
+	"bytes"
+	"testing"
+
+	"github.com/shiena/ansicolor"
+)
+
+func TestNewAnsiColor1(t *testing.T) {
+	inner := bytes.NewBufferString("")
+	w := ansicolor.NewAnsiColorWriter(inner)
+	if w == inner {
+		t.Errorf("Get %#v, want %#v", w, inner)
+	}
+}
+
+func TestNewAnsiColor2(t *testing.T) {
+	inner := bytes.NewBufferString("")
+	w1 := ansicolor.NewAnsiColorWriter(inner)
+	w2 := ansicolor.NewAnsiColorWriter(w1)
+	if w1 != w2 {
+		t.Errorf("Get %#v, want %#v", w1, w2)
+	}
+}

+ 351 - 0
Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows.go

@@ -0,0 +1,351 @@
+// Copyright 2014 shiena Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+// +build windows
+
+package ansicolor
+
+import (
+	"bytes"
+	"io"
+	"strings"
+	"syscall"
+	"unsafe"
+)
+
+type csiState int
+
+const (
+	outsideCsiCode csiState = iota
+	firstCsiCode
+	secondCsiCode
+)
+
+type ansiColorWriter struct {
+	w        io.Writer
+	state    csiState
+	paramBuf bytes.Buffer
+}
+
+const (
+	firstCsiChar   byte = '\x1b'
+	secondeCsiChar byte = '['
+	separatorChar  byte = ';'
+	sgrCode        byte = 'm'
+)
+
+const (
+	foregroundBlue      = uint16(0x0001)
+	foregroundGreen     = uint16(0x0002)
+	foregroundRed       = uint16(0x0004)
+	foregroundIntensity = uint16(0x0008)
+	backgroundBlue      = uint16(0x0010)
+	backgroundGreen     = uint16(0x0020)
+	backgroundRed       = uint16(0x0040)
+	backgroundIntensity = uint16(0x0080)
+	underscore          = uint16(0x8000)
+
+	foregroundMask = foregroundBlue | foregroundGreen | foregroundRed | foregroundIntensity
+	backgroundMask = backgroundBlue | backgroundGreen | backgroundRed | backgroundIntensity
+)
+
+const (
+	ansiReset        = "0"
+	ansiIntensityOn  = "1"
+	ansiIntensityOff = "21"
+	ansiUnderlineOn  = "4"
+	ansiUnderlineOff = "24"
+	ansiBlinkOn      = "5"
+	ansiBlinkOff     = "25"
+
+	ansiForegroundBlack   = "30"
+	ansiForegroundRed     = "31"
+	ansiForegroundGreen   = "32"
+	ansiForegroundYellow  = "33"
+	ansiForegroundBlue    = "34"
+	ansiForegroundMagenta = "35"
+	ansiForegroundCyan    = "36"
+	ansiForegroundWhite   = "37"
+	ansiForegroundDefault = "39"
+
+	ansiBackgroundBlack   = "40"
+	ansiBackgroundRed     = "41"
+	ansiBackgroundGreen   = "42"
+	ansiBackgroundYellow  = "43"
+	ansiBackgroundBlue    = "44"
+	ansiBackgroundMagenta = "45"
+	ansiBackgroundCyan    = "46"
+	ansiBackgroundWhite   = "47"
+	ansiBackgroundDefault = "49"
+
+	ansiLightForegroundGray    = "90"
+	ansiLightForegroundRed     = "91"
+	ansiLightForegroundGreen   = "92"
+	ansiLightForegroundYellow  = "93"
+	ansiLightForegroundBlue    = "94"
+	ansiLightForegroundMagenta = "95"
+	ansiLightForegroundCyan    = "96"
+	ansiLightForegroundWhite   = "97"
+
+	ansiLightBackgroundGray    = "100"
+	ansiLightBackgroundRed     = "101"
+	ansiLightBackgroundGreen   = "102"
+	ansiLightBackgroundYellow  = "103"
+	ansiLightBackgroundBlue    = "104"
+	ansiLightBackgroundMagenta = "105"
+	ansiLightBackgroundCyan    = "106"
+	ansiLightBackgroundWhite   = "107"
+)
+
+type drawType int
+
+const (
+	foreground drawType = iota
+	background
+)
+
+type winColor struct {
+	code     uint16
+	drawType drawType
+}
+
+var colorMap = map[string]winColor{
+	ansiForegroundBlack:   {0, foreground},
+	ansiForegroundRed:     {foregroundRed, foreground},
+	ansiForegroundGreen:   {foregroundGreen, foreground},
+	ansiForegroundYellow:  {foregroundRed | foregroundGreen, foreground},
+	ansiForegroundBlue:    {foregroundBlue, foreground},
+	ansiForegroundMagenta: {foregroundRed | foregroundBlue, foreground},
+	ansiForegroundCyan:    {foregroundGreen | foregroundBlue, foreground},
+	ansiForegroundWhite:   {foregroundRed | foregroundGreen | foregroundBlue, foreground},
+	ansiForegroundDefault: {foregroundRed | foregroundGreen | foregroundBlue, foreground},
+
+	ansiBackgroundBlack:   {0, background},
+	ansiBackgroundRed:     {backgroundRed, background},
+	ansiBackgroundGreen:   {backgroundGreen, background},
+	ansiBackgroundYellow:  {backgroundRed | backgroundGreen, background},
+	ansiBackgroundBlue:    {backgroundBlue, background},
+	ansiBackgroundMagenta: {backgroundRed | backgroundBlue, background},
+	ansiBackgroundCyan:    {backgroundGreen | backgroundBlue, background},
+	ansiBackgroundWhite:   {backgroundRed | backgroundGreen | backgroundBlue, background},
+	ansiBackgroundDefault: {0, background},
+
+	ansiLightForegroundGray:    {foregroundIntensity, foreground},
+	ansiLightForegroundRed:     {foregroundIntensity | foregroundRed, foreground},
+	ansiLightForegroundGreen:   {foregroundIntensity | foregroundGreen, foreground},
+	ansiLightForegroundYellow:  {foregroundIntensity | foregroundRed | foregroundGreen, foreground},
+	ansiLightForegroundBlue:    {foregroundIntensity | foregroundBlue, foreground},
+	ansiLightForegroundMagenta: {foregroundIntensity | foregroundRed | foregroundBlue, foreground},
+	ansiLightForegroundCyan:    {foregroundIntensity | foregroundGreen | foregroundBlue, foreground},
+	ansiLightForegroundWhite:   {foregroundIntensity | foregroundRed | foregroundGreen | foregroundBlue, foreground},
+
+	ansiLightBackgroundGray:    {backgroundIntensity, background},
+	ansiLightBackgroundRed:     {backgroundIntensity | backgroundRed, background},
+	ansiLightBackgroundGreen:   {backgroundIntensity | backgroundGreen, background},
+	ansiLightBackgroundYellow:  {backgroundIntensity | backgroundRed | backgroundGreen, background},
+	ansiLightBackgroundBlue:    {backgroundIntensity | backgroundBlue, background},
+	ansiLightBackgroundMagenta: {backgroundIntensity | backgroundRed | backgroundBlue, background},
+	ansiLightBackgroundCyan:    {backgroundIntensity | backgroundGreen | backgroundBlue, background},
+	ansiLightBackgroundWhite:   {backgroundIntensity | backgroundRed | backgroundGreen | backgroundBlue, background},
+}
+
+var (
+	kernel32                       = syscall.NewLazyDLL("kernel32.dll")
+	procSetConsoleTextAttribute    = kernel32.NewProc("SetConsoleTextAttribute")
+	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
+	defaultAttr                    *textAttributes
+)
+
+func init() {
+	screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout))
+	if screenInfo != nil {
+		colorMap[ansiForegroundDefault] = winColor{
+			screenInfo.WAttributes & (foregroundRed | foregroundGreen | foregroundBlue),
+			foreground,
+		}
+		colorMap[ansiBackgroundDefault] = winColor{
+			screenInfo.WAttributes & (backgroundRed | backgroundGreen | backgroundBlue),
+			background,
+		}
+		defaultAttr = convertTextAttr(screenInfo.WAttributes)
+	}
+}
+
+type coord struct {
+	X, Y int16
+}
+
+type smallRect struct {
+	Left, Top, Right, Bottom int16
+}
+
+type consoleScreenBufferInfo struct {
+	DwSize              coord
+	DwCursorPosition    coord
+	WAttributes         uint16
+	SrWindow            smallRect
+	DwMaximumWindowSize coord
+}
+
+func getConsoleScreenBufferInfo(hConsoleOutput uintptr) *consoleScreenBufferInfo {
+	var csbi consoleScreenBufferInfo
+	ret, _, _ := procGetConsoleScreenBufferInfo.Call(
+		hConsoleOutput,
+		uintptr(unsafe.Pointer(&csbi)))
+	if ret == 0 {
+		return nil
+	}
+	return &csbi
+}
+
+func setConsoleTextAttribute(hConsoleOutput uintptr, wAttributes uint16) bool {
+	ret, _, _ := procSetConsoleTextAttribute.Call(
+		hConsoleOutput,
+		uintptr(wAttributes))
+	return ret != 0
+}
+
+type textAttributes struct {
+	foregroundColor     uint16
+	backgroundColor     uint16
+	foregroundIntensity uint16
+	backgroundIntensity uint16
+	underscore          uint16
+	otherAttributes     uint16
+}
+
+func convertTextAttr(winAttr uint16) *textAttributes {
+	fgColor := winAttr & (foregroundRed | foregroundGreen | foregroundBlue)
+	bgColor := winAttr & (backgroundRed | backgroundGreen | backgroundBlue)
+	fgIntensity := winAttr & foregroundIntensity
+	bgIntensity := winAttr & backgroundIntensity
+	underline := winAttr & underscore
+	otherAttributes := winAttr &^ (foregroundMask | backgroundMask | underscore)
+	return &textAttributes{fgColor, bgColor, fgIntensity, bgIntensity, underline, otherAttributes}
+}
+
+func convertWinAttr(textAttr *textAttributes) uint16 {
+	var winAttr uint16 = 0
+	winAttr |= textAttr.foregroundColor
+	winAttr |= textAttr.backgroundColor
+	winAttr |= textAttr.foregroundIntensity
+	winAttr |= textAttr.backgroundIntensity
+	winAttr |= textAttr.underscore
+	winAttr |= textAttr.otherAttributes
+	return winAttr
+}
+
+func changeColor(param []byte) {
+	if defaultAttr == nil {
+		return
+	}
+
+	screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout))
+	if screenInfo == nil {
+		return
+	}
+
+	winAttr := convertTextAttr(screenInfo.WAttributes)
+	strParam := string(param)
+	if len(strParam) <= 0 {
+		strParam = "0"
+	}
+	csiParam := strings.Split(strParam, string(separatorChar))
+	for _, p := range csiParam {
+		c, ok := colorMap[p]
+		switch {
+		case !ok:
+			switch p {
+			case ansiReset:
+				winAttr.foregroundColor = defaultAttr.foregroundColor
+				winAttr.backgroundColor = defaultAttr.backgroundColor
+				winAttr.foregroundIntensity = defaultAttr.foregroundIntensity
+				winAttr.backgroundIntensity = defaultAttr.backgroundIntensity
+				winAttr.underscore = 0
+				winAttr.otherAttributes = 0
+			case ansiIntensityOn:
+				winAttr.foregroundIntensity = foregroundIntensity
+			case ansiIntensityOff:
+				winAttr.foregroundIntensity = 0
+			case ansiUnderlineOn:
+				winAttr.underscore = underscore
+			case ansiUnderlineOff:
+				winAttr.underscore = 0
+			case ansiBlinkOn:
+				winAttr.backgroundIntensity = backgroundIntensity
+			case ansiBlinkOff:
+				winAttr.backgroundIntensity = 0
+			default:
+				// unknown code
+			}
+		case c.drawType == foreground:
+			winAttr.foregroundColor = c.code
+		case c.drawType == background:
+			winAttr.backgroundColor = c.code
+		}
+	}
+	winTextAttribute := convertWinAttr(winAttr)
+	setConsoleTextAttribute(uintptr(syscall.Stdout), winTextAttribute)
+}
+
+func parseEscapeSequence(command byte, param []byte) {
+	switch command {
+	case sgrCode:
+		changeColor(param)
+	}
+}
+
+func isParameterChar(b byte) bool {
+	return ('0' <= b && b <= '9') || b == separatorChar
+}
+
+func (cw *ansiColorWriter) Write(p []byte) (int, error) {
+	r, nw, nc, first, last := 0, 0, 0, 0, 0
+	var err error
+	for i, ch := range p {
+		switch cw.state {
+		case outsideCsiCode:
+			if ch == firstCsiChar {
+				nc++
+				cw.state = firstCsiCode
+			}
+		case firstCsiCode:
+			switch ch {
+			case firstCsiChar:
+				nc++
+				break
+			case secondeCsiChar:
+				nc++
+				cw.state = secondCsiCode
+				last = i - 1
+			default:
+				cw.state = outsideCsiCode
+			}
+		case secondCsiCode:
+			nc++
+			if isParameterChar(ch) {
+				cw.paramBuf.WriteByte(ch)
+			} else {
+				nw, err = cw.w.Write(p[first:last])
+				r += nw
+				if err != nil {
+					return r, err
+				}
+				first = i + 1
+				param := cw.paramBuf.Bytes()
+				cw.paramBuf.Reset()
+				parseEscapeSequence(ch, param)
+				cw.state = outsideCsiCode
+			}
+		default:
+			cw.state = outsideCsiCode
+		}
+	}
+
+	if cw.state == outsideCsiCode {
+		nw, err = cw.w.Write(p[first:len(p)])
+	}
+
+	return r + nw + nc, err
+}

+ 236 - 0
Godeps/_workspace/src/github.com/shiena/ansicolor/ansicolor_windows_test.go

@@ -0,0 +1,236 @@
+// Copyright 2014 shiena Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+// +build windows
+
+package ansicolor_test
+
+import (
+	"bytes"
+	"fmt"
+	"syscall"
+	"testing"
+
+	"github.com/shiena/ansicolor"
+	. "github.com/shiena/ansicolor"
+)
+
+func TestWritePlanText(t *testing.T) {
+	inner := bytes.NewBufferString("")
+	w := ansicolor.NewAnsiColorWriter(inner)
+	expected := "plain text"
+	fmt.Fprintf(w, expected)
+	actual := inner.String()
+	if actual != expected {
+		t.Errorf("Get %s, want %s", actual, expected)
+	}
+}
+
+func TestWriteParseText(t *testing.T) {
+	inner := bytes.NewBufferString("")
+	w := ansicolor.NewAnsiColorWriter(inner)
+
+	inputTail := "\x1b[0mtail text"
+	expectedTail := "tail text"
+	fmt.Fprintf(w, inputTail)
+	actualTail := inner.String()
+	inner.Reset()
+	if actualTail != expectedTail {
+		t.Errorf("Get %s, want %s", actualTail, expectedTail)
+	}
+
+	inputHead := "head text\x1b[0m"
+	expectedHead := "head text"
+	fmt.Fprintf(w, inputHead)
+	actualHead := inner.String()
+	inner.Reset()
+	if actualHead != expectedHead {
+		t.Errorf("Get %s, want %s", actualHead, expectedHead)
+	}
+
+	inputBothEnds := "both ends \x1b[0m text"
+	expectedBothEnds := "both ends  text"
+	fmt.Fprintf(w, inputBothEnds)
+	actualBothEnds := inner.String()
+	inner.Reset()
+	if actualBothEnds != expectedBothEnds {
+		t.Errorf("Get %s, want %s", actualBothEnds, expectedBothEnds)
+	}
+
+	inputManyEsc := "\x1b\x1b\x1b\x1b[0m many esc"
+	expectedManyEsc := "\x1b\x1b\x1b many esc"
+	fmt.Fprintf(w, inputManyEsc)
+	actualManyEsc := inner.String()
+	inner.Reset()
+	if actualManyEsc != expectedManyEsc {
+		t.Errorf("Get %s, want %s", actualManyEsc, expectedManyEsc)
+	}
+
+	expectedSplit := "split  text"
+	for _, ch := range "split \x1b[0m text" {
+		fmt.Fprintf(w, string(ch))
+	}
+	actualSplit := inner.String()
+	inner.Reset()
+	if actualSplit != expectedSplit {
+		t.Errorf("Get %s, want %s", actualSplit, expectedSplit)
+	}
+}
+
+type screenNotFoundError struct {
+	error
+}
+
+func writeAnsiColor(expectedText, colorCode string) (actualText string, actualAttributes uint16, err error) {
+	inner := bytes.NewBufferString("")
+	w := ansicolor.NewAnsiColorWriter(inner)
+	fmt.Fprintf(w, "\x1b[%sm%s", colorCode, expectedText)
+
+	actualText = inner.String()
+	screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout))
+	if screenInfo != nil {
+		actualAttributes = screenInfo.WAttributes
+	} else {
+		err = &screenNotFoundError{}
+	}
+	return
+}
+
+type testParam struct {
+	text       string
+	attributes uint16
+	ansiColor  string
+}
+
+func TestWriteAnsiColorText(t *testing.T) {
+	screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout))
+	if screenInfo == nil {
+		t.Fatal("Could not get ConsoleScreenBufferInfo")
+	}
+	defer ChangeColor(screenInfo.WAttributes)
+	defaultFgColor := screenInfo.WAttributes & uint16(0x0007)
+	defaultBgColor := screenInfo.WAttributes & uint16(0x0070)
+	defaultFgIntensity := screenInfo.WAttributes & uint16(0x0008)
+	defaultBgIntensity := screenInfo.WAttributes & uint16(0x0080)
+
+	fgParam := []testParam{
+		{"foreground black  ", uint16(0x0000 | 0x0000), "30"},
+		{"foreground red    ", uint16(0x0004 | 0x0000), "31"},
+		{"foreground green  ", uint16(0x0002 | 0x0000), "32"},
+		{"foreground yellow ", uint16(0x0006 | 0x0000), "33"},
+		{"foreground blue   ", uint16(0x0001 | 0x0000), "34"},
+		{"foreground magenta", uint16(0x0005 | 0x0000), "35"},
+		{"foreground cyan   ", uint16(0x0003 | 0x0000), "36"},
+		{"foreground white  ", uint16(0x0007 | 0x0000), "37"},
+		{"foreground default", defaultFgColor | 0x0000, "39"},
+		{"foreground light gray   ", uint16(0x0000 | 0x0008 | 0x0000), "90"},
+		{"foreground light red    ", uint16(0x0004 | 0x0008 | 0x0000), "91"},
+		{"foreground light green  ", uint16(0x0002 | 0x0008 | 0x0000), "92"},
+		{"foreground light yellow ", uint16(0x0006 | 0x0008 | 0x0000), "93"},
+		{"foreground light blue   ", uint16(0x0001 | 0x0008 | 0x0000), "94"},
+		{"foreground light magenta", uint16(0x0005 | 0x0008 | 0x0000), "95"},
+		{"foreground light cyan   ", uint16(0x0003 | 0x0008 | 0x0000), "96"},
+		{"foreground light white  ", uint16(0x0007 | 0x0008 | 0x0000), "97"},
+	}
+
+	bgParam := []testParam{
+		{"background black  ", uint16(0x0007 | 0x0000), "40"},
+		{"background red    ", uint16(0x0007 | 0x0040), "41"},
+		{"background green  ", uint16(0x0007 | 0x0020), "42"},
+		{"background yellow ", uint16(0x0007 | 0x0060), "43"},
+		{"background blue   ", uint16(0x0007 | 0x0010), "44"},
+		{"background magenta", uint16(0x0007 | 0x0050), "45"},
+		{"background cyan   ", uint16(0x0007 | 0x0030), "46"},
+		{"background white  ", uint16(0x0007 | 0x0070), "47"},
+		{"background default", uint16(0x0007) | defaultBgColor, "49"},
+		{"background light gray   ", uint16(0x0007 | 0x0000 | 0x0080), "100"},
+		{"background light red    ", uint16(0x0007 | 0x0040 | 0x0080), "101"},
+		{"background light green  ", uint16(0x0007 | 0x0020 | 0x0080), "102"},
+		{"background light yellow ", uint16(0x0007 | 0x0060 | 0x0080), "103"},
+		{"background light blue   ", uint16(0x0007 | 0x0010 | 0x0080), "104"},
+		{"background light magenta", uint16(0x0007 | 0x0050 | 0x0080), "105"},
+		{"background light cyan   ", uint16(0x0007 | 0x0030 | 0x0080), "106"},
+		{"background light white  ", uint16(0x0007 | 0x0070 | 0x0080), "107"},
+	}
+
+	resetParam := []testParam{
+		{"all reset", defaultFgColor | defaultBgColor | defaultFgIntensity | defaultBgIntensity, "0"},
+		{"all reset", defaultFgColor | defaultBgColor | defaultFgIntensity | defaultBgIntensity, ""},
+	}
+
+	boldParam := []testParam{
+		{"bold on", uint16(0x0007 | 0x0008), "1"},
+		{"bold off", uint16(0x0007), "21"},
+	}
+
+	underscoreParam := []testParam{
+		{"underscore on", uint16(0x0007 | 0x8000), "4"},
+		{"underscore off", uint16(0x0007), "24"},
+	}
+
+	blinkParam := []testParam{
+		{"blink on", uint16(0x0007 | 0x0080), "5"},
+		{"blink off", uint16(0x0007), "25"},
+	}
+
+	mixedParam := []testParam{
+		{"both black,   bold, underline, blink", uint16(0x0000 | 0x0000 | 0x0008 | 0x8000 | 0x0080), "30;40;1;4;5"},
+		{"both red,     bold, underline, blink", uint16(0x0004 | 0x0040 | 0x0008 | 0x8000 | 0x0080), "31;41;1;4;5"},
+		{"both green,   bold, underline, blink", uint16(0x0002 | 0x0020 | 0x0008 | 0x8000 | 0x0080), "32;42;1;4;5"},
+		{"both yellow,  bold, underline, blink", uint16(0x0006 | 0x0060 | 0x0008 | 0x8000 | 0x0080), "33;43;1;4;5"},
+		{"both blue,    bold, underline, blink", uint16(0x0001 | 0x0010 | 0x0008 | 0x8000 | 0x0080), "34;44;1;4;5"},
+		{"both magenta, bold, underline, blink", uint16(0x0005 | 0x0050 | 0x0008 | 0x8000 | 0x0080), "35;45;1;4;5"},
+		{"both cyan,    bold, underline, blink", uint16(0x0003 | 0x0030 | 0x0008 | 0x8000 | 0x0080), "36;46;1;4;5"},
+		{"both white,   bold, underline, blink", uint16(0x0007 | 0x0070 | 0x0008 | 0x8000 | 0x0080), "37;47;1;4;5"},
+		{"both default, bold, underline, blink", uint16(defaultFgColor | defaultBgColor | 0x0008 | 0x8000 | 0x0080), "39;49;1;4;5"},
+	}
+
+	assertTextAttribute := func(expectedText string, expectedAttributes uint16, ansiColor string) {
+		actualText, actualAttributes, err := writeAnsiColor(expectedText, ansiColor)
+		if actualText != expectedText {
+			t.Errorf("Get %s, want %s", actualText, expectedText)
+		}
+		if err != nil {
+			t.Fatal("Could not get ConsoleScreenBufferInfo")
+		}
+		if actualAttributes != expectedAttributes {
+			t.Errorf("Text: %s, Get 0x%04x, want 0x%04x", expectedText, actualAttributes, expectedAttributes)
+		}
+	}
+
+	for _, v := range fgParam {
+		ResetColor()
+		assertTextAttribute(v.text, v.attributes, v.ansiColor)
+	}
+
+	for _, v := range bgParam {
+		ChangeColor(uint16(0x0070 | 0x0007))
+		assertTextAttribute(v.text, v.attributes, v.ansiColor)
+	}
+
+	for _, v := range resetParam {
+		ChangeColor(uint16(0x0000 | 0x0070 | 0x0008))
+		assertTextAttribute(v.text, v.attributes, v.ansiColor)
+	}
+
+	ResetColor()
+	for _, v := range boldParam {
+		assertTextAttribute(v.text, v.attributes, v.ansiColor)
+	}
+
+	ResetColor()
+	for _, v := range underscoreParam {
+		assertTextAttribute(v.text, v.attributes, v.ansiColor)
+	}
+
+	ResetColor()
+	for _, v := range blinkParam {
+		assertTextAttribute(v.text, v.attributes, v.ansiColor)
+	}
+
+	for _, v := range mixedParam {
+		ResetColor()
+		assertTextAttribute(v.text, v.attributes, v.ansiColor)
+	}
+}

+ 24 - 0
Godeps/_workspace/src/github.com/shiena/ansicolor/example_test.go

@@ -0,0 +1,24 @@
+// Copyright 2014 shiena Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package ansicolor_test
+
+import (
+	"fmt"
+	"os"
+
+	"github.com/shiena/ansicolor"
+)
+
+func ExampleNewAnsiColorWriter() {
+	w := ansicolor.NewAnsiColorWriter(os.Stdout)
+	text := "%sforeground %sbold%s %sbackground%s\n"
+	fmt.Fprintf(w, text, "\x1b[31m", "\x1b[1m", "\x1b[21m", "\x1b[41;32m", "\x1b[0m")
+	fmt.Fprintf(w, text, "\x1b[32m", "\x1b[1m", "\x1b[21m", "\x1b[42;31m", "\x1b[0m")
+	fmt.Fprintf(w, text, "\x1b[33m", "\x1b[1m", "\x1b[21m", "\x1b[43;34m", "\x1b[0m")
+	fmt.Fprintf(w, text, "\x1b[34m", "\x1b[1m", "\x1b[21m", "\x1b[44;33m", "\x1b[0m")
+	fmt.Fprintf(w, text, "\x1b[35m", "\x1b[1m", "\x1b[21m", "\x1b[45;36m", "\x1b[0m")
+	fmt.Fprintf(w, text, "\x1b[36m", "\x1b[1m", "\x1b[21m", "\x1b[46;35m", "\x1b[0m")
+	fmt.Fprintf(w, text, "\x1b[37m", "\x1b[1m", "\x1b[21m", "\x1b[47;30m", "\x1b[0m")
+}

+ 19 - 0
Godeps/_workspace/src/github.com/shiena/ansicolor/export_test.go

@@ -0,0 +1,19 @@
+// Copyright 2014 shiena Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+// +build windows
+
+package ansicolor
+
+import "syscall"
+
+var GetConsoleScreenBufferInfo = getConsoleScreenBufferInfo
+
+func ChangeColor(color uint16) {
+	setConsoleTextAttribute(uintptr(syscall.Stdout), color)
+}
+
+func ResetColor() {
+	ChangeColor(uint16(0x0007))
+}

+ 15 - 24
cmd/geth/js.go

@@ -252,22 +252,22 @@ func (self *jsre) batch(statement string) {
 
 // show summary of current geth instance
 func (self *jsre) welcome() {
-	self.re.Eval(`console.log('instance: ' + web3.version.client);`)
-	self.re.Eval(`console.log(' datadir: ' + admin.datadir);`)
-	self.re.Eval(`console.log("coinbase: " + eth.coinbase);`)
-	self.re.Eval(`var lastBlockTimestamp = 1000 * eth.getBlock(eth.blockNumber).timestamp`)
-	self.re.Eval(`console.log("at block: " + eth.blockNumber + " (" + new Date(lastBlockTimestamp).toLocaleDateString()
-		+ " " + new Date(lastBlockTimestamp).toLocaleTimeString() + ")");`)
-
+	self.re.Run(`
+		(function () {
+			console.log('instance: ' + web3.version.client);
+			console.log(' datadir: ' + admin.datadir);
+			console.log("coinbase: " + eth.coinbase);
+			var ts = 1000 * eth.getBlock(eth.blockNumber).timestamp;
+			console.log("at block: " + eth.blockNumber + " (" + new Date(ts) + ")");
+		})();
+	`)
 	if modules, err := self.supportedApis(); err == nil {
 		loadedModules := make([]string, 0)
 		for api, version := range modules {
 			loadedModules = append(loadedModules, fmt.Sprintf("%s:%s", api, version))
 		}
 		sort.Strings(loadedModules)
-
-		self.re.Eval(fmt.Sprintf("var modules = '%s';", strings.Join(loadedModules, " ")))
-		self.re.Eval(`console.log(" modules: " + modules);`)
+		fmt.Println("modules:", strings.Join(loadedModules, " "))
 	}
 }
 
@@ -309,12 +309,12 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
 		utils.Fatalf("Error loading web3.js: %v", err)
 	}
 
-	_, err = js.re.Eval("var web3 = require('web3');")
+	_, err = js.re.Run("var web3 = require('web3');")
 	if err != nil {
 		utils.Fatalf("Error requiring web3: %v", err)
 	}
 
-	_, err = js.re.Eval("web3.setProvider(jeth)")
+	_, err = js.re.Run("web3.setProvider(jeth)")
 	if err != nil {
 		utils.Fatalf("Error setting web3 provider: %v", err)
 	}
@@ -333,13 +333,13 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
 		}
 	}
 
-	_, err = js.re.Eval(shortcuts)
+	_, err = js.re.Run(shortcuts)
 
 	if err != nil {
 		utils.Fatalf("Error setting namespaces: %v", err)
 	}
 
-	js.re.Eval(`var GlobalRegistrar = eth.contract(` + registrar.GlobalRegistrarAbi + `);	 registrar = GlobalRegistrar.at("` + registrar.GlobalRegistrarAddr + `");`)
+	js.re.Run(`var GlobalRegistrar = eth.contract(` + registrar.GlobalRegistrarAbi + `);	 registrar = GlobalRegistrar.at("` + registrar.GlobalRegistrarAddr + `");`)
 	return nil
 }
 
@@ -458,8 +458,7 @@ func (self *jsre) parseInput(code string) {
 			fmt.Println("[native] error", r)
 		}
 	}()
-	value, err := self.re.Run(code)
-	if err != nil {
+	if err := self.re.EvalAndPrettyPrint(code); err != nil {
 		if ottoErr, ok := err.(*otto.Error); ok {
 			fmt.Println(ottoErr.String())
 		} else {
@@ -467,7 +466,6 @@ func (self *jsre) parseInput(code string) {
 		}
 		return
 	}
-	self.printValue(value)
 }
 
 var indentCount = 0
@@ -486,10 +484,3 @@ func (self *jsre) setIndent() {
 		self.ps1 += " "
 	}
 }
-
-func (self *jsre) printValue(v interface{}) {
-	val, err := self.re.PrettyPrint(v)
-	if err == nil {
-		fmt.Printf("%v", val)
-	}
-}

+ 0 - 19
cmd/geth/main.go

@@ -19,7 +19,6 @@ package main
 
 import (
 	"fmt"
-	"io"
 	"io/ioutil"
 	_ "net/http/pprof"
 	"os"
@@ -46,8 +45,6 @@ import (
 	"github.com/ethereum/go-ethereum/rlp"
 	"github.com/ethereum/go-ethereum/rpc/codec"
 	"github.com/ethereum/go-ethereum/rpc/comms"
-	"github.com/mattn/go-colorable"
-	"github.com/mattn/go-isatty"
 )
 
 const (
@@ -398,14 +395,6 @@ func run(ctx *cli.Context) {
 func attach(ctx *cli.Context) {
 	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
 
-	// Wrap the standard output with a colorified stream (windows)
-	if isatty.IsTerminal(os.Stdout.Fd()) {
-		if pr, pw, err := os.Pipe(); err == nil {
-			go io.Copy(colorable.NewColorableStdout(), pr)
-			os.Stdout = pw
-		}
-	}
-
 	var client comms.EthereumClient
 	var err error
 	if ctx.Args().Present() {
@@ -438,14 +427,6 @@ func attach(ctx *cli.Context) {
 func console(ctx *cli.Context) {
 	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
 
-	// Wrap the standard output with a colorified stream (windows)
-	if isatty.IsTerminal(os.Stdout.Fd()) {
-		if pr, pw, err := os.Pipe(); err == nil {
-			go io.Copy(colorable.NewColorableStdout(), pr)
-			os.Stdout = pw
-		}
-	}
-
 	cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
 	ethereum, err := eth.New(cfg)
 	if err != nil {

+ 8 - 25
jsre/jsre.go

@@ -65,7 +65,6 @@ func New(assetPath string) *JSRE {
 	}
 	re.loopWg.Add(1)
 	go re.runEventLoop()
-	re.Compile("pp.js", pp_js) // load prettyprint func definition
 	re.Set("loadScript", re.loadScript)
 	return re
 }
@@ -255,35 +254,19 @@ func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value {
 	return otto.TrueValue()
 }
 
-// PrettyPrint writes v to standard output.
-func (self *JSRE) PrettyPrint(v interface{}) (val otto.Value, err error) {
-	var method otto.Value
+// EvalAndPrettyPrint evaluates code and pretty prints the result to
+// standard output.
+func (self *JSRE) EvalAndPrettyPrint(code string) (err error) {
 	self.do(func(vm *otto.Otto) {
-		val, err = vm.ToValue(v)
+		var val otto.Value
+		val, err = vm.Run(code)
 		if err != nil {
 			return
 		}
-		method, err = vm.Get("prettyPrint")
-		if err != nil {
-			return
-		}
-		val, err = method.Call(method, val)
+		prettyPrint(vm, val)
+		fmt.Println()
 	})
-	return val, err
-}
-
-// Eval evaluates JS function and returns result in a pretty printed string format.
-func (self *JSRE) Eval(code string) (s string, err error) {
-	var val otto.Value
-	val, err = self.Run(code)
-	if err != nil {
-		return
-	}
-	val, err = self.PrettyPrint(val)
-	if err != nil {
-		return
-	}
-	return fmt.Sprintf("%v", val), nil
+	return err
 }
 
 // Compile compiles and then runs a piece of JS code.

+ 3 - 8
jsre/jsre_test.go

@@ -103,19 +103,14 @@ func TestNatto(t *testing.T) {
 
 func TestBind(t *testing.T) {
 	jsre := New("")
+	defer jsre.Stop(false)
 
 	jsre.Bind("no", &testNativeObjectBinding{})
 
-	val, err := jsre.Run(`no.TestMethod("testMsg")`)
+	_, err := jsre.Run(`no.TestMethod("testMsg")`)
 	if err != nil {
 		t.Errorf("expected no error, got %v", err)
 	}
-	pp, err := jsre.PrettyPrint(val)
-	if err != nil {
-		t.Errorf("expected no error, got %v", err)
-	}
-	t.Logf("no: %v", pp)
-	jsre.Stop(false)
 }
 
 func TestLoadScript(t *testing.T) {
@@ -139,4 +134,4 @@ func TestLoadScript(t *testing.T) {
 		t.Errorf("expected '%v', got '%v'", exp, got)
 	}
 	jsre.Stop(false)
-}
+}

+ 0 - 137
jsre/pp_js.go

@@ -1,137 +0,0 @@
-// Copyright 2014 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-package jsre
-
-const pp_js = `
-function pp(object, indent) {
-    try {
-        JSON.stringify(object)
-    } catch(e) {
-        return pp(e, indent);
-    }
-
-    var str = "";
-    if(object instanceof Array) {
-        str += "[";
-        for(var i = 0, l = object.length; i < l; i++) {
-            str += pp(object[i], indent);
-
-            if(i < l-1) {
-                str += ", ";
-            }
-        }
-        str += " ]";
-    } else if (object instanceof Error) {
-        str += "\033[31m" + "Error:\033[0m " + object.message;
-    } else if (isBigNumber(object)) {
-        str += "\033[32m'" + object.toString(10) + "'";
-    } else if(typeof(object) === "object") {
-        str += "{\n";
-        indent += "  ";
-
-        var fields = getFields(object);
-        var last   = fields[fields.length - 1];
-        fields.forEach(function (key) {
-            str += indent + key + ": ";
-            try {
-                str += pp(object[key], indent);
-            } catch (e) {
-                str += pp(e, indent);
-            }
-            if(key !== last) {
-                str += ",";
-            }
-            str += "\n";
-        });
-        str += indent.substr(2, indent.length) + "}";
-    } else if(typeof(object) === "string") {
-        str += "\033[32m'" + object + "'";
-    } else if(typeof(object) === "undefined") {
-        str += "\033[1m\033[30m" + object;
-    } else if(typeof(object) === "number") {
-        str += "\033[31m" + object;
-    } else if(typeof(object) === "function") {
-        str += "\033[35m" + object.toString().split(" {")[0];
-    } else {
-        str += object;
-    }
-
-    str += "\033[0m";
-
-    return str;
-}
-
-var redundantFields = [
-    'valueOf',
-    'toString',
-    'toLocaleString',
-    'hasOwnProperty',
-    'isPrototypeOf',
-    'propertyIsEnumerable',
-    'constructor'
-];
-
-var getFields = function (object) {
-    var members = Object.getOwnPropertyNames(object);
-    if (object.constructor && object.constructor.prototype) {
-        members = members.concat(Object.getOwnPropertyNames(object.constructor.prototype));
-    }
-
-    var fields = members.filter(function (member) {
-        return !isMemberFunction(object, member)
-    }).sort()
-    var funcs = members.filter(function (member) {
-        return isMemberFunction(object, member)
-    }).sort()
-
-    var results = fields.concat(funcs);
-    return results.filter(function (field) {
-        return redundantFields.indexOf(field) === -1;
-    });
-};
-
-var isMemberFunction = function(object, member) {
-    try {
-        return typeof(object[member]) === "function";
-    } catch(e) {
-        return false;
-    }
-}
-
-var isBigNumber = function (object) {
-    var result = typeof BigNumber !== 'undefined' && object instanceof BigNumber;
-
-    if (!result) {
-    	if (typeof(object) === "object" && object.constructor != null) {
-			result = object.constructor.toString().indexOf("function BigNumber(") == 0;
-		}
-    }
-
-    return result
-};
-
-function prettyPrint(/* */) {
-    var args = arguments;
-    var ret = "";
-    for(var i = 0, l = args.length; i < l; i++) {
-	    ret += pp(args[i], "") + "\n";
-    }
-    return ret;
-}
-
-var print = prettyPrint;
-`

+ 220 - 0
jsre/pretty.go

@@ -0,0 +1,220 @@
+// Copyright 2015 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package jsre
+
+import (
+	"fmt"
+	"sort"
+	"strconv"
+	"strings"
+
+	"github.com/fatih/color"
+	"github.com/robertkrimen/otto"
+)
+
+const (
+	maxPrettyPrintLevel = 3
+	indentString        = "  "
+)
+
+var (
+	functionColor = color.New(color.FgMagenta)
+	specialColor  = color.New(color.Bold)
+	numberColor   = color.New(color.FgRed)
+	stringColor   = color.New(color.FgGreen)
+)
+
+// these fields are hidden when printing objects.
+var boringKeys = map[string]bool{
+	"valueOf":              true,
+	"toString":             true,
+	"toLocaleString":       true,
+	"hasOwnProperty":       true,
+	"isPrototypeOf":        true,
+	"propertyIsEnumerable": true,
+	"constructor":          true,
+}
+
+// prettyPrint writes value to standard output.
+func prettyPrint(vm *otto.Otto, value otto.Value) {
+	ppctx{vm}.printValue(value, 0)
+}
+
+type ppctx struct{ vm *otto.Otto }
+
+func (ctx ppctx) indent(level int) string {
+	return strings.Repeat(indentString, level)
+}
+
+func (ctx ppctx) printValue(v otto.Value, level int) {
+	switch {
+	case v.IsObject():
+		ctx.printObject(v.Object(), level)
+	case v.IsNull():
+		specialColor.Print("null")
+	case v.IsUndefined():
+		specialColor.Print("undefined")
+	case v.IsString():
+		s, _ := v.ToString()
+		stringColor.Printf("%q", s)
+	case v.IsBoolean():
+		b, _ := v.ToBoolean()
+		specialColor.Printf("%t", b)
+	case v.IsNaN():
+		numberColor.Printf("NaN")
+	case v.IsNumber():
+		s, _ := v.ToString()
+		numberColor.Printf("%s", s)
+	default:
+		fmt.Printf("<unprintable>")
+	}
+}
+
+func (ctx ppctx) printObject(obj *otto.Object, level int) {
+	switch obj.Class() {
+	case "Array":
+		lv, _ := obj.Get("length")
+		len, _ := lv.ToInteger()
+		if len == 0 {
+			fmt.Printf("[]")
+			return
+		}
+		if level > maxPrettyPrintLevel {
+			fmt.Print("[...]")
+			return
+		}
+		fmt.Print("[")
+		for i := int64(0); i < len; i++ {
+			el, err := obj.Get(strconv.FormatInt(i, 10))
+			if err == nil {
+				ctx.printValue(el, level+1)
+			}
+			if i < len-1 {
+				fmt.Printf(", ")
+			}
+		}
+		fmt.Print("]")
+
+	case "Object":
+		// Print values from bignumber.js as regular numbers.
+		if ctx.isBigNumber(obj) {
+			numberColor.Print(toString(obj))
+			return
+		}
+		// Otherwise, print all fields indented, but stop if we're too deep.
+		keys := ctx.fields(obj)
+		if len(keys) == 0 {
+			fmt.Print("{}")
+			return
+		}
+		if level > maxPrettyPrintLevel {
+			fmt.Print("{...}")
+			return
+		}
+		fmt.Println("{")
+		for i, k := range keys {
+			v, _ := obj.Get(k)
+			fmt.Printf("%s%s: ", ctx.indent(level+1), k)
+			ctx.printValue(v, level+1)
+			if i < len(keys)-1 {
+				fmt.Printf(",")
+			}
+			fmt.Println()
+		}
+		fmt.Printf("%s}", ctx.indent(level))
+
+	case "Function":
+		// Use toString() to display the argument list if possible.
+		if robj, err := obj.Call("toString"); err != nil {
+			functionColor.Print("function()")
+		} else {
+			desc := strings.Trim(strings.Split(robj.String(), "{")[0], " \t\n")
+			desc = strings.Replace(desc, " (", "(", 1)
+			functionColor.Print(desc)
+		}
+
+	case "RegExp":
+		stringColor.Print(toString(obj))
+
+	default:
+		if v, _ := obj.Get("toString"); v.IsFunction() && level <= maxPrettyPrintLevel {
+			s, _ := obj.Call("toString")
+			fmt.Printf("<%s %s>", obj.Class(), s.String())
+		} else {
+			fmt.Printf("<%s>", obj.Class())
+		}
+	}
+}
+
+func (ctx ppctx) fields(obj *otto.Object) []string {
+	var (
+		vals, methods []string
+		seen          = make(map[string]bool)
+	)
+	add := func(k string) {
+		if seen[k] || boringKeys[k] {
+			return
+		}
+		seen[k] = true
+		if v, _ := obj.Get(k); v.IsFunction() {
+			methods = append(methods, k)
+		} else {
+			vals = append(vals, k)
+		}
+	}
+	// add own properties
+	ctx.doOwnProperties(obj.Value(), add)
+	// add properties of the constructor
+	if cp := constructorPrototype(obj); cp != nil {
+		ctx.doOwnProperties(cp.Value(), add)
+	}
+	sort.Strings(vals)
+	sort.Strings(methods)
+	return append(vals, methods...)
+}
+
+func (ctx ppctx) doOwnProperties(v otto.Value, f func(string)) {
+	Object, _ := ctx.vm.Object("Object")
+	rv, _ := Object.Call("getOwnPropertyNames", v)
+	gv, _ := rv.Export()
+	for _, v := range gv.([]interface{}) {
+		f(v.(string))
+	}
+}
+
+func (ctx ppctx) isBigNumber(v *otto.Object) bool {
+	BigNumber, err := ctx.vm.Run("BigNumber.prototype")
+	if err != nil {
+		panic(err)
+	}
+	cp := constructorPrototype(v)
+	return cp != nil && cp.Value() == BigNumber
+}
+
+func toString(obj *otto.Object) string {
+	s, _ := obj.Call("toString")
+	return s.String()
+}
+
+func constructorPrototype(obj *otto.Object) *otto.Object {
+	if v, _ := obj.Get("constructor"); v.Object() != nil {
+		if v, _ = v.Object().Get("prototype"); v.Object() != nil {
+			return v.Object()
+		}
+	}
+	return nil
+}