Set different default display style for different commands (#101)

* set default display and add command association
diff --git a/cmd/swctl/main.go b/cmd/swctl/main.go
index d430416..0a51e6d 100644
--- a/cmd/swctl/main.go
+++ b/cmd/swctl/main.go
@@ -106,7 +106,7 @@
 			Name:     "display",
 			Required: false,
 			Usage:    "display `style` of the result, supported styles are: json, yaml, table, graph",
-			Value:    "json",
+			Value:    "",
 		}),
 	}
 
@@ -129,6 +129,7 @@
 	})
 
 	app.Flags = flags
+	app.CommandNotFound = util.CommandNotFound
 
 	if err := app.Run(os.Args); err != nil {
 		log.Fatalln(err)
diff --git a/pkg/display/display.go b/pkg/display/display.go
index 9dd17b8..455cfb9 100644
--- a/pkg/display/display.go
+++ b/pkg/display/display.go
@@ -19,6 +19,7 @@
 
 import (
 	"fmt"
+
 	"strings"
 
 	d "github.com/apache/skywalking-cli/pkg/display/displayable"
@@ -39,10 +40,30 @@
 	GRAPH = "graph"
 )
 
+// The variable style sets the output style for the command.
+var style = map[string]string{"dashboard global": "graph",
+	"dashboard global-metrics": "graph",
+	"metrics top":              "table",
+	"metrics linear":           "graph",
+	"metrics list":             "table",
+	"service list":             "table",
+	"t":                        "graph",
+	"trace":                    "graph"}
+
 // Display the object in the style specified in flag --display
 func Display(ctx *cli.Context, displayable *d.Displayable) error {
 	displayStyle := ctx.GlobalString("display")
-
+	if displayStyle == "" {
+		commandFullName := ctx.Command.FullName()
+		if commandFullName != "" {
+			displayStyle = getDisplayStyle(commandFullName)
+		} else if ctx.Parent() != nil {
+			displayStyle = getDisplayStyle(ctx.Parent().Args()[0])
+		}
+	}
+	if displayStyle == "" {
+		displayStyle = "json"
+	}
 	switch strings.ToLower(displayStyle) {
 	case JSON:
 		return json.Display(displayable)
@@ -56,3 +77,11 @@
 		return fmt.Errorf("unsupported display style: %s", displayStyle)
 	}
 }
+
+// getDisplayStyle gets the default display settings.
+func getDisplayStyle(fullName string) string {
+	if command, ok := style[fullName]; ok {
+		return command
+	}
+	return ""
+}
diff --git a/pkg/util/commandNotFound.go b/pkg/util/commandNotFound.go
new file mode 100644
index 0000000..b310cdb
--- /dev/null
+++ b/pkg/util/commandNotFound.go
@@ -0,0 +1,94 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package util
+
+import (
+	"fmt"
+
+	"github.com/urfave/cli"
+)
+
+const GAP = 3 // Control the appropriate edit distance.
+
+// CommandNotFound is executed when the command entered does not exist.
+func CommandNotFound(c *cli.Context, s string) {
+	suppose := make([]string, 0)
+	var parentCommand string
+	if c.Parent() == nil {
+		parentCommand = "swctl"
+	} else {
+		parentCommand = c.Parent().Args()[0]
+	}
+	fmt.Printf("Error: unknown command \"%s\" for \"%s\" \n\n", s, parentCommand)
+	// Record commands whose edit distance is less than GAP to suppose.
+	for index := range c.App.Commands {
+		commandName := c.App.Commands[index].Name
+		distance := minEditDistance(commandName, s)
+		if distance <= GAP && commandName != "help" {
+			suppose = append(suppose, commandName)
+		}
+	}
+	if len(suppose) != 0 {
+		fmt.Println("Do you mean this?")
+		for index := range suppose {
+			fmt.Printf("\t%s\n", suppose[index])
+		}
+		fmt.Println()
+	}
+	if c.Parent() == nil {
+		fmt.Printf("Run '%s --help' for usage.\n", parentCommand)
+	} else {
+		fmt.Printf("Run 'swctl %s --help' for usage.\n", parentCommand)
+	}
+}
+
+// minEditDistance calculates the edit distance of two strings.
+func minEditDistance(word1, word2 string) int {
+	m, n := len(word1), len(word2)
+	dp := make([][]int, m+1)
+	for i := range dp {
+		dp[i] = make([]int, n+1)
+	}
+	for i := 0; i < m+1; i++ {
+		dp[i][0] = i
+	}
+	for j := 0; j < n+1; j++ {
+		dp[0][j] = j
+	}
+	for i := 1; i < m+1; i++ {
+		for j := 1; j < n+1; j++ {
+			if word1[i-1] == word2[j-1] {
+				dp[i][j] = dp[i-1][j-1]
+			} else {
+				dp[i][j] = min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]) + 1
+			}
+		}
+	}
+	return dp[m][n]
+}
+
+// min get The minimum of the args.
+func min(args ...int) int {
+	min := args[0]
+	for _, item := range args {
+		if item < min {
+			min = item
+		}
+	}
+	return min
+}
diff --git a/pkg/util/commandNotFound_test.go b/pkg/util/commandNotFound_test.go
new file mode 100644
index 0000000..8f23df8
--- /dev/null
+++ b/pkg/util/commandNotFound_test.go
@@ -0,0 +1,57 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package util
+
+import "testing"
+
+func Test_minEditDistance(t *testing.T) {
+	type args struct {
+		word1 string
+		word2 string
+	}
+	tests := []struct {
+		name string
+		args args
+		want int
+	}{
+		{
+			name: "empty strings",
+			args: args{"", ""},
+			want: 0,
+		}, {
+			name: "one empty string",
+			args: args{"", "dashboard"},
+			want: 9,
+		}, {
+			name: "equal length",
+			args: args{"service", "service"},
+			want: 0,
+		}, {
+			name: "unequal length",
+			args: args{"even", "event"},
+			want: 1,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := minEditDistance(tt.args.word1, tt.args.word2); got != tt.want {
+				t.Errorf("minDistance() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}