summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEyal Posener <[email protected]>2017-05-15 23:52:04 +0300
committerEyal Posener <[email protected]>2017-05-18 23:29:55 +0300
commit61d9904ba1f47bf5bbd3497ac0c9f5787adb8633 (patch)
tree17357f14eadb4654287eb664dfbe02914167f4db
parent659bd9e3d5a0113fb862bcbd06a983b0e74e8df7 (diff)
Fix './' prefix for file completion
-rw-r--r--args.go10
-rw-r--r--args_test.go4
-rw-r--r--complete_test.go18
-rw-r--r--gocomplete/tests_test.go7
-rw-r--r--match/file.go5
-rw-r--r--predict_files.go8
-rw-r--r--predict_test.go44
-rw-r--r--utils.go27
8 files changed, 85 insertions, 38 deletions
diff --git a/args.go b/args.go
index 2dbb816..73c356d 100644
--- a/args.go
+++ b/args.go
@@ -28,19 +28,13 @@ type Args struct {
// in case that it is not, we fall back to the current directory.
func (a Args) Directory() string {
if info, err := os.Stat(a.Last); err == nil && info.IsDir() {
- if !filepath.IsAbs(a.Last) {
- return relativePath(a.Last)
- }
- return a.Last
+ return fixPathForm(a.Last, a.Last)
}
dir := filepath.Dir(a.Last)
if info, err := os.Stat(dir); err != nil || !info.IsDir() {
return "./"
}
- if !filepath.IsAbs(dir) {
- dir = relativePath(dir)
- }
- return dir
+ return fixPathForm(a.Last, dir)
}
func newArgs(line []string) Args {
diff --git a/args_test.go b/args_test.go
index 78d346f..a211815 100644
--- a/args_test.go
+++ b/args_test.go
@@ -162,7 +162,7 @@ func TestArgs_Directory(t *testing.T) {
},
{
line: "a b c /tmp",
- directory: "/tmp",
+ directory: "/tmp/",
},
{
line: "a b c /tmp ",
@@ -178,7 +178,7 @@ func TestArgs_Directory(t *testing.T) {
},
{
line: "a b c dir",
- directory: "./dir/",
+ directory: "dir/",
},
{
line: "a b c ./di",
diff --git a/complete_test.go b/complete_test.go
index cd61ceb..135c6ad 100644
--- a/complete_test.go
+++ b/complete_test.go
@@ -35,8 +35,6 @@ func TestCompleter_Complete(t *testing.T) {
},
}
- testTXTFiles := []string{"./a.txt", "./b.txt", "./c.txt", "./.dot.txt"}
-
tests := []struct {
args string
want []string
@@ -75,7 +73,7 @@ func TestCompleter_Complete(t *testing.T) {
},
{
args: "sub2 ",
- want: []string{"./", "./dir/", "./outer/", "./readme.md", "-flag2", "-flag3", "-h", "-global1"},
+ want: []string{"./", "dir/", "outer/", "readme.md", "-flag2", "-flag3", "-h", "-global1"},
},
{
args: "sub2 ./",
@@ -83,11 +81,15 @@ func TestCompleter_Complete(t *testing.T) {
},
{
args: "sub2 re",
+ want: []string{"readme.md"},
+ },
+ {
+ args: "sub2 ./re",
want: []string{"./readme.md"},
},
{
args: "sub2 -flag2 ",
- want: []string{"./", "./dir/", "./outer/", "./readme.md", "-flag2", "-flag3", "-h", "-global1"},
+ want: []string{"./", "dir/", "outer/", "readme.md", "-flag2", "-flag3", "-h", "-global1"},
},
{
args: "sub1 -fl",
@@ -123,7 +125,7 @@ func TestCompleter_Complete(t *testing.T) {
},
{
args: "-o ",
- want: append(testTXTFiles, "./", "./dir/", "./outer/"),
+ want: []string{"a.txt", "b.txt", "c.txt", ".dot.txt", "./", "dir/", "outer/"},
},
{
args: "-o ./no-su",
@@ -131,7 +133,11 @@ func TestCompleter_Complete(t *testing.T) {
},
{
args: "-o ./",
- want: append(testTXTFiles, "./", "./dir/", "./outer/"),
+ want: []string{"./a.txt", "./b.txt", "./c.txt", "./.dot.txt", "./", "./dir/", "./outer/"},
+ },
+ {
+ args: "-o .",
+ want: []string{"./a.txt", "./b.txt", "./c.txt", "./.dot.txt", "./", "./dir/", "./outer/"},
},
{
args: "-o ./read",
diff --git a/gocomplete/tests_test.go b/gocomplete/tests_test.go
index f1b294a..a72f38f 100644
--- a/gocomplete/tests_test.go
+++ b/gocomplete/tests_test.go
@@ -1,10 +1,11 @@
package main
import (
+ "os"
+ "sort"
"testing"
"github.com/posener/complete"
- "os"
)
func TestPredictions(t *testing.T) {
@@ -49,7 +50,7 @@ func TestPredictions(t *testing.T) {
{
name: "predict runnable ok",
predictor: complete.PredictFunc(predictRunnableFiles),
- completion: []string{"./complete.go"},
+ completion: []string{"complete.go"},
},
{
name: "predict runnable not found",
@@ -79,6 +80,8 @@ func Example() {
}
func equal(s1, s2 []string) bool {
+ sort.Strings(s1)
+ sort.Strings(s2)
if len(s1) != len(s2) {
return false
}
diff --git a/match/file.go b/match/file.go
index eee5bec..051171e 100644
--- a/match/file.go
+++ b/match/file.go
@@ -4,13 +4,16 @@ 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/predict_files.go b/predict_files.go
index 0ba2d79..4b8c84a 100644
--- a/predict_files.go
+++ b/predict_files.go
@@ -42,7 +42,7 @@ func files(pattern string, allowFiles bool) PredictFunc {
// if the result is only one item, we might want to recursively check
// for more accurate results.
- if prediction[0] == a.Last { // avoid loop forever
+ if prediction[0] == a.Last {
return
}
@@ -73,13 +73,9 @@ func predictFiles(a Args, pattern string, allowFiles bool) []string {
// PredictFilesSet predict according to file rules to a given set of file names
func PredictFilesSet(files []string) PredictFunc {
return func(a Args) (prediction []string) {
- rel := !filepath.IsAbs(a.Directory())
// add all matching files to prediction
for _, f := range files {
- // change file name to relative if necessary
- if rel {
- f = relativePath(f)
- }
+ f = fixPathForm(a.Last, f)
// test matching of file to the argument
if match.File(f, a.Last) {
diff --git a/predict_test.go b/predict_test.go
index b2840c0..ac26e33 100644
--- a/predict_test.go
+++ b/predict_test.go
@@ -60,7 +60,7 @@ func TestPredicate(t *testing.T) {
{
name: "files/txt",
p: PredictFiles("*.txt"),
- want: []string{"./", "./dir/", "./outer/", "./a.txt", "./b.txt", "./c.txt", "./.dot.txt"},
+ want: []string{"./", "dir/", "outer/", "a.txt", "b.txt", "c.txt", ".dot.txt"},
},
{
name: "files/txt",
@@ -83,38 +83,68 @@ func TestPredicate(t *testing.T) {
{
name: "files/md",
p: PredictFiles("*.md"),
- argList: []string{"", ".", "./"},
+ argList: []string{""},
+ want: []string{"./", "dir/", "outer/", "readme.md"},
+ },
+ {
+ name: "files/md with ./ prefix",
+ p: PredictFiles("*.md"),
+ argList: []string{".", "./"},
want: []string{"./", "./dir/", "./outer/", "./readme.md"},
},
{
name: "dirs",
p: PredictDirs("*"),
- argList: []string{"./dir/", "./di", "di", "dir", "dir/"},
+ argList: []string{"di", "dir", "dir/"},
+ want: []string{"dir/"},
+ },
+ {
+ name: "dirs with ./ prefix",
+ p: PredictDirs("*"),
+ argList: []string{"./di", "./dir", "./dir/"},
want: []string{"./dir/"},
},
{
name: "predict anything in dir",
p: PredictFiles("*"),
- argList: []string{"./dir", "dir", "./dir/", "./di"},
+ argList: []string{"dir", "dir/", "di"},
+ want: []string{"dir/", "dir/foo", "dir/bar"},
+ },
+ {
+ name: "predict anything in dir with ./ prefix",
+ p: PredictFiles("*"),
+ argList: []string{"./dir", "./dir/", "./di"},
want: []string{"./dir/", "./dir/foo", "./dir/bar"},
},
{
name: "root directories",
p: PredictDirs("*"),
- argList: []string{"", ".", "./"},
+ argList: []string{""},
+ want: []string{"./", "dir/", "outer/"},
+ },
+ {
+ name: "root directories with ./ prefix",
+ p: PredictDirs("*"),
+ argList: []string{".", "./"},
want: []string{"./", "./dir/", "./outer/"},
},
{
name: "nested directories",
p: PredictDirs("*.md"),
- argList: []string{"ou", "./ou", "./outer", "./outer/"},
+ argList: []string{"ou", "outer", "outer/"},
+ want: []string{"outer/", "outer/inner/"},
+ },
+ {
+ name: "nested directories with ./ prefix",
+ p: PredictDirs("*.md"),
+ argList: []string{"./ou", "./outer", "./outer/"},
want: []string{"./outer/", "./outer/inner/"},
},
{
name: "nested inner directory",
p: PredictFiles("*.md"),
argList: []string{"outer/i"},
- want: []string{"./outer/inner/", "./outer/inner/readme.md"},
+ want: []string{"outer/inner/", "outer/inner/readme.md"},
},
}
diff --git a/utils.go b/utils.go
index a59a0d4..58b8b79 100644
--- a/utils.go
+++ b/utils.go
@@ -3,10 +3,11 @@ package complete
import (
"os"
"path/filepath"
+ "strings"
)
-// relativePath changes a file name to a relative name
-func relativePath(file string) string {
+// 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 {
@@ -17,15 +18,29 @@ func relativePath(file string) string {
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
}
- if rel != "." {
+
+ // fix ./ prefix of path
+ if rel != "." && strings.HasPrefix(last, ".") {
rel = "./" + rel
}
- if info, err := os.Stat(rel); err == nil && info.IsDir() {
- rel += "/"
+
+ return fixDirPath(rel)
+}
+
+func fixDirPath(path string) string {
+ info, err := os.Stat(path)
+ if err == nil && info.IsDir() && !strings.HasSuffix(path, "/") {
+ path += "/"
}
- return rel
+ return path
}