Skip to content

Commit 8b17420

Browse files
authored
Merge pull request #13 from yuchenliu15/add_token_counts
Add token counts in view
2 parents 34cd5b6 + 8796f06 commit 8b17420

5 files changed

Lines changed: 43 additions & 22 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ grab [options] [directory]
104104
| `--max-depth <depth>` | Maximum depth for dependency resolution (`-1` for unlimited, default: `1`). Only effective with `--deps`. |
105105
| `--max-file-size <size>` | Maximum file size to include (e.g., `"100kb"`, `"2MB"`). No limit by default. Files exceeding the specified size will be skipped. |
106106
| `--theme <name>` | Set the UI theme. Available: catppuccin-latte, catppuccin-frappe, catppuccin-macchiato, catppuccin-mocha, rose-pine, rose-pine-dawn, rose-pine-moon, dracula, nord. (default: `"catppuccin-mocha"`). |
107+
| `--show-tokens` | Show the number of tokens for each file in file tree. |
107108

108109
### 📖 Examples
109110

cmd/grab/main.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ func main() {
4747
var resolveDeps bool
4848
var maxDepth int
4949
var maxFileSizeStr string
50+
var showTokenCount bool
5051

5152
flag.BoolVar(&showHelp, "help", false, "Display help information")
5253
flag.BoolVar(&showHelp, "h", false, "Display help information (shorthand)")
@@ -85,6 +86,8 @@ func main() {
8586
maxFileSizeUsage := "Maximum file size to include (e.g., 50kb, 2MB). No limit by default."
8687
flag.StringVar(&maxFileSizeStr, "max-file-size", "", maxFileSizeUsage)
8788

89+
flag.BoolVar(&showTokenCount, "show-tokens", false, "Show the number of tokens for each file")
90+
8891
flag.Parse()
8992

9093
if showHelp {
@@ -154,15 +157,16 @@ func main() {
154157
runNonInteractive(root, filterMgr, outputPath, useTempFile, formatName, skipRedaction, resolveDeps, maxDepth, maxFileSize)
155158
} else {
156159
config := model.Config{
157-
RootPath: root,
158-
FilterMgr: filterMgr,
159-
OutputPath: outputPath,
160-
UseTempFile: useTempFile,
161-
Format: formatName,
162-
SkipRedaction: skipRedaction,
163-
ResolveDeps: resolveDeps,
164-
MaxDepth: maxDepth,
165-
MaxFileSize: maxFileSize,
160+
RootPath: root,
161+
FilterMgr: filterMgr,
162+
OutputPath: outputPath,
163+
UseTempFile: useTempFile,
164+
Format: formatName,
165+
SkipRedaction: skipRedaction,
166+
ResolveDeps: resolveDeps,
167+
MaxDepth: maxDepth,
168+
MaxFileSize: maxFileSize,
169+
ShowTokenCount: showTokenCount,
166170
}
167171

168172
m := model.NewModel(config)

internal/model/model.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,20 @@ type Model struct {
5656
isGrabbing bool
5757
redactSecrets bool
5858
resolveDeps bool
59+
showTokenCount bool
5960
}
6061

6162
type Config struct {
62-
FilterMgr *filesystem.FilterManager
63-
RootPath string
64-
OutputPath string
65-
Format string
66-
MaxDepth int
67-
MaxFileSize int64
68-
UseTempFile bool
69-
SkipRedaction bool
70-
ResolveDeps bool
63+
FilterMgr *filesystem.FilterManager
64+
RootPath string
65+
OutputPath string
66+
Format string
67+
MaxDepth int
68+
MaxFileSize int64
69+
UseTempFile bool
70+
SkipRedaction bool
71+
ResolveDeps bool
72+
ShowTokenCount bool
7173
}
7274

7375
func NewModel(config Config) Model {
@@ -105,6 +107,7 @@ func NewModel(config Config) Model {
105107
Width: 80,
106108
Height: 10,
107109
},
108-
cursor: 0,
110+
cursor: 0,
111+
showTokenCount: config.ShowTokenCount,
109112
}
110113
}

internal/model/view.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package model
22

33
import (
44
"fmt"
5+
"os"
56
"path/filepath"
67
"strings"
78

89
"github.com/charmbracelet/lipgloss"
910
"github.com/epilande/codegrab/internal/ui"
11+
"github.com/epilande/codegrab/internal/utils"
1012
)
1113

1214
func (m Model) View() string {
@@ -229,10 +231,20 @@ func (m *Model) refreshViewportContent() {
229231
if count := dirSelectedCounts[node.Path]; count > 0 {
230232
rawSuffix = fmt.Sprintf(" [%d]", count)
231233
}
232-
} else if node.IsDependency {
233-
rawSuffix = " [dep]"
234+
} else {
235+
if node.IsDependency {
236+
rawSuffix += " [dep]"
237+
}
238+
if m.showTokenCount {
239+
if ok, err := utils.IsTextFile(node.Path); ok && err == nil {
240+
if contentBytes, err := os.ReadFile(node.Path); err == nil {
241+
content := string(contentBytes)
242+
tokensEstimate := utils.EstimateTokens(content)
243+
rawSuffix += fmt.Sprintf(" [%d tokens]", tokensEstimate)
244+
}
245+
}
246+
}
234247
}
235-
236248
isCursorLine := i == m.cursor
237249

238250
rendered := ui.StyleFileLine(

internal/ui/help.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const UsageText = `Usage:
5454
--theme <name> Set the UI theme. Available: catppuccin-latte, catppuccin-frappe,
5555
catppuccin-macchiato, catppuccin-mocha, rose-pine, rose-pine-dawn,
5656
rose-pine-moon, dracula, nord. (default: "catppuccin-mocha").
57+
--show-tokens Show the number of tokens for each file in file tree.
5758
5859
Examples:
5960
# Run interactively in the current directory

0 commit comments

Comments
 (0)