summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--command.go6
-rw-r--r--complete_test.go45
-rw-r--r--gocomplete/complete.go1
-rw-r--r--option.go5
-rw-r--r--predicate.go51
-rw-r--r--tests/a.txt0
-rw-r--r--tests/b.txt0
-rw-r--r--tests/c.txt0
-rw-r--r--tests/readme.md3
9 files changed, 95 insertions, 16 deletions
diff --git a/command.go b/command.go
index 9292a89..e2f5eb4 100644
--- a/command.go
+++ b/command.go
@@ -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
}
diff --git a/complete_test.go b/complete_test.go
index aad747e..a6daa98 100644
--- a/complete_test.go
+++ b/complete_test.go
@@ -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 ./tes",
+ want: []string{},
+ },
+ {
+ args: "-o tests/",
+ want: testTXTFiles,
+ },
+ {
+ args: "-o tests",
+ want: testTXTFiles,
},
{
- args: "-o goco",
- want: []string{"./gocomplete/complete.go"},
+ args: "-o ./compl",
+ want: []string{},
},
{
- args: "-o ./goco",
- want: []string{"./gocomplete/complete.go"},
+ args: "-o ./complete.go",
+ want: []string{},
+ },
+ {
+ args: "-o ./complete.go ",
+ want: allGlobals,
},
}
diff --git a/gocomplete/complete.go b/gocomplete/complete.go
index 5b31cc6..9233b4e 100644
--- a/gocomplete/complete.go
+++ b/gocomplete/complete.go
@@ -10,6 +10,7 @@ var (
"-o": complete.PredictFiles("*"),
"-i": complete.PredictNothing,
},
+ Args: complete.PredictFiles("**.go").Or(complete.PredictDirs("./")),
}
test = complete.Command{
diff --git a/option.go b/option.go
index 9333e84..6a067ea 100644
--- a/option.go
+++ b/option.go
@@ -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:], "/"))
}
diff --git a/predicate.go b/predicate.go
index 5ba544b..1cc6cca 100644
--- a/predicate.go
+++ b/predicate.go
@@ -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
+}
diff --git a/tests/a.txt b/tests/a.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/a.txt
diff --git a/tests/b.txt b/tests/b.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/b.txt
diff --git a/tests/c.txt b/tests/c.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/c.txt
diff --git a/tests/readme.md b/tests/readme.md
new file mode 100644
index 0000000..25ea22c
--- /dev/null
+++ b/tests/readme.md
@@ -0,0 +1,3 @@
+# About this directory
+
+This directory is for testing file completion purposes \ No newline at end of file