Roughly add all go commands
This commit is contained in:
parent
c8263230e1
commit
1af7c0b3b7
|
@ -19,7 +19,7 @@ func (c *Command) options(args []string) (options []Option, only bool) {
|
|||
|
||||
// if prev has something that needs to follow it,
|
||||
// it is the most relevant completion
|
||||
if predicate, ok := c.Flags[last(args)]; ok && predicate.Expects {
|
||||
if predicate, ok := c.Flags[last(args)]; ok && !predicate.ExpectsNothing {
|
||||
return predicate.predict(), true
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ func (c *Command) options(args []string) (options []Option, only bool) {
|
|||
}
|
||||
|
||||
// add additional expected argument of the command
|
||||
if c.Args.Expects {
|
||||
if !c.Args.ExpectsNothing {
|
||||
options = append(options, c.Args.predict()...)
|
||||
}
|
||||
|
||||
|
|
|
@ -21,11 +21,11 @@ func New(c Command) *Completer {
|
|||
|
||||
func (c *Completer) Complete() {
|
||||
args := getLine()
|
||||
logger("Completing args: %s", args)
|
||||
Log("Completing args: %s", args)
|
||||
|
||||
options := c.complete(args)
|
||||
|
||||
logger("Completion: %s", options)
|
||||
Log("Completion: %s", options)
|
||||
output(options)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,33 +4,187 @@ import (
|
|||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
var (
|
||||
build = complete.Command{
|
||||
var predictEllipsis = complete.Predicate{
|
||||
Predictor: func() []complete.Option { return []complete.Option{complete.Arg("./...")} },
|
||||
}
|
||||
|
||||
var goFilesOrPackages = complete.PredictFiles("**.go").
|
||||
Or(complete.PredictDirs("./")).
|
||||
Or(predictEllipsis)
|
||||
|
||||
func main() {
|
||||
build := complete.Command{
|
||||
Flags: complete.Flags{
|
||||
"-o": complete.PredictFiles("*"),
|
||||
"-o": complete.PredictFiles("**"),
|
||||
"-i": complete.PredictNothing,
|
||||
|
||||
"-a": complete.PredictNothing,
|
||||
"-n": complete.PredictNothing,
|
||||
"-p": complete.PredictAnything,
|
||||
"-race": complete.PredictNothing,
|
||||
"-msan": complete.PredictNothing,
|
||||
"-v": complete.PredictNothing,
|
||||
"-work": complete.PredictNothing,
|
||||
"-x": complete.PredictNothing,
|
||||
"-asmflags": complete.PredictAnything,
|
||||
"-buildmode": complete.PredictAnything,
|
||||
"-compiler": complete.PredictAnything,
|
||||
"-gccgoflags": complete.PredictAnything,
|
||||
"-gcflags": complete.PredictAnything,
|
||||
"-installsuffix": complete.PredictAnything,
|
||||
"-ldflags": complete.PredictAnything,
|
||||
"-linkshared": complete.PredictNothing,
|
||||
"-pkgdir": complete.PredictDirs("./"),
|
||||
"-tags": complete.PredictAnything,
|
||||
"-toolexec": complete.PredictAnything,
|
||||
},
|
||||
Args: complete.PredictFiles("**.go").Or(complete.PredictDirs("./")),
|
||||
Args: goFilesOrPackages,
|
||||
}
|
||||
|
||||
test = complete.Command{
|
||||
run := complete.Command{
|
||||
Flags: complete.Flags{
|
||||
"-run": complete.PredictAnything,
|
||||
"-count": complete.PredictAnything,
|
||||
"-exec": complete.PredictAnything,
|
||||
},
|
||||
Args: complete.PredictFiles("**.go"),
|
||||
}
|
||||
|
||||
gogo = complete.Command{
|
||||
test := complete.Command{
|
||||
Flags: complete.Flags{
|
||||
"-args": complete.PredictAnything,
|
||||
"-c": complete.PredictNothing,
|
||||
"-exec": complete.PredictAnything,
|
||||
|
||||
"-bench": predictTest("Benchmark"),
|
||||
"-benchtime": complete.PredictAnything,
|
||||
"-count": complete.PredictAnything,
|
||||
"-cover": complete.PredictNothing,
|
||||
"-covermode": complete.PredictSet([]string{"set", "count", "atomic"}),
|
||||
"-coverpkg": complete.PredictDirs("./"),
|
||||
"-cpu": complete.PredictAnything,
|
||||
"-run": predictTest("test"),
|
||||
"-short": complete.PredictNothing,
|
||||
"-timeout": complete.PredictAnything,
|
||||
|
||||
"-benchmem": complete.PredictNothing,
|
||||
"-blockprofile": complete.PredictFiles("**.out"),
|
||||
"-blockprofilerate": complete.PredictAnything,
|
||||
"-coverprofile": complete.PredictFiles("**.out"),
|
||||
"-cpuprofile": complete.PredictFiles("**.out"),
|
||||
"-memprofile": complete.PredictFiles("**.out"),
|
||||
"-memprofilerate": complete.PredictAnything,
|
||||
"-mutexprofile": complete.PredictFiles("**.out"),
|
||||
"-mutexprofilefraction": complete.PredictAnything,
|
||||
"-outputdir": complete.PredictDirs("./"),
|
||||
"-trace": complete.PredictFiles("**.out"),
|
||||
},
|
||||
Args: goFilesOrPackages,
|
||||
}
|
||||
|
||||
fmt := complete.Command{
|
||||
Flags: complete.Flags{
|
||||
"-n": complete.PredictNothing,
|
||||
"-x": complete.PredictNothing,
|
||||
},
|
||||
Args: goFilesOrPackages,
|
||||
}
|
||||
|
||||
get := complete.Command{
|
||||
Flags: complete.Flags{
|
||||
"-d": complete.PredictNothing,
|
||||
"-f": complete.PredictNothing,
|
||||
"-fix": complete.PredictNothing,
|
||||
"-insecure": complete.PredictNothing,
|
||||
"-t": complete.PredictNothing,
|
||||
"-u": complete.PredictNothing,
|
||||
},
|
||||
Args: goFilesOrPackages,
|
||||
}
|
||||
|
||||
generate := complete.Command{
|
||||
Flags: complete.Flags{
|
||||
"-n": complete.PredictNothing,
|
||||
"-x": complete.PredictNothing,
|
||||
"-v": complete.PredictNothing,
|
||||
"-run": complete.PredictAnything,
|
||||
},
|
||||
Args: goFilesOrPackages,
|
||||
}
|
||||
|
||||
vet := complete.Command{
|
||||
Flags: complete.Flags{
|
||||
"-n": complete.PredictNothing,
|
||||
"-x": complete.PredictNothing,
|
||||
},
|
||||
Args: complete.PredictDirs("./"),
|
||||
}
|
||||
|
||||
list := complete.Command{
|
||||
Flags: complete.Flags{
|
||||
"-e": complete.PredictNothing,
|
||||
"-f": complete.PredictAnything,
|
||||
"-json": complete.PredictNothing,
|
||||
},
|
||||
Args: complete.PredictDirs("./"),
|
||||
}
|
||||
|
||||
tool := complete.Command{
|
||||
Flags: complete.Flags{
|
||||
"-n": complete.PredictNothing,
|
||||
},
|
||||
Args: complete.PredictAnything,
|
||||
}
|
||||
|
||||
clean := complete.Command{
|
||||
Flags: complete.Flags{
|
||||
"-i": complete.PredictNothing,
|
||||
"-r": complete.PredictNothing,
|
||||
"-n": complete.PredictNothing,
|
||||
"-x": complete.PredictNothing,
|
||||
},
|
||||
Args: complete.PredictDirs("./"),
|
||||
}
|
||||
|
||||
env := complete.Command{
|
||||
Args: complete.PredictAnything,
|
||||
}
|
||||
|
||||
bug := complete.Command{}
|
||||
version := complete.Command{}
|
||||
|
||||
fix := complete.Command{
|
||||
Args: complete.PredictDirs("./"),
|
||||
}
|
||||
|
||||
// commands that also accepts the build flags
|
||||
for name, options := range build.Flags {
|
||||
test.Flags[name] = options
|
||||
run.Flags[name] = options
|
||||
list.Flags[name] = options
|
||||
vet.Flags[name] = options
|
||||
}
|
||||
|
||||
gogo := complete.Command{
|
||||
Sub: complete.Commands{
|
||||
"build": build,
|
||||
"test": test,
|
||||
"build": build,
|
||||
"install": build, // install and build have the same flags
|
||||
"run": run,
|
||||
"test": test,
|
||||
"fmt": fmt,
|
||||
"get": get,
|
||||
"generate": generate,
|
||||
"vet": vet,
|
||||
"list": list,
|
||||
"tool": tool,
|
||||
"clean": clean,
|
||||
"env": env,
|
||||
"bug": bug,
|
||||
"fix": fix,
|
||||
"version": version,
|
||||
},
|
||||
Flags: complete.Flags{
|
||||
"-h": complete.PredictNothing,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func main() {
|
||||
complete.New(gogo).Complete()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
func predictTest(testType string) complete.Predicate {
|
||||
return complete.Predicate{
|
||||
Predictor: func() []complete.Option {
|
||||
tests := testNames(testType)
|
||||
options := make([]complete.Option, len(tests))
|
||||
for i := range tests {
|
||||
options[i] = complete.Arg(tests[i])
|
||||
}
|
||||
return options
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// get all test names in current directory
|
||||
func testNames(testType string) (tests []string) {
|
||||
filepath.Walk("./", func(path string, info os.FileInfo, err error) error {
|
||||
// if not a test file, skip
|
||||
if !strings.HasSuffix(path, "_test.go") {
|
||||
return nil
|
||||
}
|
||||
// inspect test file and append all the test names
|
||||
tests = append(tests, testsInFile(testType, path)...)
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func testsInFile(testType, path string) (tests []string) {
|
||||
fset := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset, path, nil, 0)
|
||||
if err != nil {
|
||||
complete.Log("Failed parsing %s: %s", path, err)
|
||||
return nil
|
||||
}
|
||||
for _, d := range f.Decls {
|
||||
if f, ok := d.(*ast.FuncDecl); ok {
|
||||
name := f.Name.String()
|
||||
if strings.HasPrefix(name, testType) {
|
||||
tests = append(tests, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
7
log.go
7
log.go
|
@ -7,7 +7,12 @@ import (
|
|||
"os"
|
||||
)
|
||||
|
||||
var logger = getLogger()
|
||||
// Log is used for debugging purposes
|
||||
// since complete is running on tab completion, it is nice to
|
||||
// have logs to the stderr (when writing your own completer)
|
||||
// to write logs, set the COMP_DEBUG environment variable and
|
||||
// use complete.Log in the complete program
|
||||
var Log = getLogger()
|
||||
|
||||
func getLogger() func(format string, args ...interface{}) {
|
||||
var logfile io.Writer = ioutil.Discard
|
||||
|
|
|
@ -29,11 +29,11 @@ func (a ArgFileName) String() string {
|
|||
func (a ArgFileName) Matches(prefix string) bool {
|
||||
full, err := filepath.Abs(string(a))
|
||||
if err != nil {
|
||||
logger("failed getting abs path of %s: %s", a, err)
|
||||
Log("failed getting abs path of %s: %s", a, err)
|
||||
}
|
||||
prefixFull, err := filepath.Abs(prefix)
|
||||
if err != nil {
|
||||
logger("failed getting abs path of %s: %s", prefix, err)
|
||||
Log("failed getting abs path of %s: %s", prefix, err)
|
||||
}
|
||||
|
||||
// if the file has the prefix as prefix,
|
||||
|
|
35
predicate.go
35
predicate.go
|
@ -7,10 +7,10 @@ import (
|
|||
|
||||
// Predicate determines what terms can follow a command or a flag
|
||||
type Predicate struct {
|
||||
// Expects determine if the predicate expects something after.
|
||||
// ExpectsNothing determine if the predicate expects something after.
|
||||
// flags/commands that do not expect any specific argument should
|
||||
// leave it on false
|
||||
Expects bool
|
||||
ExpectsNothing bool
|
||||
// Predictor is function that returns list of arguments that can
|
||||
// come after the flag/command
|
||||
Predictor func() []Option
|
||||
|
@ -20,8 +20,8 @@ type Predicate struct {
|
|||
// returns the union of their predication
|
||||
func (p Predicate) Or(other Predicate) Predicate {
|
||||
return Predicate{
|
||||
Expects: p.Expects && other.Expects,
|
||||
Predictor: func() []Option { return append(p.predict(), other.predict()...) },
|
||||
ExpectsNothing: p.ExpectsNothing && other.ExpectsNothing,
|
||||
Predictor: func() []Option { return append(p.predict(), other.predict()...) },
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,23 +33,30 @@ func (p Predicate) predict() []Option {
|
|||
}
|
||||
|
||||
var (
|
||||
PredictNothing = Predicate{Expects: false}
|
||||
PredictAnything = Predicate{Expects: true}
|
||||
PredictNothing = Predicate{ExpectsNothing: true}
|
||||
PredictAnything = Predicate{}
|
||||
)
|
||||
|
||||
func PredictFiles(pattern string) Predicate {
|
||||
func PredictSet(options []string) Predicate {
|
||||
return Predicate{
|
||||
Expects: true,
|
||||
Predictor: glob(pattern),
|
||||
Predictor: func() []Option {
|
||||
ret := make([]Option, len(options))
|
||||
for i := range options {
|
||||
ret[i] = Arg(options[i])
|
||||
}
|
||||
return ret
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func PredictFiles(pattern string) Predicate {
|
||||
return Predicate{Predictor: glob(pattern)}
|
||||
}
|
||||
|
||||
func PredictDirs(path string) Predicate {
|
||||
return Predicate{
|
||||
Expects: true,
|
||||
Predictor: dirs(path),
|
||||
}
|
||||
return Predicate{Predictor: dirs(path)}
|
||||
}
|
||||
|
||||
func dirs(path string) func() []Option {
|
||||
return func() (options []Option) {
|
||||
dirs := []string{}
|
||||
|
@ -70,7 +77,7 @@ func glob(pattern string) func() []Option {
|
|||
return func() []Option {
|
||||
files, err := filepath.Glob(pattern)
|
||||
if err != nil {
|
||||
logger("failed glob operation with pattern '%s': %s", pattern, err)
|
||||
Log("failed glob operation with pattern '%s': %s", pattern, err)
|
||||
}
|
||||
if !filepath.IsAbs(pattern) {
|
||||
filesToRel(files)
|
||||
|
|
Loading…
Reference in New Issue