Improve files and directories completion
This commit is contained in:
parent
1c743d8c0b
commit
72dfe017e9
26
command.go
26
command.go
|
@ -33,11 +33,13 @@ func (c *Command) options(args []string) (options []match.Matcher, only bool) {
|
||||||
|
|
||||||
// remove the first argument, which is the command name
|
// remove the first argument, which is the command name
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
last := last(args)
|
wordCurrent := last(args)
|
||||||
// if prev has something that needs to follow it,
|
wordCompleted := last(removeLast(args))
|
||||||
|
// if wordCompleted has something that needs to follow it,
|
||||||
// it is the most relevant completion
|
// it is the most relevant completion
|
||||||
if predicate, ok := c.Flags[last]; ok && predicate != nil {
|
if predicate, ok := c.Flags[wordCompleted]; ok && predicate != nil {
|
||||||
return predicate.predict(last), true
|
Log("Predicting according to flag %s", wordCurrent)
|
||||||
|
return predicate.predict(wordCurrent), true
|
||||||
}
|
}
|
||||||
|
|
||||||
sub, options, only := c.searchSub(args)
|
sub, options, only := c.searchSub(args)
|
||||||
|
@ -57,7 +59,7 @@ func (c *Command) options(args []string) (options []match.Matcher, only bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add additional expected argument of the command
|
// add additional expected argument of the command
|
||||||
options = append(options, c.Args.predict(last)...)
|
options = append(options, c.Args.predict(wordCurrent)...)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -65,7 +67,12 @@ func (c *Command) options(args []string) (options []match.Matcher, only bool) {
|
||||||
// searchSub searches recursively within sub commands if the sub command appear
|
// searchSub searches recursively within sub commands if the sub command appear
|
||||||
// in the on of the arguments.
|
// in the on of the arguments.
|
||||||
func (c *Command) searchSub(args []string) (sub string, all []match.Matcher, only bool) {
|
func (c *Command) searchSub(args []string) (sub string, all []match.Matcher, only bool) {
|
||||||
for i, arg := range args {
|
|
||||||
|
// search for sub command in all arguments except the last one
|
||||||
|
// because that one might not be completed yet
|
||||||
|
searchArgs := removeLast(args)
|
||||||
|
|
||||||
|
for i, arg := range searchArgs {
|
||||||
if cmd, ok := c.Sub[arg]; ok {
|
if cmd, ok := c.Sub[arg]; ok {
|
||||||
sub = arg
|
sub = arg
|
||||||
all, only = cmd.options(args[i:])
|
all, only = cmd.options(args[i:])
|
||||||
|
@ -83,3 +90,10 @@ func (c *Command) subCommands() []match.Matcher {
|
||||||
}
|
}
|
||||||
return subs
|
return subs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func removeLast(a []string) []string {
|
||||||
|
if len(a) > 0 {
|
||||||
|
return a[:len(a)-1]
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
|
@ -59,11 +59,12 @@ func (c *Complete) Run() bool {
|
||||||
// complete get a command an command line arguments and returns
|
// complete get a command an command line arguments and returns
|
||||||
// matching completion options
|
// matching completion options
|
||||||
func complete(c Command, args []string) (matching []string) {
|
func complete(c Command, args []string) (matching []string) {
|
||||||
options, _ := c.options(args[:len(args)-1])
|
options, _ := c.options(args)
|
||||||
|
|
||||||
// choose only matching options
|
// choose only matching options
|
||||||
l := last(args)
|
l := last(args)
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
|
Log("option %T, %s -> %t", option, option, option.Match(l))
|
||||||
if option.Match(l) {
|
if option.Match(l) {
|
||||||
matching = append(matching, option.String())
|
matching = append(matching, option.String())
|
||||||
}
|
}
|
||||||
|
@ -87,6 +88,7 @@ func last(args []string) (last string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func output(options []string) {
|
func output(options []string) {
|
||||||
|
Log("")
|
||||||
// stdout of program defines the complete options
|
// stdout of program defines the complete options
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
fmt.Println(option)
|
fmt.Println(option)
|
||||||
|
|
|
@ -23,7 +23,7 @@ func TestCompleter_Complete(t *testing.T) {
|
||||||
"-flag2": PredictNothing,
|
"-flag2": PredictNothing,
|
||||||
"-flag3": PredictSet("opt1", "opt2", "opt12"),
|
"-flag3": PredictSet("opt1", "opt2", "opt12"),
|
||||||
},
|
},
|
||||||
Args: Predicate(PredictDirs).Or(PredictFiles("*.md")),
|
Args: Predicate(PredictDirs("*")).Or(PredictFiles("*.md")),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Flags: map[string]Predicate{
|
Flags: map[string]Predicate{
|
||||||
|
@ -41,7 +41,7 @@ func TestCompleter_Complete(t *testing.T) {
|
||||||
allGlobals = append(allGlobals, flag)
|
allGlobals = append(allGlobals, flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
testTXTFiles := []string{"./a.txt", "./b.txt", "./c.txt"}
|
testTXTFiles := []string{"./a.txt", "./b.txt", "./c.txt", "./.dot.txt"}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
args string
|
args string
|
||||||
|
@ -81,11 +81,11 @@ func TestCompleter_Complete(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
args: "sub2 ",
|
args: "sub2 ",
|
||||||
want: []string{"./", "./dir", "./readme.md", "-flag2", "-flag3", "-h", "-global1", "-o"},
|
want: []string{"./", "./dir/", "./readme.md", "-flag2", "-flag3", "-h", "-global1", "-o"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
args: "sub2 ./",
|
args: "sub2 ./",
|
||||||
want: []string{"./", "./readme.md", "./dir"},
|
want: []string{"./", "./readme.md", "./dir/"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
args: "sub2 re",
|
args: "sub2 re",
|
||||||
|
@ -93,7 +93,7 @@ func TestCompleter_Complete(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
args: "sub2 -flag2 ",
|
args: "sub2 -flag2 ",
|
||||||
want: []string{"./", "./dir", "./readme.md", "-flag2", "-flag3", "-h", "-global1", "-o"},
|
want: []string{"./", "./dir/", "./readme.md", "-flag2", "-flag3", "-h", "-global1", "-o"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
args: "sub1 -fl",
|
args: "sub1 -fl",
|
||||||
|
|
|
@ -7,7 +7,7 @@ var (
|
||||||
predictEllipsis = complete.PredictSet("./...")
|
predictEllipsis = complete.PredictSet("./...")
|
||||||
|
|
||||||
goFilesOrPackages = complete.PredictFiles("*.go").
|
goFilesOrPackages = complete.PredictFiles("*.go").
|
||||||
Or(complete.PredictDirs).
|
Or(complete.PredictDirs("*")).
|
||||||
Or(predictEllipsis)
|
Or(predictEllipsis)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ func main() {
|
||||||
"-installsuffix": complete.PredictAnything,
|
"-installsuffix": complete.PredictAnything,
|
||||||
"-ldflags": complete.PredictAnything,
|
"-ldflags": complete.PredictAnything,
|
||||||
"-linkshared": complete.PredictNothing,
|
"-linkshared": complete.PredictNothing,
|
||||||
"-pkgdir": complete.PredictDirs,
|
"-pkgdir": complete.PredictDirs("*"),
|
||||||
"-tags": complete.PredictAnything,
|
"-tags": complete.PredictAnything,
|
||||||
"-toolexec": complete.PredictAnything,
|
"-toolexec": complete.PredictAnything,
|
||||||
},
|
},
|
||||||
|
@ -58,7 +58,7 @@ func main() {
|
||||||
"-count": complete.PredictAnything,
|
"-count": complete.PredictAnything,
|
||||||
"-cover": complete.PredictNothing,
|
"-cover": complete.PredictNothing,
|
||||||
"-covermode": complete.PredictSet("set", "count", "atomic"),
|
"-covermode": complete.PredictSet("set", "count", "atomic"),
|
||||||
"-coverpkg": complete.PredictDirs,
|
"-coverpkg": complete.PredictDirs("*"),
|
||||||
"-cpu": complete.PredictAnything,
|
"-cpu": complete.PredictAnything,
|
||||||
"-run": predictTest("Test", "Example"),
|
"-run": predictTest("Test", "Example"),
|
||||||
"-short": complete.PredictNothing,
|
"-short": complete.PredictNothing,
|
||||||
|
@ -73,7 +73,7 @@ func main() {
|
||||||
"-memprofilerate": complete.PredictAnything,
|
"-memprofilerate": complete.PredictAnything,
|
||||||
"-mutexprofile": complete.PredictFiles("*.out"),
|
"-mutexprofile": complete.PredictFiles("*.out"),
|
||||||
"-mutexprofilefraction": complete.PredictAnything,
|
"-mutexprofilefraction": complete.PredictAnything,
|
||||||
"-outputdir": complete.PredictDirs,
|
"-outputdir": complete.PredictDirs("*"),
|
||||||
"-trace": complete.PredictFiles("*.out"),
|
"-trace": complete.PredictFiles("*.out"),
|
||||||
},
|
},
|
||||||
Args: goFilesOrPackages,
|
Args: goFilesOrPackages,
|
||||||
|
@ -114,7 +114,7 @@ func main() {
|
||||||
"-n": complete.PredictNothing,
|
"-n": complete.PredictNothing,
|
||||||
"-x": complete.PredictNothing,
|
"-x": complete.PredictNothing,
|
||||||
},
|
},
|
||||||
Args: complete.PredictDirs,
|
Args: complete.PredictDirs("*"),
|
||||||
}
|
}
|
||||||
|
|
||||||
list := complete.Command{
|
list := complete.Command{
|
||||||
|
@ -123,7 +123,7 @@ func main() {
|
||||||
"-f": complete.PredictAnything,
|
"-f": complete.PredictAnything,
|
||||||
"-json": complete.PredictNothing,
|
"-json": complete.PredictNothing,
|
||||||
},
|
},
|
||||||
Args: complete.PredictDirs,
|
Args: complete.PredictDirs("*"),
|
||||||
}
|
}
|
||||||
|
|
||||||
tool := complete.Command{
|
tool := complete.Command{
|
||||||
|
@ -140,7 +140,7 @@ func main() {
|
||||||
"-n": complete.PredictNothing,
|
"-n": complete.PredictNothing,
|
||||||
"-x": complete.PredictNothing,
|
"-x": complete.PredictNothing,
|
||||||
},
|
},
|
||||||
Args: complete.PredictDirs,
|
Args: complete.PredictDirs("*"),
|
||||||
}
|
}
|
||||||
|
|
||||||
env := complete.Command{
|
env := complete.Command{
|
||||||
|
@ -151,7 +151,7 @@ func main() {
|
||||||
version := complete.Command{}
|
version := complete.Command{}
|
||||||
|
|
||||||
fix := complete.Command{
|
fix := complete.Command{
|
||||||
Args: complete.PredictDirs,
|
Args: complete.PredictDirs("*"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// commands that also accepts the build flags
|
// commands that also accepts the build flags
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package match
|
package match
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,16 +14,13 @@ func (a File) String() string {
|
||||||
|
|
||||||
// Match returns true if prefix's abs path prefixes a's abs path
|
// Match returns true if prefix's abs path prefixes a's abs path
|
||||||
func (a File) Match(prefix string) bool {
|
func (a File) Match(prefix string) bool {
|
||||||
full, err := filepath.Abs(string(a))
|
|
||||||
if err != nil {
|
// special case for current directory completion
|
||||||
return false
|
if a == "./" && (prefix == "." || prefix == "") {
|
||||||
}
|
return true
|
||||||
prefixFull, err := filepath.Abs(prefix)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the file has the prefix as prefix,
|
cmp := strings.TrimPrefix(string(a), "./")
|
||||||
// but we don't want to show too many files, so, if it is in a deeper directory - omit it.
|
prefix = strings.TrimPrefix(prefix, "./")
|
||||||
return strings.HasPrefix(full, prefixFull) && (full == prefixFull || !strings.Contains(full[len(prefixFull)+1:], "/"))
|
return strings.HasPrefix(cmp, prefix)
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ func TestMatch(t *testing.T) {
|
||||||
{prefix: "", want: true},
|
{prefix: "", want: true},
|
||||||
{prefix: "f", want: true},
|
{prefix: "f", want: true},
|
||||||
{prefix: "./f", want: true},
|
{prefix: "./f", want: true},
|
||||||
|
{prefix: "./.", want: false},
|
||||||
{prefix: "file.", want: true},
|
{prefix: "file.", want: true},
|
||||||
{prefix: "./file.", want: true},
|
{prefix: "./file.", want: true},
|
||||||
{prefix: "file.txt", want: true},
|
{prefix: "file.txt", want: true},
|
||||||
|
@ -54,6 +55,7 @@ func TestMatch(t *testing.T) {
|
||||||
{prefix: "/file.txt", want: false},
|
{prefix: "/file.txt", want: false},
|
||||||
{prefix: "/fil", want: false},
|
{prefix: "/fil", want: false},
|
||||||
{prefix: "/file.txt2", want: false},
|
{prefix: "/file.txt2", want: false},
|
||||||
|
{prefix: "/.", want: false},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -62,6 +64,7 @@ func TestMatch(t *testing.T) {
|
||||||
{prefix: "", want: true},
|
{prefix: "", want: true},
|
||||||
{prefix: "f", want: true},
|
{prefix: "f", want: true},
|
||||||
{prefix: "./f", want: true},
|
{prefix: "./f", want: true},
|
||||||
|
{prefix: "./.", want: false},
|
||||||
{prefix: "file.", want: true},
|
{prefix: "file.", want: true},
|
||||||
{prefix: "./file.", want: true},
|
{prefix: "./file.", want: true},
|
||||||
{prefix: "file.txt", want: true},
|
{prefix: "file.txt", want: true},
|
||||||
|
@ -71,14 +74,16 @@ func TestMatch(t *testing.T) {
|
||||||
{prefix: "/file.txt", want: false},
|
{prefix: "/file.txt", want: false},
|
||||||
{prefix: "/fil", want: false},
|
{prefix: "/fil", want: false},
|
||||||
{prefix: "/file.txt2", want: false},
|
{prefix: "/file.txt2", want: false},
|
||||||
|
{prefix: "/.", want: false},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
m: File("/file.txt"),
|
m: File("/file.txt"),
|
||||||
tests: []matcherTest{
|
tests: []matcherTest{
|
||||||
{prefix: "", want: false},
|
{prefix: "", want: true},
|
||||||
{prefix: "f", want: false},
|
{prefix: "f", want: false},
|
||||||
{prefix: "./f", want: false},
|
{prefix: "./f", want: false},
|
||||||
|
{prefix: "./.", want: false},
|
||||||
{prefix: "file.", want: false},
|
{prefix: "file.", want: false},
|
||||||
{prefix: "./file.", want: false},
|
{prefix: "./file.", want: false},
|
||||||
{prefix: "file.txt", want: false},
|
{prefix: "file.txt", want: false},
|
||||||
|
@ -88,13 +93,23 @@ func TestMatch(t *testing.T) {
|
||||||
{prefix: "/file.txt", want: true},
|
{prefix: "/file.txt", want: true},
|
||||||
{prefix: "/fil", want: true},
|
{prefix: "/fil", want: true},
|
||||||
{prefix: "/file.txt2", want: false},
|
{prefix: "/file.txt2", want: false},
|
||||||
|
{prefix: "/.", want: false},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
m: File("./"),
|
||||||
|
tests: []matcherTest{
|
||||||
|
{prefix: "", want: true},
|
||||||
|
{prefix: ".", want: true},
|
||||||
|
{prefix: "./", want: true},
|
||||||
|
{prefix: "./.", want: false},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
for _, ttt := range tt.tests {
|
for _, ttt := range tt.tests {
|
||||||
name := "matcher:" + tt.m.String() + "/prefix:" + ttt.prefix
|
name := "matcher='" + tt.m.String() + "'&prefix='" + ttt.prefix + "'"
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
got := tt.m.Match(ttt.prefix)
|
got := tt.m.Match(ttt.prefix)
|
||||||
if got != ttt.want {
|
if got != ttt.want {
|
||||||
|
|
60
predicate.go
60
predicate.go
|
@ -3,7 +3,6 @@ package complete
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/posener/complete/match"
|
"github.com/posener/complete/match"
|
||||||
)
|
)
|
||||||
|
@ -53,23 +52,8 @@ func PredictSet(options ...string) Predicate {
|
||||||
// PredictDirs will search for directories in the given started to be typed
|
// PredictDirs will search for directories in the given started to be typed
|
||||||
// path, if no path was started to be typed, it will complete to directories
|
// path, if no path was started to be typed, it will complete to directories
|
||||||
// in the current working directory.
|
// in the current working directory.
|
||||||
func PredictDirs(last string) (options []match.Matcher) {
|
func PredictDirs(pattern string) Predicate {
|
||||||
path := dirFromLast(last)
|
return files(pattern, true, false)
|
||||||
dirs := []string{}
|
|
||||||
filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if info.IsDir() {
|
|
||||||
dirs = append(dirs, path)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
// if given path is not absolute, return relative paths
|
|
||||||
if !filepath.IsAbs(path) {
|
|
||||||
filesToRel(dirs)
|
|
||||||
}
|
|
||||||
return filesToMatchers(dirs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PredictFiles will search for files matching the given pattern in the started to
|
// PredictFiles will search for files matching the given pattern in the started to
|
||||||
|
@ -77,12 +61,26 @@ func PredictDirs(last string) (options []match.Matcher) {
|
||||||
// match the pattern in the current working directory.
|
// match the pattern in the current working directory.
|
||||||
// To match any file, use "*" as pattern. To match go files use "*.go", and so on.
|
// To match any file, use "*" as pattern. To match go files use "*.go", and so on.
|
||||||
func PredictFiles(pattern string) Predicate {
|
func PredictFiles(pattern string) Predicate {
|
||||||
|
return files(pattern, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PredictFilesOrDirs predict any file or directory that matches the pattern
|
||||||
|
func PredictFilesOrDirs(pattern string) Predicate {
|
||||||
|
return files(pattern, true, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func files(pattern string, allowDirs, allowFiles bool) Predicate {
|
||||||
return func(last string) []match.Matcher {
|
return func(last string) []match.Matcher {
|
||||||
dir := dirFromLast(last)
|
dir := dirFromLast(last)
|
||||||
|
Log("looking for files in %s (last=%s)", dir, last)
|
||||||
files, err := filepath.Glob(filepath.Join(dir, pattern))
|
files, err := filepath.Glob(filepath.Join(dir, pattern))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Log("failed glob operation with pattern '%s': %s", pattern, err)
|
Log("failed glob operation with pattern '%s': %s", pattern, err)
|
||||||
}
|
}
|
||||||
|
if allowDirs {
|
||||||
|
files = append(files, dir)
|
||||||
|
}
|
||||||
|
files = selectByType(files, allowDirs, allowFiles)
|
||||||
if !filepath.IsAbs(pattern) {
|
if !filepath.IsAbs(pattern) {
|
||||||
filesToRel(files)
|
filesToRel(files)
|
||||||
}
|
}
|
||||||
|
@ -90,6 +88,21 @@ func PredictFiles(pattern string) Predicate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func selectByType(names []string, allowDirs bool, allowFiles bool) []string {
|
||||||
|
filtered := make([]string, 0, len(names))
|
||||||
|
for _, name := range names {
|
||||||
|
stat, err := os.Stat(name)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (stat.IsDir() && !allowDirs) || (!stat.IsDir() && !allowFiles) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
filtered = append(filtered, name)
|
||||||
|
}
|
||||||
|
return filtered
|
||||||
|
}
|
||||||
|
|
||||||
// filesToRel, change list of files to their names in the relative
|
// filesToRel, change list of files to their names in the relative
|
||||||
// to current directory form.
|
// to current directory form.
|
||||||
func filesToRel(files []string) {
|
func filesToRel(files []string) {
|
||||||
|
@ -106,12 +119,12 @@ func filesToRel(files []string) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if rel == "." {
|
if rel != "." {
|
||||||
rel = ""
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(rel, ".") {
|
|
||||||
rel = "./" + rel
|
rel = "./" + rel
|
||||||
}
|
}
|
||||||
|
if info, err := os.Stat(rel); err == nil && info.IsDir() {
|
||||||
|
rel += "/"
|
||||||
|
}
|
||||||
files[i] = rel
|
files[i] = rel
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -129,6 +142,9 @@ func filesToMatchers(files []string) []match.Matcher {
|
||||||
// last argument if it represents a file name being written.
|
// last argument if it represents a file name being written.
|
||||||
// in case that it is not, we fall back to the current directory.
|
// in case that it is not, we fall back to the current directory.
|
||||||
func dirFromLast(last string) string {
|
func dirFromLast(last string) string {
|
||||||
|
if info, err := os.Stat(last); err == nil && info.IsDir() {
|
||||||
|
return last
|
||||||
|
}
|
||||||
dir := filepath.Dir(last)
|
dir := filepath.Dir(last)
|
||||||
_, err := os.Stat(dir)
|
_, err := os.Stat(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -21,6 +21,12 @@ func TestPredicate(t *testing.T) {
|
||||||
p: PredictSet("a", "b", "c"),
|
p: PredictSet("a", "b", "c"),
|
||||||
want: []string{"a", "b", "c"},
|
want: []string{"a", "b", "c"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "set with does",
|
||||||
|
p: PredictSet("./..", "./x"),
|
||||||
|
arg: "./.",
|
||||||
|
want: []string{"./.."},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "set/empty",
|
name: "set/empty",
|
||||||
p: PredictSet(),
|
p: PredictSet(),
|
||||||
|
@ -59,7 +65,7 @@ func TestPredicate(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "files/txt",
|
name: "files/txt",
|
||||||
p: PredictFiles("*.txt"),
|
p: PredictFiles("*.txt"),
|
||||||
want: []string{"./a.txt", "./b.txt", "./c.txt"},
|
want: []string{"./a.txt", "./b.txt", "./c.txt", "./.dot.txt"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "files/txt",
|
name: "files/txt",
|
||||||
|
@ -86,24 +92,40 @@ func TestPredicate(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "dirs",
|
name: "dirs",
|
||||||
p: PredictDirs,
|
p: PredictDirs("*"),
|
||||||
arg: "./dir/",
|
arg: "./dir/",
|
||||||
want: []string{"./dir"},
|
want: []string{"./dir/"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "dirs and files",
|
||||||
|
p: PredictFilesOrDirs("*"),
|
||||||
|
arg: "./dir",
|
||||||
|
want: []string{"./dir/", "./dir/x"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "dirs",
|
name: "dirs",
|
||||||
p: PredictDirs,
|
p: PredictDirs("*"),
|
||||||
want: []string{"./", "./dir"},
|
want: []string{"./", "./dir/"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "subdir",
|
||||||
|
p: PredictFiles("*"),
|
||||||
|
arg: "./dir/",
|
||||||
|
want: []string{"./dir/x"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name+"/"+tt.arg, func(t *testing.T) {
|
t.Run(tt.name+"?arg='"+tt.arg+"'", func(t *testing.T) {
|
||||||
|
|
||||||
matchers := tt.p.predict(tt.arg)
|
matchers := tt.p.predict(tt.arg)
|
||||||
|
|
||||||
matchersString := []string{}
|
matchersString := []string{}
|
||||||
for _, m := range matchers {
|
for _, m := range matchers {
|
||||||
|
if m.Match(tt.arg) {
|
||||||
matchersString = append(matchersString, m.String())
|
matchersString = append(matchersString, m.String())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
sort.Strings(matchersString)
|
sort.Strings(matchersString)
|
||||||
sort.Strings(tt.want)
|
sort.Strings(tt.want)
|
||||||
|
|
||||||
|
@ -111,7 +133,7 @@ func TestPredicate(t *testing.T) {
|
||||||
want := strings.Join(tt.want, ",")
|
want := strings.Join(tt.want, ",")
|
||||||
|
|
||||||
if got != want {
|
if got != want {
|
||||||
t.Errorf("failed %s\ngot = %s\nwant: %s", tt.name, got, want)
|
t.Errorf("failed %s\ngot = %s\nwant: %s", t.Name(), got, want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue