...

Source file src/github.com/c-bata/go-prompt/completer/file.go

Documentation: github.com/c-bata/go-prompt/completer

     1  package completer
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"os/user"
     7  	"path/filepath"
     8  	"runtime"
     9  
    10  	prompt "github.com/c-bata/go-prompt"
    11  	"github.com/c-bata/go-prompt/internal/debug"
    12  )
    13  
    14  var (
    15  	// FilePathCompletionSeparator holds separate characters.
    16  	FilePathCompletionSeparator = string([]byte{' ', os.PathSeparator})
    17  )
    18  
    19  // FilePathCompleter is a completer for your local file system.
    20  // Please caution that you need to set OptionCompletionWordSeparator(completer.FilePathCompletionSeparator)
    21  // when you use this completer.
    22  type FilePathCompleter struct {
    23  	Filter        func(fi os.FileInfo) bool
    24  	IgnoreCase    bool
    25  	fileListCache map[string][]prompt.Suggest
    26  }
    27  
    28  func cleanFilePath(path string) (dir, base string, err error) {
    29  	if path == "" {
    30  		return ".", "", nil
    31  	}
    32  
    33  	var endsWithSeparator bool
    34  	if len(path) >= 1 && path[len(path)-1] == os.PathSeparator {
    35  		endsWithSeparator = true
    36  	}
    37  
    38  	if runtime.GOOS != "windows" && len(path) >= 2 && path[0:2] == "~/" {
    39  		me, err := user.Current()
    40  		if err != nil {
    41  			return "", "", err
    42  		}
    43  		path = filepath.Join(me.HomeDir, path[1:])
    44  	}
    45  	path = filepath.Clean(os.ExpandEnv(path))
    46  	dir = filepath.Dir(path)
    47  	base = filepath.Base(path)
    48  
    49  	if endsWithSeparator {
    50  		dir = path + string(os.PathSeparator) // Append slash(in POSIX) if path ends with slash.
    51  		base = ""                             // Set empty string if path ends with separator.
    52  	}
    53  	return dir, base, nil
    54  }
    55  
    56  // Complete returns suggestions from your local file system.
    57  func (c *FilePathCompleter) Complete(d prompt.Document) []prompt.Suggest {
    58  	if c.fileListCache == nil {
    59  		c.fileListCache = make(map[string][]prompt.Suggest, 4)
    60  	}
    61  
    62  	path := d.GetWordBeforeCursor()
    63  	dir, base, err := cleanFilePath(path)
    64  	if err != nil {
    65  		debug.Log("completer: cannot get current user:" + err.Error())
    66  		return nil
    67  	}
    68  
    69  	if cached, ok := c.fileListCache[dir]; ok {
    70  		return prompt.FilterHasPrefix(cached, base, c.IgnoreCase)
    71  	}
    72  
    73  	files, err := ioutil.ReadDir(dir)
    74  	if err != nil && os.IsNotExist(err) {
    75  		return nil
    76  	} else if err != nil {
    77  		debug.Log("completer: cannot read directory items:" + err.Error())
    78  		return nil
    79  	}
    80  
    81  	suggests := make([]prompt.Suggest, 0, len(files))
    82  	for _, f := range files {
    83  		if c.Filter != nil && !c.Filter(f) {
    84  			continue
    85  		}
    86  		suggests = append(suggests, prompt.Suggest{Text: f.Name()})
    87  	}
    88  	c.fileListCache[dir] = suggests
    89  	return prompt.FilterHasPrefix(suggests, base, c.IgnoreCase)
    90  }
    91  

View as plain text