From f71e6baaf2e0d387a847f8e599af7d75be650283 Mon Sep 17 00:00:00 2001 From: Eyal Posener Date: Fri, 5 Jul 2019 14:39:11 +0300 Subject: [PATCH 1/3] Travis: remove test.sh, improve travis file --- .travis.yml | 16 ++++++++-------- test.sh | 12 ------------ 2 files changed, 8 insertions(+), 20 deletions(-) delete mode 100755 test.sh 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/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 From 29f43e246ec41ee311a0a9bc24b15cb4ece4e513 Mon Sep 17 00:00:00 2001 From: Eyal Posener Date: Fri, 5 Jul 2019 14:58:49 +0300 Subject: [PATCH 2/3] deprecate match package --- complete.go | 4 +- match/file.go | 19 --------- match/match.go | 32 +++++++++++++++ match/prefix.go | 9 ----- predict_files.go | 20 ++++++++-- predict_test.go | 102 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 153 insertions(+), 33 deletions(-) delete mode 100644 match/file.go delete mode 100644 match/prefix.go 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/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..c8baec1 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 @@ -70,7 +68,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 +104,19 @@ 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) +} 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) + } + }) + } + } +} From 72c5c945f0d5861ba1d4e51a0a5ac36a4bef3868 Mon Sep 17 00:00:00 2001 From: Eyal Posener Date: Fri, 5 Jul 2019 15:10:58 +0300 Subject: [PATCH 3/3] Deprecate Args.Directory() --- args.go | 2 ++ gocomplete/complete.go | 2 +- predict_files.go | 54 +++++++++++++++++++++++++++++++++++++++++- utils.go | 46 ----------------------------------- 4 files changed, 56 insertions(+), 48 deletions(-) delete mode 100644 utils.go 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/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/predict_files.go b/predict_files.go index c8baec1..25ae2d5 100644 --- a/predict_files.go +++ b/predict_files.go @@ -51,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 @@ -60,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) { @@ -120,3 +133,42 @@ func matchFile(file, prefix string) bool { 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/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 -}