-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a6761f9
commit a0c5e38
Showing
7 changed files
with
399 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,26 @@ | ||
# gostdsym | ||
Fuzzy finding go doc symbols | ||
# Fuzzy finding go doc symbols | ||
|
||
`stdsym` simplifies Go documentation exploration by extracting all exported | ||
symbols from the standard library, enabling fuzzy searching through Go | ||
documents. | ||
|
||
## Demo | ||
|
||
Watch a quick demo showcasing the usage of this tool: | ||
|
||
![Demo](./demo.gif) | ||
|
||
## Installation | ||
|
||
Get started quickly with `stdsym`: | ||
|
||
``` | ||
go install github.com/lotusirous/gostdsym/stdsym@latest | ||
``` | ||
|
||
Create a handy `gdoc` alias for instant symbol lookups: | ||
|
||
```bash | ||
$ stdsym > ~/.gostdsym | ||
$ alias gdoc="cat ~/.gostdsym |fzf | xargs go doc " | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module github.com/lotusirous/gostdsym | ||
|
||
go 1.21.5 | ||
|
||
require golang.org/x/tools v0.16.1 | ||
|
||
require golang.org/x/mod v0.14.0 // indirect |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= | ||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= | ||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= | ||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | ||
golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= | ||
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"log" | ||
"os" | ||
|
||
"github.com/lotusirous/gostdsym" | ||
) | ||
|
||
func main() { | ||
log.SetPrefix("stdsym: ") | ||
log.SetFlags(0) | ||
if err := run(); err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
|
||
func run() error { | ||
cwd, err := os.Getwd() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
pkgs, err := gostdsym.LoadPackages("std") | ||
if err != nil { | ||
return err | ||
} | ||
|
||
w := os.Stdout | ||
var buf bytes.Buffer | ||
for _, v := range pkgs { | ||
out, err := gostdsym.GetPackageSymbols(v, cwd) | ||
if err != nil { | ||
return err | ||
} | ||
for _, sym := range out { | ||
buf.WriteString(sym + "\n") | ||
} | ||
} | ||
_, err = buf.WriteTo(w) | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
package gostdsym | ||
|
||
import ( | ||
"fmt" | ||
"go/build" | ||
"go/doc" | ||
"go/parser" | ||
"go/token" | ||
"io/fs" | ||
"regexp" | ||
"slices" | ||
"strings" | ||
|
||
"golang.org/x/tools/go/packages" | ||
) | ||
|
||
var internalPkg = regexp.MustCompile(`(^|/)internal($|/)`) | ||
|
||
func isSkipPackage(v string) bool { | ||
return internalPkg.MatchString(v) || strings.HasPrefix(v, "vendor/") | ||
} | ||
|
||
// LoadPackages returns a list of packages. | ||
func LoadPackages(pattern string) ([]string, error) { | ||
pkgs, err := packages.Load(nil, pattern) | ||
if err != nil { | ||
return nil, err | ||
} | ||
out := make([]string, len(pkgs)) | ||
for i := 0; i < len(pkgs); i++ { | ||
path := pkgs[i].PkgPath | ||
if isSkipPackage(path) { | ||
continue | ||
} | ||
out[i] = pkgs[i].PkgPath | ||
} | ||
return out, nil | ||
} | ||
|
||
// GetPackageSymbols extracts all exported symbols from a package. | ||
func GetPackageSymbols(name, srcDir string) ([]string, error) { | ||
buildPkg, err := build.Import(name, srcDir, build.ImportComment) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
syms, err := buildSymbols(buildPkg) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
syms = slices.Compact(syms) | ||
for i := range syms { | ||
syms[i] = buildPkg.ImportPath + "." + syms[i] | ||
} | ||
syms = append(syms, buildPkg.ImportPath) | ||
return syms, nil | ||
} | ||
|
||
func buildSymbols(pkg *build.Package) ([]string, error) { | ||
fset := token.NewFileSet() | ||
include := func(info fs.FileInfo) bool { | ||
for _, name := range pkg.GoFiles { | ||
if name == info.Name() { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
pkgs, err := parser.ParseDir(fset, pkg.Dir, include, parser.ParseComments) | ||
if err != nil { | ||
return nil, err | ||
} | ||
astPkg, ok := pkgs[pkg.Name] | ||
if !ok { | ||
return nil, fmt.Errorf("not found package name: %s", pkg.Name) | ||
} | ||
docPkg := doc.New(astPkg, pkg.ImportPath, doc.AllDecls) | ||
|
||
typs := types(docPkg) | ||
vars := variables(docPkg.Vars) | ||
consts := constants(docPkg.Consts) | ||
fns := functions(docPkg.Funcs) | ||
return append(append(append(typs, vars...), consts...), fns...), nil | ||
} | ||
|
||
func types(docPkg *doc.Package) []string { | ||
var out []string | ||
for _, typ := range docPkg.Types { | ||
if !token.IsExported(typ.Name) { | ||
continue | ||
} | ||
out = append(out, typ.Name) | ||
for _, va := range typ.Vars { | ||
for _, name := range va.Names { | ||
if name == "_" { | ||
continue | ||
} | ||
out = append(out, name) | ||
} | ||
} | ||
for _, va := range typ.Consts { | ||
for _, name := range va.Names { | ||
if name == "_" { | ||
continue | ||
} | ||
out = append(out, name) | ||
} | ||
} | ||
for _, fn := range typ.Funcs { | ||
out = append(out, fn.Name) | ||
} | ||
for _, method := range typ.Methods { | ||
if !token.IsExported(method.Name) { | ||
continue | ||
} | ||
out = append(out, typ.Name+"."+method.Name) | ||
} | ||
} | ||
return out | ||
} | ||
|
||
func variables(vars []*doc.Value) []string { | ||
var out []string | ||
for _, va := range vars { | ||
for _, name := range va.Names { | ||
if name == "_" { | ||
continue | ||
} | ||
if token.IsExported(name) { | ||
out = append(out, name) | ||
} | ||
} | ||
} | ||
return out | ||
} | ||
|
||
func constants(consts []*doc.Value) []string { | ||
var out []string | ||
for _, va := range consts { | ||
for _, name := range va.Names { | ||
if name == "_" { | ||
continue | ||
} | ||
if token.IsExported(name) { | ||
out = append(out, name) | ||
} | ||
} | ||
} | ||
return out | ||
} | ||
|
||
func functions(funcs []*doc.Func) []string { | ||
var out []string | ||
for _, fn := range funcs { | ||
if token.IsExported(fn.Name) { | ||
out = append(out, fn.Name) | ||
} | ||
} | ||
return out | ||
} |
Oops, something went wrong.