glide list: support json output format
diff --git a/action/list.go b/action/list.go
index a2d35c7..0e5158f 100644
--- a/action/list.go
+++ b/action/list.go
@@ -13,8 +13,7 @@
 // Params:
 //  - dir (string): basedir
 //  - deep (bool): whether to do a deep scan or a shallow scan
-func List(basedir string, deep bool) {
-
+func List(basedir string, deep bool) PackageList {
 	basedir, err := filepath.Abs(basedir)
 	if err != nil {
 		msg.Die("Could not read directory: %s", err)
@@ -27,34 +26,29 @@
 	h := &dependency.DefaultMissingPackageHandler{Missing: []string{}, Gopath: []string{}}
 	r.Handler = h
 
-	sortable, err := r.ResolveLocal(deep)
+	localPkgs, err := r.ResolveLocal(deep)
 	if err != nil {
 		msg.Die("Error listing dependencies: %s", err)
 	}
-
-	msg.Info("Sorting...")
-	sort.Strings(sortable)
-
-	msg.Puts("INSTALLED packages:")
-	for _, k := range sortable {
-		v, err := filepath.Rel(basedir, k)
+	sort.Strings(localPkgs)
+	installed := make([]string, len(localPkgs))
+	for i, pkg := range localPkgs {
+		relPkg, err := filepath.Rel(basedir, pkg)
 		if err != nil {
-			//msg.Warn("Failed to Rel path: %s", err)
-			v = k
+			// msg.Warn("Failed to Rel path: %s", err)
+			relPkg = pkg
 		}
-		msg.Puts("\t%s", v)
+		installed[i] = relPkg
 	}
+	return PackageList{
+		Installed: installed,
+		Missing:   h.Missing,
+		Gopath:    h.Gopath,
+	}
+}
 
-	if len(h.Missing) > 0 {
-		msg.Puts("\nMISSING packages:")
-		for _, pkg := range h.Missing {
-			msg.Puts("\t%s", pkg)
-		}
-	}
-	if len(h.Gopath) > 0 {
-		msg.Puts("\nGOPATH packages:")
-		for _, pkg := range h.Gopath {
-			msg.Puts("\t%s", pkg)
-		}
-	}
+type PackageList struct {
+	Installed []string `json:"installed"`
+	Missing   []string `json:"missing"`
+	Gopath    []string `json:"gopath"`
 }
diff --git a/action/list_test.go b/action/list_test.go
index 6792210..1f2aed5 100644
--- a/action/list_test.go
+++ b/action/list_test.go
@@ -1,21 +1,9 @@
 package action
 
-import (
-	"bytes"
-	"testing"
-
-	"github.com/Masterminds/glide/msg"
-)
+import "testing"
 
 func TestList(t *testing.T) {
-	var buf bytes.Buffer
-	old := msg.Default.Stdout
-	msg.Default.PanicOnDie = true
-	msg.Default.Stdout = &buf
-	List("../", false)
-	if buf.Len() < 5 {
-		t.Error("Expected some data to be found.")
+	if len(List("../", false).Installed) < 1 {
+		t.Error("Expected some packages to be found")
 	}
-	// TODO: We should capture and test output.
-	msg.Default.Stdout = old
 }
diff --git a/glide.go b/glide.go
index d00dee4..566a86f 100644
--- a/glide.go
+++ b/glide.go
@@ -37,6 +37,7 @@
 package main
 
 import (
+	"encoding/json"
 	"path/filepath"
 
 	"github.com/Masterminds/glide/action"
@@ -587,7 +588,16 @@
 			vendor are only included if they are used by the project.
 			`,
 			Action: func(c *cli.Context) {
-				action.List(".", true)
+				outputFormat := c.String("output")
+				pkgList := action.List(".", true)
+				outputList(pkgList, outputFormat)
+			},
+			Flags: []cli.Flag{
+				cli.StringFlag{
+					Name:  "output, o",
+					Usage: "Output format. One of: json|json-pretty|text",
+					Value: "text",
+				},
 			},
 		},
 		{
@@ -639,3 +649,42 @@
 	}
 	return a
 }
+
+const (
+	textFormat       = "text"
+	jsonFormat       = "json"
+	jsonPrettyFormat = "json-pretty"
+)
+
+func outputList(l action.PackageList, format string) {
+	switch format {
+	case textFormat:
+		msg.Puts("INSTALLED packages:")
+		for _, pkg := range l.Installed {
+			msg.Puts("\t%s", pkg)
+		}
+
+		if len(l.Missing) > 0 {
+			msg.Puts("\nMISSING packages:")
+			for _, pkg := range l.Missing {
+				msg.Puts("\t%s", pkg)
+			}
+		}
+		if len(l.Gopath) > 0 {
+			msg.Puts("\nGOPATH packages:")
+			for _, pkg := range l.Gopath {
+				msg.Puts("\t%s", pkg)
+			}
+		}
+	case jsonFormat:
+		json.NewEncoder(os.Stdout).Encode(l)
+	case jsonPrettyFormat:
+		b, err := json.MarshalIndent(l, "", "  ")
+		if err != nil {
+			msg.Die("could not unmarshal package list: %s", err)
+		}
+		fmt.Println(string(b))
+	default:
+		msg.Die("invalid output format: must be one of: json|json-pretty|text")
+	}
+}