github.com/linux4life798/complete@v1.1.2-0.20180410072631-7426158f3bcb/predict_files.go (about) 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 }