-
Notifications
You must be signed in to change notification settings - Fork 57
/
commandsuggest.go
77 lines (66 loc) · 1.53 KB
/
commandsuggest.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package main
import (
"fmt"
"strings"
"unicode/utf8"
"github.com/rackspace/rack/internal/github.com/codegangsta/cli"
)
func commandNotFound(c *cli.Context, command string) {
app := c.App
var choices []string
for _, cmd := range app.Commands {
choices = append(choices, cmd.Name)
}
//choices := globalOptionsNames(app)
currentMin := 50
bestSuggestion := ""
for _, choice := range choices {
similarity := levenshtein(choice, command)
tmpMin := min(currentMin, similarity)
if tmpMin < currentMin {
bestSuggestion = choice
currentMin = tmpMin
}
}
suggestion := []string{fmt.Sprintf("Unrecognized command: %s", command),
"",
"Did you mean this?",
fmt.Sprintf("\t%s\n", bestSuggestion),
"",
"You can use the --h or --help flag to see a list of options for any command.",
"Examples:",
"\track --h",
"\track servers --h",
"\track block-storage volumes --help",
"",
}
fmt.Fprintf(c.App.Writer, strings.Join(suggestion, "\n"))
}
func levenshtein(a, b string) int {
f := make([]int, utf8.RuneCountInString(b)+1)
for j := range f {
f[j] = j
}
for _, ca := range a {
j := 1
fj1 := f[0] // fj1 is the value of f[j - 1] in last iteration
f[0]++
for _, cb := range b {
mn := min(f[j]+1, f[j-1]+1) // delete & insert
if cb != ca {
mn = min(mn, fj1+1) // change
} else {
mn = min(mn, fj1) // matched
}
fj1, f[j] = f[j], mn // save f[j] to fj1(j is about to increase), update f[j] to mn
j++
}
}
return f[len(f)-1]
}
func min(a, b int) int {
if a <= b {
return a
}
return b
}