-
Notifications
You must be signed in to change notification settings - Fork 6
/
main.go
139 lines (124 loc) · 4.61 KB
/
main.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
139
// Copyright (c) 2016 David R. Jenni. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
A is a wrapper around several Go tools for use inside of Acme.
Usage:
A <cmd>
The following commands are available:
A addtags <tags> # Adds the given tags to the selected struct fields.
A cle <scope> # Shows possible targets of the function call under the cursor.
A clr <scope> # Shows possible callers of the function under the cursor.
A cs <scope> # Shows the path from the callgraph root to the function under the cursor.
A def # Shows the declaration for the identifier under the cursor.
A desc # Describes the declaration for the syntax under the cursor.
A doc # Shows the documentation for the entity under the cursor.
A err <scope> # Shows possible values of the error variable under the cursor.
A ex <name> # Extracts the selected statements to a new function/method with name <name>.
A fstruct # Fills a struct literal with default values.
A fswitch # Fills a (type) switch statement with case statements.
A fv # Shows the free variables of the selected snippet.
A impl <recv> <iface> # Generates method stubs with receiver <recv> for implementing the interface <iface> and inserts them at the location of the cursor.
A impls <scope> # Shows the `implements` relation for the type or method under the cursor.
A peers <scope> # Shows send/receive corresponding to the selected channel op.
A pto <scope> # Shows variables the selected pointer may point to.
A refs # Shows all refs to the entity denoted by identifier under the cursor.
A rmtags <tags> # Removes the given tags from the selected struct fields.
A rn <name> # Renames the entity under the cursor with <name>.
A share # Uploads the selected snippet to play.golang.org and prints the URL.
A what # Shows basic information about the selected syntax node.
<scope> is a comma-separated list of packages the analysis should be limited to, this parameter is optional.
The following tools are used:
golang.org/x/tools/cmd/gorename
golang.org/x/tools/cmd/guru
github.com/godoctor/godoctor
github.com/zmb3/gogetdoc
github.com/josharian/impl
github.com/fatih/gomodifytags
github.com/davidrjenni/reftools/cmd/fillstruct
github.com/davidrjenni/reftools/cmd/fillswitch
*/
package main
import (
"bytes"
"io"
"log"
"os"
"os/exec"
)
const usage = `Usage: A <cmd>
Commands:
addtags adds tags to the selected struct fields
cle shows possible targets of the selected function call
clr shows possible callers of the selected function
cs shows the path from the callgraph root to the selected function
def shows declaration of selected identifier
desc describes the selected syntax: definition, methods, etc.
doc shows documentation for items in Go source code
err shows possible values of the selected error variable
ex extracts statements to a new function/method
fstruct fills a struct literal with default values
fv shows declaration of selected identifier
impl generate method stubs for implementing an interface
impls shows the 'implements' relation for the selected type or method
peers shows send/receive corresponding to selected channel op
pto shows variables the selected pointer may point to
rmtags removes tags from the selected struct fields
rn renames the selected identifier
refs shows all refs to the entity denoted by selected identifier
share uploads the selected code to play.golang.org
what shows basic information about the selected syntax node
`
var cmds = map[string]func(selection, []string){
"addtags": addTags,
"cle": callees,
"clr": callers,
"cs": callstack,
"def": definition,
"desc": describe,
"doc": godoc,
"err": whicherrs,
"ex": extract,
"fstruct": fillstruct,
"fswitch": fillswitch,
"fv": freevars,
"impl": impl,
"impls": implements,
"peers": peers,
"pto": pointsto,
"refs": referrers,
"rmtags": rmTags,
"rn": rename,
"share": share,
"what": what,
}
func main() {
log.SetPrefix("")
log.SetFlags(0)
if len(os.Args) < 2 {
log.Fatal(usage)
}
s, err := readSelection()
if err != nil {
log.Fatalf("cannot read selection: %v\n", err)
}
f, ok := cmds[os.Args[1]]
if !ok {
log.Fatal(usage)
}
f(s, os.Args[2:])
}
func run(cmd string, args ...string) string {
return runWithStdin(nil, cmd, args...)
}
func runWithStdin(stdin io.Reader, cmd string, args ...string) string {
var buf bytes.Buffer
c := exec.Command(cmd, args...)
c.Stderr = os.Stderr
c.Stdout = &buf
c.Stdin = stdin
if err := c.Run(); err != nil {
log.Fatalf("%s failed: %v\n", cmd, err)
}
return buf.String()
}