-
-
Notifications
You must be signed in to change notification settings - Fork 43
/
symbol.go
138 lines (124 loc) · 3.83 KB
/
symbol.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
134
135
136
137
138
package golang
import (
"fmt"
"regexp"
"strings"
"github.com/carapace-sh/carapace"
"github.com/carapace-sh/carapace-bin/pkg/styles"
)
type SymbolOpts struct {
Package string
Unexported bool
}
// ActionSymbols completes symbols of given package
//
// Action
// ActionCallback
func ActionSymbols(opts SymbolOpts) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
args := []string{"doc", "-short"}
if opts.Unexported {
args = append(args, "-u")
}
args = append(args, opts.Package)
return carapace.ActionExecCommand("go", args...)(func(output []byte) carapace.Action {
lines := strings.Split(string(output), "\n")
r := regexp.MustCompile(`^ *(?P<type>var|func|type|const) (?P<symbol>[^( =\[]+).*`) // TODO incomplete (e.g. generics))
variables := make([]string, 0)
functions := make([]string, 0)
types := make([]string, 0)
constants := make([]string, 0)
for _, line := range lines {
if matches := r.FindStringSubmatch(line); matches != nil {
switch matches[1] {
case "var":
variables = append(variables, matches[2])
case "func":
functions = append(functions, matches[2])
case "type":
types = append(types, matches[2])
case "const":
constants = append(constants, matches[2])
default:
}
}
}
return carapace.Batch(
carapace.ActionValues(variables...).Style(styles.Golang.Variable).Tag("variables"),
carapace.ActionValues(functions...).Style(styles.Golang.Function).Tag("functions"),
carapace.ActionValues(types...).Style(styles.Golang.Type).Tag("types"),
carapace.ActionValues(constants...).Style(styles.Golang.Constant).Tag("constants"),
).ToA()
})
})
}
type MethodOrFieldOpts struct {
Package string
Symbol string
Unexported bool
}
// ActionMethodOrFields completes methods and fields of given symbol
//
// Cache
// Chdir
func ActionMethodOrFields(opts MethodOrFieldOpts) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
args := []string{"doc", "-short"}
if opts.Unexported {
args = append(args, "-u")
}
args = append(args, opts.Package, opts.Symbol)
return carapace.ActionExecCommand("go", args...)(func(output []byte) carapace.Action {
lines := strings.Split(string(output), "\n")
rFunc := regexp.MustCompile(fmt.Sprintf(`^func \([^ ]+ \*?%v(\[[^)]+)?\) (?P<method>[^( =]+).*`, opts.Symbol))
rType := regexp.MustCompile(fmt.Sprintf(`^type %v[\[ ].*\{$`, opts.Symbol))
methods := make([]string, 0)
for _, line := range lines {
if matches := rFunc.FindStringSubmatch(line); matches != nil {
methods = append(methods, matches[2])
}
}
found := false
fields := make([]string, 0)
for _, line := range lines {
if rType.MatchString(line) {
found = true
continue
}
if !found {
continue
}
if strings.HasPrefix(line, "}") {
break
}
line = strings.SplitN(line, "//", 2)[0]
line = strings.TrimSpace(line)
if f := strings.Fields(line); len(f) > 1 {
fields = append(fields, f[0])
}
}
return carapace.Batch(
carapace.ActionValues(methods...).Style(styles.Golang.Function).Tag("functions"),
carapace.ActionValues(fields...).Style(styles.Golang.Field).Tag("fields"),
).ToA()
})
})
}
// ActionSymbolTypes completes symbol types
//
// t (static text segment symbol)
// R (read-only data segment symbol)
func ActionSymbolTypes() carapace.Action {
return carapace.ActionValuesDescribed(
"T", "text (code) segment symbol",
"t", "static text segment symbol",
"R", "read-only data segment symbol",
"r", "static read-only data segment symbol",
"D", "data segment symbol",
"d", "static data segment symbol",
"B", "bss segment symbol",
"b", "static bss segment symbol",
"C", "constant address",
"U", "referenced but undefined symbol",
)
}