Skip to content

Commit 3acd03f

Browse files
committed
minor updates
1 parent d9130f9 commit 3acd03f

File tree

4 files changed

+124
-15
lines changed

4 files changed

+124
-15
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Ingest is a command-line tool designed to parse directories of plain text files,
44

55
It's intended use case is for preparing content to be provided to AI/LLMs.
66

7+
![ingest screenshot](screenshot.png)
8+
79
## Features
810

911
- Traverse directory structures and generate a tree view
@@ -86,7 +88,8 @@ ingest -o output.md /path/to/project
8688
- `--print-default-excludes`: Print the default exclude patterns
8789
- `--print-default-template`: Print the default template
8890
- `--report`: Print the largest parsed files
89-
- `-v, --version`: Print the version number (WIP - still trying to get this to work nicely)
91+
- `--verbose`: Print verbose output
92+
- `-V, --version`: Print the version number (WIP - still trying to get this to work nicely)
9093

9194
## Configuration
9295

main.go

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,18 @@ var (
3636
printDefaultExcludes bool
3737
printDefaultTemplate bool
3838
report bool
39+
verbose bool
3940
Version string // This will be set by the linker at build time
4041
)
4142

4243
func main() {
4344
rootCmd := &cobra.Command{
44-
Use: "ingest [path]",
45+
Use: "ingest [flags] [path]",
4546
Short: "Generate a markdown LLM prompt from a codebase directory",
4647
Long: `ingest is a command-line tool to generate an LLM prompt from a codebase directory.`,
4748
RunE: run,
4849
}
4950

50-
// if run with no arguments, assume the current directory
51-
if len(os.Args) == 1 {
52-
os.Args = append(os.Args, ".")
53-
}
54-
5551
rootCmd.Flags().StringSliceP("include", "i", nil, "Patterns to include")
5652
rootCmd.Flags().StringSliceP("exclude", "e", nil, "Patterns to exclude")
5753
rootCmd.Flags().BoolVar(&includePriority, "include-priority", false, "Include files in case of conflict between include and exclude patterns")
@@ -71,16 +67,23 @@ func main() {
7167
rootCmd.Flags().StringVar(&patternExclude, "pattern-exclude", "", "Path to a specific .glob file for exclude patterns")
7268
rootCmd.Flags().BoolVar(&printDefaultExcludes, "print-default-excludes", false, "Print the default exclude patterns")
7369
rootCmd.Flags().BoolVar(&printDefaultTemplate, "print-default-template", false, "Print the default template")
74-
rootCmd.Flags().BoolP("version", "v", false, "Print the version number")
70+
rootCmd.Flags().BoolP("version", "V", false, "Print the version number")
7571
rootCmd.Flags().BoolVar(&report, "report", false, "Report the top 5 largest files included in the output")
72+
rootCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Enable verbose output")
73+
74+
rootCmd.ParseFlags(os.Args[1:])
75+
76+
// if run with no arguments, assume the current directory
77+
if len(rootCmd.Flags().Args()) == 0 {
78+
rootCmd.SetArgs([]string{"."})
79+
}
7680

7781
if err := rootCmd.Execute(); err != nil {
7882
fmt.Println(err)
7983
os.Exit(1)
8084
}
8185
}
8286

83-
8487
func run(cmd *cobra.Command, args []string) error {
8588
if version, _ := cmd.Flags().GetBool("version"); version {
8689
fmt.Printf("ingest version %s\n", Version)
@@ -120,6 +123,15 @@ func run(cmd *cobra.Command, args []string) error {
120123
spinner := utils.SetupSpinner("Traversing directory and building tree...")
121124
defer spinner.Finish()
122125

126+
// If verbose, print active excludes
127+
if verbose {
128+
activeExcludes, err := filesystem.ReadExcludePatterns(patternExclude)
129+
if err != nil {
130+
return fmt.Errorf("failed to read exclude patterns: %w", err)
131+
}
132+
printExcludePatterns(activeExcludes)
133+
}
134+
123135
// Traverse directory with parallel processing
124136
tree, files, err := filesystem.WalkDirectory(absPath, includePatterns, excludePatterns, patternExclude, includePriority, lineNumber, relativePaths, excludeFromTree, noCodeblock)
125137
if err != nil {
@@ -184,7 +196,7 @@ func run(cmd *cobra.Command, args []string) error {
184196
}
185197

186198
// Handle output
187-
if err := handleOutput(rendered, tokens, encoding, noClipboard, output, jsonOutput, report, files); err != nil {
199+
if err := handleOutput(rendered, tokens, encoding, noClipboard, output, jsonOutput, report || verbose, files); err != nil {
188200
return fmt.Errorf("failed to handle output: %w", err)
189201
}
190202

@@ -196,16 +208,17 @@ func reportLargestFiles(files []filesystem.FileInfo) {
196208
return len(files[i].Code) > len(files[j].Code)
197209
})
198210

199-
fmt.Println("\nTop 5 largest files:")
211+
fmt.Println("\nTop 5 largest files (by estimated token count):")
200212
for i, file := range files[:min(5, len(files))] {
201-
fmt.Printf("%d. %s (%d bytes)\n", i+1, file.Path, len(file.Code))
213+
tokenCount := token.CountTokens(file.Code, encoding)
214+
fmt.Printf("%d. %s (%s tokens)\n", i+1, file.Path, utils.FormatNumber(tokenCount))
202215
}
203216
}
204217

205218
func handleOutput(rendered string, countTokens bool, encoding string, noClipboard bool, output string, jsonOutput bool, report bool, files []filesystem.FileInfo) error {
206219
if countTokens {
207220
tokenCount := token.CountTokens(rendered, encoding)
208-
utils.PrintColouredMessage("i", fmt.Sprintf("%d Tokens (Approximate)", tokenCount), color.FgYellow)
221+
utils.PrintColouredMessage("i", fmt.Sprintf("%s Tokens (Approximate)", utils.FormatNumber(tokenCount)), color.FgYellow)
209222
}
210223

211224
if report {
@@ -248,3 +261,54 @@ func handleOutput(rendered string, countTokens bool, encoding string, noClipboar
248261

249262
return nil
250263
}
264+
265+
266+
func printExcludePatterns(patterns []string) {
267+
utils.PrintColouredMessage("i", "Active exclude patterns:", color.FgCyan)
268+
269+
// Define colours for syntax highlighting
270+
starColour := color.New(color.FgYellow).SprintFunc()
271+
slashColour := color.New(color.FgGreen).SprintFunc()
272+
dotColour := color.New(color.FgBlue).SprintFunc()
273+
274+
// Calculate the maximum width of patterns for alignment
275+
maxWidth := 0
276+
for _, pattern := range patterns {
277+
if len(pattern) > maxWidth {
278+
maxWidth = len(pattern)
279+
}
280+
}
281+
282+
// Print patterns in a horizontal list
283+
lineWidth := 0
284+
285+
// get the width of the terminal
286+
w := utils.GetTerminalWidth()
287+
288+
for i, pattern := range patterns {
289+
highlighted := pattern
290+
highlighted = strings.ReplaceAll(highlighted, "*", starColour("*"))
291+
highlighted = strings.ReplaceAll(highlighted, "/", slashColour("/"))
292+
highlighted = strings.ReplaceAll(highlighted, ".", dotColour("."))
293+
294+
// Add padding to align patterns
295+
padding := strings.Repeat(" ", maxWidth - len(pattern) + 2)
296+
297+
if lineWidth + len(pattern) + 2 > w && i > 0 {
298+
fmt.Println()
299+
lineWidth = 0
300+
}
301+
302+
if lineWidth == 0 {
303+
fmt.Print(" ")
304+
}
305+
306+
fmt.Print(highlighted + padding)
307+
lineWidth += len(pattern) + len(padding)
308+
309+
if i < len(patterns)-1 {
310+
fmt.Print("| ")
311+
lineWidth += 2
312+
}
313+
}
314+
}

screenshot.png

787 KB
Loading

utils/utils.go

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,23 @@ import (
44
"fmt"
55
"os"
66
"path/filepath"
7+
"strconv"
8+
"syscall"
9+
"unsafe"
710

811
"github.com/atotto/clipboard"
912
"github.com/fatih/color"
1013
"github.com/mitchellh/go-homedir"
1114
"github.com/schollz/progressbar/v3"
1215
)
1316

17+
type termSize struct {
18+
Row uint16
19+
Col uint16
20+
Xpixel uint16
21+
Ypixel uint16
22+
}
23+
1424
func CopyToClipboard(rendered string) error {
1525
err := clipboard.WriteAll(rendered)
1626
if err != nil {
@@ -55,9 +65,9 @@ func Label(path string) string {
5565

5666
func PrintColouredMessage(symbol string, message string, messageColor color.Attribute) {
5767
white := color.New(color.FgWhite, color.Bold).SprintFunc()
58-
coloredMessage := color.New(messageColor).SprintFunc()
68+
colouredMessage := color.New(messageColor).SprintFunc()
5969

60-
fmt.Printf("%s%s%s %s\n", white("["), white(symbol), white("]"), coloredMessage(message))
70+
fmt.Printf("%s%s%s %s\n", white("["), white(symbol), white("]"), colouredMessage(message))
6171
}
6272

6373
func EnsureConfigDirectories() error {
@@ -90,3 +100,35 @@ func EnsureConfigDirectories() error {
90100

91101
return nil
92102
}
103+
104+
func FormatNumber(n int) string {
105+
in := strconv.Itoa(n)
106+
out := make([]byte, len(in)+(len(in)-2+int(in[0]/'0'))/3)
107+
if in[0] == '-' {
108+
in, out[0] = in[1:], '-'
109+
}
110+
111+
for i, j, k := len(in)-1, len(out)-1, 0; ; i, j = i-1, j-1 {
112+
out[j] = in[i]
113+
if i == 0 {
114+
return string(out)
115+
}
116+
if k++; k == 3 {
117+
j, k = j-1, 0
118+
out[j] = ','
119+
}
120+
}
121+
}
122+
123+
func GetTerminalWidth() int {
124+
ws := &termSize{}
125+
retCode, _, _ := syscall.Syscall(syscall.SYS_IOCTL,
126+
uintptr(syscall.Stdin),
127+
uintptr(syscall.TIOCGWINSZ),
128+
uintptr(unsafe.Pointer(ws)))
129+
130+
if int(retCode) == -1 {
131+
return 100
132+
}
133+
return int(ws.Col)
134+
}

0 commit comments

Comments
 (0)