From 0ebfaf835d6fb0cb4785fd20d1b855516854f3d6 Mon Sep 17 00:00:00 2001 From: Joakim Date: Fri, 2 Jan 2026 20:18:50 +0100 Subject: [PATCH] Add root command to open depository with $EDITOR - Implement openDepository function in cmd/root.go to open the depository directory in $EDITOR - Falls back to vi if $EDITOR is not set - Update README.md with new usage section documenting bare 'jade' command - Include config.go changes that move config location to depository/.jade/ --- jade-depo/README.md | 18 +++++++--- jade-depo/cmd/root.go | 29 ++++++++++++++- jade-depo/internal/engine/config.go | 56 ++++++++++++++--------------- 3 files changed, 69 insertions(+), 34 deletions(-) diff --git a/jade-depo/README.md b/jade-depo/README.md index ce45679..39ad41e 100644 --- a/jade-depo/README.md +++ b/jade-depo/README.md @@ -19,6 +19,16 @@ go build -o jade ## Usage +### Open Depository + +```bash +# Open the depository directory in your $EDITOR +jade + +# This opens ~/jade-depository (or your configured path) in your editor +# Works great with neovim, vim, or any editor that supports directory opening +``` + ### Initialize and List Notes ```bash @@ -77,24 +87,24 @@ jade tags ## Configuration -Configuration is stored in `~/.config/jade/config.yml` (by default). +Configuration is stored in `/.jade/config.yml` and is created automatically when you first run jade. Example config: ```yaml depo_path: /home/user/jade-depository -config_path: /home/user/.config/jade tag_prefix: "+" ``` You can override these with flags: - `--depo`: Depository path -- `--config`: Config directory path +- `--config`: Config file path (if you need to override the default location) ## Depository Structure ``` jade-depository/ ├── .jade/ +│ ├── config.yml # Configuration file │ └── trash/ # Deleted notes go here ├── note-1.md ├── note-2.md @@ -102,7 +112,7 @@ jade-depository/ └── note-3.md ``` -The `.jade/` directory is automatically created and should be added to `.gitignore`. +The `.jade/` directory is automatically created and contains configuration and metadata. You can optionally add it to `.gitignore` if you don't want to track it in version control. ## Note Format diff --git a/jade-depo/cmd/root.go b/jade-depo/cmd/root.go index 6486e80..3f392fa 100644 --- a/jade-depo/cmd/root.go +++ b/jade-depo/cmd/root.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" "os" + "os/exec" "git.jnss.me/joakim/jadedepo/internal/engine" "github.com/spf13/cobra" @@ -11,6 +12,7 @@ import ( var ( rootCmd = &cobra.Command{ Short: "Jade CLI is a note-manager and orchestrator.", + Run: openDepository, } ) @@ -27,11 +29,36 @@ func init() { } }) - rootCmd.PersistentFlags().StringVar(&cfgPath, "config", "", "Configuration path. Default $HOME/.config/jade") + rootCmd.PersistentFlags().StringVar(&cfgPath, "config", "", "Configuration file path. Default /.jade/config.yml") rootCmd.PersistentFlags().StringVar(&depoPath, "depo", "", "Depository path. Default $HOME/jade-depository") } +func openDepository(cmd *cobra.Command, args []string) { + jd, err := engine.GetInstance() + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } + + // Get editor from environment variable, fallback to vi + editor := os.Getenv("EDITOR") + if editor == "" { + editor = "vi" + } + + // Open the depository directory with the editor + editorCmd := exec.Command(editor, jd.Config.DepoPath) + editorCmd.Stdin = os.Stdin + editorCmd.Stdout = os.Stdout + editorCmd.Stderr = os.Stderr + + if err := editorCmd.Run(); err != nil { + fmt.Fprintf(os.Stderr, "Error opening depository: %v\n", err) + os.Exit(1) + } +} + func Execute() { if err := rootCmd.Execute(); err != nil { fmt.Println(err) diff --git a/jade-depo/internal/engine/config.go b/jade-depo/internal/engine/config.go index 29fcec4..3435c56 100644 --- a/jade-depo/internal/engine/config.go +++ b/jade-depo/internal/engine/config.go @@ -11,8 +11,6 @@ import ( type Config struct { // DepoPath is the path to the jade depository. Default ~/jade-depository DepoPath string `mapstructure:"depo_path"` - // ConfigPath is the path to the config directory. Default ~/.config/jade/config.yml - ConfigPath string `mapstructure:"config_path"` // TagPrefix is the prefix used for tags in notes. Default "+" TagPrefix string `mapstructure:"tag_prefix"` } @@ -26,13 +24,9 @@ func getDefaultDepoPath() string { return filepath.Join(home, "jade-depository") } -// getDefaultConfigPath returns the default config directory path -func getDefaultConfigPath() string { - home, err := os.UserHomeDir() - if err != nil { - return "./.config/jade/config.yml" - } - return filepath.Join(home, ".config", "jade", "config.yml") +// getConfigPath returns the config file path within the depository +func getConfigPath(depoPath string) string { + return filepath.Join(depoPath, ".jade", "config.yml") } // initConfig initializes the configuration using Viper @@ -42,32 +36,39 @@ func initConfig(cfgPath, depoPath string) (*Config, error) { viper.SetEnvPrefix("JADE") viper.AutomaticEnv() - // Set defaults - viper.SetDefault("depo_path", getDefaultDepoPath()) - viper.SetDefault("config_path", getDefaultConfigPath()) - viper.SetDefault("tag_prefix", "+") - - // Determine config file location - configDir := cfgPath - if configDir == "" { - configDir = getDefaultConfigPath() + // Determine depository path (from flag, env var, or default) + actualDepoPath := depoPath + if actualDepoPath == "" { + actualDepoPath = viper.GetString("depo_path") + if actualDepoPath == "" { + actualDepoPath = getDefaultDepoPath() + } } - // Ensure config directory exists - if err := os.MkdirAll(configDir, 0755); err != nil { - return nil, fmt.Errorf("failed to create config directory: %w", err) + // Set defaults + viper.SetDefault("depo_path", actualDepoPath) + viper.SetDefault("tag_prefix", "+") + + // Ensure depository and .jade directory exist + jadeDir := filepath.Join(actualDepoPath, ".jade") + if err := os.MkdirAll(jadeDir, 0755); err != nil { + return nil, fmt.Errorf("failed to create .jade directory: %w", err) + } + + // Determine config file location + configFilePath := cfgPath + if configFilePath == "" { + configFilePath = getConfigPath(actualDepoPath) } // Set up config file - viper.SetConfigName("config") - viper.SetConfigType("yaml") - viper.AddConfigPath(configDir) + viper.SetConfigFile(configFilePath) // Try to read existing config file if err := viper.ReadInConfig(); err != nil { - if _, ok := err.(viper.ConfigFileNotFoundError); ok { + // Check if file doesn't exist (handles both viper.ConfigFileNotFoundError and os.IsNotExist) + if _, ok := err.(viper.ConfigFileNotFoundError); ok || os.IsNotExist(err) { // Config file not found, create it with defaults - configFilePath := filepath.Join(configDir, "config.yaml") if err := viper.SafeWriteConfigAs(configFilePath); err != nil { return nil, fmt.Errorf("failed to create config file: %w", err) } @@ -81,9 +82,6 @@ func initConfig(cfgPath, depoPath string) (*Config, error) { if depoPath != "" { viper.Set("depo_path", depoPath) } - if cfgPath != "" { - viper.Set("config_path", cfgPath) - } // Unmarshal config into struct cfg := &Config{}