File: file.go

package info (click to toggle)
golang-github-c-bata-go-prompt 0.2.5-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 396 kB
  • sloc: makefile: 37; python: 13; sh: 9
file content (90 lines) | stat: -rw-r--r-- 2,401 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package completer

import (
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"runtime"

	prompt "github.com/c-bata/go-prompt"
	"github.com/c-bata/go-prompt/internal/debug"
)

var (
	// FilePathCompletionSeparator holds separate characters.
	FilePathCompletionSeparator = string([]byte{' ', os.PathSeparator})
)

// FilePathCompleter is a completer for your local file system.
// Please caution that you need to set OptionCompletionWordSeparator(completer.FilePathCompletionSeparator)
// when you use this completer.
type FilePathCompleter struct {
	Filter        func(fi os.FileInfo) bool
	IgnoreCase    bool
	fileListCache map[string][]prompt.Suggest
}

func cleanFilePath(path string) (dir, base string, err error) {
	if path == "" {
		return ".", "", nil
	}

	var endsWithSeparator bool
	if len(path) >= 1 && path[len(path)-1] == os.PathSeparator {
		endsWithSeparator = true
	}

	if runtime.GOOS != "windows" && len(path) >= 2 && path[0:2] == "~/" {
		me, err := user.Current()
		if err != nil {
			return "", "", err
		}
		path = filepath.Join(me.HomeDir, path[1:])
	}
	path = filepath.Clean(os.ExpandEnv(path))
	dir = filepath.Dir(path)
	base = filepath.Base(path)

	if endsWithSeparator {
		dir = path + string(os.PathSeparator) // Append slash(in POSIX) if path ends with slash.
		base = ""                             // Set empty string if path ends with separator.
	}
	return dir, base, nil
}

// 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()
	dir, base, err := cleanFilePath(path)
	if err != nil {
		debug.Log("completer: cannot get current user:" + err.Error())
		return nil
	}

	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 {
		debug.Log("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) {
			continue
		}
		suggests = append(suggests, prompt.Suggest{Text: f.Name()})
	}
	c.fileListCache[dir] = suggests
	return prompt.FilterHasPrefix(suggests, base, c.IgnoreCase)
}