summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml16
-rw-r--r--args.go2
-rw-r--r--complete.go4
-rw-r--r--gocomplete/complete.go2
-rw-r--r--match/file.go19
-rw-r--r--match/match.go32
-rw-r--r--match/prefix.go9
-rw-r--r--predict_files.go74
-rw-r--r--predict_test.go102
-rwxr-xr-xtest.sh12
-rw-r--r--utils.go46
11 files changed, 217 insertions, 101 deletions
diff --git a/.travis.yml b/.travis.yml
index 2fae945..6ba8d86 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,16 +1,16 @@
language: go
-sudo: false
go:
- - 1.11
+ - tip
+ - 1.12.x
+ - 1.11.x
- 1.10.x
- - 1.9
- - 1.8
-
-before_install:
- - go get -u -t ./...
script:
- - GO111MODULE=on ./test.sh
+ - go test -race -coverprofile=coverage.txt -covermode=atomic ./...
after_success:
- bash <(curl -s https://codecov.io/bash)
+
+matrix:
+ allow_failures:
+ - go: tip \ No newline at end of file
diff --git a/args.go b/args.go
index 17ab2c6..16e5ab3 100644
--- a/args.go
+++ b/args.go
@@ -28,6 +28,8 @@ type Args struct {
// Directory gives the directory of the current written
// last argument if it represents a file name being written.
// in case that it is not, we fall back to the current directory.
+//
+// Deprecated.
func (a Args) Directory() string {
if info, err := os.Stat(a.Last); err == nil && info.IsDir() {
return fixPathForm(a.Last, a.Last)
diff --git a/complete.go b/complete.go
index 991bdea..423cbec 100644
--- a/complete.go
+++ b/complete.go
@@ -6,9 +6,9 @@ import (
"io"
"os"
"strconv"
+ "strings"
"github.com/posener/complete/cmd"
- "github.com/posener/complete/match"
)
const (
@@ -72,7 +72,7 @@ func (c *Complete) Complete() bool {
// filter only options that match the last argument
matches := []string{}
for _, option := range options {
- if match.Prefix(option, a.Last) {
+ if strings.HasPrefix(option, a.Last) {
matches = append(matches, option)
}
}
diff --git a/gocomplete/complete.go b/gocomplete/complete.go
index 95f2002..2c31010 100644
--- a/gocomplete/complete.go
+++ b/gocomplete/complete.go
@@ -449,7 +449,7 @@ func main() {
"-unusedfuncs": complete.PredictAnything,
"-unusedresult": complete.PredictNothing,
"-unusedstringmethods": complete.PredictAnything,
- "-v": complete.PredictNothing,
+ "-v": complete.PredictNothing,
},
Args: anyGo,
},
diff --git a/match/file.go b/match/file.go
deleted file mode 100644
index 051171e..0000000
--- a/match/file.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package match
-
-import "strings"
-
-// File returns true if prefix can match the file
-func File(file, prefix string) bool {
- // special case for current directory completion
- if file == "./" && (prefix == "." || prefix == "") {
- return true
- }
- if prefix == "." && strings.HasPrefix(file, ".") {
- return true
- }
-
- file = strings.TrimPrefix(file, "./")
- prefix = strings.TrimPrefix(prefix, "./")
-
- return strings.HasPrefix(file, prefix)
-}
diff --git a/match/match.go b/match/match.go
index b9c0973..b5f1814 100644
--- a/match/match.go
+++ b/match/match.go
@@ -1,7 +1,39 @@
// Package match contains matchers that decide if to apply completion.
+//
+// This package is deprecated.
package match
+import "strings"
+
// Match matches two strings
// it is used for comparing a term to the last typed
// word, the prefix, and see if it is a possible auto complete option.
+//
+// Deprecated.
type Match func(term, prefix string) bool
+
+// Prefix is a simple Matcher, if the word is it's prefix, there is a match
+// Match returns true if a has the prefix as prefix
+//
+// Deprecated.
+func Prefix(long, prefix string) bool {
+ return strings.HasPrefix(long, prefix)
+}
+
+// File returns true if prefix can match the file
+//
+// Deprecated.
+func File(file, prefix string) bool {
+ // special case for current directory completion
+ if file == "./" && (prefix == "." || prefix == "") {
+ return true
+ }
+ if prefix == "." && strings.HasPrefix(file, ".") {
+ return true
+ }
+
+ file = strings.TrimPrefix(file, "./")
+ prefix = strings.TrimPrefix(prefix, "./")
+
+ return strings.HasPrefix(file, prefix)
+}
diff --git a/match/prefix.go b/match/prefix.go
deleted file mode 100644
index 9a01ba6..0000000
--- a/match/prefix.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package match
-
-import "strings"
-
-// Prefix is a simple Matcher, if the word is it's prefix, there is a match
-// Match returns true if a has the prefix as prefix
-func Prefix(long, prefix string) bool {
- return strings.HasPrefix(long, prefix)
-}
diff --git a/predict_files.go b/predict_files.go
index c8adf7e..25ae2d5 100644
--- a/predict_files.go
+++ b/predict_files.go
@@ -5,8 +5,6 @@ import (
"os"
"path/filepath"
"strings"
-
- "github.com/posener/complete/match"
)
// PredictDirs will search for directories in the given started to be typed
@@ -53,7 +51,7 @@ func predictFiles(a Args, pattern string, allowFiles bool) []string {
return nil
}
- dir := a.Directory()
+ dir := directory(a.Last)
files := listFiles(dir, pattern, allowFiles)
// add dir if match
@@ -62,6 +60,19 @@ func predictFiles(a Args, pattern string, allowFiles bool) []string {
return PredictFilesSet(files).Predict(a)
}
+// directory gives the directory of the given partial path
+// in case that it is not, we fall back to the current directory.
+func directory(path string) string {
+ if info, err := os.Stat(path); err == nil && info.IsDir() {
+ return fixPathForm(path, path)
+ }
+ dir := filepath.Dir(path)
+ if info, err := os.Stat(dir); err == nil && info.IsDir() {
+ return fixPathForm(path, dir)
+ }
+ return "./"
+}
+
// PredictFilesSet predict according to file rules to a given set of file names
func PredictFilesSet(files []string) PredictFunc {
return func(a Args) (prediction []string) {
@@ -70,7 +81,7 @@ func PredictFilesSet(files []string) PredictFunc {
f = fixPathForm(a.Last, f)
// test matching of file to the argument
- if match.File(f, a.Last) {
+ if matchFile(f, a.Last) {
prediction = append(prediction, f)
}
}
@@ -106,3 +117,58 @@ func listFiles(dir, pattern string, allowFiles bool) []string {
}
return list
}
+
+// MatchFile returns true if prefix can match the file
+func matchFile(file, prefix string) bool {
+ // special case for current directory completion
+ if file == "./" && (prefix == "." || prefix == "") {
+ return true
+ }
+ if prefix == "." && strings.HasPrefix(file, ".") {
+ return true
+ }
+
+ file = strings.TrimPrefix(file, "./")
+ prefix = strings.TrimPrefix(prefix, "./")
+
+ return strings.HasPrefix(file, prefix)
+}
+
+// fixPathForm changes a file name to a relative name
+func fixPathForm(last string, file string) string {
+ // get wording directory for relative name
+ workDir, err := os.Getwd()
+ if err != nil {
+ return file
+ }
+
+ abs, err := filepath.Abs(file)
+ if err != nil {
+ return file
+ }
+
+ // if last is absolute, return path as absolute
+ if filepath.IsAbs(last) {
+ return fixDirPath(abs)
+ }
+
+ rel, err := filepath.Rel(workDir, abs)
+ if err != nil {
+ return file
+ }
+
+ // fix ./ prefix of path
+ if rel != "." && strings.HasPrefix(last, ".") {
+ rel = "./" + rel
+ }
+
+ return fixDirPath(rel)
+}
+
+func fixDirPath(path string) string {
+ info, err := os.Stat(path)
+ if err == nil && info.IsDir() && !strings.HasSuffix(path, "/") {
+ path += "/"
+ }
+ return path
+}
diff --git a/predict_test.go b/predict_test.go
index 24df78d..c376207 100644
--- a/predict_test.go
+++ b/predict_test.go
@@ -1,6 +1,8 @@
package complete
import (
+ "fmt"
+ "os"
"sort"
"strings"
"testing"
@@ -167,3 +169,103 @@ func TestPredicate(t *testing.T) {
}
}
}
+
+func TestMatchFile(t *testing.T) {
+ t.Parallel()
+
+ // Change to tests directory for testing completion of
+ // files and directories
+ err := os.Chdir("../tests")
+ if err != nil {
+ panic(err)
+ }
+
+ type matcherTest struct {
+ prefix string
+ want bool
+ }
+
+ tests := []struct {
+ long string
+ tests []matcherTest
+ }{
+ {
+ long: "file.txt",
+ tests: []matcherTest{
+ {prefix: "", want: true},
+ {prefix: "f", want: true},
+ {prefix: "./f", want: true},
+ {prefix: "./.", want: false},
+ {prefix: "file.", want: true},
+ {prefix: "./file.", want: true},
+ {prefix: "file.txt", want: true},
+ {prefix: "./file.txt", want: true},
+ {prefix: "other.txt", want: false},
+ {prefix: "/other.txt", want: false},
+ {prefix: "/file.txt", want: false},
+ {prefix: "/fil", want: false},
+ {prefix: "/file.txt2", want: false},
+ {prefix: "/.", want: false},
+ },
+ },
+ {
+ long: "./file.txt",
+ tests: []matcherTest{
+ {prefix: "", want: true},
+ {prefix: "f", want: true},
+ {prefix: "./f", want: true},
+ {prefix: "./.", want: false},
+ {prefix: "file.", want: true},
+ {prefix: "./file.", want: true},
+ {prefix: "file.txt", want: true},
+ {prefix: "./file.txt", want: true},
+ {prefix: "other.txt", want: false},
+ {prefix: "/other.txt", want: false},
+ {prefix: "/file.txt", want: false},
+ {prefix: "/fil", want: false},
+ {prefix: "/file.txt2", want: false},
+ {prefix: "/.", want: false},
+ },
+ },
+ {
+ long: "/file.txt",
+ tests: []matcherTest{
+ {prefix: "", want: true},
+ {prefix: "f", want: false},
+ {prefix: "./f", want: false},
+ {prefix: "./.", want: false},
+ {prefix: "file.", want: false},
+ {prefix: "./file.", want: false},
+ {prefix: "file.txt", want: false},
+ {prefix: "./file.txt", want: false},
+ {prefix: "other.txt", want: false},
+ {prefix: "/other.txt", want: false},
+ {prefix: "/file.txt", want: true},
+ {prefix: "/fil", want: true},
+ {prefix: "/file.txt2", want: false},
+ {prefix: "/.", want: false},
+ },
+ },
+ {
+ long: "./",
+ tests: []matcherTest{
+ {prefix: "", want: true},
+ {prefix: ".", want: true},
+ {prefix: "./", want: true},
+ {prefix: "./.", want: false},
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ for _, ttt := range tt.tests {
+ name := fmt.Sprintf("long=%q&prefix=%q", tt.long, ttt.prefix)
+ t.Run(name, func(t *testing.T) {
+ got := matchFile(tt.long, ttt.prefix)
+ if got != ttt.want {
+ t.Errorf("Failed %s: got = %t, want: %t", name, got, ttt.want)
+ }
+ })
+ }
+ }
+}
diff --git a/test.sh b/test.sh
deleted file mode 100755
index 56bfcf1..0000000
--- a/test.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-echo "" > coverage.txt
-
-for d in $(go list ./... | grep -v vendor); do
- go test -v -race -coverprofile=profile.out -covermode=atomic $d
- if [ -f profile.out ]; then
- cat profile.out >> coverage.txt
- rm profile.out
- fi
-done \ No newline at end of file
diff --git a/utils.go b/utils.go
deleted file mode 100644
index 58b8b79..0000000
--- a/utils.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package complete
-
-import (
- "os"
- "path/filepath"
- "strings"
-)
-
-// fixPathForm changes a file name to a relative name
-func fixPathForm(last string, file string) string {
- // get wording directory for relative name
- workDir, err := os.Getwd()
- if err != nil {
- return file
- }
-
- abs, err := filepath.Abs(file)
- if err != nil {
- return file
- }
-
- // if last is absolute, return path as absolute
- if filepath.IsAbs(last) {
- return fixDirPath(abs)
- }
-
- rel, err := filepath.Rel(workDir, abs)
- if err != nil {
- return file
- }
-
- // fix ./ prefix of path
- if rel != "." && strings.HasPrefix(last, ".") {
- rel = "./" + rel
- }
-
- return fixDirPath(rel)
-}
-
-func fixDirPath(path string) string {
- info, err := os.Stat(path)
- if err == nil && info.IsDir() && !strings.HasSuffix(path, "/") {
- path += "/"
- }
- return path
-}