├── .github
├── FUNDING.yml
└── workflows
│ └── go.yml
├── .gitignore
├── LICENSE
├── README.md
├── autocomplete.go
├── autocomplete_test.go
├── docs
└── example.gif
├── generator.go
├── go.mod
├── go.sum
├── main.go
├── manager.go
├── manager_test.go
├── parser.go
├── parser_test.go
├── scripts
├── fetcher.go
└── visiter.go
└── template.go
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: ahmedakef
2 | ko_fi: ahmedakef
3 |
--------------------------------------------------------------------------------
/.github/workflows/go.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a golang project
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
3 |
4 | name: Go
5 |
6 | on:
7 | push:
8 | branches: [ "main" ]
9 | pull_request:
10 | branches: [ "main" ]
11 |
12 | jobs:
13 |
14 | build:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v3
18 |
19 | - name: Set up Go
20 | uses: actions/setup-go@v4
21 | with:
22 | go-version: '1.20'
23 |
24 | - name: Install goimports
25 | run: go install golang.org/x/tools/cmd/goimports@latest
26 |
27 | - name: Build
28 | run: go build -v ./...
29 |
30 | - name: Test
31 | run: go test -v ./...
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | goshell
2 | bin
3 | program.go
4 | .vscode
5 | scripts/pkgNames.json
6 | scripts/pkgFunctions.json
7 | scripts/listResponse.html
8 | scripts/detailsResponse.html
9 | .DS_Store
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 ahmedakef
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Goshell
2 |
3 | Goshell is REPL shell for golang.
4 |
5 | the project is inspired by [rango](https://github.com/emicklei/rango/) but took different decisions.
6 |
7 | ## Table of Contents
8 |
9 | - [Installation](#installation)
10 | - [Features](#features)
11 | - [Examples](#examples)
12 | - [Contact](#contact)
13 |
14 | ## Installation
15 |
16 | ```sh
17 | go install github.com/ahmedakef/goshell@latest
18 | ```
19 | ## Features
20 |
21 | - auto import the needed libraries using `goimports` just write `fmt.Print()` and `fmt` will be imported.
22 | - autocompletion for languages keywords and libraries's functions and types without the need for language server.
23 | - print the variablles by writing them, no need to use `fmt.Print()`
24 | - supports all shell line editing commands supported by [liner](https://github.com/peterh/liner?tab=readme-ov-file#line-editing)
25 | - don't have dependancy on goimports
26 |
27 | ## Examples
28 |
29 | ## live demo
30 | 
31 |
32 | ### Simple variable printing
33 |
34 |
35 |
36 |
37 |
38 | code you write |
39 | generated code |
40 |
41 |
42 |
43 |
44 |
45 |
46 | ```go
47 | >>> a:=1
48 | >>> b:=2
49 | >>> a
50 | 1
51 | ```
52 |
53 | |
54 |
55 |
56 | ```go
57 | package main
58 |
59 | import "fmt"
60 |
61 | func main() {
62 | a := 1
63 | b := 2
64 | fmt.Println(a)
65 | use(a, b)
66 | }
67 |
68 | // used to avoid "declared and not used" error
69 | func use(vals ...any) {
70 | for _, val := range vals {
71 | _ = val
72 | }
73 | }
74 | ```
75 |
76 | |
77 |
78 | 3 lines | 17 lines |
79 |
80 |
81 | ### Calling functions
82 |
83 |
84 |
85 |
86 |
87 | code you write |
88 | generated code |
89 |
90 |
91 |
92 |
93 |
94 |
95 | ```go
96 | >>> func add(x,y int) int {
97 | ... return x+y
98 | ... }
99 | >>> a:=1
100 | >>> b:=2
101 | >>> add(a,b)
102 | 3
103 | ```
104 |
105 | |
106 |
107 |
108 | ```go
109 | package main
110 |
111 | import "fmt"
112 |
113 | func add(x, y int) int {
114 | return x + y
115 | }
116 |
117 | func main() {
118 | a := 1
119 | b := 2
120 | fmt.Println(add(a, b))
121 | use(a, b)
122 | }
123 |
124 | // used to avoid "declared and not used" error
125 | func use(vals ...any) {
126 | for _, val := range vals {
127 | _ = val
128 | }
129 | }
130 | ```
131 |
132 | |
133 |
134 | 6 lines | 21 lines |
135 |
136 | ## Contact
137 |
138 | ahmedakef - aemed.akef.1@gmail.com
139 |
--------------------------------------------------------------------------------
/autocomplete.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "strings"
5 |
6 | "golang.org/x/exp/maps"
7 | )
8 |
9 | func WordCompleter(line string, pos int) (head string, completions []string, tail string) {
10 | head = line[:pos]
11 | tail = line[pos:]
12 | if head == "" {
13 | return
14 | }
15 |
16 | lastToken, lastTokenPos := getLastToken(head)
17 | head = head[:lastTokenPos]
18 |
19 | headSplitted := strings.SplitN(lastToken, ".", 2)
20 | packageName := headSplitted[0]
21 |
22 | if !contains(supportedPackages, packageName) {
23 | // this is a not known package, we match to the language keywords
24 | completions = getPossipleSuggestions(autoComplete, packageName)
25 | if len(completions) == 0 {
26 | head += lastToken
27 | }
28 | return
29 | }
30 |
31 | packagePart := packageName + "."
32 | head = head + packagePart
33 | function := ""
34 |
35 | allPkgFunctions := packageFunctions[packageName]
36 | if len(headSplitted) == 2 {
37 | function = headSplitted[1]
38 | if function == "" {
39 | completions = allPkgFunctions
40 | return
41 | }
42 | }
43 |
44 | completions = getPossipleSuggestions(allPkgFunctions, function)
45 | if len(completions) == 0 {
46 | head = lastToken
47 | }
48 | return
49 | }
50 |
51 | func getPossipleSuggestions(possibleWords []string, word string) []string {
52 | var completions []string
53 | for _, possibleWord := range possibleWords {
54 | if strings.HasPrefix(strings.ToLower(possibleWord), strings.ToLower(word)) {
55 | completions = append(completions, possibleWord)
56 | }
57 | }
58 | return completions
59 | }
60 |
61 | func getLastToken(head string) (token string, pos int) {
62 | headSplitted := strings.Split(head, " ")
63 | token = headSplitted[len(headSplitted)-1]
64 | pos = len(head) - len(token)
65 | return
66 | }
67 |
68 | func contains(arr []string, str string) bool {
69 | for _, a := range arr {
70 | if a == str {
71 | return true
72 | }
73 | }
74 | return false
75 | }
76 |
77 | var (
78 |
79 | // populated using scipts/fetcher.go
80 |
81 | packageFunctions = map[string][]string{"archive/tar": {"Format", "Header", "FileInfoHeader", "Reader", "NewReader", "Writer", "NewWriter"},
82 | "archive/zip": {"RegisterCompressor", "RegisterDecompressor", "Compressor", "Decompressor", "File", "FileHeader", "FileInfoHeader", "ReadCloser", "OpenReader", "Reader", "NewReader", "Writer", "NewWriter"},
83 | "bufio": {"ScanBytes", "ScanLines", "ScanRunes", "ScanWords", "ReadWriter", "NewReadWriter", "Reader", "NewReader", "NewReaderSize", "Scanner", "NewScanner", "SplitFunc", "Writer", "NewWriter", "NewWriterSize"},
84 | "builtin": {"append", "cap", "clear", "close", "complex", "copy", "delete", "imag", "len", "make", "max", "min", "new", "panic", "print", "println", "real", "recover", "ComplexType", "FloatType", "IntegerType", "Type", "Type1", "any", "bool", "byte", "comparable", "complex128", "complex64", "error", "float32", "float64", "int", "int16", "int32", "int64", "int8", "rune", "string", "uint", "uint16", "uint32", "uint64", "uint8", "uintptr"},
85 | "bytes": {"Clone", "Compare", "Contains", "ContainsAny", "ContainsFunc", "ContainsRune", "Count", "Cut", "CutPrefix", "CutSuffix", "Equal", "EqualFold", "Fields", "FieldsFunc", "HasPrefix", "HasSuffix", "Index", "IndexAny", "IndexByte", "IndexFunc", "IndexRune", "Join", "LastIndex", "LastIndexAny", "LastIndexByte", "LastIndexFunc", "Map", "Repeat", "Replace", "ReplaceAll", "Runes", "Split", "SplitAfter", "SplitAfterN", "SplitN", "Title", "ToLower", "ToLowerSpecial", "ToTitle", "ToTitleSpecial", "ToUpper", "ToUpperSpecial", "ToValidUTF8", "Trim", "TrimFunc", "TrimLeft", "TrimLeftFunc", "TrimPrefix", "TrimRight", "TrimRightFunc", "TrimSpace", "TrimSuffix", "Buffer", "NewBuffer", "NewBufferString", "Reader", "NewReader"},
86 | "cmp": {"Compare", "Less", "Or", "Ordered"},
87 | "compress/bzip2": {"NewReader", "StructuralError"},
88 | "compress/flate": {"NewReader", "NewReaderDict", "CorruptInputError", "InternalError", "ReadError", "Reader", "Resetter", "WriteError", "Writer", "NewWriter", "NewWriterDict"},
89 | "compress/gzip": {"Header", "Reader", "NewReader", "Writer", "NewWriter", "NewWriterLevel"},
90 | "compress/lzw": {"NewReader", "NewWriter", "Order", "Reader", "Writer"},
91 | "compress/zlib": {"NewReader", "NewReaderDict", "Resetter", "Writer", "NewWriter", "NewWriterLevel", "NewWriterLevelDict"},
92 | "container/heap": {"Fix", "Init", "Pop", "Push", "Remove", "Interface"},
93 | "container/list": {"Element", "List", "New"},
94 | "container/ring": {"Ring", "New"},
95 | "context": {"AfterFunc", "Cause", "WithCancel", "WithCancelCause", "WithDeadline", "WithDeadlineCause", "WithTimeout", "WithTimeoutCause", "CancelCauseFunc", "CancelFunc", "Context", "Background", "TODO", "WithValue", "WithoutCancel"},
96 | "crypto": {"RegisterHash", "Decrypter", "DecrypterOpts", "Hash", "PrivateKey", "PublicKey", "Signer", "SignerOpts"},
97 | "crypto/aes": {"NewCipher", "KeySizeError"},
98 | "crypto/cipher": {"AEAD", "NewGCM", "NewGCMWithNonceSize", "NewGCMWithTagSize", "Block", "BlockMode", "NewCBCDecrypter", "NewCBCEncrypter", "Stream", "NewCFBDecrypter", "NewCFBEncrypter", "NewCTR", "NewOFB", "StreamReader", "StreamWriter"},
99 | "crypto/des": {"NewCipher", "NewTripleDESCipher", "KeySizeError"},
100 | "crypto/dsa": {"GenerateKey", "GenerateParameters", "Sign", "Verify", "ParameterSizes", "Parameters", "PrivateKey", "PublicKey"},
101 | "crypto/ecdh": {"Curve", "P256", "P384", "P521", "X25519", "PrivateKey", "PublicKey"},
102 | "crypto/ecdsa": {"Sign", "SignASN1", "Verify", "VerifyASN1", "PrivateKey", "GenerateKey", "PublicKey"},
103 | "crypto/ed25519": {"GenerateKey", "Sign", "Verify", "VerifyWithOptions", "Options", "PrivateKey", "NewKeyFromSeed", "PublicKey"},
104 | "crypto/elliptic": {"GenerateKey", "Marshal", "MarshalCompressed", "Unmarshal", "UnmarshalCompressed", "Curve", "P224", "P256", "P384", "P521", "CurveParams"},
105 | "crypto/hmac": {"Equal", "New"},
106 | "crypto/internal/alias": {"AnyOverlap", "InexactOverlap"},
107 | "crypto/internal/bigmod": {"Modulus", "NewModulusFromBig", "Nat", "NewNat"},
108 | "crypto/internal/boring": {"DecryptRSANoPadding", "DecryptRSAOAEP", "DecryptRSAPKCS1", "ECDH", "EncryptRSANoPadding", "EncryptRSAOAEP", "EncryptRSAPKCS1", "NewAESCipher", "NewGCMTLS", "NewHMAC", "NewSHA1", "NewSHA224", "NewSHA256", "NewSHA384", "NewSHA512", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "SignMarshalECDSA", "SignRSAPKCS1v15", "SignRSAPSS", "Unreachable", "UnreachableExceptTests", "VerifyECDSA", "VerifyRSAPKCS1v15", "VerifyRSAPSS", "BigInt", "GenerateKeyECDSA", "GenerateKeyRSA", "PrivateKeyECDH", "GenerateKeyECDH", "NewPrivateKeyECDH", "PublicKey", "PrivateKeyECDSA", "NewPrivateKeyECDSA", "PrivateKeyRSA", "NewPrivateKeyRSA", "PublicKeyECDH", "NewPublicKeyECDH", "Bytes", "PublicKeyECDSA", "NewPublicKeyECDSA", "PublicKeyRSA", "NewPublicKeyRSA"},
109 | "crypto/internal/boring/bbig": {"Dec", "Enc"},
110 | "crypto/internal/boring/bcache": {"Cache"},
111 | "crypto/internal/boring/sig": {"BoringCrypto", "FIPSOnly", "StandardCrypto"},
112 | "crypto/internal/edwards25519": {"Point", "NewGeneratorPoint", "NewIdentityPoint", "Scalar", "NewScalar"},
113 | "crypto/internal/edwards25519/field": {"Element"},
114 | "crypto/internal/nistec": {"P256OrdInverse", "P224Point", "NewP224Point", "P256Point", "NewP256Point", "P384Point", "NewP384Point", "P521Point", "NewP521Point"},
115 | "crypto/internal/nistec/fiat": {"P224Element", "P256Element", "P384Element", "P521Element"},
116 | "crypto/internal/randutil": {"MaybeReadByte"},
117 | "crypto/md5": {"New", "Sum"},
118 | "crypto/rand": {"Int", "Prime", "Read"},
119 | "crypto/rc4": {"Cipher", "NewCipher", "KeySizeError"},
120 | "crypto/rsa": {"DecryptOAEP", "DecryptPKCS1v15", "DecryptPKCS1v15SessionKey", "EncryptOAEP", "EncryptPKCS1v15", "SignPKCS1v15", "SignPSS", "VerifyPKCS1v15", "VerifyPSS", "CRTValue", "OAEPOptions", "PKCS1v15DecryptOptions", "PSSOptions", "PrecomputedValues", "PrivateKey", "GenerateKey", "GenerateMultiPrimeKey", "PublicKey"},
121 | "crypto/sha1": {"New", "Sum"},
122 | "crypto/sha256": {"New", "New224", "Sum224", "Sum256"},
123 | "crypto/sha512": {"New", "New384", "New512_224", "New512_256", "Sum384", "Sum512", "Sum512_224", "Sum512_256"},
124 | "crypto/subtle": {"ConstantTimeByteEq", "ConstantTimeCompare", "ConstantTimeCopy", "ConstantTimeEq", "ConstantTimeLessOrEq", "ConstantTimeSelect", "XORBytes"},
125 | "crypto/tls": {"CipherSuiteName", "Listen", "NewListener", "VersionName", "AlertError", "Certificate", "LoadX509KeyPair", "X509KeyPair", "CertificateRequestInfo", "CertificateVerificationError", "CipherSuite", "CipherSuites", "InsecureCipherSuites", "ClientAuthType", "ClientHelloInfo", "ClientSessionCache", "NewLRUClientSessionCache", "ClientSessionState", "NewResumptionState", "Config", "Conn", "Client", "Dial", "DialWithDialer", "Server", "ConnectionState", "CurveID", "Dialer", "QUICConfig", "QUICConn", "QUICClient", "QUICServer", "QUICEncryptionLevel", "QUICEvent", "QUICEventKind", "QUICSessionTicketOptions", "RecordHeaderError", "RenegotiationSupport", "SessionState", "ParseSessionState", "SignatureScheme"},
126 | "crypto/x509": {"CreateCertificate", "CreateCertificateRequest", "CreateRevocationList", "DecryptPEMBlock", "EncryptPEMBlock", "IsEncryptedPEMBlock", "MarshalECPrivateKey", "MarshalPKCS1PrivateKey", "MarshalPKCS1PublicKey", "MarshalPKCS8PrivateKey", "MarshalPKIXPublicKey", "ParseCRL", "ParseDERCRL", "ParseECPrivateKey", "ParsePKCS1PrivateKey", "ParsePKCS1PublicKey", "ParsePKCS8PrivateKey", "ParsePKIXPublicKey", "SetFallbackRoots", "CertPool", "NewCertPool", "SystemCertPool", "Certificate", "ParseCertificate", "ParseCertificates", "CertificateInvalidError", "CertificateRequest", "ParseCertificateRequest", "ConstraintViolationError", "Error", "ExtKeyUsage", "HostnameError", "InsecureAlgorithmError", "InvalidReason", "KeyUsage", "OID", "OIDFromInts", "PEMCipher", "PublicKeyAlgorithm", "RevocationList", "ParseRevocationList", "RevocationListEntry", "SignatureAlgorithm", "SystemRootsError", "UnhandledCriticalExtension", "UnknownAuthorityError", "VerifyOptions"},
127 | "crypto/x509/internal/macos": {"CFArrayAppendValue", "CFArrayGetCount", "CFDataGetBytePtr", "CFDataGetLength", "CFDataToSlice", "CFEqual", "CFErrorGetCode", "CFNumberGetValue", "CFRelease", "CFStringToString", "ReleaseCFArray", "SecCertificateCopyData", "SecTrustEvaluateWithError", "SecTrustGetCertificateCount", "SecTrustGetResult", "SecTrustSetVerifyDate", "CFRef", "BytesToCFData", "CFArrayCreateMutable", "CFArrayGetValueAtIndex", "CFDateCreate", "CFDictionaryGetValueIfPresent", "CFErrorCopyDescription", "CFStringCreateExternalRepresentation", "SecCertificateCreateWithData", "SecPolicyCreateSSL", "SecTrustCreateWithCertificates", "SecTrustEvaluate", "SecTrustGetCertificateAtIndex", "SecTrustSettingsCopyCertificates", "SecTrustSettingsCopyTrustSettings", "TimeToCFDateRef", "CFString", "StringToCFString", "OSStatus", "SecTrustResultType", "SecTrustSettingsDomain", "SecTrustSettingsResult"},
128 | "crypto/x509/pkix": {"AlgorithmIdentifier", "AttributeTypeAndValue", "AttributeTypeAndValueSET", "CertificateList", "Extension", "Name", "RDNSequence", "RelativeDistinguishedNameSET", "RevokedCertificate", "TBSCertificateList"},
129 | "database/sql": {"Drivers", "Register", "ColumnType", "Conn", "DB", "Open", "OpenDB", "DBStats", "IsolationLevel", "NamedArg", "Named", "Null", "NullBool", "NullByte", "NullFloat64", "NullInt16", "NullInt32", "NullInt64", "NullString", "NullTime", "Out", "RawBytes", "Result", "Row", "Rows", "Scanner", "Stmt", "Tx", "TxOptions"},
130 | "database/sql/driver": {"IsScanValue", "IsValue", "ColumnConverter", "Conn", "ConnBeginTx", "ConnPrepareContext", "Connector", "Driver", "DriverContext", "Execer", "ExecerContext", "IsolationLevel", "NamedValue", "NamedValueChecker", "NotNull", "Null", "Pinger", "Queryer", "QueryerContext", "Result", "Rows", "RowsAffected", "LastInsertId", "RowsColumnTypeDatabaseTypeName", "RowsColumnTypeLength", "RowsColumnTypeNullable", "RowsColumnTypePrecisionScale", "RowsColumnTypeScanType", "RowsNextResultSet", "SessionResetter", "Stmt", "StmtExecContext", "StmtQueryContext", "Tx", "TxOptions", "Validator", "Value", "ValueConverter", "Valuer"},
131 | "debug/buildinfo": {"BuildInfo", "Read", "ReadFile"},
132 | "debug/dwarf": {"AddrType", "ArrayType", "Attr", "BasicType", "BoolType", "CharType", "Class", "CommonType", "ComplexType", "Data", "New", "DecodeError", "DotDotDotType", "Entry", "EnumType", "EnumValue", "Field", "FloatType", "FuncType", "IntType", "LineEntry", "LineFile", "LineReader", "LineReaderPos", "Offset", "PtrType", "QualType", "Reader", "StructField", "StructType", "Tag", "Type", "TypedefType", "UcharType", "UintType", "UnspecifiedType", "UnsupportedType", "VoidType"},
133 | "debug/elf": {"R_INFO", "R_INFO32", "R_SYM32", "R_SYM64", "R_TYPE32", "R_TYPE64", "ST_INFO", "Chdr32", "Chdr64", "Class", "CompressionType", "Data", "Dyn32", "Dyn64", "DynFlag", "DynFlag1", "DynTag", "File", "NewFile", "Open", "FileHeader", "FormatError", "Header32", "Header64", "ImportedSymbol", "Machine", "NType", "OSABI", "Prog", "Prog32", "Prog64", "ProgFlag", "ProgHeader", "ProgType", "R_386", "R_390", "R_AARCH64", "R_ALPHA", "R_ARM", "R_LARCH", "R_MIPS", "R_PPC", "R_PPC64", "R_RISCV", "R_SPARC", "R_X86_64", "Rel32", "Rel64", "Rela32", "Rela64", "Section", "Section32", "Section64", "SectionFlag", "SectionHeader", "SectionIndex", "SectionType", "Sym32", "Sym64", "SymBind", "ST_BIND", "SymType", "ST_TYPE", "SymVis", "ST_VISIBILITY", "Symbol", "Type", "Version"},
134 | "debug/gosym": {"DecodingError", "Func", "LineTable", "NewLineTable", "Obj", "Sym", "Table", "NewTable", "UnknownFileError", "UnknownLineError"},
135 | "debug/macho": {"Cpu", "Dylib", "DylibCmd", "Dysymtab", "DysymtabCmd", "FatArch", "FatArchHeader", "FatFile", "NewFatFile", "OpenFat", "File", "NewFile", "Open", "FileHeader", "FormatError", "Load", "LoadBytes", "LoadCmd", "Nlist32", "Nlist64", "Regs386", "RegsAMD64", "Reloc", "RelocTypeARM", "RelocTypeARM64", "RelocTypeGeneric", "RelocTypeX86_64", "Rpath", "RpathCmd", "Section", "Section32", "Section64", "SectionHeader", "Segment", "Segment32", "Segment64", "SegmentHeader", "Symbol", "Symtab", "SymtabCmd", "Thread", "Type"},
136 | "debug/pe": {"COFFSymbol", "COFFSymbolAuxFormat5", "DataDirectory", "File", "NewFile", "Open", "FileHeader", "FormatError", "ImportDirectory", "OptionalHeader32", "OptionalHeader64", "Reloc", "Section", "SectionHeader", "SectionHeader32", "StringTable", "Symbol"},
137 | "debug/plan9obj": {"File", "NewFile", "Open", "FileHeader", "Section", "SectionHeader", "Sym"},
138 | "embed": {"FS"},
139 | "encoding": {"BinaryMarshaler", "BinaryUnmarshaler", "TextMarshaler", "TextUnmarshaler"},
140 | "encoding/ascii85": {"Decode", "Encode", "MaxEncodedLen", "NewDecoder", "NewEncoder", "CorruptInputError"},
141 | "encoding/asn1": {"Marshal", "MarshalWithParams", "Unmarshal", "UnmarshalWithParams", "BitString", "Enumerated", "Flag", "ObjectIdentifier", "RawContent", "RawValue", "StructuralError", "SyntaxError"},
142 | "encoding/base32": {"NewDecoder", "NewEncoder", "CorruptInputError", "Encoding", "NewEncoding"},
143 | "encoding/base64": {"NewDecoder", "NewEncoder", "CorruptInputError", "Encoding", "NewEncoding"},
144 | "encoding/binary": {"AppendUvarint", "AppendVarint", "PutUvarint", "PutVarint", "Read", "ReadUvarint", "ReadVarint", "Size", "Uvarint", "Varint", "Write", "AppendByteOrder", "ByteOrder"},
145 | "encoding/csv": {"ParseError", "Reader", "NewReader", "Writer", "NewWriter"},
146 | "encoding/gob": {"Register", "RegisterName", "CommonType", "Decoder", "NewDecoder", "Encoder", "NewEncoder", "GobDecoder", "GobEncoder"},
147 | "encoding/hex": {"AppendDecode", "AppendEncode", "Decode", "DecodeString", "DecodedLen", "Dump", "Dumper", "Encode", "EncodeToString", "EncodedLen", "NewDecoder", "NewEncoder", "InvalidByteError"},
148 | "encoding/json": {"Compact", "HTMLEscape", "Indent", "Marshal", "MarshalIndent", "Unmarshal", "Valid", "Decoder", "NewDecoder", "Delim", "Encoder", "NewEncoder", "InvalidUTF8Error", "InvalidUnmarshalError", "Marshaler", "MarshalerError", "Number", "RawMessage", "SyntaxError", "Token", "UnmarshalFieldError", "UnmarshalTypeError", "Unmarshaler", "UnsupportedTypeError", "UnsupportedValueError"},
149 | "encoding/pem": {"Encode", "EncodeToMemory", "Block", "Decode"},
150 | "encoding/xml": {"Escape", "EscapeText", "Marshal", "MarshalIndent", "Unmarshal", "Attr", "CharData", "Comment", "Decoder", "NewDecoder", "NewTokenDecoder", "Directive", "Encoder", "NewEncoder", "EndElement", "Marshaler", "MarshalerAttr", "Name", "ProcInst", "StartElement", "SyntaxError", "TagPathError", "Token", "CopyToken", "TokenReader", "UnmarshalError", "Unmarshaler", "UnmarshalerAttr", "UnsupportedTypeError"},
151 | "errors": {"As", "Is", "Join", "New", "Unwrap"},
152 | "expvar": {"Do", "Handler", "Publish", "Float", "NewFloat", "Func", "Int", "NewInt", "KeyValue", "Map", "NewMap", "String", "NewString", "Var", "Get"},
153 | "flag": {"Arg", "Args", "Bool", "BoolFunc", "BoolVar", "Duration", "DurationVar", "Float64", "Float64Var", "Func", "Int", "Int64", "Int64Var", "IntVar", "NArg", "NFlag", "Parse", "Parsed", "PrintDefaults", "Set", "String", "StringVar", "TextVar", "Uint", "Uint64", "Uint64Var", "UintVar", "UnquoteUsage", "Var", "Visit", "VisitAll", "ErrorHandling", "Flag", "Lookup", "FlagSet", "NewFlagSet", "Getter", "Value"},
154 | "fmt": {"Append", "Appendf", "Appendln", "Errorf", "FormatString", "Fprint", "Fprintf", "Fprintln", "Fscan", "Fscanf", "Fscanln", "Print", "Printf", "Println", "Scan", "Scanf", "Scanln", "Sprint", "Sprintf", "Sprintln", "Sscan", "Sscanf", "Sscanln", "Formatter", "GoStringer", "ScanState", "Scanner", "State", "Stringer"},
155 | "go/ast": {"FileExports", "FilterDecl", "FilterFile", "FilterPackage", "Fprint", "Inspect", "IsExported", "IsGenerated", "NotNilFilter", "PackageExports", "Print", "SortImports", "Walk", "ArrayType", "AssignStmt", "BadDecl", "BadExpr", "BadStmt", "BasicLit", "BinaryExpr", "BlockStmt", "BranchStmt", "CallExpr", "CaseClause", "ChanDir", "ChanType", "CommClause", "Comment", "CommentGroup", "CommentMap", "NewCommentMap", "CompositeLit", "Decl", "DeclStmt", "DeferStmt", "Ellipsis", "EmptyStmt", "Expr", "Unparen", "ExprStmt", "Field", "FieldFilter", "FieldList", "File", "MergePackageFiles", "Filter", "ForStmt", "FuncDecl", "FuncLit", "FuncType", "GenDecl", "GoStmt", "Ident", "NewIdent", "IfStmt", "ImportSpec", "Importer", "IncDecStmt", "IndexExpr", "IndexListExpr", "InterfaceType", "KeyValueExpr", "LabeledStmt", "MapType", "MergeMode", "Node", "ObjKind", "Object", "NewObj", "Package", "NewPackage", "ParenExpr", "RangeStmt", "ReturnStmt", "Scope", "NewScope", "SelectStmt", "SelectorExpr", "SendStmt", "SliceExpr", "Spec", "StarExpr", "Stmt", "StructType", "SwitchStmt", "TypeAssertExpr", "TypeSpec", "TypeSwitchStmt", "UnaryExpr", "ValueSpec", "Visitor"},
156 | "go/build": {"ArchChar", "IsLocalImport", "Context", "Directive", "ImportMode", "MultiplePackageError", "NoGoError", "Package", "Import", "ImportDir"},
157 | "go/build/constraint": {"GoVersion", "IsGoBuild", "IsPlusBuild", "PlusBuildLines", "AndExpr", "Expr", "Parse", "NotExpr", "OrExpr", "SyntaxError", "TagExpr"},
158 | "go/constant": {"BitLen", "BoolVal", "Bytes", "Compare", "Float32Val", "Float64Val", "Int64Val", "Sign", "StringVal", "Uint64Val", "Val", "Kind", "Value", "BinaryOp", "Denom", "Imag", "Make", "MakeBool", "MakeFloat64", "MakeFromBytes", "MakeFromLiteral", "MakeImag", "MakeInt64", "MakeString", "MakeUint64", "MakeUnknown", "Num", "Real", "Shift", "ToComplex", "ToFloat", "ToInt", "UnaryOp"},
159 | "go/doc": {"IsPredeclared", "Synopsis", "ToHTML", "ToText", "Example", "Examples", "Filter", "Func", "Mode", "Note", "Package", "New", "NewFromFiles", "Type", "Value"},
160 | "go/doc/comment": {"DefaultLookupPackage", "Block", "Code", "Doc", "DocLink", "Heading", "Italic", "Link", "LinkDef", "List", "ListItem", "Paragraph", "Parser", "Plain", "Printer", "Text"},
161 | "go/format": {"Node", "Source"},
162 | "go/importer": {"Default", "For", "ForCompiler", "Lookup"},
163 | "go/internal/gccgoimporter": {"GccgoInstallation", "Importer", "GetImporter", "InitData", "PackageInit"},
164 | "go/internal/gcimporter": {"FindExportData", "FindPkg", "Import"},
165 | "go/internal/srcimporter": {"Importer", "New"},
166 | "go/internal/typeparams": {"PackIndexExpr", "IndexExpr", "UnpackIndexExpr"},
167 | "go/parser": {"ParseDir", "ParseExpr", "ParseExprFrom", "ParseFile", "Mode"},
168 | "go/printer": {"Fprint", "CommentedNode", "Config", "Mode"},
169 | "go/scanner": {"PrintError", "Error", "ErrorHandler", "ErrorList", "Mode", "Scanner"},
170 | "go/token": {"IsExported", "IsIdentifier", "IsKeyword", "File", "FileSet", "NewFileSet", "Pos", "Position", "Token", "Lookup"},
171 | "go/types": {"AssertableTo", "AssignableTo", "CheckExpr", "Comparable", "ConvertibleTo", "DefPredeclaredTestFuncs", "ExprString", "Id", "Identical", "IdenticalIgnoreTags", "Implements", "IsInterface", "ObjectString", "Satisfies", "SelectionString", "TypeString", "WriteExpr", "WriteSignature", "WriteType", "Alias", "NewAlias", "ArgumentError", "Array", "NewArray", "Basic", "BasicInfo", "BasicKind", "Builtin", "Chan", "NewChan", "ChanDir", "Checker", "NewChecker", "Config", "Const", "NewConst", "Context", "NewContext", "Error", "Func", "MissingMethod", "NewFunc", "ImportMode", "Importer", "ImporterFrom", "Info", "Initializer", "Instance", "Interface", "NewInterface", "NewInterfaceType", "Label", "NewLabel", "Map", "NewMap", "MethodSet", "NewMethodSet", "Named", "NewNamed", "Nil", "Object", "LookupFieldOrMethod", "Package", "NewPackage", "PkgName", "NewPkgName", "Pointer", "NewPointer", "Qualifier", "RelativeTo", "Scope", "NewScope", "Selection", "SelectionKind", "Signature", "NewSignature", "NewSignatureType", "Sizes", "SizesFor", "Slice", "NewSlice", "StdSizes", "Struct", "NewStruct", "Term", "NewTerm", "Tuple", "NewTuple", "Type", "Default", "Instantiate", "Unalias", "TypeAndValue", "Eval", "TypeList", "TypeName", "NewTypeName", "TypeParam", "NewTypeParam", "TypeParamList", "Union", "NewUnion", "Var", "NewField", "NewParam", "NewVar"},
172 | "go/version": {"Compare", "IsValid", "Lang"},
173 | "hash": {"Hash", "Hash32", "Hash64"},
174 | "hash/adler32": {"Checksum", "New"},
175 | "hash/crc32": {"Checksum", "ChecksumIEEE", "New", "NewIEEE", "Update", "Table", "MakeTable"},
176 | "hash/crc64": {"Checksum", "New", "Update", "Table", "MakeTable"},
177 | "hash/fnv": {"New128", "New128a", "New32", "New32a", "New64", "New64a"},
178 | "hash/maphash": {"Bytes", "String", "Hash", "Seed", "MakeSeed"},
179 | "html": {"EscapeString", "UnescapeString"},
180 | "html/template": {"HTMLEscape", "HTMLEscapeString", "HTMLEscaper", "IsTrue", "JSEscape", "JSEscapeString", "JSEscaper", "URLQueryEscaper", "CSS", "Error", "ErrorCode", "FuncMap", "HTML", "HTMLAttr", "JS", "JSStr", "Srcset", "Template", "Must", "New", "ParseFS", "ParseFiles", "ParseGlob", "URL"},
181 | "image": {"RegisterFormat", "Alpha", "NewAlpha", "Alpha16", "NewAlpha16", "CMYK", "NewCMYK", "Config", "DecodeConfig", "Gray", "NewGray", "Gray16", "NewGray16", "Image", "Decode", "NRGBA", "NewNRGBA", "NRGBA64", "NewNRGBA64", "NYCbCrA", "NewNYCbCrA", "Paletted", "NewPaletted", "PalettedImage", "Point", "Pt", "RGBA", "NewRGBA", "RGBA64", "NewRGBA64", "RGBA64Image", "Rectangle", "Rect", "Uniform", "NewUniform", "YCbCr", "NewYCbCr", "YCbCrSubsampleRatio"},
182 | "image/color": {"CMYKToRGB", "RGBToCMYK", "RGBToYCbCr", "YCbCrToRGB", "Alpha", "Alpha16", "CMYK", "Color", "Gray", "Gray16", "Model", "ModelFunc", "NRGBA", "NRGBA64", "NYCbCrA", "Palette", "RGBA", "RGBA64", "YCbCr"},
183 | "image/color/palette": {},
184 | "image/draw": {"Draw", "DrawMask", "Drawer", "Image", "Op", "Quantizer", "RGBA64Image"},
185 | "image/gif": {"Decode", "DecodeConfig", "Encode", "EncodeAll", "GIF", "DecodeAll", "Options"},
186 | "image/internal/imageutil": {"DrawYCbCr"},
187 | "image/jpeg": {"Decode", "DecodeConfig", "Encode", "FormatError", "Options", "Reader", "UnsupportedError"},
188 | "image/png": {"Decode", "DecodeConfig", "Encode", "CompressionLevel", "Encoder", "EncoderBuffer", "EncoderBufferPool", "FormatError", "UnsupportedError"},
189 | "index/suffixarray": {"Index", "New"},
190 | "internal/abi": {"CommonSize", "FuncPCABI0", "FuncPCABIInternal", "StructFieldSize", "TFlagOff", "UncommonSize", "UseInterfaceSwitchCache", "ArrayType", "ChanDir", "ChanType", "FuncFlag", "FuncID", "FuncType", "Imethod", "IntArgRegBitmap", "InterfaceSwitch", "InterfaceSwitchCache", "InterfaceSwitchCacheEntry", "InterfaceType", "Kind", "MapType", "Method", "Name", "NewName", "NameOff", "PtrType", "RegArgs", "SliceType", "StructField", "StructType", "TFlag", "TextOff", "Type", "TypeAssert", "TypeAssertCache", "TypeAssertCacheEntry", "TypeOff", "UncommonType"},
191 | "internal/bisect": {"AppendMarker", "CutMarker", "Hash", "Marker", "PrintMarker", "Matcher", "New", "Writer"},
192 | "internal/buildcfg": {"Check", "GOGOARCH", "Getgoextlinkenabled", "ExperimentFlags", "ParseGOEXPERIMENT"},
193 | "internal/bytealg": {"Compare", "Count", "CountString", "Cutover", "Equal", "HashStr", "HashStrRev", "Index", "IndexByte", "IndexByteString", "IndexRabinKarp", "IndexString", "LastIndexByte", "LastIndexByteString", "LastIndexRabinKarp", "MakeNoZero"},
194 | "internal/cfg": {},
195 | "internal/chacha8rand": {"Marshal", "Unmarshal", "State"},
196 | "internal/coverage": {"HardCodedPkgID", "Round4", "CounterFileFooter", "CounterFileHeader", "CounterFlavor", "CounterGranularity", "CounterMode", "ParseCounterMode", "CounterSegmentHeader", "CoverableUnit", "FuncDesc", "MetaFileCollection", "MetaFileHeader", "MetaSymbolHeader"},
197 | "internal/coverage/calloc": {"BatchCounterAlloc"},
198 | "internal/coverage/cformat": {"Formatter", "NewFormatter"},
199 | "internal/coverage/cmerge": {"SaturatingAdd", "Merger", "ModeMergePolicy"},
200 | "internal/coverage/decodecounter": {"CounterDataReader", "NewCounterDataReader", "FuncPayload"},
201 | "internal/coverage/decodemeta": {"CoverageMetaDataDecoder", "NewCoverageMetaDataDecoder", "CoverageMetaFileReader", "NewCoverageMetaFileReader"},
202 | "internal/coverage/encodecounter": {"CounterVisitor", "CounterVisitorFn", "CoverageDataWriter", "NewCoverageDataWriter"},
203 | "internal/coverage/encodemeta": {"HashFuncDesc", "CoverageMetaDataBuilder", "NewCoverageMetaDataBuilder", "CoverageMetaFileWriter", "NewCoverageMetaFileWriter"},
204 | "internal/coverage/pods": {"Pod", "CollectPods", "CollectPodsFromFiles"},
205 | "internal/coverage/rtcov": {"CovCounterBlob", "CovMetaBlob"},
206 | "internal/coverage/slicereader": {"Reader", "NewReader"},
207 | "internal/coverage/slicewriter": {"WriteSeeker"},
208 | "internal/coverage/stringtab": {"Reader", "NewReader", "Writer"},
209 | "internal/coverage/uleb128": {"AppendUleb128"},
210 | "internal/cpu": {"Initialize", "Name", "CacheLinePad"},
211 | "internal/dag": {"Graph", "Parse"},
212 | "internal/diff": {"Diff"},
213 | "internal/fmtsort": {"SortedMap", "Sort"},
214 | "internal/fuzz": {"CheckCorpus", "CoordinateFuzzing", "ResetCoverage", "RunFuzzWorker", "SnapshotCoverage", "CoordinateFuzzingOpts", "CorpusEntry", "ReadCorpus", "MalformedCorpusError"},
215 | "internal/goarch": {"ArchFamilyType"},
216 | "internal/godebug": {"Setting", "New"},
217 | "internal/godebugs": {"Info", "Lookup"},
218 | "internal/goexperiment": {"Flags"},
219 | "internal/goos": {},
220 | "internal/goroot": {"IsStandardPackage"},
221 | "internal/gover": {"CmpInt", "Compare", "DecInt", "IsLang", "IsValid", "Lang", "Max", "Version", "Parse"},
222 | "internal/goversion": {},
223 | "internal/intern": {"Value", "Get", "GetByString"},
224 | "internal/itoa": {"Itoa", "Uitoa", "Uitox"},
225 | "internal/lazyregexp": {"Regexp", "New"},
226 | "internal/lazytemplate": {"Template", "New"},
227 | "internal/nettrace": {"LookupIPAltResolverKey", "Trace", "TraceKey"},
228 | "internal/obscuretestdata": {"DecodeToTempFile", "ReadFile", "Rot13"},
229 | "internal/oserror": {},
230 | "internal/pkgbits": {"Code", "CodeObj", "CodeType", "CodeVal", "Decoder", "Encoder", "Index", "PkgDecoder", "NewPkgDecoder", "PkgEncoder", "NewPkgEncoder", "RelocEnt", "RelocKind", "SyncMarker"},
231 | "internal/platform": {"ASanSupported", "Broken", "BuildModeSupported", "CgoSupported", "DefaultPIE", "ExecutableHasDWARF", "FirstClass", "FuzzInstrumented", "FuzzSupported", "InternalLinkPIESupported", "MSanSupported", "MustLinkExternal", "RaceDetectorSupported", "OSArch"},
232 | "internal/poll": {"CopyFileRange", "DupCloseOnExec", "IsPollDescriptor", "SendFile", "Splice", "DeadlineExceededError", "FD", "String", "SysFile"},
233 | "internal/profile": {"Demangler", "Function", "Label", "Line", "Location", "Mapping", "Profile", "Merge", "Parse", "ParseTracebacks", "Sample", "TagMatch", "ValueType"},
234 | "internal/race": {"Acquire", "Disable", "Enable", "Errors", "Read", "ReadRange", "Release", "ReleaseMerge", "Write", "WriteRange"},
235 | "internal/reflectlite": {"Swapper", "Kind", "Type", "TypeOf", "Value", "ValueOf", "ValueError"},
236 | "internal/safefilepath": {"FromFS"},
237 | "internal/saferio": {"ReadData", "ReadDataAt", "SliceCap", "SliceCapWithSize"},
238 | "internal/singleflight": {"Group", "Result"},
239 | "internal/syscall/execenv": {"Default"},
240 | "internal/syscall/unix": {"CopyFileRange", "Eaccess", "Fcntl", "Fstatat", "GetRandom", "HasNonblockFlag", "IsNonblock", "KernelVersion", "Openat", "PidFDSendSignal", "RecvfromInet4", "RecvfromInet6", "RecvmsgInet4", "RecvmsgInet6", "SendmsgNInet4", "SendmsgNInet6", "SendtoInet4", "SendtoInet6", "Unlinkat", "GetRandomFlag"},
241 | "internal/syscall/windows": {"AdjustTokenPrivileges", "CreateEnvironmentBlock", "CreateEvent", "DestroyEnvironmentBlock", "DuplicateTokenEx", "ErrorLoadingGetTempPath2", "GetACP", "GetAdaptersAddresses", "GetComputerNameEx", "GetConsoleCP", "GetCurrentThread", "GetFileInformationByHandleEx", "GetFinalPathNameByHandle", "GetModuleFileName", "GetProcessMemoryInfo", "GetProfilesDirectory", "GetSystemDirectory", "GetTempPath2", "GetVolumeInformationByHandle", "GetVolumeNameForVolumeMountPoint", "ImpersonateSelf", "LockFileEx", "LookupPrivilegeValue", "Module32First", "Module32Next", "MoveFileEx", "MultiByteToWideChar", "NetShareAdd", "NetShareDel", "NetUserGetLocalGroups", "OpenSCManager", "OpenService", "OpenThreadToken", "ProcessPrng", "QueryServiceStatus", "Rename", "RevertToSelf", "RtlLookupFunctionEntry", "RtlVirtualUnwind", "SetFileInformationByHandle", "SetTokenInformation", "UTF16PtrToString", "UnlockFileEx", "VirtualQuery", "WSARecvMsg", "WSASendMsg", "WSASendtoInet4", "WSASendtoInet6", "WSASocket", "FILE_ATTRIBUTE_TAG_INFO", "FILE_BASIC_INFO", "FILE_FULL_DIR_INFO", "FILE_ID_BOTH_DIR_INFO", "IpAdapterAddresses", "IpAdapterAnycastAddress", "IpAdapterDnsServerAdapter", "IpAdapterMulticastAddress", "IpAdapterPrefix", "IpAdapterUnicastAddress", "LUID", "LUID_AND_ATTRIBUTES", "LocalGroupUserInfo0", "MemoryBasicInformation", "ModuleEntry32", "MountPointReparseBuffer", "PROCESS_MEMORY_COUNTERS", "REPARSE_DATA_BUFFER", "REPARSE_DATA_BUFFER_HEADER", "SERVICE_STATUS", "SHARE_INFO_2", "SID_AND_ATTRIBUTES", "SecurityAttributes", "SocketAddress", "SymbolicLinkReparseBuffer", "TCP_INITIAL_RTO_PARAMETERS", "TOKEN_MANDATORY_LABEL", "TOKEN_PRIVILEGES", "TokenType", "UserInfo4", "WSAMsg"},
242 | "internal/syscall/windows/registry": {"DeleteKey", "ExpandString", "Key", "CreateKey", "OpenKey", "KeyInfo"},
243 | "internal/syscall/windows/sysdll": {"Add"},
244 | "internal/sysinfo": {"CPUName"},
245 | "internal/testenv": {"Builder", "CPUIsSlow", "CanInternalLink", "CleanCmdEnv", "Command", "CommandContext", "GOROOT", "GoTool", "GoToolPath", "HasCGO", "HasExternalNetwork", "HasGoBuild", "HasGoRun", "HasLink", "HasParallelism", "HasSrc", "HasSymlink", "MustHaveBuildMode", "MustHaveCGO", "MustHaveExec", "MustHaveExecPath", "MustHaveExternalNetwork", "MustHaveGoBuild", "MustHaveGoRun", "MustHaveLink", "MustHaveParallelism", "MustHaveSymlink", "MustInternalLink", "OptimizationOff", "SkipFlaky", "SkipFlakyNet", "SkipIfOptimizationOff", "SkipIfShortAndSlow", "SyscallIsNotSupported", "WriteImportcfg"},
246 | "internal/testlog": {"Getenv", "Open", "PanicOnExit0", "SetLogger", "SetPanicOnExit0", "Stat", "Interface", "Logger"},
247 | "internal/testpty": {"Open", "PtyError"},
248 | "internal/trace": {"GoroutineStats", "IsSystemGoroutine", "MutatorUtilization", "MutatorUtilizationV2", "Print", "PrintEvent", "ReadVersion", "RelatedGoroutines", "RelatedGoroutinesV2", "Event", "Frame", "GDesc", "GExecutionStat", "GoroutineExecStats", "GoroutineSummary", "MMUCurve", "NewMMUCurve", "MutatorUtil", "ParseResult", "Parse", "Summarizer", "NewSummarizer", "Summary", "UserRegionDesc", "UserRegionSummary", "UserTaskSummary", "UtilFlags", "UtilWindow", "Writer", "NewWriter"},
249 | "internal/trace/traceviewer": {"BuildProfile", "MMUHandlerFunc", "MainHandler", "SVGProfileHandlerFunc", "StaticHandler", "TraceHandler", "WalkStackFrames", "ArrowEvent", "AsyncSliceEvent", "Emitter", "NewEmitter", "GState", "InstantEvent", "Mode", "MutatorUtilFunc", "ProfileFunc", "ProfileRecord", "Range", "SliceEvent", "ThreadState", "TimeHistogram", "TraceConsumer", "SplittingTraceConsumer", "ViewerDataTraceConsumer", "View", "ViewType"},
250 | "internal/trace/traceviewer/format": {"BlockedArg", "Data", "Event", "Frame", "GoroutineCountersArg", "HeapCountersArg", "NameArg", "SortIndexArg", "ThreadCountersArg", "ThreadIDArg"},
251 | "internal/trace/v2": {"Event", "EventKind", "GoID", "GoState", "Label", "Log", "Metric", "ProcID", "ProcState", "Range", "RangeAttribute", "Reader", "NewReader", "Region", "ResourceID", "MakeResourceID", "ResourceKind", "Stack", "StackFrame", "StateTransition", "Task", "TaskID", "ThreadID", "Time", "Value", "ValueKind"},
252 | "internal/trace/v2/event": {"Names", "Constraint", "SchedReqs", "Spec", "Type"},
253 | "internal/trace/v2/event/go122": {"EventString", "Specs", "GoStatus", "ProcStatus"},
254 | "internal/trace/v2/internal/testgen/go122": {"Main", "Batch", "Generation", "Seq", "Time", "Trace", "NewTrace"},
255 | "internal/trace/v2/raw": {"Event", "Reader", "NewReader", "TextReader", "NewTextReader", "TextWriter", "NewTextWriter", "Writer", "NewWriter"},
256 | "internal/trace/v2/testtrace": {"Expectation", "ExpectSuccess", "ParseExpectation", "ParseFile", "Validator", "NewValidator"},
257 | "internal/trace/v2/version": {"WriteHeader", "Version", "ReadHeader"},
258 | "internal/txtar": {"Format", "Archive", "Parse", "ParseFile", "File"},
259 | "internal/types/errors": {"Code"},
260 | "internal/unsafeheader": {"Slice", "String"},
261 | "internal/xcoff": {"Archive", "NewArchive", "OpenArchive", "ArchiveHeader", "AuxCSect32", "AuxCSect64", "AuxFcn32", "AuxFcn64", "AuxFile64", "AuxSect64", "AuxiliaryCSect", "AuxiliaryFcn", "File", "NewFile", "Open", "FileHeader", "FileHeader32", "FileHeader64", "ImportedSymbol", "LoaderHeader32", "LoaderHeader64", "LoaderSymbol32", "LoaderSymbol64", "Member", "MemberHeader", "Reloc", "Reloc32", "Reloc64", "Section", "SectionHeader", "SectionHeader32", "SectionHeader64", "SymEnt32", "SymEnt64", "Symbol"},
262 | "internal/zstd": {"Reader", "NewReader"},
263 | "io": {"Copy", "CopyBuffer", "CopyN", "Pipe", "ReadAll", "ReadAtLeast", "ReadFull", "WriteString", "ByteReader", "ByteScanner", "ByteWriter", "Closer", "LimitedReader", "OffsetWriter", "NewOffsetWriter", "PipeReader", "PipeWriter", "ReadCloser", "NopCloser", "ReadSeekCloser", "ReadSeeker", "ReadWriteCloser", "ReadWriteSeeker", "ReadWriter", "Reader", "LimitReader", "MultiReader", "TeeReader", "ReaderAt", "ReaderFrom", "RuneReader", "RuneScanner", "SectionReader", "NewSectionReader", "Seeker", "StringWriter", "WriteCloser", "WriteSeeker", "Writer", "MultiWriter", "WriterAt", "WriterTo"},
264 | "io/fs": {"FormatDirEntry", "FormatFileInfo", "Glob", "ReadFile", "ValidPath", "WalkDir", "DirEntry", "FileInfoToDirEntry", "ReadDir", "FS", "Sub", "File", "FileInfo", "Stat", "FileMode", "GlobFS", "PathError", "ReadDirFS", "ReadDirFile", "ReadFileFS", "StatFS", "SubFS", "WalkDirFunc"},
265 | "io/ioutil": {"NopCloser", "ReadAll", "ReadDir", "ReadFile", "TempDir", "TempFile", "WriteFile"},
266 | "log": {"Fatal", "Fatalf", "Fatalln", "Flags", "Output", "Panic", "Panicf", "Panicln", "Prefix", "Print", "Printf", "Println", "SetFlags", "SetOutput", "SetPrefix", "Writer", "Logger", "Default", "New"},
267 | "log/internal": {},
268 | "log/slog": {"Debug", "DebugContext", "Error", "ErrorContext", "Info", "InfoContext", "Log", "LogAttrs", "NewLogLogger", "SetDefault", "Warn", "WarnContext", "Attr", "Any", "Bool", "Duration", "Float64", "Group", "Int", "Int64", "String", "Time", "Uint64", "Handler", "HandlerOptions", "JSONHandler", "NewJSONHandler", "Kind", "Level", "SetLogLoggerLevel", "LevelVar", "Leveler", "LogValuer", "Logger", "Default", "New", "With", "Record", "NewRecord", "Source", "TextHandler", "NewTextHandler", "Value", "AnyValue", "BoolValue", "DurationValue", "Float64Value", "GroupValue", "Int64Value", "IntValue", "StringValue", "TimeValue", "Uint64Value"},
269 | "log/slog/internal": {},
270 | "log/slog/internal/benchmarks": {},
271 | "log/slog/internal/buffer": {"Buffer", "New"},
272 | "log/slog/internal/slogtest": {"RemoveTime"},
273 | "log/syslog": {"NewLogger", "Priority", "Writer", "Dial", "New"},
274 | "maps": {"Clone", "Copy", "DeleteFunc", "Equal", "EqualFunc"},
275 | "math": {"Abs", "Acos", "Acosh", "Asin", "Asinh", "Atan", "Atan2", "Atanh", "Cbrt", "Ceil", "Copysign", "Cos", "Cosh", "Dim", "Erf", "Erfc", "Erfcinv", "Erfinv", "Exp", "Exp2", "Expm1", "FMA", "Float32bits", "Float32frombits", "Float64bits", "Float64frombits", "Floor", "Frexp", "Gamma", "Hypot", "Ilogb", "Inf", "IsInf", "IsNaN", "J0", "J1", "Jn", "Ldexp", "Lgamma", "Log", "Log10", "Log1p", "Log2", "Logb", "Max", "Min", "Mod", "Modf", "NaN", "Nextafter", "Nextafter32", "Pow", "Pow10", "Remainder", "Round", "RoundToEven", "Signbit", "Sin", "Sincos", "Sinh", "Sqrt", "Tan", "Tanh", "Trunc", "Y0", "Y1", "Yn"},
276 | "math/big": {"Jacobi", "Accuracy", "ErrNaN", "Float", "NewFloat", "ParseFloat", "Int", "NewInt", "Rat", "NewRat", "RoundingMode", "Word"},
277 | "math/bits": {"Add", "Add32", "Add64", "Div", "Div32", "Div64", "LeadingZeros", "LeadingZeros16", "LeadingZeros32", "LeadingZeros64", "LeadingZeros8", "Len", "Len16", "Len32", "Len64", "Len8", "Mul", "Mul32", "Mul64", "OnesCount", "OnesCount16", "OnesCount32", "OnesCount64", "OnesCount8", "Rem", "Rem32", "Rem64", "Reverse", "Reverse16", "Reverse32", "Reverse64", "Reverse8", "ReverseBytes", "ReverseBytes16", "ReverseBytes32", "ReverseBytes64", "RotateLeft", "RotateLeft16", "RotateLeft32", "RotateLeft64", "RotateLeft8", "Sub", "Sub32", "Sub64", "TrailingZeros", "TrailingZeros16", "TrailingZeros32", "TrailingZeros64", "TrailingZeros8"},
278 | "math/cmplx": {"Abs", "Acos", "Acosh", "Asin", "Asinh", "Atan", "Atanh", "Conj", "Cos", "Cosh", "Cot", "Exp", "Inf", "IsInf", "IsNaN", "Log", "Log10", "NaN", "Phase", "Polar", "Pow", "Rect", "Sin", "Sinh", "Sqrt", "Tan", "Tanh"},
279 | "math/rand": {"ExpFloat64", "Float32", "Float64", "Int", "Int31", "Int31n", "Int63", "Int63n", "Intn", "NormFloat64", "Perm", "Read", "Seed", "Shuffle", "Uint32", "Uint64", "Rand", "New", "Source", "NewSource", "Source64", "Zipf", "NewZipf"},
280 | "math/rand/v2": {"ExpFloat64", "Float32", "Float64", "Int", "Int32", "Int32N", "Int64", "Int64N", "IntN", "N", "NormFloat64", "Perm", "Shuffle", "Uint32", "Uint32N", "Uint64", "Uint64N", "UintN", "ChaCha8", "NewChaCha8", "PCG", "NewPCG", "Rand", "New", "Source", "Zipf", "NewZipf"},
281 | "mime": {"AddExtensionType", "ExtensionsByType", "FormatMediaType", "ParseMediaType", "TypeByExtension", "WordDecoder", "WordEncoder"},
282 | "mime/multipart": {"File", "FileHeader", "Form", "Part", "Reader", "NewReader", "Writer", "NewWriter"},
283 | "mime/quotedprintable": {"Reader", "NewReader", "Writer", "NewWriter"},
284 | "net": {"JoinHostPort", "LookupAddr", "LookupCNAME", "LookupHost", "LookupPort", "LookupTXT", "ParseCIDR", "Pipe", "SplitHostPort", "Addr", "InterfaceAddrs", "AddrError", "Buffers", "Conn", "Dial", "DialTimeout", "FileConn", "DNSConfigError", "DNSError", "Dialer", "Error", "Flags", "HardwareAddr", "ParseMAC", "IP", "IPv4", "LookupIP", "ParseIP", "IPAddr", "ResolveIPAddr", "IPConn", "DialIP", "ListenIP", "IPMask", "CIDRMask", "IPv4Mask", "IPNet", "Interface", "InterfaceByIndex", "InterfaceByName", "Interfaces", "InvalidAddrError", "ListenConfig", "Listener", "FileListener", "Listen", "MX", "LookupMX", "NS", "LookupNS", "OpError", "PacketConn", "FilePacketConn", "ListenPacket", "ParseError", "Resolver", "SRV", "LookupSRV", "TCPAddr", "ResolveTCPAddr", "TCPAddrFromAddrPort", "TCPConn", "DialTCP", "TCPListener", "ListenTCP", "UDPAddr", "ResolveUDPAddr", "UDPAddrFromAddrPort", "UDPConn", "DialUDP", "ListenMulticastUDP", "ListenUDP", "UnixAddr", "ResolveUnixAddr", "UnixConn", "DialUnix", "ListenUnixgram", "UnixListener", "ListenUnix", "UnknownNetworkError"},
285 | "net/http": {"CanonicalHeaderKey", "DetectContentType", "Error", "Handle", "HandleFunc", "ListenAndServe", "ListenAndServeTLS", "MaxBytesReader", "NotFound", "ParseHTTPVersion", "ParseTime", "ProxyFromEnvironment", "ProxyURL", "Redirect", "Serve", "ServeContent", "ServeFile", "ServeFileFS", "ServeTLS", "SetCookie", "StatusText", "Client", "CloseNotifier", "ConnState", "Cookie", "CookieJar", "Dir", "File", "FileSystem", "FS", "Flusher", "Handler", "AllowQuerySemicolons", "FileServer", "FileServerFS", "MaxBytesHandler", "NotFoundHandler", "RedirectHandler", "StripPrefix", "TimeoutHandler", "HandlerFunc", "Header", "Hijacker", "MaxBytesError", "ProtocolError", "PushOptions", "Pusher", "Request", "NewRequest", "NewRequestWithContext", "ReadRequest", "Response", "Get", "Head", "Post", "PostForm", "ReadResponse", "ResponseController", "NewResponseController", "ResponseWriter", "RoundTripper", "NewFileTransport", "NewFileTransportFS", "SameSite", "ServeMux", "NewServeMux", "Server", "Transport"},
286 | "net/http/cgi": {"Request", "RequestFromMap", "Serve", "Handler"},
287 | "net/http/cookiejar": {"Jar", "New", "Options", "PublicSuffixList"},
288 | "net/http/fcgi": {"ProcessEnv", "Serve"},
289 | "net/http/httptest": {"NewRequest", "ResponseRecorder", "NewRecorder", "Server", "NewServer", "NewTLSServer", "NewUnstartedServer"},
290 | "net/http/httptrace": {"WithClientTrace", "ClientTrace", "ContextClientTrace", "DNSDoneInfo", "DNSStartInfo", "GotConnInfo", "WroteRequestInfo"},
291 | "net/http/httputil": {"DumpRequest", "DumpRequestOut", "DumpResponse", "NewChunkedReader", "NewChunkedWriter", "BufferPool", "ClientConn", "NewClientConn", "NewProxyClientConn", "ProxyRequest", "ReverseProxy", "NewSingleHostReverseProxy", "ServerConn", "NewServerConn"},
292 | "net/http/internal": {"NewChunkedReader", "NewChunkedWriter", "FlushAfterChunkWriter"},
293 | "net/http/internal/ascii": {"EqualFold", "Is", "IsPrint", "ToLower"},
294 | "net/http/internal/testcert": {},
295 | "net/http/pprof": {"Cmdline", "Handler", "Index", "Profile", "Symbol", "Trace"},
296 | "net/internal/socktest": {"AfterFilter", "Cookie", "Filter", "FilterType", "Sockets", "Stat", "Status", "Switch"},
297 | "net/mail": {"ParseDate", "Address", "ParseAddress", "ParseAddressList", "AddressParser", "Header", "Message", "ReadMessage"},
298 | "net/netip": {"Addr", "AddrFrom16", "AddrFrom4", "AddrFromSlice", "IPv4Unspecified", "IPv6LinkLocalAllNodes", "IPv6LinkLocalAllRouters", "IPv6Loopback", "IPv6Unspecified", "MustParseAddr", "ParseAddr", "AddrPort", "AddrPortFrom", "MustParseAddrPort", "ParseAddrPort", "Prefix", "MustParsePrefix", "ParsePrefix", "PrefixFrom"},
299 | "net/rpc": {"Accept", "HandleHTTP", "Register", "RegisterName", "ServeCodec", "ServeConn", "ServeRequest", "Call", "Client", "Dial", "DialHTTP", "DialHTTPPath", "NewClient", "NewClientWithCodec", "ClientCodec", "Request", "Response", "Server", "NewServer", "ServerCodec", "ServerError"},
300 | "net/rpc/jsonrpc": {"Dial", "NewClient", "NewClientCodec", "NewServerCodec", "ServeConn"},
301 | "net/smtp": {"SendMail", "Auth", "CRAMMD5Auth", "PlainAuth", "Client", "Dial", "NewClient", "ServerInfo"},
302 | "net/textproto": {"CanonicalMIMEHeaderKey", "TrimBytes", "TrimString", "Conn", "Dial", "NewConn", "Error", "MIMEHeader", "Pipeline", "ProtocolError", "Reader", "NewReader", "Writer", "NewWriter"},
303 | "net/url": {"JoinPath", "PathEscape", "PathUnescape", "QueryEscape", "QueryUnescape", "Error", "EscapeError", "InvalidHostError", "URL", "Parse", "ParseRequestURI", "Userinfo", "User", "UserPassword", "Values", "ParseQuery"},
304 | "os": {"Chdir", "Chmod", "Chown", "Chtimes", "Clearenv", "DirFS", "Environ", "Executable", "Exit", "Expand", "ExpandEnv", "Getegid", "Getenv", "Geteuid", "Getgid", "Getgroups", "Getpagesize", "Getpid", "Getppid", "Getuid", "Getwd", "Hostname", "IsExist", "IsNotExist", "IsPathSeparator", "IsPermission", "IsTimeout", "Lchown", "Link", "LookupEnv", "Mkdir", "MkdirAll", "MkdirTemp", "NewSyscallError", "Pipe", "ReadFile", "Readlink", "Remove", "RemoveAll", "Rename", "SameFile", "Setenv", "Symlink", "TempDir", "Truncate", "Unsetenv", "UserCacheDir", "UserConfigDir", "UserHomeDir", "WriteFile", "DirEntry", "ReadDir", "File", "Create", "CreateTemp", "NewFile", "Open", "OpenFile", "FileInfo", "Lstat", "Stat", "FileMode", "LinkError", "PathError", "ProcAttr", "Process", "FindProcess", "StartProcess", "ProcessState", "Signal", "SyscallError"},
305 | "os/exec": {"LookPath", "Cmd", "Command", "CommandContext", "Error", "ExitError"},
306 | "os/exec/internal/fdtest": {"Exists"},
307 | "os/signal": {"Ignore", "Ignored", "Notify", "NotifyContext", "Reset", "Stop"},
308 | "os/user": {"Group", "LookupGroup", "LookupGroupId", "UnknownGroupError", "UnknownGroupIdError", "UnknownUserError", "UnknownUserIdError", "User", "Current", "Lookup", "LookupId"},
309 | "path": {"Base", "Clean", "Dir", "Ext", "IsAbs", "Join", "Match", "Split"},
310 | "path/filepath": {"Abs", "Base", "Clean", "Dir", "EvalSymlinks", "Ext", "FromSlash", "Glob", "HasPrefix", "IsAbs", "IsLocal", "Join", "Match", "Rel", "Split", "SplitList", "ToSlash", "VolumeName", "Walk", "WalkDir", "WalkFunc"},
311 | "plugin": {"Plugin", "Open", "Symbol"},
312 | "reflect": {"Copy", "DeepEqual", "Swapper", "ChanDir", "Kind", "MapIter", "Method", "SelectCase", "SelectDir", "SliceHeader", "StringHeader", "StructField", "VisibleFields", "StructTag", "Type", "ArrayOf", "ChanOf", "FuncOf", "MapOf", "PointerTo", "PtrTo", "SliceOf", "StructOf", "TypeFor", "TypeOf", "Value", "Append", "AppendSlice", "Indirect", "MakeChan", "MakeFunc", "MakeMap", "MakeMapWithSize", "MakeSlice", "New", "NewAt", "Select", "ValueOf", "Zero", "ValueError"},
313 | "reflect/internal/example1": {"MyStruct"},
314 | "reflect/internal/example2": {"MyStruct"},
315 | "regexp": {"Match", "MatchReader", "MatchString", "QuoteMeta", "Regexp", "Compile", "CompilePOSIX", "MustCompile", "MustCompilePOSIX"},
316 | "regexp/syntax": {"IsWordChar", "EmptyOp", "EmptyOpContext", "Error", "ErrorCode", "Flags", "Inst", "InstOp", "Op", "Prog", "Compile", "Regexp", "Parse"},
317 | "runtime": {"BlockProfile", "Breakpoint", "CPUProfile", "Caller", "Callers", "GC", "GOMAXPROCS", "GOROOT", "Goexit", "GoroutineProfile", "Gosched", "KeepAlive", "LockOSThread", "MemProfile", "MutexProfile", "NumCPU", "NumCgoCall", "NumGoroutine", "ReadMemStats", "ReadTrace", "SetBlockProfileRate", "SetCPUProfileRate", "SetCgoTraceback", "SetFinalizer", "SetMutexProfileFraction", "Stack", "StartTrace", "StopTrace", "ThreadCreateProfile", "UnlockOSThread", "Version", "BlockProfileRecord", "Error", "Frame", "Frames", "CallersFrames", "Func", "FuncForPC", "MemProfileRecord", "MemStats", "PanicNilError", "RuntimeError", "Pinner", "StackRecord", "TypeAssertionError"},
318 | "runtime/cgo": {"Handle", "NewHandle", "Incomplete"},
319 | "runtime/coverage": {"ClearCounters", "WriteCounters", "WriteCountersDir", "WriteMeta", "WriteMetaDir"},
320 | "runtime/debug": {"FreeOSMemory", "PrintStack", "ReadGCStats", "SetGCPercent", "SetMaxStack", "SetMaxThreads", "SetMemoryLimit", "SetPanicOnFault", "SetTraceback", "Stack", "WriteHeapDump", "BuildInfo", "ParseBuildInfo", "ReadBuildInfo", "BuildSetting", "GCStats", "Module"},
321 | "runtime/internal/atomic": {"And", "And32", "And64", "And8", "Anduintptr", "Cas", "Cas64", "CasRel", "Casint32", "Casint64", "Casp1", "Casuintptr", "Load", "Load64", "Load8", "LoadAcq", "LoadAcq64", "LoadAcquintptr", "Loadint32", "Loadint64", "Loadp", "Loaduint", "Loaduintptr", "Or", "Or32", "Or64", "Or8", "Oruintptr", "Store", "Store64", "Store8", "StoreRel", "StoreRel64", "StoreReluintptr", "Storeint32", "Storeint64", "StorepNoWB", "Storeuintptr", "Xadd", "Xadd64", "Xaddint32", "Xaddint64", "Xadduintptr", "Xchg", "Xchg64", "Xchgint32", "Xchgint64", "Xchguintptr", "Bool", "Float64", "Int32", "Int64", "Pointer", "Uint32", "Uint64", "Uint8", "Uintptr", "UnsafePointer"},
322 | "runtime/internal/math": {"Add64", "Mul64", "MulUintptr"},
323 | "runtime/internal/startlinetest": {"AsmFunc"},
324 | "runtime/internal/sys": {"Bswap32", "Bswap64", "LeadingZeros64", "LeadingZeros8", "Len64", "Len8", "OnesCount64", "Prefetch", "PrefetchStreamed", "TrailingZeros32", "TrailingZeros64", "TrailingZeros8", "NotInHeap"},
325 | "runtime/internal/syscall": {"EpollCreate1", "EpollCtl", "EpollWait", "Syscall6", "EpollEvent"},
326 | "runtime/metrics": {"Read", "Description", "All", "Float64Histogram", "Sample", "Value", "ValueKind"},
327 | "runtime/pprof": {"Do", "ForLabels", "Label", "SetGoroutineLabels", "StartCPUProfile", "StopCPUProfile", "WithLabels", "WriteHeapProfile", "LabelSet", "Labels", "Profile", "Lookup", "NewProfile", "Profiles"},
328 | "runtime/race": {},
329 | "runtime/race/internal/amd64v1": {},
330 | "runtime/trace": {"IsEnabled", "Log", "Logf", "Start", "Stop", "WithRegion", "Region", "StartRegion", "Task", "NewTask"},
331 | "slices": {"BinarySearch", "BinarySearchFunc", "Clip", "Clone", "Compact", "CompactFunc", "Compare", "CompareFunc", "Concat", "Contains", "ContainsFunc", "Delete", "DeleteFunc", "Equal", "EqualFunc", "Grow", "Index", "IndexFunc", "Insert", "IsSorted", "IsSortedFunc", "Max", "MaxFunc", "Min", "MinFunc", "Replace", "Reverse", "Sort", "SortFunc", "SortStableFunc"},
332 | "sort": {"Find", "Float64s", "Float64sAreSorted", "Ints", "IntsAreSorted", "IsSorted", "Search", "SearchFloat64s", "SearchInts", "SearchStrings", "Slice", "SliceIsSorted", "SliceStable", "Sort", "Stable", "Strings", "StringsAreSorted", "Float64Slice", "IntSlice", "Interface", "Reverse", "StringSlice"},
333 | "strconv": {"AppendBool", "AppendFloat", "AppendInt", "AppendQuote", "AppendQuoteRune", "AppendQuoteRuneToASCII", "AppendQuoteRuneToGraphic", "AppendQuoteToASCII", "AppendQuoteToGraphic", "AppendUint", "Atoi", "CanBackquote", "FormatBool", "FormatComplex", "FormatFloat", "FormatInt", "FormatUint", "IsGraphic", "IsPrint", "Itoa", "ParseBool", "ParseComplex", "ParseFloat", "ParseInt", "ParseUint", "Quote", "QuoteRune", "QuoteRuneToASCII", "QuoteRuneToGraphic", "QuoteToASCII", "QuoteToGraphic", "QuotedPrefix", "Unquote", "UnquoteChar", "NumError"},
334 | "strings": {"Clone", "Compare", "Contains", "ContainsAny", "ContainsFunc", "ContainsRune", "Count", "Cut", "CutPrefix", "CutSuffix", "EqualFold", "Fields", "FieldsFunc", "HasPrefix", "HasSuffix", "Index", "IndexAny", "IndexByte", "IndexFunc", "IndexRune", "Join", "LastIndex", "LastIndexAny", "LastIndexByte", "LastIndexFunc", "Map", "Repeat", "Replace", "ReplaceAll", "Split", "SplitAfter", "SplitAfterN", "SplitN", "Title", "ToLower", "ToLowerSpecial", "ToTitle", "ToTitleSpecial", "ToUpper", "ToUpperSpecial", "ToValidUTF8", "Trim", "TrimFunc", "TrimLeft", "TrimLeftFunc", "TrimPrefix", "TrimRight", "TrimRightFunc", "TrimSpace", "TrimSuffix", "Builder", "Reader", "NewReader", "Replacer", "NewReplacer"},
335 | "sync": {"OnceFunc", "OnceValue", "OnceValues", "Cond", "NewCond", "Locker", "Map", "Mutex", "Once", "Pool", "RWMutex", "WaitGroup"},
336 | "sync/atomic": {"AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr", "CompareAndSwapInt32", "CompareAndSwapInt64", "CompareAndSwapPointer", "CompareAndSwapUint32", "CompareAndSwapUint64", "CompareAndSwapUintptr", "LoadInt32", "LoadInt64", "LoadPointer", "LoadUint32", "LoadUint64", "LoadUintptr", "StoreInt32", "StoreInt64", "StorePointer", "StoreUint32", "StoreUint64", "StoreUintptr", "SwapInt32", "SwapInt64", "SwapPointer", "SwapUint32", "SwapUint64", "SwapUintptr", "Bool", "Int32", "Int64", "Pointer", "Uint32", "Uint64", "Uintptr", "Value"},
337 | "syscall": {"Access", "Acct", "Adjtimex", "AttachLsf", "Bind", "BindToDevice", "BytePtrFromString", "ByteSliceFromString", "Chdir", "Chmod", "Chown", "Chroot", "Clearenv", "Close", "CloseOnExec", "CmsgLen", "CmsgSpace", "Connect", "Creat", "DetachLsf", "Dup", "Dup2", "Dup3", "Environ", "EpollCreate", "EpollCreate1", "EpollCtl", "EpollWait", "Exec", "Exit", "Faccessat", "Fallocate", "Fchdir", "Fchmod", "Fchmodat", "Fchown", "Fchownat", "FcntlFlock", "Fdatasync", "Flock", "ForkExec", "Fstat", "Fstatfs", "Fsync", "Ftruncate", "Futimes", "Futimesat", "Getcwd", "Getdents", "Getegid", "Getenv", "Geteuid", "Getgid", "Getgroups", "Getpagesize", "Getpgid", "Getpgrp", "Getpid", "Getppid", "Getpriority", "Getrlimit", "Getrusage", "GetsockoptInet4Addr", "GetsockoptInt", "Gettid", "Gettimeofday", "Getuid", "Getwd", "Getxattr", "InotifyAddWatch", "InotifyInit", "InotifyInit1", "InotifyRmWatch", "Ioperm", "Iopl", "Kill", "Klogctl", "Lchown", "Link", "Listen", "Listxattr", "LsfSocket", "Lstat", "Madvise", "Mkdir", "Mkdirat", "Mkfifo", "Mknod", "Mknodat", "Mlock", "Mlockall", "Mmap", "Mount", "Mprotect", "Munlock", "Munlockall", "Munmap", "Nanosleep", "NetlinkRIB", "Open", "Openat", "ParseDirent", "ParseUnixRights", "Pause", "Pipe", "Pipe2", "PivotRoot", "Pread", "PtraceAttach", "PtraceCont", "PtraceDetach", "PtraceGetEventMsg", "PtraceGetRegs", "PtracePeekData", "PtracePeekText", "PtracePokeData", "PtracePokeText", "PtraceSetOptions", "PtraceSetRegs", "PtraceSingleStep", "PtraceSyscall", "Pwrite", "Read", "ReadDirent", "Readlink", "Reboot", "Removexattr", "Rename", "Renameat", "Rmdir", "Seek", "Select", "Sendfile", "Sendmsg", "SendmsgN", "Sendto", "SetLsfPromisc", "SetNonblock", "Setdomainname", "Setegid", "Setenv", "Seteuid", "Setfsgid", "Setfsuid", "Setgid", "Setgroups", "Sethostname", "Setpgid", "Setpriority", "Setregid", "Setresgid", "Setresuid", "Setreuid", "Setrlimit", "Setsid", "SetsockoptByte", "SetsockoptICMPv6Filter", "SetsockoptIPMreq", "SetsockoptIPMreqn", "SetsockoptIPv6Mreq", "SetsockoptInet4Addr", "SetsockoptInt", "SetsockoptLinger", "SetsockoptString", "SetsockoptTimeval", "Settimeofday", "Setuid", "Setxattr", "Shutdown", "SlicePtrFromStrings", "Socket", "Socketpair", "Splice", "StartProcess", "Stat", "Statfs", "StringBytePtr", "StringByteSlice", "StringSlicePtr", "Symlink", "Sync", "SyncFileRange", "Sysinfo", "Tee", "Tgkill", "Times", "TimespecToNsec", "TimevalToNsec", "Truncate", "Umask", "Uname", "UnixCredentials", "UnixRights", "Unlink", "Unlinkat", "Unmount", "Unsetenv", "Unshare", "Ustat", "Utime", "Utimes", "UtimesNano", "Wait4", "Write", "Cmsghdr", "Conn", "Credential", "Dirent", "EpollEvent", "Errno", "AllThreadsSyscall", "AllThreadsSyscall6", "RawSyscall", "RawSyscall6", "Syscall", "Syscall6", "FdSet", "Flock_t", "Fsid", "ICMPv6Filter", "GetsockoptICMPv6Filter", "IPMreq", "GetsockoptIPMreq", "IPMreqn", "GetsockoptIPMreqn", "IPv6MTUInfo", "GetsockoptIPv6MTUInfo", "IPv6Mreq", "GetsockoptIPv6Mreq", "IfAddrmsg", "IfInfomsg", "Inet4Pktinfo", "Inet6Pktinfo", "InotifyEvent", "Iovec", "Linger", "Msghdr", "NetlinkMessage", "ParseNetlinkMessage", "NetlinkRouteAttr", "ParseNetlinkRouteAttr", "NetlinkRouteRequest", "NlAttr", "NlMsgerr", "NlMsghdr", "ProcAttr", "PtraceRegs", "RawConn", "RawSockaddr", "RawSockaddrAny", "RawSockaddrInet4", "RawSockaddrInet6", "RawSockaddrLinklayer", "RawSockaddrNetlink", "RawSockaddrUnix", "Rlimit", "RtAttr", "RtGenmsg", "RtMsg", "RtNexthop", "Rusage", "Signal", "SockFilter", "LsfJump", "LsfStmt", "SockFprog", "Sockaddr", "Accept", "Accept4", "Getpeername", "Getsockname", "Recvfrom", "Recvmsg", "SockaddrInet4", "SockaddrInet6", "SockaddrLinklayer", "SockaddrNetlink", "SockaddrUnix", "SocketControlMessage", "ParseSocketControlMessage", "Stat_t", "Statfs_t", "SysProcAttr", "SysProcIDMap", "Sysinfo_t", "TCPInfo", "Termios", "Time_t", "Time", "Timespec", "NsecToTimespec", "Timeval", "NsecToTimeval", "Timex", "Tms", "Ucred", "GetsockoptUcred", "ParseUnixCredentials", "Ustat_t", "Utimbuf", "Utsname", "WaitStatus"},
338 | "syscall/js": {"CopyBytesToGo", "CopyBytesToJS", "Error", "Func", "FuncOf", "Type", "Value", "Global", "Null", "Undefined", "ValueOf", "ValueError"},
339 | "testing": {"AllocsPerRun", "CoverMode", "Coverage", "Init", "Main", "RegisterCover", "RunBenchmarks", "RunExamples", "RunTests", "Short", "Testing", "Verbose", "B", "BenchmarkResult", "Benchmark", "Cover", "CoverBlock", "F", "InternalBenchmark", "InternalExample", "InternalFuzzTarget", "InternalTest", "M", "MainStart", "PB", "T", "TB"},
340 | "testing/fstest": {"TestFS", "MapFS", "MapFile"},
341 | "testing/internal/testdeps": {"TestDeps", "CheckCorpus", "CoordinateFuzzing", "ImportPath", "MatchString", "ReadCorpus", "ResetCoverage", "RunFuzzWorker", "SetPanicOnExit0", "SnapshotCoverage", "StartCPUProfile", "StartTestLog", "StopCPUProfile", "StopTestLog", "WriteProfileTo"},
342 | "testing/iotest": {"DataErrReader", "ErrReader", "HalfReader", "NewReadLogger", "NewWriteLogger", "OneByteReader", "TestReader", "TimeoutReader", "TruncateWriter"},
343 | "testing/quick": {"Check", "CheckEqual", "Value", "CheckEqualError", "CheckError", "Config", "Generator", "SetupError"},
344 | "testing/slogtest": {"Run", "TestHandler"},
345 | "text/scanner": {"TokenString", "Position", "Scanner"},
346 | "text/tabwriter": {"Writer", "NewWriter"},
347 | "text/template": {"HTMLEscape", "HTMLEscapeString", "HTMLEscaper", "IsTrue", "JSEscape", "JSEscapeString", "JSEscaper", "URLQueryEscaper", "ExecError", "FuncMap", "Template", "Must", "New", "ParseFS", "ParseFiles", "ParseGlob"},
348 | "text/template/parse": {"IsEmptyTree", "Parse", "ActionNode", "BoolNode", "BranchNode", "BreakNode", "ChainNode", "CommandNode", "CommentNode", "ContinueNode", "DotNode", "FieldNode", "IdentifierNode", "NewIdentifier", "IfNode", "ListNode", "Mode", "NilNode", "Node", "NodeType", "NumberNode", "PipeNode", "Pos", "RangeNode", "StringNode", "TemplateNode", "TextNode", "Tree", "New", "VariableNode", "WithNode"},
349 | "time": {"After", "Sleep", "Tick", "Duration", "ParseDuration", "Since", "Until", "Location", "FixedZone", "LoadLocation", "LoadLocationFromTZData", "Month", "ParseError", "Ticker", "NewTicker", "Time", "Date", "Now", "Parse", "ParseInLocation", "Unix", "UnixMicro", "UnixMilli", "Timer", "AfterFunc", "NewTimer", "Weekday"},
350 | "time/tzdata": {},
351 | "unicode": {"In", "Is", "IsControl", "IsDigit", "IsGraphic", "IsLetter", "IsLower", "IsMark", "IsNumber", "IsOneOf", "IsPrint", "IsPunct", "IsSpace", "IsSymbol", "IsTitle", "IsUpper", "SimpleFold", "To", "ToLower", "ToTitle", "ToUpper", "CaseRange", "Range16", "Range32", "RangeTable", "SpecialCase"},
352 | "unicode/utf16": {"AppendRune", "Decode", "DecodeRune", "Encode", "EncodeRune", "IsSurrogate"},
353 | "unicode/utf8": {"AppendRune", "DecodeLastRune", "DecodeLastRuneInString", "DecodeRune", "DecodeRuneInString", "EncodeRune", "FullRune", "FullRuneInString", "RuneCount", "RuneCountInString", "RuneLen", "RuneStart", "Valid", "ValidRune", "ValidString"},
354 | "unsafe": {"Alignof", "Offsetof", "Sizeof", "String", "StringData", "ArbitraryType", "Slice", "SliceData", "IntegerType", "Pointer", "Add"},
355 | }
356 | supportedPackages = maps.Keys(packageFunctions)
357 |
358 | autoComplete = append(supportedPackages,
359 | // language keywords
360 | "package",
361 | "import",
362 | "func",
363 | "var",
364 | "const",
365 | "return",
366 | "if",
367 | "else",
368 | "for",
369 | "range",
370 | "switch",
371 | "case",
372 | "default",
373 | "select",
374 | "break",
375 | "continue",
376 | "goto",
377 | "fallthrough",
378 | "defer",
379 | "go",
380 | "chan",
381 | "map",
382 | "struct",
383 | "interface",
384 | "type",
385 | "append",
386 | "cap",
387 | "close",
388 | "complex",
389 | "copy",
390 | "delete",
391 | "imag",
392 | "len",
393 | "make",
394 | "new",
395 | "panic",
396 | "real",
397 | "bool",
398 | "byte",
399 | "complex64",
400 | "complex128",
401 | "error",
402 | "float32",
403 | "float64",
404 | "int",
405 | "int8",
406 | "int16",
407 | "int32",
408 | "int64",
409 | "rune",
410 | "string",
411 |
412 | // used for goshell
413 | ".quit",
414 | ".vars",
415 | ".source",
416 | ".undo",
417 | ".help",
418 | )
419 | )
420 |
--------------------------------------------------------------------------------
/autocomplete_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestWordCompleter(t *testing.T) {
10 | tests := []struct {
11 | name string
12 | line string
13 | pos int
14 | head string
15 | completions []string
16 | tail string
17 | }{
18 | {
19 | name: "Package known, function specified",
20 | line: "fmt.Pr",
21 | pos: 6,
22 | head: "fmt.",
23 | completions: []string{"Print", "Printf", "Println"},
24 | tail: "",
25 | },
26 | {
27 | name: "Empty line",
28 | line: "",
29 | pos: 0,
30 | head: "",
31 | completions: []string{},
32 | tail: "",
33 | },
34 | {
35 | name: "Package not known",
36 | line: "foo.",
37 | pos: 4,
38 | head: "foo.",
39 | completions: []string{},
40 | tail: "",
41 | },
42 | {
43 | name: "Package known, no function specified",
44 | line: "fmt.",
45 | pos: 4,
46 | head: "fmt.",
47 | completions: packageFunctions["fmt"],
48 | tail: "",
49 | },
50 | {
51 | name: "Package known, function specified",
52 | line: "fmt.Pr",
53 | pos: 6,
54 | head: "fmt.",
55 | completions: []string{"Print", "Printf", "Println"},
56 | tail: "",
57 | },
58 | {
59 | name: "Package known, unkown function specified",
60 | line: "fmt.Zz",
61 | pos: 6,
62 | head: "fmt.Zz",
63 | completions: []string{},
64 | tail: "",
65 | },
66 | {
67 | name: "complete even in the middle of the line",
68 | line: "a:= struc random",
69 | pos: 9,
70 | head: "a:= ",
71 | completions: []string{"struct"},
72 | tail: " random",
73 | },
74 | }
75 |
76 | for _, tt := range tests {
77 | t.Run(tt.name, func(t *testing.T) {
78 | head, completions, tail := WordCompleter(tt.line, tt.pos)
79 | assert.Equal(t, tt.head, head)
80 | assert.ElementsMatch(t, tt.completions, completions)
81 | assert.Equal(t, tt.tail, tail)
82 | })
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/docs/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahmedakef/goshell/8c7403a9d965d8ccb6624d612c90fb18727b1730/docs/example.gif
--------------------------------------------------------------------------------
/generator.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "os"
7 | "text/template"
8 |
9 | "golang.org/x/tools/imports"
10 | )
11 |
12 | func prepareProgram(templatePath string, commands []command, functions []function) (string, error) {
13 | // Read the template file
14 | t := template.Must(template.New("template.txt").Parse(programTemplate))
15 | var buf bytes.Buffer
16 | err := t.Execute(&buf, map[string]any{
17 | "commands": commands,
18 | "functions": functions,
19 | })
20 | if err != nil {
21 | return "", err
22 | }
23 |
24 | return buf.String(), nil
25 | }
26 |
27 | func formatProgram(programPath string) error {
28 |
29 | output, err := imports.Process(programPath, nil, nil)
30 | if err != nil {
31 | fmt.Println("Error formatting the program:", err)
32 | return err
33 | }
34 | err = os.WriteFile(programPath, output, 0644)
35 | if err != nil {
36 | fmt.Println("Error writing the formatted program:", err)
37 | return err
38 | }
39 |
40 | return nil
41 | }
42 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/ahmedakef/goshell
2 |
3 | go 1.21
4 |
5 | require (
6 | github.com/gocolly/colly v1.2.0
7 | github.com/peterh/liner v1.2.2
8 | github.com/stretchr/testify v1.8.4
9 | golang.org/x/exp v0.0.0-20240213143201-ec583247a57a
10 | golang.org/x/tools v0.18.0
11 | )
12 |
13 | require (
14 | github.com/PuerkitoBio/goquery v1.8.1 // indirect
15 | github.com/andybalholm/cascadia v1.3.1 // indirect
16 | github.com/antchfx/htmlquery v1.3.0 // indirect
17 | github.com/antchfx/xmlquery v1.3.18 // indirect
18 | github.com/antchfx/xpath v1.2.4 // indirect
19 | github.com/davecgh/go-spew v1.1.1 // indirect
20 | github.com/gobwas/glob v0.2.3 // indirect
21 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
22 | github.com/golang/protobuf v1.5.2 // indirect
23 | github.com/kennygrant/sanitize v1.2.4 // indirect
24 | github.com/mattn/go-runewidth v0.0.3 // indirect
25 | github.com/pmezard/go-difflib v1.0.0 // indirect
26 | github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
27 | github.com/temoto/robotstxt v1.1.2 // indirect
28 | golang.org/x/mod v0.15.0 // indirect
29 | golang.org/x/net v0.21.0 // indirect
30 | golang.org/x/sys v0.17.0 // indirect
31 | golang.org/x/text v0.14.0 // indirect
32 | google.golang.org/appengine v1.6.8 // indirect
33 | google.golang.org/protobuf v1.26.0 // indirect
34 | gopkg.in/yaml.v3 v3.0.1 // indirect
35 | )
36 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
2 | github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
3 | github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
4 | github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
5 | github.com/antchfx/htmlquery v1.3.0 h1:5I5yNFOVI+egyia5F2s/5Do2nFWxJz41Tr3DyfKD25E=
6 | github.com/antchfx/htmlquery v1.3.0/go.mod h1:zKPDVTMhfOmcwxheXUsx4rKJy8KEY/PU6eXr/2SebQ8=
7 | github.com/antchfx/xmlquery v1.3.18 h1:FSQ3wMuphnPPGJOFhvc+cRQ2CT/rUj4cyQXkJcjOwz0=
8 | github.com/antchfx/xmlquery v1.3.18/go.mod h1:Afkq4JIeXut75taLSuI31ISJ/zeq+3jG7TunF7noreA=
9 | github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
10 | github.com/antchfx/xpath v1.2.4 h1:dW1HB/JxKvGtJ9WyVGJ0sIoEcqftV3SqIstujI+B9XY=
11 | github.com/antchfx/xpath v1.2.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
12 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
13 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
14 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
15 | github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
16 | github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
17 | github.com/gocolly/colly v1.2.0 h1:qRz9YAn8FIH0qzgNUw+HT9UN7wm1oF9OBAilwEWpyrI=
18 | github.com/gocolly/colly v1.2.0/go.mod h1:Hof5T3ZswNVsOHYmba1u03W65HDWgpV5HifSuueE0EA=
19 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
20 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
21 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
22 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
23 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
24 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
25 | github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
26 | github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
27 | github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
28 | github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak=
29 | github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
30 | github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
31 | github.com/peterh/liner v1.2.2 h1:aJ4AOodmL+JxOZZEL2u9iJf8omNRpqHc/EbrK+3mAXw=
32 | github.com/peterh/liner v1.2.2/go.mod h1:xFwJyiKIXJZUKItq5dGHZSTBRAuG/CpeNpWLyiNRNwI=
33 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
34 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
35 | github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
36 | github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
37 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
38 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
39 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
40 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
41 | github.com/temoto/robotstxt v1.1.2 h1:W2pOjSJ6SWvldyEuiFXNxz3xZ8aiWX5LbfDiOFd7Fxg=
42 | github.com/temoto/robotstxt v1.1.2/go.mod h1:+1AmkuG3IYkh1kv0d2qEB9Le88ehNO0zwOr3ujewlOo=
43 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
44 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
45 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
46 | golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE=
47 | golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
48 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
49 | golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
50 | golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
51 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
52 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
53 | golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
54 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
55 | golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
56 | golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
57 | golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
58 | golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
59 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
60 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
61 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
62 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
63 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
64 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
65 | golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
66 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
67 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
68 | golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
69 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
70 | golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
71 | golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
72 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
73 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
74 | golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
75 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
76 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
77 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
78 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
79 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
80 | golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
81 | golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
82 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
83 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
84 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
85 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
86 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
87 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
88 | golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
89 | golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
90 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
91 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
92 | google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
93 | google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
94 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
95 | google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
96 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
97 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
98 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
99 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
100 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
101 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "io"
7 | "os"
8 | "os/signal"
9 | "path/filepath"
10 | "strings"
11 | "syscall"
12 |
13 | "github.com/peterh/liner"
14 | )
15 |
16 | const (
17 | version = "0.0.9"
18 | startUpMessage = "Go Shell - A Repl for Go"
19 | helpMessage = `Commands:
20 | .q(uit) exit Go Shell
21 | .v(ars) show all variable names
22 | .s(ource) print the source entered since startup
23 | .u(ndo) undo the last entry
24 | .h(elp) print this help message
25 | `
26 |
27 | _programName = "goshell_program.go"
28 | )
29 |
30 | func main() {
31 | versionFlag := flag.Bool("v", false, "Print the version")
32 | debugFlag := flag.Bool("debug", false, "debug mode")
33 | flag.Parse()
34 | if *versionFlag {
35 | fmt.Println(version)
36 | return
37 | }
38 |
39 | done := make(chan bool, 1)
40 | go waitForSignal(done)
41 | commandsChan := make(chan string, 1)
42 | continueChan := make(chan bool, 1)
43 |
44 | line, history_path := setupLiner()
45 | defer line.Close()
46 |
47 | fmt.Println(startUpMessage)
48 | fmt.Println(helpMessage)
49 | continueChan <- true
50 | go waitForInput(commandsChan, continueChan, done, line)
51 |
52 | path := filepath.Join(os.TempDir(), _programName)
53 | if *debugFlag {
54 | fmt.Println("Debug mode, using the file:", path)
55 | }
56 | manager := newManager(path)
57 | manager.cleanUp()
58 |
59 | for {
60 | select {
61 | case <-done:
62 | manager.cleanUp()
63 | if f, err := os.Create(history_path); err != nil {
64 | fmt.Println("Error writing history file: ", err)
65 | } else {
66 | line.WriteHistory(f)
67 | f.Close()
68 | }
69 | return
70 | case command := <-commandsChan:
71 | switch command {
72 | case ".quit", ".q":
73 | manager.cleanUp()
74 | return
75 | case ".vars", ".v":
76 | fmt.Println(manager.extractVariables())
77 | case ".source", ".s":
78 | program, err := manager.getProgram()
79 | if err != nil {
80 | fmt.Println("Error geting the source code:", err)
81 | } else {
82 | fmt.Println(program)
83 | }
84 | case ".undo", ".u":
85 | manager.removeLastInput()
86 | case ".help", ".h":
87 | fmt.Println(helpMessage)
88 |
89 | default:
90 | if command == "" {
91 | break // ignore empty commands
92 | }
93 | err := manager.addInput(command)
94 | if err != nil {
95 | fmt.Println("Error parsing the input:", err)
96 | continueChan <- true
97 | continue
98 | }
99 | output, err := manager.runProgram()
100 | if err != nil {
101 | fmt.Println("Error running the program:", err)
102 | fmt.Println("Removing last input, type '.s(ource)' to see the program")
103 | manager.removeLastInput()
104 | }
105 | if output != "" {
106 | fmt.Print(output)
107 | }
108 | }
109 | }
110 | continueChan <- true
111 | }
112 | }
113 |
114 | func waitForInput(commands chan<- string, continueChan <-chan bool, done chan bool, line *liner.State) {
115 | for <-continueChan {
116 | command, err := line.Prompt(">>> ")
117 | if err == liner.ErrPromptAborted || err == io.EOF {
118 | done <- true
119 | return
120 | } else if err != nil {
121 | fmt.Println("Error reading input: ", err)
122 | done <- true
123 | }
124 |
125 | if command == "exit" {
126 | done <- true
127 | return
128 | }
129 | openBrackets := strings.Count(command, "{")
130 | openBrackets -= strings.Count(command, "}")
131 | if openBrackets > 0 {
132 | multiLineCommand := command + "\n"
133 | userExit := false
134 | for {
135 | identation := strings.Repeat(" ", openBrackets)
136 | if subCommand, err := line.Prompt("... " + identation); err == nil {
137 | if subCommand == "" {
138 | continue
139 | }
140 | multiLineCommand += subCommand + "\n"
141 | openBrackets += strings.Count(subCommand, "{")
142 | openBrackets -= strings.Count(subCommand, "}")
143 | if openBrackets == 0 {
144 | break
145 | }
146 | } else if err == io.EOF || err == liner.ErrPromptAborted {
147 | userExit = true
148 | break
149 | } else {
150 | fmt.Println("Error reading input: ", err)
151 | done <- true
152 | return
153 | }
154 | }
155 | if userExit {
156 | command = ""
157 | } else {
158 | command = multiLineCommand
159 | }
160 | }
161 | commands <- command
162 | if command != "" {
163 | line.AppendHistory(command)
164 | }
165 | }
166 | }
167 |
168 | func waitForSignal(done chan bool) {
169 | sigs := make(chan os.Signal, 1)
170 | signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
171 |
172 | sig := <-sigs
173 | fmt.Println("\nreceived:", sig)
174 | done <- true
175 |
176 | }
177 |
178 | func setupLiner() (*liner.State, string) {
179 | homedir, err := os.UserHomeDir()
180 | if err != nil {
181 | fmt.Println("Error getting home directory:", err)
182 | homedir = os.TempDir()
183 | }
184 | history_path := filepath.Join(homedir, ".goshell_history")
185 | line := liner.NewLiner()
186 | line.SetCtrlCAborts(true)
187 | line.SetMultiLineMode(true)
188 | line.SetTabCompletionStyle(liner.TabCircular)
189 |
190 | line.SetWordCompleter(WordCompleter)
191 |
192 | if f, err := os.Open(history_path); err == nil {
193 | line.ReadHistory(f)
194 | f.Close()
195 | }
196 | return line, history_path
197 | }
198 |
--------------------------------------------------------------------------------
/manager.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io/fs"
6 | "os"
7 | "os/exec"
8 | "strings"
9 | )
10 |
11 | const (
12 | _templatePath = "template.txt"
13 | )
14 |
15 | type command struct {
16 | Src string
17 | variablesAssigned []string
18 | variablesDeclared []string
19 | isExpression bool
20 | Hidden bool
21 | isCallExpression bool
22 | calleeName string
23 | }
24 |
25 | type function struct {
26 | Name string
27 | Src string
28 | returnVariables []string
29 | }
30 |
31 | type Manager struct {
32 | commands []command
33 | functions []function
34 | functionsIndex map[string]function
35 | lastInputFunctionDef bool
36 | programPath string
37 | templatePath string
38 | }
39 |
40 | func newManager(programPath string) *Manager {
41 | return &Manager{
42 | commands: []command{},
43 | functions: []function{},
44 | functionsIndex: map[string]function{},
45 | programPath: programPath,
46 | templatePath: _templatePath,
47 | }
48 | }
49 |
50 | func (m *Manager) addInput(input string) error {
51 | if isFunctionDeclaration(input) {
52 | err := m.addFunction(input)
53 | if err != nil {
54 | return err
55 | }
56 | m.lastInputFunctionDef = true
57 | return nil
58 | }
59 |
60 | err := m.addCommand(input)
61 | if err != nil {
62 | return err
63 | }
64 | m.lastInputFunctionDef = false
65 | return nil
66 | }
67 |
68 | func (m *Manager) addCommand(input string) error {
69 | av, err := ParseStatement(input)
70 | if err != nil {
71 | return err
72 | }
73 | m.commands = append(m.commands, command{
74 | Src: input,
75 | variablesAssigned: av.VariablesAssigned,
76 | variablesDeclared: av.VariablesDeclared,
77 | isExpression: av.IsExpression,
78 | isCallExpression: av.callExpression,
79 | calleeName: av.calleeName,
80 | })
81 | return nil
82 | }
83 |
84 | func (m *Manager) addFunction(input string) error {
85 | function, err := ParseFunction(input)
86 | if err != nil {
87 | return err
88 | }
89 | m.functions = append(m.functions, function)
90 | m.functionsIndex[function.Name] = function
91 | return nil
92 | }
93 |
94 | func (m *Manager) removeLastInput() {
95 | if m.lastInputFunctionDef {
96 | functionName := m.functions[len(m.functions)-1].Name
97 | delete(m.functionsIndex, functionName)
98 | m.functions = m.functions[:len(m.functions)-1]
99 | } else {
100 | m.commands = m.commands[:len(m.commands)-1]
101 | }
102 | }
103 |
104 | func (m *Manager) runProgram() (string, error) {
105 | commands := m.prepareCommands()
106 | program, err := prepareProgram(m.templatePath, commands, m.functions)
107 | if err != nil {
108 | return "", err
109 | }
110 |
111 | // Save the substituted template to the output file
112 | err = os.WriteFile(m.programPath, []byte(program), fs.FileMode(0644))
113 | if err != nil {
114 | return "", err
115 | }
116 |
117 | err = formatProgram(m.programPath)
118 | if err != nil {
119 | return "", err
120 | }
121 |
122 | cmd := exec.Command("go", "run", m.programPath)
123 | output, err := cmd.CombinedOutput()
124 | if err != nil {
125 | fmt.Println(string(output))
126 | return "", err
127 | }
128 | return string(output), nil
129 | }
130 |
131 | func (m *Manager) getProgram() (string, error) {
132 | commands := m.prepareCommands()
133 | return prepareProgram(m.templatePath, commands, m.functions)
134 | }
135 |
136 | func (m *Manager) prepareCommands() []command {
137 | commands := make([]command, len(m.commands))
138 | copy(commands, m.commands)
139 |
140 | for i := range commands {
141 | if !commands[i].isExpression {
142 | continue
143 | }
144 | if i < len(commands)-1 || m.lastInputFunctionDef {
145 | // remove all expression commands and function definitions before the last one
146 | commands[i].Hidden = true
147 | continue
148 | }
149 | if strings.HasPrefix(commands[i].Src, "fmt.Print") {
150 | // expression already contain printing
151 | continue
152 | }
153 | if commands[i].isCallExpression {
154 | if len(m.functionsIndex[commands[i].calleeName].returnVariables) == 0 {
155 | // function call without return value
156 | continue
157 | }
158 | }
159 | commands[i].Src = commandPrintted(commands[i].Src)
160 | }
161 | commands = append(commands, m.useCallStatement())
162 | return commands
163 | }
164 |
165 | func (m *Manager) extractVariables() []string {
166 | variables := []string{}
167 | for _, command := range m.commands {
168 | variables = append(variables, command.variablesDeclared...)
169 | variables = append(variables, command.variablesAssigned...)
170 | }
171 | return variables
172 | }
173 |
174 | func (m *Manager) useCallStatement() command {
175 | variables := m.extractVariables()
176 | if len(variables) == 0 {
177 | return command{}
178 | }
179 | return command{
180 | Src: fmt.Sprintf("use(%s)", strings.Join(variables, ", ")),
181 | isExpression: true,
182 | }
183 | }
184 |
185 | func commandPrintted(command string) string {
186 | return fmt.Sprintf("fmt.Printf(%s, %s)", "\"%#v\\n\"", command)
187 | }
188 |
189 | func (m *Manager) cleanUp() {
190 | os.Remove(m.programPath)
191 | }
192 |
--------------------------------------------------------------------------------
/manager_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "os"
5 | "path"
6 | "testing"
7 |
8 | "github.com/stretchr/testify/assert"
9 | )
10 |
11 | func TestManager_RunProgram(t *testing.T) {
12 | tests := []struct {
13 | name string
14 | input []string
15 | expectedOutput string
16 | expectedError error
17 | }{
18 | {
19 | name: "simple addition",
20 | input: []string{
21 | "1+1",
22 | },
23 | expectedOutput: "2\n",
24 | expectedError: nil,
25 | },
26 | {
27 | name: "function declaration and call",
28 | input: []string{
29 | "func add(a int, b int) int { return a+b }",
30 | "add(2,3)",
31 | },
32 | expectedOutput: "5\n",
33 | expectedError: nil,
34 | },
35 | {
36 | name: "declation then experiment",
37 | input: []string{
38 | "a:=1",
39 | "a",
40 | "a=3",
41 | "a",
42 | },
43 | expectedOutput: "3\n",
44 | expectedError: nil,
45 | },
46 | {
47 | name: "slice initialization",
48 | input: []string{
49 | "a:= []int{1}",
50 | "a",
51 | },
52 | expectedOutput: "[]int{1}\n",
53 | expectedError: nil,
54 | },
55 | {
56 | name: "assignment, experiment, function declaration",
57 | input: []string{
58 | "a:=1",
59 | "a",
60 | "func add(a int, b int) int { return a+b }",
61 | },
62 | expectedOutput: "",
63 | expectedError: nil,
64 | },
65 | {
66 | name: "function declaration without return variables and call",
67 | input: []string{
68 | "func x() { fmt.Println(3) }",
69 | "x()",
70 | },
71 | expectedOutput: "3\n",
72 | expectedError: nil,
73 | },
74 | {
75 | name: "slice indexin",
76 | input: []string{
77 | "a:= []int{1}",
78 | "a[0] = 2",
79 | "a[0]",
80 | },
81 | expectedOutput: "2\n",
82 | expectedError: nil,
83 | },
84 | }
85 |
86 | for _, tt := range tests {
87 | t.Run(tt.name, func(t *testing.T) {
88 | // Create a temporary directory for the program file
89 | tempDir, err := os.MkdirTemp("", "test-program")
90 | if err != nil {
91 | t.Fatal("Failed to create temporary directory:", err)
92 | }
93 | defer os.RemoveAll(tempDir)
94 |
95 | // Create a Manager instance
96 | m := newManager(path.Join(tempDir, "program.go"))
97 |
98 | for _, input := range tt.input {
99 | m.addInput(input)
100 | }
101 | output, err := m.runProgram()
102 | assert.Equal(t, tt.expectedError, err)
103 | assert.Equal(t, tt.expectedOutput, output)
104 |
105 | })
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/parser.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "go/ast"
6 | "go/parser"
7 | "go/token"
8 | "strings"
9 | )
10 |
11 | func ParseFunction(x string) (function, error) {
12 | function := function{
13 | Src: x,
14 | }
15 | code := "package p;" + x
16 | file, err := parser.ParseFile(token.NewFileSet(), "", code, 0)
17 | if err != nil {
18 | return function, err
19 | }
20 | funcDecl := file.Decls[0].(*ast.FuncDecl)
21 | function.Name = funcDecl.Name.Name
22 | returnVariables := funcDecl.Type.Results
23 | if returnVariables == nil {
24 | return function, nil
25 | }
26 | for _, variable := range returnVariables.List {
27 | ident, ok := variable.Type.(*ast.Ident)
28 | if ok {
29 | function.returnVariables = append(function.returnVariables, ident.Name)
30 | }
31 | }
32 | return function, nil
33 | }
34 |
35 | // ParseStatement is a modified version of go/parser.ParseExpr
36 | func ParseStatement(x string) (*AstVisitor, error) {
37 | // parse x within the context of a complete package for correct scopes;
38 | // put x alone on a separate line (handles line comments), followed by a ';'
39 | // to force an error if the expression is incomplete
40 |
41 | var node ast.Node
42 | code := "package p;func _(){" + x + "\n;}"
43 | file, err := parser.ParseFile(token.NewFileSet(), "", code, 0)
44 | if err != nil {
45 | return nil, err
46 | }
47 | node = file.Decls[0].(*ast.FuncDecl).Body.List[0]
48 |
49 | av := new(AstVisitor)
50 | ast.Walk(av, node)
51 | return av, nil
52 | }
53 |
54 | // AstVisitor implements a ast.Visitor and collect variable and import info
55 | type AstVisitor struct {
56 | VariablesAssigned []string
57 | VariablesDeclared []string
58 | Imports []string
59 | Functions []string
60 | IsExpression bool
61 | callExpression bool // this is a call to function or method expression
62 | calleeName string // name of the function or method being called
63 | }
64 |
65 | // Visit inspects the type of a Node to detect a Assignment, Declaration or Import
66 | func (av *AstVisitor) Visit(node ast.Node) ast.Visitor {
67 | switch node := node.(type) {
68 | case *ast.AssignStmt:
69 | for _, each := range node.Lhs {
70 | // assert on each type
71 | switch v := each.(type) {
72 | case *ast.Ident:
73 | av.VariablesAssigned = append(av.VariablesAssigned, v.Name)
74 | case *ast.IndexExpr:
75 | // like a[0] = 1
76 | // variable already assigned
77 | default:
78 | fmt.Printf("I don't know about type %T!\n", each)
79 | }
80 | }
81 | case *ast.DeclStmt:
82 | for _, each := range node.Decl.(*ast.GenDecl).Specs {
83 | valueSpec, ok := each.(*ast.ValueSpec)
84 | if ok {
85 | for _, other := range valueSpec.Names {
86 | av.VariablesDeclared = append(av.VariablesDeclared, other.Name)
87 | }
88 | }
89 | }
90 | case *ast.ImportSpec:
91 | av.Imports = append(av.Imports, node.Path.Value)
92 | case *ast.ExprStmt:
93 | av.IsExpression = true
94 | callExpr, ok := node.X.(*ast.CallExpr)
95 | if ok {
96 | ident, ok := callExpr.Fun.(*ast.Ident)
97 | if ok {
98 | av.callExpression = true
99 | av.calleeName = ident.Name
100 | }
101 | }
102 | case *ast.IncDecStmt: // like a++ or a--
103 | }
104 | return av
105 | }
106 |
107 | func isFunctionDeclaration(statement string) bool {
108 | return strings.HasPrefix(statement, "func")
109 | }
110 |
--------------------------------------------------------------------------------
/parser_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestParse(t *testing.T) {
10 | tests := []struct {
11 | name string
12 | input string
13 | expectedAssigned []string
14 | expectedDeclared []string
15 | expectedError error
16 | }{
17 | {
18 | name: "simple expression1",
19 | input: "1 + 2",
20 | },
21 | {
22 | name: "simple print",
23 | input: "fmt.Println(\"Hello, World!\")",
24 | },
25 | {
26 | name: "assignment",
27 | input: "a:= 1",
28 | expectedAssigned: []string{"a"},
29 | },
30 | {
31 | name: "assignment without colon",
32 | input: "a = 1",
33 | expectedAssigned: []string{"a"},
34 | },
35 | }
36 |
37 | for _, tt := range tests {
38 | t.Run(tt.name, func(t *testing.T) {
39 | av, err := ParseStatement(tt.input)
40 | if tt.expectedError != nil {
41 | assert.Equal(t, tt.expectedError, err)
42 | return
43 | }
44 | assert.NoError(t, err)
45 |
46 | assert.Equal(t, tt.expectedAssigned, av.VariablesAssigned)
47 | assert.Equal(t, tt.expectedDeclared, av.VariablesDeclared)
48 | })
49 | }
50 | }
51 |
52 | func TestParseFunction(t *testing.T) {
53 | tests := []struct {
54 | name string
55 | input string
56 | expectedName string
57 | expectedReturn []string
58 | expectedError error
59 | }{
60 | {
61 | name: "valid expression",
62 | input: "func add(a int, b int) int { return a+b }",
63 | expectedName: "add",
64 | expectedReturn: []string{"int"},
65 | },
66 | }
67 |
68 | for _, tt := range tests {
69 | t.Run(tt.name, func(t *testing.T) {
70 | result, err := ParseFunction(tt.input)
71 | if tt.expectedError != nil {
72 | assert.Equal(t, tt.expectedError, err)
73 | return
74 | }
75 | assert.NoError(t, err)
76 |
77 | assert.Equal(t, tt.expectedName, result.Name)
78 | assert.Equal(t, tt.expectedReturn, result.returnVariables)
79 | })
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/scripts/fetcher.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "encoding/json"
6 | "flag"
7 | "fmt"
8 | "os"
9 | "os/exec"
10 | "time"
11 |
12 | "github.com/gocolly/colly"
13 | )
14 |
15 | const (
16 | version = "0.0.1"
17 | listURI = "https://pkg.go.dev/std/"
18 | packagesFunctionsFiles = "pkgFunctions.json"
19 | packagesNamesFiles = "pkgNames.json"
20 | listPageSelector = "article.go-Main-article table tbody tr"
21 | )
22 |
23 | var (
24 | mapOfLibs = map[string][]string{}
25 | debugFlag = flag.Bool("debug", false, "debug mode")
26 | )
27 |
28 | func main() {
29 | flag.Parse()
30 | listPageCollector := colly.NewCollector()
31 | listPageCollector.SetRequestTimeout(120 * time.Second)
32 |
33 | listPageCollector.OnRequest(func(r *colly.Request) {
34 | fmt.Println("Visiting", r.URL)
35 | })
36 | listPageCollector.OnHTML(listPageSelector, listPageHandler)
37 | listPageCollector.OnResponse(func(r *colly.Response) {
38 | if !*debugFlag {
39 | return
40 | }
41 | err := os.WriteFile("listResponse.html", r.Body, 0644)
42 | if err != nil {
43 | fmt.Println(err)
44 | }
45 | })
46 | err := listPageCollector.Visit(listURI)
47 | if err != nil {
48 | fmt.Println(err)
49 | }
50 |
51 | jsonData, err := json.Marshal(mapOfLibs)
52 | if err != nil {
53 | fmt.Println(err)
54 | }
55 | os.WriteFile(packagesFunctionsFiles, jsonData, 0644)
56 | commands := [][]string{
57 | {"sed", "-i", "", "s/\\[\\]/{}/g", packagesFunctionsFiles},
58 | {"sed", "-i", "", "s/\\[/{/g", packagesFunctionsFiles},
59 | {"sed", "-i", "", "s/\\]/}/g", packagesFunctionsFiles},
60 | {"sed", "-i", "", "s/},/},\\n/g", packagesFunctionsFiles},
61 | }
62 | executeCommands(commands)
63 |
64 | }
65 |
66 | func executeCommands(commands [][]string) {
67 | for _, command := range commands {
68 | cmd := exec.Command(command[0], command[1:]...)
69 | fmt.Println("Running command", cmd.String())
70 | var stderr bytes.Buffer
71 | cmd.Stderr = &stderr
72 | err := cmd.Run()
73 | if err != nil {
74 | fmt.Println("Stderr:", stderr.String())
75 | fmt.Println(err)
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/scripts/visiter.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "strings"
7 | "time"
8 |
9 | "log"
10 |
11 | "github.com/gocolly/colly"
12 | )
13 |
14 | const (
15 | detailURIBase = "https://pkg.go.dev/"
16 | detailsPageSelector = "li.DocNav-functions,li.DocNav-types"
17 | )
18 |
19 | func listPageHandler(el *colly.HTMLElement) {
20 | libPartOfURI := el.ChildAttr("td:first-child div div:first-child a", "href")
21 | if libPartOfURI == "" {
22 | // nested inside a directory
23 | libPartOfURI = el.ChildAttr("td:first-child div span:first-child a", "href")
24 | if libPartOfURI == "" {
25 | // the directory itself
26 | return
27 | }
28 | }
29 | elID := el.ChildAttr("td:first-child", "data-id")
30 | if elID == "" {
31 | elID = el.Attr("data-id")
32 | if elID == "" {
33 | log.Println("No data-id found")
34 | return
35 | }
36 | }
37 | packagename := strings.Join(strings.Split(elID, "-"), "/")
38 |
39 | functionsNames := visitPackage(detailURIBase + libPartOfURI)
40 |
41 | mapOfLibs[packagename] = functionsNames
42 | }
43 |
44 | func visitPackage(libURI string) []string {
45 | membersNames := []string{}
46 | // for some reason the "li.DocNav-types > ul > li > ul > li > a" selector return an item twice
47 | membrersLookup := map[string]struct{}{}
48 | detailsPageCollector := colly.NewCollector()
49 | detailsPageCollector.SetRequestTimeout(120 * time.Second)
50 | detailsPageCollector.OnRequest(func(r *colly.Request) {
51 | log.Println("Visiting", r.URL)
52 | })
53 | detailsPageCollector.OnHTML(detailsPageSelector, func(category *colly.HTMLElement) {
54 | category.ForEach("ul > li", func(i int, e *colly.HTMLElement) {
55 | if category.Attr("class") == "DocNav-functions" {
56 | functionText := strings.TrimSpace(e.ChildText("a:first-child"))
57 | function := clearFunctionName(functionText)
58 | membersNames = append(membersNames, function)
59 | } else if category.Attr("class") == "DocNav-types" {
60 | e.ForEach("li.DocNav-types > ul > li > a", func(i int, el *colly.HTMLElement) {
61 | text := strings.TrimSpace(el.Text)
62 | if strings.Contains(text, "type") {
63 | typeCleared := strings.Split(text, "type ")[1]
64 | if _, ok := membrersLookup[typeCleared]; !ok {
65 | membersNames = append(membersNames, typeCleared)
66 | membrersLookup[typeCleared] = struct{}{}
67 | }
68 | }
69 | })
70 | e.ForEach("li.DocNav-types > ul > li > ul > li > a", func(i int, el *colly.HTMLElement) {
71 | text := strings.TrimSpace(el.Text)
72 | if strings.HasPrefix(text, "(") {
73 | // type methods, skipped for now as it is complex to support them
74 | return
75 | }
76 | function := clearFunctionName(text)
77 | if _, ok := membrersLookup[function]; !ok {
78 | membersNames = append(membersNames, function)
79 | membrersLookup[function] = struct{}{}
80 | }
81 |
82 | })
83 | }
84 | })
85 | })
86 |
87 | detailsPageCollector.OnResponse(func(r *colly.Response) {
88 | if !*debugFlag {
89 | return
90 | }
91 | err := os.WriteFile("detailsResponse.html", r.Body, 0644)
92 | if err != nil {
93 | fmt.Println(err)
94 | }
95 | })
96 |
97 | err := detailsPageCollector.Visit(libURI)
98 | if err != nil {
99 | log.Println(err)
100 | }
101 |
102 | return membersNames
103 | }
104 |
105 | func clearFunctionName(function string) string {
106 | return strings.Split(function, "(")[0]
107 | }
108 |
--------------------------------------------------------------------------------
/template.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | var programTemplate = `
4 | package main
5 | {{range .functions}}
6 | {{.Src}}
7 | {{end}}
8 | func main() {
9 | {{- range .commands}}
10 | {{- if not .Hidden}}
11 | {{.Src -}}
12 | {{end -}}
13 | {{end}}
14 | }
15 |
16 | // used to avoid "declared and not used" error
17 | func use(vals ...any) {
18 | for _, val := range vals {
19 | _ = val
20 | }
21 | }`
22 |
--------------------------------------------------------------------------------