summaryrefslogtreecommitdiffhomepage
path: root/internal/completions
diff options
context:
space:
mode:
Diffstat (limited to 'internal/completions')
-rw-r--r--internal/completions/files-folders.go191
1 files changed, 0 insertions, 191 deletions
diff --git a/internal/completions/files-folders.go b/internal/completions/files-folders.go
deleted file mode 100644
index a405b34cd..000000000
--- a/internal/completions/files-folders.go
+++ /dev/null
@@ -1,191 +0,0 @@
-package completions
-
-import (
- "bytes"
- "fmt"
- "os/exec"
- "path/filepath"
-
- "github.com/lithammer/fuzzysearch/fuzzy"
- "github.com/sst/opencode/internal/fileutil"
- "github.com/sst/opencode/internal/status"
- "github.com/sst/opencode/internal/tui/components/dialog"
-)
-
-type filesAndFoldersContextGroup struct {
- prefix string
-}
-
-func (cg *filesAndFoldersContextGroup) GetId() string {
- return cg.prefix
-}
-
-func (cg *filesAndFoldersContextGroup) GetEntry() dialog.CompletionItemI {
- return dialog.NewCompletionItem(dialog.CompletionItem{
- Title: "Files & Folders",
- Value: "files",
- })
-}
-
-func processNullTerminatedOutput(outputBytes []byte) []string {
- if len(outputBytes) > 0 && outputBytes[len(outputBytes)-1] == 0 {
- outputBytes = outputBytes[:len(outputBytes)-1]
- }
-
- if len(outputBytes) == 0 {
- return []string{}
- }
-
- split := bytes.Split(outputBytes, []byte{0})
- matches := make([]string, 0, len(split))
-
- for _, p := range split {
- if len(p) == 0 {
- continue
- }
-
- path := string(p)
- path = filepath.Join(".", path)
-
- if !fileutil.SkipHidden(path) {
- matches = append(matches, path)
- }
- }
-
- return matches
-}
-
-func (cg *filesAndFoldersContextGroup) getFiles(query string) ([]string, error) {
- cmdRg := fileutil.GetRgCmd("") // No glob pattern for this use case
- cmdFzf := fileutil.GetFzfCmd(query)
-
- var matches []string
- // Case 1: Both rg and fzf available
- if cmdRg != nil && cmdFzf != nil {
- rgPipe, err := cmdRg.StdoutPipe()
- if err != nil {
- return nil, fmt.Errorf("failed to get rg stdout pipe: %w", err)
- }
- defer rgPipe.Close()
-
- cmdFzf.Stdin = rgPipe
- var fzfOut bytes.Buffer
- var fzfErr bytes.Buffer
- cmdFzf.Stdout = &fzfOut
- cmdFzf.Stderr = &fzfErr
-
- if err := cmdFzf.Start(); err != nil {
- return nil, fmt.Errorf("failed to start fzf: %w", err)
- }
-
- errRg := cmdRg.Run()
- errFzf := cmdFzf.Wait()
-
- if errRg != nil {
- status.Warn(fmt.Sprintf("rg command failed during pipe: %v", errRg))
- }
-
- if errFzf != nil {
- if exitErr, ok := errFzf.(*exec.ExitError); ok && exitErr.ExitCode() == 1 {
- return []string{}, nil // No matches from fzf
- }
- return nil, fmt.Errorf("fzf command failed: %w\nStderr: %s", errFzf, fzfErr.String())
- }
-
- matches = processNullTerminatedOutput(fzfOut.Bytes())
-
- // Case 2: Only rg available
- } else if cmdRg != nil {
- status.Debug("Using Ripgrep with fuzzy match fallback for file completions")
- var rgOut bytes.Buffer
- var rgErr bytes.Buffer
- cmdRg.Stdout = &rgOut
- cmdRg.Stderr = &rgErr
-
- if err := cmdRg.Run(); err != nil {
- return nil, fmt.Errorf("rg command failed: %w\nStderr: %s", err, rgErr.String())
- }
-
- allFiles := processNullTerminatedOutput(rgOut.Bytes())
- matches = fuzzy.Find(query, allFiles)
-
- // Case 3: Only fzf available
- } else if cmdFzf != nil {
- status.Debug("Using FZF with doublestar fallback for file completions")
- files, _, err := fileutil.GlobWithDoublestar("**/*", ".", 0)
- if err != nil {
- return nil, fmt.Errorf("failed to list files for fzf: %w", err)
- }
-
- allFiles := make([]string, 0, len(files))
- for _, file := range files {
- if !fileutil.SkipHidden(file) {
- allFiles = append(allFiles, file)
- }
- }
-
- var fzfIn bytes.Buffer
- for _, file := range allFiles {
- fzfIn.WriteString(file)
- fzfIn.WriteByte(0)
- }
-
- cmdFzf.Stdin = &fzfIn
- var fzfOut bytes.Buffer
- var fzfErr bytes.Buffer
- cmdFzf.Stdout = &fzfOut
- cmdFzf.Stderr = &fzfErr
-
- if err := cmdFzf.Run(); err != nil {
- if exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() == 1 {
- return []string{}, nil
- }
- return nil, fmt.Errorf("fzf command failed: %w\nStderr: %s", err, fzfErr.String())
- }
-
- matches = processNullTerminatedOutput(fzfOut.Bytes())
-
- // Case 4: Fallback to doublestar with fuzzy match
- } else {
- status.Debug("Using doublestar with fuzzy match for file completions")
- allFiles, _, err := fileutil.GlobWithDoublestar("**/*", ".", 0)
- if err != nil {
- return nil, fmt.Errorf("failed to glob files: %w", err)
- }
-
- filteredFiles := make([]string, 0, len(allFiles))
- for _, file := range allFiles {
- if !fileutil.SkipHidden(file) {
- filteredFiles = append(filteredFiles, file)
- }
- }
-
- matches = fuzzy.Find(query, filteredFiles)
- }
-
- return matches, nil
-}
-
-func (cg *filesAndFoldersContextGroup) GetChildEntries(query string) ([]dialog.CompletionItemI, error) {
- matches, err := cg.getFiles(query)
- if err != nil {
- return nil, err
- }
-
- items := make([]dialog.CompletionItemI, 0, len(matches))
- for _, file := range matches {
- item := dialog.NewCompletionItem(dialog.CompletionItem{
- Title: file,
- Value: file,
- })
- items = append(items, item)
- }
-
- return items, nil
-}
-
-func NewFileAndFolderContextGroup() dialog.CompletionProvider {
- return &filesAndFoldersContextGroup{
- prefix: "file",
- }
-}