From a537115cfd76f309735a3535912b1d5034f1fdbe Mon Sep 17 00:00:00 2001 From: c-bata Date: Sat, 23 Jun 2018 22:30:33 +0900 Subject: [PATCH] Add FileSystemCompleter and example --- _tools/complete_file/main.go | 30 +++++++++++++++++++ completer/file.go | 56 ++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 _tools/complete_file/main.go create mode 100644 completer/file.go diff --git a/_tools/complete_file/main.go b/_tools/complete_file/main.go new file mode 100644 index 00000000..a7420b32 --- /dev/null +++ b/_tools/complete_file/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "os" + "strings" + + "github.com/c-bata/go-prompt" + "github.com/c-bata/go-prompt/completer" +) + +func executor(in string) { + fmt.Println("Your input: " + in) +} + +func main() { + c := completer.FilePathCompleter{ + IgnoreCase: true, + Filter: func(fi os.FileInfo, filename string) bool { + return fi.IsDir() || strings.HasSuffix(fi.Name(), ".go") + }, + } + p := prompt.New( + executor, + c.Complete, + prompt.OptionPrefix(">>> "), + prompt.OptionCompletionWordSeparator(completer.FilePathCompletionSeparator), + ) + p.Run() +} diff --git a/completer/file.go b/completer/file.go new file mode 100644 index 00000000..fab9bab5 --- /dev/null +++ b/completer/file.go @@ -0,0 +1,56 @@ +package completer + +import ( + "io/ioutil" + "log" + "os" + "path/filepath" + + "github.com/c-bata/go-prompt" +) + +var ( + FilePathCompletionSeparator = string([]byte{' ', os.PathSeparator}) +) + +// FilePathCompleter is a completer for your local file system. +type FilePathCompleter struct { + Filter func(fi os.FileInfo, filename string) bool + IgnoreCase bool + fileListCache map[string][]prompt.Suggest +} + +// Complete returns suggestions from your local file system. +func (c *FilePathCompleter) Complete(d prompt.Document) []prompt.Suggest { + if c.fileListCache == nil { + c.fileListCache = make(map[string][]prompt.Suggest, 4) + } + path := d.GetWordBeforeCursor() + base := filepath.Base(path) + if len(path) == 0 || path[len(path)-1] == os.PathSeparator { + base = "" + } + + dir := filepath.Dir(path) + if cached, ok := c.fileListCache[dir]; ok { + return prompt.FilterHasPrefix(cached, base, c.IgnoreCase) + } + + files, err := ioutil.ReadDir(dir) + if err != nil && os.IsNotExist(err) { + return nil + } else if err != nil { + log.Print("[ERROR] completer: cannot read directory items " + err.Error()) + return nil + } + + suggests := make([]prompt.Suggest, 0, len(files)) + for _, f := range files { + if c.Filter != nil && !c.Filter(f, f.Name()) { + continue + } + suggests = append(suggests, prompt.Suggest{Text: f.Name()}) + } + c.fileListCache[dir] = suggests + return prompt.FilterHasPrefix(suggests, base, c.IgnoreCase) +}