-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfuncmap.go
More file actions
94 lines (77 loc) · 1.93 KB
/
funcmap.go
File metadata and controls
94 lines (77 loc) · 1.93 KB
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
package main
import (
"fmt"
"reflect"
"sort"
"strings"
"text/template"
sprig "github.com/Masterminds/sprig/v3"
)
func funcMap() template.FuncMap {
// NOTE: FuncMap is for html/template, TxtFuncMap is for text/template
funcMap := sprig.TxtFuncMap()
// add (meta-)functions to describe functions
// TODO: include built-in funcs
funcMap["searchFunc"] = searchFunc(funcMap)
funcMap["docFunc"] = docFunc(funcMap)
return funcMap
}
func searchFunc(
funcMap template.FuncMap,
) func(string) []string {
return func(prefix string) []string {
keys := []string{}
for k := range funcMap {
if strings.HasPrefix(k, prefix) {
keys = append(keys, k)
}
}
// sort alphabetically
sort.Strings(keys)
return keys
}
}
func docFunc(
funcMap template.FuncMap,
) func(string) string {
return func(name string) string {
rt, ok := findElement(name, funcMap)
if !ok {
return fmt.Sprintf("function %s is not defined", name)
}
if rt.Kind() != reflect.Func {
return fmt.Sprintf("%s is not a function", name)
}
paramTypes := []string{}
for i := 0; i < rt.NumIn(); i++ {
paramTypes = append(paramTypes, rt.In(i).String())
}
if rt.IsVariadic() {
paramTypes[len(paramTypes)-1] = toVariadic(paramTypes[len(paramTypes)-1])
}
returnTypes := []string{}
for i := 0; i < rt.NumOut(); i++ {
returnTypes = append(returnTypes, rt.Out(i).String())
}
paramList := strings.Join(paramTypes, " ")
returnList := strings.Join(returnTypes, " ")
if paramList == "" {
return fmt.Sprintf("%s -> (%s)", name, returnList)
}
return fmt.Sprintf("%s %s -> (%s)", name, paramList, returnList)
}
}
func findElement(
name string,
funcMap template.FuncMap,
) (reflect.Type, bool) {
elem, ok := funcMap[name]
if ok {
return reflect.TypeOf(elem), true
}
return nil, false
}
func toVariadic(typeStr string) string {
// replace prefix `[]` to `...` in variadic parameter
return "..." + strings.TrimPrefix(typeStr, "[]")
}