Files
joakim 1d87d93172 Add multi-depository support with global config
- Implement global CLI config at ~/.config/jade/config.yml
- Add jade depo commands (add, list, remove, set-default)
- Support depository short names and context-aware detection
- Remove tag_prefix config, hardcode + syntax for consistency
- Update depository resolution: flag -> context -> default
- Auto-initialize .jade/ directory structure when adding depos
- Update documentation with new multi-depository workflow
2026-01-03 16:25:23 +01:00

114 lines
2.6 KiB
Go

package engine
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
)
// SearchContent performs a full-text search using ripgrep
func (jd *JadeDepo) SearchContent(query string) ([]string, error) {
// Check if ripgrep is available
if _, err := exec.LookPath("rg"); err != nil {
return nil, fmt.Errorf("ripgrep (rg) is not installed. Please install it to use search functionality")
}
// Run ripgrep to search for content
cmd := exec.Command("rg",
"--files-with-matches", // Only show filenames
"--glob", "*.md", // Only search markdown files
"--glob", "!.jade", // Exclude .jade directory
query,
jd.Config.DepoPath,
)
output, err := cmd.Output()
if err != nil {
// ripgrep returns exit code 1 when no matches found
if exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() == 1 {
return []string{}, nil
}
return nil, fmt.Errorf("search failed: %w", err)
}
// Parse output into list of files
files := strings.Split(strings.TrimSpace(string(output)), "\n")
// Make paths relative to depo
var results []string
for _, file := range files {
if file != "" {
relPath, err := filepath.Rel(jd.Config.DepoPath, file)
if err != nil {
relPath = file
}
results = append(results, relPath)
}
}
return results, nil
}
// ListAllNotes returns all markdown notes in the depository
func (jd *JadeDepo) ListAllNotes() ([]*Note, error) {
var notes []*Note
err := filepath.Walk(jd.Config.DepoPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// Skip .jade directory
if info.IsDir() && info.Name() == ".jade" {
return filepath.SkipDir
}
// Only process .md files
if !info.IsDir() && strings.HasSuffix(info.Name(), ".md") {
relPath, err := filepath.Rel(jd.Config.DepoPath, path)
if err != nil {
return err
}
note, err := LoadNote(jd.Config.DepoPath, relPath)
if err != nil {
// Log error but continue
fmt.Fprintf(os.Stderr, "Warning: failed to load note %s: %v\n", relPath, err)
return nil
}
notes = append(notes, note)
}
return nil
})
if err != nil {
return nil, fmt.Errorf("failed to list notes: %w", err)
}
return notes, nil
}
// FindNoteByTitle searches for a note by title (fuzzy match)
func (jd *JadeDepo) FindNoteByTitle(title string) ([]*Note, error) {
allNotes, err := jd.ListAllNotes()
if err != nil {
return nil, err
}
var matches []*Note
titleLower := strings.ToLower(title)
for _, note := range allNotes {
// Check if title contains the search term
if strings.Contains(strings.ToLower(note.Title), titleLower) {
matches = append(matches, note)
}
}
return matches, nil
}