Add additional args

add predition of directories
add ability for prediction union
This commit is contained in:
Eyal Posener 2017-05-05 23:07:18 +03:00
parent 04d16f6064
commit c8263230e1
9 changed files with 95 additions and 16 deletions

View File

@ -7,6 +7,7 @@ type Flags map[string]Predicate
type Command struct {
Sub Commands
Flags Flags
Args Predicate
}
// options returns all available complete options for the given command
@ -38,6 +39,11 @@ func (c *Command) options(args []string) (options []Option, only bool) {
options = append(options, Arg(flag))
}
// add additional expected argument of the command
if c.Args.Expects {
options = append(options, c.Args.predict()...)
}
return
}

View File

@ -27,12 +27,13 @@ func TestCompleter_Complete(t *testing.T) {
"-flag2": PredictNothing,
"-flag3": PredictNothing,
},
Args: PredictDirs("./tests/").Or(PredictFiles("./tests/*.md")),
},
},
Flags: map[string]Predicate{
"-h": PredictNothing,
"-global1": PredictAnything,
"-o": PredictFiles("./gocomplete/*.go"),
"-o": PredictFiles("./tests/*.txt"),
},
},
}
@ -45,6 +46,8 @@ func TestCompleter_Complete(t *testing.T) {
allGlobals = append(allGlobals, flag)
}
testTXTFiles := []string{"./tests/a.txt", "./tests/b.txt", "./tests/c.txt"}
tests := []struct {
args string
want []string
@ -83,7 +86,19 @@ func TestCompleter_Complete(t *testing.T) {
},
{
args: "sub2 ",
want: []string{"-flag2", "-flag3", "-h", "-global1", "-o"},
want: []string{"./tests", "-flag2", "-flag3", "-h", "-global1", "-o"},
},
{
args: "sub2 tests",
want: []string{"./tests", "./tests/readme.md", "./tests/dir"},
},
{
args: "sub2 tests/re",
want: []string{"./tests/readme.md"},
},
{
args: "sub2 -flag2 ",
want: []string{"./tests", "-flag2", "-flag3", "-h", "-global1", "-o"},
},
{
args: "sub1 -fl",
@ -119,15 +134,31 @@ func TestCompleter_Complete(t *testing.T) {
},
{
args: "-o ",
want: []string{"./gocomplete/complete.go"},
want: []string{},
},
{
args: "-o goco",
want: []string{"./gocomplete/complete.go"},
args: "-o ./tes",
want: []string{},
},
{
args: "-o ./goco",
want: []string{"./gocomplete/complete.go"},
args: "-o tests/",
want: testTXTFiles,
},
{
args: "-o tests",
want: testTXTFiles,
},
{
args: "-o ./compl",
want: []string{},
},
{
args: "-o ./complete.go",
want: []string{},
},
{
args: "-o ./complete.go ",
want: allGlobals,
},
}

View File

@ -10,6 +10,7 @@ var (
"-o": complete.PredictFiles("*"),
"-i": complete.PredictNothing,
},
Args: complete.PredictFiles("**.go").Or(complete.PredictDirs("./")),
}
test = complete.Command{

View File

@ -35,5 +35,8 @@ func (a ArgFileName) Matches(prefix string) bool {
if err != nil {
logger("failed getting abs path of %s: %s", prefix, err)
}
return strings.HasPrefix(full, prefixFull)
// if the file has the prefix as prefix,
// but we don't want to show too many files, so, if it is in a deeper directory - omit it.
return strings.HasPrefix(full, prefixFull) && (full == prefixFull || !strings.Contains(full[len(prefixFull)+1:], "/"))
}

View File

@ -16,11 +16,20 @@ type Predicate struct {
Predictor func() []Option
}
func (f *Predicate) predict() []Option {
if f.Predictor == nil {
// Or unions two predicate struct, so that the result predicate
// returns the union of their predication
func (p Predicate) Or(other Predicate) Predicate {
return Predicate{
Expects: p.Expects && other.Expects,
Predictor: func() []Option { return append(p.predict(), other.predict()...) },
}
}
func (p Predicate) predict() []Option {
if p.Predictor == nil {
return nil
}
return f.Predictor()
return p.Predictor()
}
var (
@ -35,6 +44,28 @@ func PredictFiles(pattern string) Predicate {
}
}
func PredictDirs(path string) Predicate {
return Predicate{
Expects: true,
Predictor: dirs(path),
}
}
func dirs(path string) func() []Option {
return func() (options []Option) {
dirs := []string{}
filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
dirs = append(dirs, path)
}
return nil
})
if !filepath.IsAbs(path) {
filesToRel(dirs)
}
return filesToOptions(dirs)
}
}
func glob(pattern string) func() []Option {
return func() []Option {
files, err := filepath.Glob(pattern)
@ -44,11 +75,7 @@ func glob(pattern string) func() []Option {
if !filepath.IsAbs(pattern) {
filesToRel(files)
}
options := make([]Option, len(files))
for i, f := range files {
options[i] = ArgFileName(f)
}
return options
return filesToOptions(files)
}
}
func filesToRel(files []string) {
@ -69,3 +96,11 @@ func filesToRel(files []string) {
}
return
}
func filesToOptions(files []string) []Option {
options := make([]Option, len(files))
for i, f := range files {
options[i] = ArgFileName(f)
}
return options
}

0
tests/a.txt Normal file
View File

0
tests/b.txt Normal file
View File

0
tests/c.txt Normal file
View File

3
tests/readme.md Normal file
View File

@ -0,0 +1,3 @@
# About this directory
This directory is for testing file completion purposes