├── .gitignore ├── LICENSE ├── README.md ├── go.mod ├── go.sum ├── images └── icon16.png ├── main.go ├── parser ├── helpers.go ├── parse.go ├── run.go ├── tree.go └── vars.go ├── prompts └── vars.go └── super-diff.sh /.gitignore: -------------------------------------------------------------------------------- 1 | sendGPT -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Samuel Stoltenberg 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 | # code-to-gpt 2 | 3 | `code-to-gpt -c` parses current working directory and outputs each file to clipboard. Each file will have a comment of the file location. 4 | 5 | > For example given a directory: 6 | 7 | ``` 8 | ├── lib 9 | │ └── hello.go 10 | ``` 11 | 12 | > Running the following commands 13 | 14 | ```shell 15 | cd lib 16 | code-to-gpt -c 17 | ``` 18 | 19 | > Will write this to your clipboard 20 | 21 | ``` 22 | ------------------------------------------------------------------------------- 23 | // hello.go 24 | package lib 25 | 26 | import ( 27 | "fmt" 28 | ) 29 | 30 | fmt.Println("Hello, world!") 31 | ``` 32 | 33 | ## Installation 34 | 35 | ```shell 36 | go install github.com/skelouse/code-to-gpt@latest 37 | ``` 38 | 39 | ## Super Diff 40 | 41 | > Note: If you have a problem run `git reset` 42 | 43 | The super-diff.sh script is a utility to output all un-staged changes of a local git repository. It uses a diff on un-staged files, displaying the output in the terminal. You can easily redirect the output to a file or copy it to your clipboard. 44 | 45 | > Redirect output to a file 46 | 47 | ```sh 48 | $ ./super-diff.sh > diff.txt 49 | ``` 50 | 51 | > Copy output to clipboard (Linux) 52 | 53 | ```shell 54 | $ ./super-diff.sh | xclip -selection clipboard 55 | ``` 56 | 57 | > Copy output to clipboard (MacOS) 58 | 59 | ```shell 60 | $ ./super-diff.sh | pbcopy 61 | ``` 62 | 63 | > Or write it as a function in your .bashrc or .zshrc 64 | 65 | > (linux) 66 | 67 | ```shell 68 | function super-diff() { 69 | ./super-diff.sh | xclip -selection clipboard 70 | } 71 | ``` 72 | 73 | > (MacOS) 74 | 75 | ```shell 76 | function super-diff() { 77 | ./super-diff.sh | pbcopy 78 | } 79 | ``` 80 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/skelouse/code-to-gpt 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/atotto/clipboard v0.1.4 7 | github.com/bmatcuk/doublestar/v4 v4.7.1 8 | github.com/urfave/cli/v3 v3.0.0-alpha4 9 | ) 10 | 11 | require ( 12 | github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect 13 | github.com/russross/blackfriday/v2 v2.1.0 // indirect 14 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect 15 | ) 16 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= 2 | github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= 3 | github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q= 4 | github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= 5 | github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= 6 | github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 7 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 8 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 9 | github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= 10 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 11 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 12 | github.com/urfave/cli/v3 v3.0.0-alpha4 h1:RJFGIs3mcalmc2YgliDh0Pa4l79S+Dqdz7cW8Fcp7Rg= 13 | github.com/urfave/cli/v3 v3.0.0-alpha4/go.mod h1:ZFqSEHhze0duJACOdz43I5IcnKhf4RoTlOoUMBUggOI= 14 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= 15 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= 16 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 17 | -------------------------------------------------------------------------------- /images/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skelouse/code-to-gpt/4f968dab4f342e5a460806d3e78d50466b19792a/images/icon16.png -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "os" 8 | 9 | "github.com/skelouse/code-to-gpt/parser" 10 | "github.com/urfave/cli/v3" 11 | ) 12 | 13 | func main() { 14 | cmd := &cli.Command{ 15 | Flags: []cli.Flag{ 16 | &cli.BoolFlag{ 17 | Name: "clipboard", 18 | Usage: "does not work with split-files", 19 | Aliases: []string{"c"}, 20 | }, 21 | &cli.BoolFlag{ 22 | Name: "quiet", 23 | Usage: "silences success and tree printout", 24 | Aliases: []string{"q"}, 25 | }, 26 | &cli.StringSliceFlag{ 27 | Name: "include", 28 | Usage: "Include files matching glob patterns", 29 | Aliases: []string{"i"}, 30 | }, 31 | &cli.StringSliceFlag{ 32 | Name: "exclude", 33 | Usage: "Exclude files matching glob patterns", 34 | Aliases: []string{"e"}, 35 | }, 36 | &cli.IntFlag{ 37 | Name: "max-size", 38 | Usage: "Maximum total size of files to process (in bytes)", 39 | Value: 2 * 1024 * 1024, // Default to 2MB 40 | }, 41 | &cli.BoolFlag{ 42 | Name: "split-files", 43 | Aliases: []string{"s"}, 44 | }, 45 | }, 46 | Action: func(ctx *cli.Context) error { 47 | // Check for unexpected positional arguments 48 | if ctx.Args().Len() > 0 { 49 | if len(ctx.StringSlice("include")) > 0 || len(ctx.StringSlice("exclude")) > 0 { 50 | return fmt.Errorf( 51 | "unexpected arguments: %v\nThis may be due to shell glob expansion.\nPlease quote your glob patterns to prevent shell expansion.\nExample: --include \"**/*.js\"", 52 | ctx.Args().Slice()) 53 | } 54 | 55 | return fmt.Errorf("arguments not supported: %s", ctx.Args().Slice()) 56 | } 57 | 58 | return parser.Run(parser.Options{ 59 | SplitFiles: ctx.Bool("split-files"), 60 | Clipboard: ctx.Bool("clipboard"), 61 | Include: ctx.StringSlice("include"), 62 | Exclude: ctx.StringSlice("exclude"), 63 | Quiet: ctx.Bool("quiet"), 64 | MaxSize: ctx.Int("max-size"), 65 | }) 66 | }, 67 | } 68 | 69 | err := cmd.Run(context.Background(), os.Args) 70 | if err != nil { 71 | log.Fatal(err) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /parser/helpers.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "math" 7 | "os" 8 | "path/filepath" 9 | "strings" 10 | 11 | "github.com/bmatcuk/doublestar/v4" 12 | "github.com/skelouse/code-to-gpt/prompts" 13 | ) 14 | 15 | func isIgnoredFile(relativePath string, opts Options) bool { 16 | filename := filepath.Base(relativePath) 17 | 18 | for _, ignoreFile := range IgnoreFiles { 19 | if filename == ignoreFile || relativePath == ignoreFile { 20 | return true 21 | } 22 | } 23 | 24 | fileExt := filepath.Ext(filename) 25 | for _, ignoreExt := range IgnoreExt { 26 | if fileExt == ignoreExt { 27 | return true 28 | } 29 | } 30 | 31 | // Then, check exclude patterns 32 | for _, pattern := range opts.Exclude { 33 | if relativePath == pattern { 34 | return true 35 | } 36 | 37 | matched, err := doublestar.Match(pattern, relativePath) 38 | if err != nil { 39 | continue 40 | } 41 | if matched { 42 | return true 43 | } 44 | } 45 | 46 | // Then, check include patterns 47 | if len(opts.Include) > 0 { 48 | for _, pattern := range opts.Include { 49 | if relativePath == pattern { 50 | return false 51 | } 52 | 53 | matched, err := doublestar.Match(pattern, relativePath) 54 | if err != nil { 55 | fmt.Fprintf(os.Stderr, "Error matching pattern '%s' with path '%s': %v\n", pattern, relativePath, err) 56 | continue 57 | } 58 | if matched { 59 | return false 60 | } 61 | } 62 | return true 63 | } 64 | 65 | // Otherwise, include the file 66 | return false 67 | } 68 | 69 | func isIgnoredDirectory(relativePath string, opts Options) bool { 70 | dirName := filepath.Base(relativePath) 71 | 72 | // First, check hard ignores 73 | for _, ignoreDir := range IgnoreDirectories { 74 | if dirName == ignoreDir || relativePath == ignoreDir { 75 | return true 76 | } 77 | } 78 | 79 | // Then, check exclude patterns 80 | for _, pattern := range opts.Exclude { 81 | if relativePath == pattern { 82 | return true 83 | } 84 | 85 | matched, err := doublestar.Match(pattern, relativePath) 86 | if err != nil { 87 | fmt.Fprintf(os.Stderr, "Error matching pattern '%s' with path '%s': %v\n", pattern, relativePath, err) 88 | continue 89 | } 90 | if matched { 91 | return true 92 | } 93 | } 94 | 95 | // Otherwise, include the directory 96 | return false 97 | } 98 | 99 | func writeFileContents(basePath, path string, newFile *os.File) error { 100 | relativePath, err := filepath.Rel(basePath, path) 101 | if err != nil { 102 | return err 103 | } 104 | 105 | extension := filepath.Ext(path) 106 | var ( 107 | commentPrefix string 108 | commentSuffix string 109 | ) 110 | switch strings.ToLower(extension) { 111 | case ".js", ".go", ".java", ".c", ".cpp", ".cs": 112 | commentPrefix = "//" 113 | case ".md": 114 | commentPrefix = "" 116 | default: 117 | commentPrefix = "#" 118 | } 119 | 120 | _, err = newFile.WriteString(prompts.FileSeparator) 121 | if err != nil { 122 | return err 123 | } 124 | 125 | // Write the comment with the relative path to the "mash.gpt" file 126 | _, err = newFile.WriteString(fmt.Sprintf("%s %s %s\n", commentPrefix, relativePath, commentSuffix)) 127 | if err != nil { 128 | return err 129 | } 130 | 131 | // Open the file 132 | srcFile, err := os.Open(path) 133 | if err != nil { 134 | return err 135 | } 136 | defer srcFile.Close() 137 | 138 | // Write the contents of the file to the "mash.gpt" file 139 | _, err = io.Copy(newFile, srcFile) 140 | if err != nil { 141 | return err 142 | } 143 | 144 | // Add a newline after the contents 145 | _, err = newFile.WriteString("\n") 146 | if err != nil { 147 | return err 148 | } 149 | 150 | return nil 151 | } 152 | 153 | func splitMashFile(mashFile *os.File) error { 154 | fileInfo, err := mashFile.Stat() 155 | if err != nil { 156 | return fmt.Errorf("getting mash file information: %s", err) 157 | } 158 | 159 | fileSize := fileInfo.Size() 160 | numFiles := int(math.Ceil(float64(fileSize) / float64(MaxFileLength))) 161 | 162 | buffer := make([]byte, MaxFileLength) 163 | for i := 1; i <= numFiles; i++ { 164 | bytesRead, err := mashFile.Read(buffer) 165 | if err != nil && err != io.EOF { 166 | return fmt.Errorf("reading mash file: %s", err) 167 | } 168 | 169 | outputFilename := fmt.Sprintf("%s/send%d-%d.gpt", ToSendDirName, i, numFiles) 170 | outputFile, err := os.Create(outputFilename) 171 | if err != nil { 172 | return fmt.Errorf("creating output file: %s", err) 173 | } 174 | defer outputFile.Close() 175 | 176 | _, err = outputFile.WriteString(outputFilename + "\n\n") 177 | if err != nil { 178 | return fmt.Errorf("writing output file name: %s", err) 179 | } 180 | 181 | _, err = outputFile.Write(buffer[:bytesRead]) 182 | if err != nil { 183 | return fmt.Errorf("writing output file: %s", err) 184 | } 185 | } 186 | 187 | return nil 188 | } 189 | 190 | func writeMashFile(mashFile *os.File) error { 191 | outputFilename := fmt.Sprintf("%s/send.gpt", ToSendDirName) 192 | outputFile, err := os.Create(outputFilename) 193 | if err != nil { 194 | return fmt.Errorf("creating output file: %s", err) 195 | } 196 | defer outputFile.Close() 197 | 198 | data, err := io.ReadAll(mashFile) 199 | if err != nil { 200 | return fmt.Errorf("reading mashFile failed with: %s", err) 201 | } 202 | _, err = outputFile.Write(data) 203 | if err != nil { 204 | return fmt.Errorf("writing to outputFile(%s) failed with: %s", outputFilename, err) 205 | } 206 | 207 | return nil 208 | } 209 | -------------------------------------------------------------------------------- /parser/parse.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os" 7 | "path/filepath" 8 | ) 9 | 10 | type ParseOptions struct { 11 | baseOptions Options 12 | basePath string 13 | currentPath string 14 | newFile *os.File 15 | remainingRecursions int 16 | filesProcessed *[]string 17 | currentSize int64 18 | } 19 | 20 | func parse(opts ParseOptions) error { 21 | // Return if the recursion limit has been reached 22 | if opts.remainingRecursions == 0 { 23 | return nil 24 | } 25 | 26 | // Read the contents of the current directory 27 | files, err := ioutil.ReadDir(opts.currentPath) 28 | if err != nil { 29 | return err 30 | } 31 | 32 | for _, file := range files { 33 | path := filepath.Join(opts.currentPath, file.Name()) 34 | 35 | relativePath, err := filepath.Rel(opts.basePath, path) 36 | if err != nil { 37 | return err 38 | } 39 | 40 | if file.IsDir() { 41 | if !isIgnoredDirectory(relativePath, opts.baseOptions) { 42 | err := parse(ParseOptions{ 43 | baseOptions: opts.baseOptions, 44 | basePath: opts.basePath, 45 | currentPath: path, 46 | newFile: opts.newFile, 47 | remainingRecursions: opts.remainingRecursions - 1, 48 | filesProcessed: opts.filesProcessed, 49 | currentSize: opts.currentSize, 50 | }) 51 | if err != nil { 52 | return err 53 | } 54 | } 55 | } else { 56 | if !isIgnoredFile(relativePath, opts.baseOptions) { 57 | // Get file size 58 | fileInfo, err := os.Stat(path) 59 | if err != nil { 60 | return err 61 | } 62 | 63 | // Calculate new total size 64 | fileSize := fileInfo.Size() 65 | newTotalSize := opts.currentSize + fileSize 66 | 67 | // Check if new total size exceeds MaxSize 68 | if opts.baseOptions.MaxSize > 0 && newTotalSize > opts.baseOptions.MaxSize { 69 | return fmt.Errorf("\n...maximum size limit reached at %s (%d bytes).\n...current limit (%d bytes), maybe set --max-size to a value higher than that", path, fileSize, opts.baseOptions.MaxSize) 70 | } 71 | 72 | // Write file contents 73 | err = writeFileContents(opts.basePath, path, opts.newFile) 74 | if err != nil { 75 | return err 76 | } 77 | 78 | // Update current size 79 | opts.currentSize = newTotalSize 80 | 81 | *opts.filesProcessed = append(*opts.filesProcessed, relativePath) 82 | } 83 | } 84 | } 85 | 86 | return nil 87 | } 88 | -------------------------------------------------------------------------------- /parser/run.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | 8 | "github.com/atotto/clipboard" 9 | ) 10 | 11 | type Options struct { 12 | SplitFiles bool 13 | Clipboard bool 14 | Include []string 15 | Exclude []string 16 | Quiet bool 17 | MaxSize int64 18 | } 19 | 20 | func Run(opts Options) error { 21 | cwd, err := os.Getwd() 22 | if err != nil { 23 | return fmt.Errorf("getting current working directory: %s", err) 24 | } 25 | 26 | // Remove the send directory if it exists 27 | if _, err := os.Stat(ToSendDirName); err == nil { 28 | os.RemoveAll(ToSendDirName) 29 | } 30 | 31 | mashFile, err := os.Create(MashFileName) 32 | if err != nil { 33 | return fmt.Errorf("creating mash file: %s", err) 34 | } 35 | 36 | // Clean up the mash file when we're done 37 | defer func() { 38 | mashFile.Close() 39 | err := os.Remove(MashFileName) 40 | if err != nil { 41 | panic(fmt.Errorf("removing mash file: %s", err)) 42 | } 43 | }() 44 | 45 | filesProcessed := new([]string) 46 | err = parse(ParseOptions{ 47 | baseOptions: opts, 48 | basePath: cwd, 49 | currentPath: cwd, 50 | newFile: mashFile, 51 | remainingRecursions: MaxRecursions, 52 | filesProcessed: filesProcessed, 53 | }) 54 | if err != nil { 55 | return fmt.Errorf("parsing files: %s", err) 56 | } 57 | 58 | mashFile.Seek(0, 0) 59 | if opts.Clipboard { 60 | if opts.SplitFiles { 61 | return fmt.Errorf("cannot copy multiple files to clipboard") 62 | } 63 | 64 | data, err := io.ReadAll(mashFile) 65 | if err != nil { 66 | return fmt.Errorf("splitting mash file: %s", err) 67 | } 68 | 69 | err = clipboard.WriteAll(string(data)) 70 | if err != nil { 71 | return fmt.Errorf("writing to clipboard: %s", err) 72 | } 73 | 74 | } else { // Write to sendGPT directory 75 | // Create the file directory 76 | if err := os.MkdirAll(ToSendDirName, os.ModePerm); err != nil { 77 | return fmt.Errorf("creating send directory: %s", err) 78 | } 79 | 80 | if opts.SplitFiles { 81 | // Split the mash file into smaller files to be consumed by chat bot 82 | err = splitMashFile(mashFile) 83 | if err != nil { 84 | return fmt.Errorf("splitting mash file: %s", err) 85 | } 86 | } else { 87 | err = writeMashFile(mashFile) 88 | if err != nil { 89 | return err 90 | } 91 | 92 | } 93 | } 94 | 95 | if opts.Quiet { 96 | return nil 97 | } 98 | 99 | // Build the tree and print it 100 | root := buildTree(*filesProcessed) 101 | printTree(root, "", true) 102 | 103 | // Print counts 104 | _, fileCount := countNodes(root) 105 | 106 | message := "" 107 | if opts.Clipboard { 108 | message = "copied to clipboard" 109 | } else { 110 | message = "written to ./sendGPT/" 111 | } 112 | 113 | fmt.Printf("\n%d files %s\n", fileCount, message) 114 | 115 | return nil 116 | } 117 | -------------------------------------------------------------------------------- /parser/tree.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "sort" 7 | "strings" 8 | ) 9 | 10 | type Node struct { 11 | Name string 12 | IsDir bool 13 | Children []*Node 14 | } 15 | 16 | func buildTree(paths []string) *Node { 17 | root := &Node{Name: ".", IsDir: true} 18 | for _, path := range paths { 19 | parts := strings.Split(path, string(os.PathSeparator)) 20 | currentNode := root 21 | for i, part := range parts { 22 | // Check if part already exists as a child 23 | var childNode *Node 24 | for _, child := range currentNode.Children { 25 | if child.Name == part { 26 | childNode = child 27 | break 28 | } 29 | } 30 | if childNode == nil { 31 | // Create new node 32 | isDir := i < len(parts)-1 33 | childNode = &Node{Name: part, IsDir: isDir} 34 | currentNode.Children = append(currentNode.Children, childNode) 35 | } 36 | currentNode = childNode 37 | } 38 | } 39 | return root 40 | } 41 | 42 | func printTree(node *Node, prefix string, isLast bool) { 43 | if node.Name != "." { 44 | fmt.Print(prefix) 45 | if isLast { 46 | fmt.Print("└── ") 47 | prefix += " " 48 | } else { 49 | fmt.Print("├── ") 50 | prefix += "│ " 51 | } 52 | fmt.Println(node.Name) 53 | } 54 | // Sort children by name 55 | sort.Slice(node.Children, func(i, j int) bool { 56 | return node.Children[i].Name < node.Children[j].Name 57 | }) 58 | for i, child := range node.Children { 59 | printTree(child, prefix, i == len(node.Children)-1) 60 | } 61 | } 62 | 63 | func countNodes(node *Node) (dirs int, files int) { 64 | if node.IsDir { 65 | dirs++ 66 | } else { 67 | files++ 68 | } 69 | for _, child := range node.Children { 70 | d, f := countNodes(child) 71 | dirs += d 72 | files += f 73 | } 74 | return 75 | } 76 | -------------------------------------------------------------------------------- /parser/vars.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | var ( 4 | MaxRecursions = 20 5 | MaxFileLength = 10000 6 | ToSendDirName = "sendGPT" 7 | MashFileName = "mash.gpt" 8 | IgnoreFiles = []string{MashFileName, "package-lock.json"} 9 | IgnoreExt = []string{".png", ".jpg", ".gpt"} 10 | IgnoreDirectories = []string{".git", ToSendDirName, "node_modules"} 11 | ) 12 | -------------------------------------------------------------------------------- /prompts/vars.go: -------------------------------------------------------------------------------- 1 | package prompts 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | var ( 8 | FileSeparator = strings.Repeat("-", 79) + "\n" 9 | ) 10 | -------------------------------------------------------------------------------- /super-diff.sh: -------------------------------------------------------------------------------- 1 | # This file is provided free of charge and may be modified and used by anyone. While I appreciate any improvements through pull requests to https://github.com/skelouse/code-to-gpt, they are not required. I hold no liability for any issues arising from the use of this script. 2 | 3 | if test "$#" = 0; then 4 | ( 5 | added_files=() 6 | git ls-files --others --exclude-standard | 7 | while read -r i; do 8 | git add --intent-to-add "$i" 9 | added_files+=("$i") 10 | done 11 | git diff --no-color 12 | 13 | # Revert the --intent-to-add 14 | for i in "${added_files[@]}"; do 15 | git reset "$i" 16 | done 17 | ) 18 | else 19 | git diff "$@" 20 | fi --------------------------------------------------------------------------------