all repos

viye @ 4e123d7d637534d8d950d5453448cba198a520f9

my shot at reimplementing xiki

viye/internal/plumbing/files/files.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
add config, 2 months ago
1
package files
2
3
import (
4
	"bufio"
5
	"fmt"
6
	"os"
7
	"path/filepath"
8
	"strings"
9
10
	"github.com/olexsmir/viye/internal/viye"
11
)
12
13
type Tool struct{}
14
15
func (Tool) Name() string { return "files(~/..., /...)" }
16
17
func (Tool) Match(ctx *viye.Context) bool {
18
	p := ctx.Path[0]
19
	if p == "~" || strings.HasPrefix(p, "/") {
20
		return true
21
	}
22
	_, err := os.Stat(filepath.Join(ctx.Dir, p))
23
	return err == nil
24
}
25
26
func (Tool) Execute(ctx *viye.Context) (string, error) {
27
	path := resolve(ctx.Path[0], ctx.Dir)
28
29
	info, err := os.Stat(path)
30
	if err != nil {
31
		return "", err
32
	}
33
34
	switch {
35
	case info.IsDir():
36
		if len(ctx.Path) == 1 {
37
			ls, err := listDir(path)
38
			if err != nil {
39
				return "", err
40
			}
41
			return viye.FormatBulletlist(ls), nil
42
		}
43
		ctx.Dir = path
44
		ctx.Path = ctx.Path[1:]
45
		return ctx.Next()
46
47
	// case info.Mode()&0o111 != 0:
48
	// 	return runExec(path)
49
50
	default:
51
		s, err := head(path, 10)
52
		if err != nil {
53
			return "", err
54
		}
55
		return s, nil
56
	}
57
}
58
59
func resolve(p, dir string) string {
60
	if p == "~" {
61
		home, _ := os.UserHomeDir()
62
		return home
63
	}
64
	if strings.HasPrefix(p, "~/") {
65
		home, _ := os.UserHomeDir()
66
		return filepath.Join(home, p[2:])
67
	}
68
	if filepath.IsAbs(p) {
69
		return filepath.Clean(p)
70
	}
71
	return filepath.Join(dir, p)
72
}
73
74
func listDir(dir string) (string, error) {
75
	entries, err := os.ReadDir(dir)
76
	if err != nil {
77
		return "", err
78
	}
79
	var b strings.Builder
80
	for _, e := range entries {
81
		name := e.Name()
82
		if e.IsDir() {
83
			name += "/"
84
		}
85
		b.WriteString(name)
86
		b.WriteByte('\n')
87
	}
88
	return b.String(), nil
89
}
90
91
func head(path string, n int) (string, error) {
92
	f, err := os.Open(path)
93
	if err != nil {
94
		return "", err
95
	}
96
	defer f.Close()
97
98
	sc := bufio.NewScanner(f)
99
	var b strings.Builder
100
	for i := 0; i < n && sc.Scan(); i++ {
101
		fmt.Fprintf(&b, "| %s\n", sc.Text())
102
	}
103
	if sc.Scan() {
104
		b.WriteString("| ...\n")
105
	}
106
	return b.String(), sc.Err()
107
}