on main help sign in
Merge pull request #34 from charmbracelet/fsutil
8026953Raphael Amorim
internal/fileutil/fileutil.go → internal/fsext/fileutil.gorenamed+1−1
@@ -1,4 +1,4 @@
1−package fileutil
1+package fsext
2
2
3import (
3import (
4 "fmt"
4 "fmt"
internal/fileutil/ls.go → internal/fsext/ls.gorenamed+1−1
@@ -1,4 +1,4 @@
1−package fileutil
1+package fsext
2
2
3import (
3import (
4 "os"
4 "os"
internal/llm/tools/glob.go+4−4
@@ -11,7 +11,7 @@ import (
11 "strings"
11 "strings"
12
12
13 "github.com/charmbracelet/crush/internal/config"
13 "github.com/charmbracelet/crush/internal/config"
14− "github.com/charmbracelet/crush/internal/fileutil"
14+ "github.com/charmbracelet/crush/internal/fsext"
15 "github.com/charmbracelet/crush/internal/logging"
15 "github.com/charmbracelet/crush/internal/logging"
16)
16)
17
17
@@ -127,7 +127,7 @@ func (g *globTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error)
127}
127}
128
128
129func globFiles(pattern, searchPath string, limit int) ([]string, bool, error) {
129func globFiles(pattern, searchPath string, limit int) ([]string, bool, error) {
130− cmdRg := fileutil.GetRgCmd(pattern)
130+ cmdRg := fsext.GetRgCmd(pattern)
131 if cmdRg != nil {
131 if cmdRg != nil {
132 cmdRg.Dir = searchPath
132 cmdRg.Dir = searchPath
133 matches, err := runRipgrep(cmdRg, searchPath, limit)
133 matches, err := runRipgrep(cmdRg, searchPath, limit)
@@ -137,7 +137,7 @@ func globFiles(pattern, searchPath string, limit int) ([]string, bool, error) {
137 logging.Warn(fmt.Sprintf("Ripgrep execution failed: %v. Falling back to doublestar.", err))
137 logging.Warn(fmt.Sprintf("Ripgrep execution failed: %v. Falling back to doublestar.", err))
138 }
138 }
139
139
140− return fileutil.GlobWithDoubleStar(pattern, searchPath, limit)
140+ return fsext.GlobWithDoubleStar(pattern, searchPath, limit)
141}
141}
142
142
143func runRipgrep(cmd *exec.Cmd, searchRoot string, limit int) ([]string, error) {
143func runRipgrep(cmd *exec.Cmd, searchRoot string, limit int) ([]string, error) {
@@ -158,7 +158,7 @@ func runRipgrep(cmd *exec.Cmd, searchRoot string, limit int) ([]string, error) {
158 if !filepath.IsAbs(absPath) {
158 if !filepath.IsAbs(absPath) {
159 absPath = filepath.Join(searchRoot, absPath)
159 absPath = filepath.Join(searchRoot, absPath)
160 }
160 }
161− if fileutil.SkipHidden(absPath) {
161+ if fsext.SkipHidden(absPath) {
162 continue
162 continue
163 }
163 }
164 matches = append(matches, absPath)
164 matches = append(matches, absPath)
internal/llm/tools/grep.go+2−2
@@ -17,7 +17,7 @@ import (
17 "time"
17 "time"
18
18
19 "github.com/charmbracelet/crush/internal/config"
19 "github.com/charmbracelet/crush/internal/config"
20− "github.com/charmbracelet/crush/internal/fileutil"
20+ "github.com/charmbracelet/crush/internal/fsext"
21)
21)
22
22
23// regexCache provides thread-safe caching of compiled regex patterns
23// regexCache provides thread-safe caching of compiled regex patterns
@@ -342,7 +342,7 @@ func searchFilesWithRegex(pattern, rootPath, include string) ([]grepMatch, error
342 return nil // Skip directories
342 return nil // Skip directories
343 }
343 }
344
344
345− if fileutil.SkipHidden(path) {
345+ if fsext.SkipHidden(path) {
346 return nil
346 return nil
347 }
347 }
348
348
internal/llm/tools/ls.go+2−2
@@ -9,7 +9,7 @@ import (
9 "strings"
9 "strings"
10
10
11 "github.com/charmbracelet/crush/internal/config"
11 "github.com/charmbracelet/crush/internal/config"
12− "github.com/charmbracelet/crush/internal/fileutil"
12+ "github.com/charmbracelet/crush/internal/fsext"
13)
13)
14
14
15type LSParams struct {
15type LSParams struct {
@@ -108,7 +108,7 @@ func (l *lsTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error) {
108 return NewTextErrorResponse(fmt.Sprintf("path does not exist: %s", searchPath)), nil
108 return NewTextErrorResponse(fmt.Sprintf("path does not exist: %s", searchPath)), nil
109 }
109 }
110
110
111− files, truncated, err := fileutil.ListDirectory(searchPath, params.Ignore, MaxLSFiles)
111+ files, truncated, err := fsext.ListDirectory(searchPath, params.Ignore, MaxLSFiles)
112 if err != nil {
112 if err != nil {
113 return ToolResponse{}, fmt.Errorf("error listing directory: %w", err)
113 return ToolResponse{}, fmt.Errorf("error listing directory: %w", err)
114 }
114 }
internal/tui/components/chat/editor/editor.go+2−2
@@ -12,7 +12,7 @@ import (
12 "github.com/charmbracelet/bubbles/v2/textarea"
12 "github.com/charmbracelet/bubbles/v2/textarea"
13 tea "github.com/charmbracelet/bubbletea/v2"
13 tea "github.com/charmbracelet/bubbletea/v2"
14 "github.com/charmbracelet/crush/internal/app"
14 "github.com/charmbracelet/crush/internal/app"
15− "github.com/charmbracelet/crush/internal/fileutil"
15+ "github.com/charmbracelet/crush/internal/fsext"
16 "github.com/charmbracelet/crush/internal/logging"
16 "github.com/charmbracelet/crush/internal/logging"
17 "github.com/charmbracelet/crush/internal/message"
17 "github.com/charmbracelet/crush/internal/message"
18 "github.com/charmbracelet/crush/internal/session"
18 "github.com/charmbracelet/crush/internal/session"
@@ -327,7 +327,7 @@ func (m *editorCmp) SetPosition(x, y int) tea.Cmd {
327}
327}
328
328
329func (m *editorCmp) startCompletions() tea.Msg {
329func (m *editorCmp) startCompletions() tea.Msg {
330− files, _, _ := fileutil.ListDirectory(".", []string{}, 0)
330+ files, _, _ := fsext.ListDirectory(".", []string{}, 0)
331 completionItems := make([]completions.Completion, 0, len(files))
331 completionItems := make([]completions.Completion, 0, len(files))
332 for _, file := range files {
332 for _, file := range files {
333 file = strings.TrimPrefix(file, "./")
333 file = strings.TrimPrefix(file, "./")
internal/tui/components/chat/messages/renderer.go+7−7
@@ -6,7 +6,7 @@ import (
6 "strings"
6 "strings"
7 "time"
7 "time"
8
8
9− "github.com/charmbracelet/crush/internal/fileutil"
9+ "github.com/charmbracelet/crush/internal/fsext"
10 "github.com/charmbracelet/crush/internal/highlight"
10 "github.com/charmbracelet/crush/internal/highlight"
11 "github.com/charmbracelet/crush/internal/llm/agent"
11 "github.com/charmbracelet/crush/internal/llm/agent"
12 "github.com/charmbracelet/crush/internal/llm/tools"
12 "github.com/charmbracelet/crush/internal/llm/tools"
@@ -208,7 +208,7 @@ func (vr viewRenderer) Render(v *toolCallCmp) string {
208 return vr.renderError(v, "Invalid view parameters")
208 return vr.renderError(v, "Invalid view parameters")
209 }
209 }
210
210
211− file := fileutil.PrettyPath(params.FilePath)
211+ file := fsext.PrettyPath(params.FilePath)
212 args := newParamBuilder().
212 args := newParamBuilder().
213 addMain(file).
213 addMain(file).
214 addKeyValue("limit", formatNonZero(params.Limit)).
214 addKeyValue("limit", formatNonZero(params.Limit)).
@@ -248,7 +248,7 @@ func (er editRenderer) Render(v *toolCallCmp) string {
248 return er.renderError(v, "Invalid edit parameters")
248 return er.renderError(v, "Invalid edit parameters")
249 }
249 }
250
250
251− file := fileutil.PrettyPath(params.FilePath)
251+ file := fsext.PrettyPath(params.FilePath)
252 args := newParamBuilder().addMain(file).build()
252 args := newParamBuilder().addMain(file).build()
253
253
254 return er.renderWithParams(v, "Edit", args, func() string {
254 return er.renderWithParams(v, "Edit", args, func() string {
@@ -258,8 +258,8 @@ func (er editRenderer) Render(v *toolCallCmp) string {
258 }
258 }
259
259
260 formatter := core.DiffFormatter().
260 formatter := core.DiffFormatter().
261− Before(fileutil.PrettyPath(params.FilePath), meta.OldContent).
261+ Before(fsext.PrettyPath(params.FilePath), meta.OldContent).
262− After(fileutil.PrettyPath(params.FilePath), meta.NewContent).
262+ After(fsext.PrettyPath(params.FilePath), meta.NewContent).
263 Split().
263 Split().
264 Width(v.textWidth() - 2) // -2 for padding
264 Width(v.textWidth() - 2) // -2 for padding
265 return formatter.String()
265 return formatter.String()
@@ -282,7 +282,7 @@ func (wr writeRenderer) Render(v *toolCallCmp) string {
282 return wr.renderError(v, "Invalid write parameters")
282 return wr.renderError(v, "Invalid write parameters")
283 }
283 }
284
284
285− file := fileutil.PrettyPath(params.FilePath)
285+ file := fsext.PrettyPath(params.FilePath)
286 args := newParamBuilder().addMain(file).build()
286 args := newParamBuilder().addMain(file).build()
287
287
288 return wr.renderWithParams(v, "Write", args, func() string {
288 return wr.renderWithParams(v, "Write", args, func() string {
@@ -412,7 +412,7 @@ func (lr lsRenderer) Render(v *toolCallCmp) string {
412 if path == "" {
412 if path == "" {
413 path = "."
413 path = "."
414 }
414 }
415− path = fileutil.PrettyPath(path)
415+ path = fsext.PrettyPath(path)
416
416
417 args := newParamBuilder().addMain(path).build()
417 args := newParamBuilder().addMain(path).build()
418
418
internal/tui/components/chat/sidebar/sidebar.go+2−2
@@ -9,7 +9,7 @@ import (
9 tea "github.com/charmbracelet/bubbletea/v2"
9 tea "github.com/charmbracelet/bubbletea/v2"
10 "github.com/charmbracelet/crush/internal/config"
10 "github.com/charmbracelet/crush/internal/config"
11 "github.com/charmbracelet/crush/internal/diff"
11 "github.com/charmbracelet/crush/internal/diff"
12− "github.com/charmbracelet/crush/internal/fileutil"
12+ "github.com/charmbracelet/crush/internal/fsext"
13 "github.com/charmbracelet/crush/internal/history"
13 "github.com/charmbracelet/crush/internal/history"
14 "github.com/charmbracelet/crush/internal/llm/models"
14 "github.com/charmbracelet/crush/internal/llm/models"
15 "github.com/charmbracelet/crush/internal/logging"
15 "github.com/charmbracelet/crush/internal/logging"
@@ -231,7 +231,7 @@ func (m *sidebarCmp) filesBlock() string {
231 }
231 }
232
232
233 extraContent := strings.Join(statusParts, " ")
233 extraContent := strings.Join(statusParts, " ")
234− filePath := fileutil.DirTrim(fileutil.PrettyPath(file.FilePath), 2)
234+ filePath := fsext.DirTrim(fsext.PrettyPath(file.FilePath), 2)
235 filePath = ansi.Truncate(filePath, maxWidth-lipgloss.Width(extraContent)-2, "…")
235 filePath = ansi.Truncate(filePath, maxWidth-lipgloss.Width(extraContent)-2, "…")
236 fileList = append(fileList,
236 fileList = append(fileList,
237 core.Status(
237 core.Status(
internal/tui/components/dialogs/permissions/permissions.go+6−6
@@ -8,7 +8,7 @@ import (
8 "github.com/charmbracelet/bubbles/v2/viewport"
8 "github.com/charmbracelet/bubbles/v2/viewport"
9 tea "github.com/charmbracelet/bubbletea/v2"
9 tea "github.com/charmbracelet/bubbletea/v2"
10 "github.com/charmbracelet/crush/internal/diff"
10 "github.com/charmbracelet/crush/internal/diff"
11− "github.com/charmbracelet/crush/internal/fileutil"
11+ "github.com/charmbracelet/crush/internal/fsext"
12 "github.com/charmbracelet/crush/internal/llm/tools"
12 "github.com/charmbracelet/crush/internal/llm/tools"
13 "github.com/charmbracelet/crush/internal/permission"
13 "github.com/charmbracelet/crush/internal/permission"
14 "github.com/charmbracelet/crush/internal/tui/components/core"
14 "github.com/charmbracelet/crush/internal/tui/components/core"
@@ -170,7 +170,7 @@ func (p *permissionDialogCmp) renderHeader() string {
170 pathKey := t.S().Muted.Render("Path")
170 pathKey := t.S().Muted.Render("Path")
171 pathValue := t.S().Text.
171 pathValue := t.S().Text.
172 Width(p.width - lipgloss.Width(pathKey)).
172 Width(p.width - lipgloss.Width(pathKey)).
173− Render(fmt.Sprintf(" %s", fileutil.PrettyPath(p.permission.Path)))
173+ Render(fmt.Sprintf(" %s", fsext.PrettyPath(p.permission.Path)))
174
174
175 headerParts := []string{
175 headerParts := []string{
176 lipgloss.JoinHorizontal(
176 lipgloss.JoinHorizontal(
@@ -196,7 +196,7 @@ func (p *permissionDialogCmp) renderHeader() string {
196 fileKey := t.S().Muted.Render("File")
196 fileKey := t.S().Muted.Render("File")
197 filePath := t.S().Text.
197 filePath := t.S().Text.
198 Width(p.width - lipgloss.Width(fileKey)).
198 Width(p.width - lipgloss.Width(fileKey)).
199− Render(fmt.Sprintf(" %s", fileutil.PrettyPath(params.FilePath)))
199+ Render(fmt.Sprintf(" %s", fsext.PrettyPath(params.FilePath)))
200 headerParts = append(headerParts,
200 headerParts = append(headerParts,
201 lipgloss.JoinHorizontal(
201 lipgloss.JoinHorizontal(
202 lipgloss.Left,
202 lipgloss.Left,
@@ -211,7 +211,7 @@ func (p *permissionDialogCmp) renderHeader() string {
211 fileKey := t.S().Muted.Render("File")
211 fileKey := t.S().Muted.Render("File")
212 filePath := t.S().Text.
212 filePath := t.S().Text.
213 Width(p.width - lipgloss.Width(fileKey)).
213 Width(p.width - lipgloss.Width(fileKey)).
214− Render(fmt.Sprintf(" %s", fileutil.PrettyPath(params.FilePath)))
214+ Render(fmt.Sprintf(" %s", fsext.PrettyPath(params.FilePath)))
215 headerParts = append(headerParts,
215 headerParts = append(headerParts,
216 lipgloss.JoinHorizontal(
216 lipgloss.JoinHorizontal(
217 lipgloss.Left,
217 lipgloss.Left,
@@ -268,8 +268,8 @@ func (p *permissionDialogCmp) renderBashContent() string {
268func (p *permissionDialogCmp) renderEditContent() string {
268func (p *permissionDialogCmp) renderEditContent() string {
269 if pr, ok := p.permission.Params.(tools.EditPermissionsParams); ok {
269 if pr, ok := p.permission.Params.(tools.EditPermissionsParams); ok {
270 formatter := core.DiffFormatter().
270 formatter := core.DiffFormatter().
271− Before(fileutil.PrettyPath(pr.FilePath), pr.OldContent).
271+ Before(fsext.PrettyPath(pr.FilePath), pr.OldContent).
272− After(fileutil.PrettyPath(pr.FilePath), pr.NewContent).
272+ After(fsext.PrettyPath(pr.FilePath), pr.NewContent).
273 Width(p.contentViewPort.Width()).
273 Width(p.contentViewPort.Width()).
274 Split()
274 Split()
275
275