forked from KurokuLabs/margo
/
snippets.go
133 lines (108 loc) · 3.77 KB
/
snippets.go
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package golang
import (
"go/ast"
"margo.sh/golang/goutil"
"margo.sh/golang/snippets"
"margo.sh/mg"
"sort"
"strings"
)
var (
Snippets = SnippetFuncs(append([]snippets.SnippetFunc{ImportPathSnippet}, snippets.DefaultSnippets...)...)
)
// SnippetFunc is an alias of snippets.SnippetFunc
type SnippetFunc = snippets.SnippetFunc
type SnippetFuncsList struct {
mg.ReducerType
Funcs []SnippetFunc
}
func SnippetFuncs(l ...SnippetFunc) *SnippetFuncsList {
return &SnippetFuncsList{Funcs: l}
}
func (sf *SnippetFuncsList) RCond(mx *mg.Ctx) bool {
return mx.ActionIs(mg.QueryCompletions{}) && mx.LangIs(mg.Go)
}
func (sf *SnippetFuncsList) Reduce(mx *mg.Ctx) *mg.State {
cx := NewViewCursorCtx(mx)
var cl []mg.Completion
for _, f := range sf.Funcs {
cl = append(cl, f(cx)...)
}
for i, _ := range cl {
sf.fixCompletion(&cl[i])
}
return mx.State.AddCompletions(cl...)
}
func (sf *SnippetFuncsList) fixCompletion(c *mg.Completion) {
c.Src = goutil.DedentCompletion(c.Src)
if c.Tag == "" {
c.Tag = mg.SnippetTag
}
}
// PackageNameSnippet is an alias of snippets.PackageNameSnippet
func PackageNameSnippet(cx *CompletionCtx) []mg.Completion { return snippets.PackageNameSnippet(cx) }
// MainFuncSnippet is an alias of snippets.MainFuncSnippet
func MainFuncSnippet(cx *CompletionCtx) []mg.Completion { return snippets.MainFuncSnippet(cx) }
// InitFuncSnippet is an alias of snippets.InitFuncSnippet
func InitFuncSnippet(cx *CompletionCtx) []mg.Completion { return snippets.InitFuncSnippet(cx) }
// FuncSnippet is an alias of snippets.FuncSnippet
func FuncSnippet(cx *CompletionCtx) []mg.Completion { return snippets.FuncSnippet(cx) }
// MethodSnippet is an alias of snippets.MethodSnippet
func MethodSnippet(cx *CompletionCtx) []mg.Completion { return snippets.MethodSnippet(cx) }
// GenDeclSnippet is an alias of snippets.GenDeclSnippet
func GenDeclSnippet(cx *CompletionCtx) []mg.Completion { return snippets.GenDeclSnippet(cx) }
// MapSnippet is an alias of snippets.MapSnippet
func MapSnippet(cx *CompletionCtx) []mg.Completion { return snippets.MapSnippet(cx) }
// TypeSnippet is an alias of snippets.TypeSnippet
func TypeSnippet(cx *CompletionCtx) []mg.Completion { return snippets.TypeSnippet(cx) }
// AppendSnippet is an alias of snippets.AppendSnippet
func AppendSnippet(cx *CompletionCtx) []mg.Completion { return snippets.AppendSnippet(cx) }
// DocSnippet is an alias of snippets.DocSnippet
func DocSnippet(cx *CompletionCtx) []mg.Completion { return snippets.DocSnippet(cx) }
func ImportPathSnippet(cx *CompletionCtx) []mg.Completion {
lit, ok := cx.Node.(*ast.BasicLit)
if !ok || !cx.Scope.Is(ImportPathScope) {
return nil
}
pfx := unquote(lit.Value)
if i := strings.LastIndexByte(pfx, '/'); i >= 0 {
pfx = pfx[:i+1]
} else {
// if there's no slash, don't do any filtering
// this allows the fuzzy selection to work in editor
pfx = ""
}
pkl := mctl.plst.View().List
skip := map[string]bool{}
srcDir := cx.View.Dir()
for _, spec := range cx.AstFile.Imports {
skip[unquote(spec.Path.Value)] = true
}
cl := make([]mg.Completion, 0, len(pkl))
for _, p := range pkl {
if skip[p.ImportPath] || !p.Importable(srcDir) {
continue
}
src := p.ImportPath
if pfx != "" {
src = strings.TrimPrefix(p.ImportPath, pfx)
if src == p.ImportPath || src == "" {
continue
}
// BUG: in ST
// given candidate `margo.sh/xxx`, and prefix `margo.sh`
// if we return xxx, it will replace the whole path
if !strings.ContainsRune(src, '/') {
src = p.ImportPath
}
}
cl = append(cl, mg.Completion{
Query: p.ImportPath,
Src: src,
})
}
sort.Slice(cl, func(i, j int) bool { return cl[i].Query < cl[j].Query })
return cl
}
// DeferSnippet is an alias of snippets.DeferSnippet
func DeferSnippet(cx *CompletionCtx) []mg.Completion { return snippets.DeferSnippet(cx) }