diff options
Diffstat (limited to 'vendor/github.com/posener/complete/predict_files.go')
-rw-r--r-- | vendor/github.com/posener/complete/predict_files.go | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/vendor/github.com/posener/complete/predict_files.go b/vendor/github.com/posener/complete/predict_files.go new file mode 100644 index 0000000..c8adf7e --- /dev/null +++ b/vendor/github.com/posener/complete/predict_files.go | |||
@@ -0,0 +1,108 @@ | |||
1 | package complete | ||
2 | |||
3 | import ( | ||
4 | "io/ioutil" | ||
5 | "os" | ||
6 | "path/filepath" | ||
7 | "strings" | ||
8 | |||
9 | "github.com/posener/complete/match" | ||
10 | ) | ||
11 | |||
12 | // PredictDirs will search for directories in the given started to be typed | ||
13 | // path, if no path was started to be typed, it will complete to directories | ||
14 | // in the current working directory. | ||
15 | func PredictDirs(pattern string) Predictor { | ||
16 | return files(pattern, false) | ||
17 | } | ||
18 | |||
19 | // PredictFiles will search for files matching the given pattern in the started to | ||
20 | // be typed path, if no path was started to be typed, it will complete to files that | ||
21 | // match the pattern in the current working directory. | ||
22 | // To match any file, use "*" as pattern. To match go files use "*.go", and so on. | ||
23 | func PredictFiles(pattern string) Predictor { | ||
24 | return files(pattern, true) | ||
25 | } | ||
26 | |||
27 | func files(pattern string, allowFiles bool) PredictFunc { | ||
28 | |||
29 | // search for files according to arguments, | ||
30 | // if only one directory has matched the result, search recursively into | ||
31 | // this directory to give more results. | ||
32 | return func(a Args) (prediction []string) { | ||
33 | prediction = predictFiles(a, pattern, allowFiles) | ||
34 | |||
35 | // if the number of prediction is not 1, we either have many results or | ||
36 | // have no results, so we return it. | ||
37 | if len(prediction) != 1 { | ||
38 | return | ||
39 | } | ||
40 | |||
41 | // only try deeper, if the one item is a directory | ||
42 | if stat, err := os.Stat(prediction[0]); err != nil || !stat.IsDir() { | ||
43 | return | ||
44 | } | ||
45 | |||
46 | a.Last = prediction[0] | ||
47 | return predictFiles(a, pattern, allowFiles) | ||
48 | } | ||
49 | } | ||
50 | |||
51 | func predictFiles(a Args, pattern string, allowFiles bool) []string { | ||
52 | if strings.HasSuffix(a.Last, "/..") { | ||
53 | return nil | ||
54 | } | ||
55 | |||
56 | dir := a.Directory() | ||
57 | files := listFiles(dir, pattern, allowFiles) | ||
58 | |||
59 | // add dir if match | ||
60 | files = append(files, dir) | ||
61 | |||
62 | return PredictFilesSet(files).Predict(a) | ||
63 | } | ||
64 | |||
65 | // PredictFilesSet predict according to file rules to a given set of file names | ||
66 | func PredictFilesSet(files []string) PredictFunc { | ||
67 | return func(a Args) (prediction []string) { | ||
68 | // add all matching files to prediction | ||
69 | for _, f := range files { | ||
70 | f = fixPathForm(a.Last, f) | ||
71 | |||
72 | // test matching of file to the argument | ||
73 | if match.File(f, a.Last) { | ||
74 | prediction = append(prediction, f) | ||
75 | } | ||
76 | } | ||
77 | return | ||
78 | } | ||
79 | } | ||
80 | |||
81 | func listFiles(dir, pattern string, allowFiles bool) []string { | ||
82 | // set of all file names | ||
83 | m := map[string]bool{} | ||
84 | |||
85 | // list files | ||
86 | if files, err := filepath.Glob(filepath.Join(dir, pattern)); err == nil { | ||
87 | for _, f := range files { | ||
88 | if stat, err := os.Stat(f); err != nil || stat.IsDir() || allowFiles { | ||
89 | m[f] = true | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | |||
94 | // list directories | ||
95 | if dirs, err := ioutil.ReadDir(dir); err == nil { | ||
96 | for _, d := range dirs { | ||
97 | if d.IsDir() { | ||
98 | m[filepath.Join(dir, d.Name())] = true | ||
99 | } | ||
100 | } | ||
101 | } | ||
102 | |||
103 | list := make([]string, 0, len(m)) | ||
104 | for k := range m { | ||
105 | list = append(list, k) | ||
106 | } | ||
107 | return list | ||
108 | } | ||