Implement Jade CLI v1.0 MVP

Complete implementation of note management CLI with all core features:

Commands:
- add: Create new notes in $EDITOR with auto-generated filenames
- list: Display all notes with titles, paths, and tags
- search: Full-text search via ripgrep, tag-based filtering
- tags: List all tags with occurrence counts
- edit: Fuzzy search and edit notes by title
- rm: Move notes to trash with confirmation prompt

Features:
- Automatic depository structure initialization (.jade/trash/)
- Configurable tag prefix (default '+')
- Parse title from first # heading (filename fallback)
- Extract tags anywhere in content
- Parse both [[wiki-links]] and [markdown](links)
- Trash system with timestamps to prevent conflicts

Technical:
- Global config at ~/.config/jade/config.yml
- Per-depository settings support
- Ripgrep integration for fast search
- $EDITOR integration for note editing
- Comprehensive README with usage examples
This commit is contained in:
2026-01-01 21:54:36 +01:00
parent 26a46f92c1
commit 52160345bf
14 changed files with 927 additions and 16 deletions
+52 -5
View File
@@ -1,6 +1,12 @@
package engine
import "fmt"
import (
"fmt"
"os"
"path/filepath"
)
var instance *JadeDepo
type JadeDepo struct {
Config *Config
@@ -12,11 +18,52 @@ func Init(cfgPath, depoPath string) (*JadeDepo, error) {
return nil, fmt.Errorf("failed to initialize config: %w", err)
}
return &JadeDepo{
jd := &JadeDepo{
Config: cfg,
}, nil
}
// Initialize depository structure
if err := jd.initDepoStructure(); err != nil {
return nil, fmt.Errorf("failed to initialize depository structure: %w", err)
}
// Store global instance
instance = jd
return jd, nil
}
// AddNote creates a new note in the depository
func AddNote() Note {
// GetInstance returns the global JadeDepo instance
func GetInstance() (*JadeDepo, error) {
if instance == nil {
return nil, fmt.Errorf("jade depository not initialized")
}
return instance, nil
}
// initDepoStructure creates the necessary directories in the depository
func (jd *JadeDepo) initDepoStructure() error {
// Create depository root if it doesn't exist
if err := os.MkdirAll(jd.Config.DepoPath, 0755); err != nil {
return fmt.Errorf("failed to create depository: %w", err)
}
// Create .jade directory for metadata
jadeDir := filepath.Join(jd.Config.DepoPath, ".jade")
if err := os.MkdirAll(jadeDir, 0755); err != nil {
return fmt.Errorf("failed to create .jade directory: %w", err)
}
// Create trash directory
trashDir := filepath.Join(jadeDir, "trash")
if err := os.MkdirAll(trashDir, 0755); err != nil {
return fmt.Errorf("failed to create trash directory: %w", err)
}
return nil
}
// GetTrashPath returns the path to the trash directory
func (jd *JadeDepo) GetTrashPath() string {
return filepath.Join(jd.Config.DepoPath, ".jade", "trash")
}