Browse Source

console, internal/jsre: colorize JavaScript exceptions too

Péter Szilágyi 9 years ago
parent
commit
14ae5708d6
4 changed files with 37 additions and 12 deletions
  1. 5 10
      console/console.go
  2. 12 0
      console/console_test.go
  3. 2 2
      internal/jsre/jsre.go
  4. 18 0
      internal/jsre/pretty.go

+ 5 - 10
console/console.go

@@ -182,7 +182,11 @@ func (c *Console) init(preload []string) error {
 	// Preload any JavaScript files before starting the console
 	for _, path := range preload {
 		if err := c.jsre.Exec(path); err != nil {
-			return fmt.Errorf("%s: %v", path, jsErrorString(err))
+			failure := err.Error()
+			if ottoErr, ok := err.(*otto.Error); ok {
+				failure = ottoErr.String()
+			}
+			return fmt.Errorf("%s: %v", path, failure)
 		}
 	}
 	// Configure the console's input prompter for scrollback and tab completion
@@ -269,7 +273,6 @@ func (c *Console) Evaluate(statement string) error {
 		}
 	}()
 	if err := c.jsre.Evaluate(statement, c.printer); err != nil {
-		fmt.Fprintf(c.printer, "%v\n", jsErrorString(err))
 		return err
 	}
 	return nil
@@ -359,11 +362,3 @@ func (c *Console) Stop(graceful bool) error {
 	c.jsre.Stop(graceful)
 	return nil
 }
-
-// jsErrorString adds a backtrace to errors generated by otto.
-func jsErrorString(err error) string {
-	if ottoErr, ok := err.(*otto.Error); ok {
-		return ottoErr.String()
-	}
-	return err.Error()
-}

+ 12 - 0
console/console_test.go

@@ -281,3 +281,15 @@ func TestPrettyPrint(t *testing.T) {
 		t.Fatalf("pretty print mismatch: have %s, want %s", output, want)
 	}
 }
+
+// Tests that the JavaScript exceptions are properly formatted and colored.
+func TestPrettyError(t *testing.T) {
+	tester := newTester(t, nil)
+	defer tester.Close(t)
+	tester.console.Evaluate("throw 'hello'")
+
+	want := jsre.ErrorColor("hello") + "\n"
+	if output := string(tester.output.Bytes()); output != want {
+		t.Fatalf("pretty error mismatch: have %s, want %s", output, want)
+	}
+}

+ 2 - 2
internal/jsre/jsre.go

@@ -303,11 +303,11 @@ func (self *JSRE) Evaluate(code string, w io.Writer) error {
 	self.Do(func(vm *otto.Otto) {
 		val, err := vm.Run(code)
 		if err != nil {
-			fail = err
+			prettyError(vm, err, w)
 		} else {
 			prettyPrint(vm, val, w)
-			fmt.Fprintln(w)
 		}
+		fmt.Fprintln(w)
 	})
 	return fail
 }

+ 18 - 0
internal/jsre/pretty.go

@@ -37,6 +37,7 @@ var (
 	SpecialColor  = color.New(color.Bold).SprintfFunc()
 	NumberColor   = color.New(color.FgRed).SprintfFunc()
 	StringColor   = color.New(color.FgGreen).SprintfFunc()
+	ErrorColor    = color.New(color.FgHiRed).SprintfFunc()
 )
 
 // these fields are hidden when printing objects.
@@ -55,6 +56,23 @@ func prettyPrint(vm *otto.Otto, value otto.Value, w io.Writer) {
 	ppctx{vm: vm, w: w}.printValue(value, 0, false)
 }
 
+// prettyError writes err to standard output.
+func prettyError(vm *otto.Otto, err error, w io.Writer) {
+	failure := err.Error()
+	if ottoErr, ok := err.(*otto.Error); ok {
+		failure = ottoErr.String()
+	}
+	fmt.Fprint(w, ErrorColor("%s", failure))
+}
+
+// jsErrorString adds a backtrace to errors generated by otto.
+func jsErrorString(err error) string {
+	if ottoErr, ok := err.(*otto.Error); ok {
+		return ottoErr.String()
+	}
+	return err.Error()
+}
+
 func prettyPrintJS(call otto.FunctionCall, w io.Writer) otto.Value {
 	for _, v := range call.ArgumentList {
 		prettyPrint(call.Otto, v, w)