diff --git a/README.md b/README.md index d7b6101..447fcb6 100644 --- a/README.md +++ b/README.md @@ -267,6 +267,7 @@ All `toml` files will be scraped and found snippets will be added. Example1: single directory +```toml [GHEGist] base_url = "" # GHE base URL upload_url = "" # GHE upload URL (often the same as the base URL) @@ -275,6 +276,7 @@ Example1: single directory gist_id = "" # Gist ID public = false # public or priate auto_sync = false # sync automatically when editing snippets +``` ``` $ pet configure diff --git a/cmd/edit.go b/cmd/edit.go index dc66edb..6fdcfe1 100644 --- a/cmd/edit.go +++ b/cmd/edit.go @@ -39,7 +39,7 @@ func edit(cmd *cobra.Command, args []string) (err error) { } if snippetFile == "" { - return errors.New("No sippet file seleted") + return errors.New("No snippet file seleted") } // file content before editing diff --git a/cmd/new.go b/cmd/new.go index e9857a1..dc97151 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -166,11 +166,16 @@ func createAndEditSnippet(newSnippet snippet.SnippetInfo, snippets snippet.Snipp } func countSnippetLines() int { - // Count lines in snippet file - f, err := os.Open(config.Conf.General.SnippetFile) + filepath, err := config.ExpandPath(config.Conf.General.SnippetFile) + if err != nil { + return 0 + } + + f, err := os.Open(filepath) if err != nil { panic("Error reading snippet file") } + lineCount, err := CountLines(f) if err != nil { panic("Error counting lines in snippet file") @@ -218,10 +223,10 @@ func _new(in io.ReadCloser, out io.Writer, args []string) (err error) { } return createAndEditSnippet(newSnippet, snippets, lineCount+3) - } else { command, err = scan(color.HiYellowString("Command> "), out, in, false) } + if err != nil { return err } @@ -258,6 +263,7 @@ func _new(in io.ReadCloser, out io.Writer, args []string) (err error) { Command: command, Tag: tags, } + snippets.Snippets = append(snippets.Snippets, newSnippet) if err = snippets.Save(); err != nil { return err diff --git a/config/config.go b/config/config.go index cba6a82..fae9d69 100644 --- a/config/config.go +++ b/config/config.go @@ -6,6 +6,7 @@ import ( "os/exec" "path/filepath" "runtime" + "strings" "github.com/pelletier/go-toml" "github.com/pkg/errors" @@ -98,9 +99,12 @@ func (cfg *Config) Load(file string) error { return err } var snippetdirs []string - cfg.General.SnippetFile = expandPath(cfg.General.SnippetFile) for _, dir := range cfg.General.SnippetDirs { - snippetdirs = append(snippetdirs, expandPath(dir)) // note the = instead of := + if !strings.HasSuffix(dir, "/") { + dir = dir + "/" + } + + snippetdirs = append(snippetdirs, dir) // note the = instead of := } cfg.General.SnippetDirs = snippetdirs return nil @@ -109,6 +113,7 @@ func (cfg *Config) Load(file string) error { if !os.IsNotExist(err) { return err } + f, err := os.Create(file) if err != nil { return err @@ -118,10 +123,16 @@ func (cfg *Config) Load(file string) error { if err != nil { return errors.Wrap(err, "Failed to get the default config directory") } + cfg.General.SnippetFile = filepath.Join(dir, "snippet.toml") - _, err = os.Create(cfg.General.SnippetFile) + file_path, err := ExpandPath(cfg.General.SnippetFile) if err != nil { - return errors.Wrap(err, "Failed to create a config file") + return errors.Wrap(err, "SnippetFile path is invalid: %v") + } + + _, err = os.Create(file_path) + if err != nil { + return errors.Wrap(err, "Failed to create a snippet file") } cfg.General.Editor = os.Getenv("EDITOR") @@ -132,6 +143,7 @@ func (cfg *Config) Load(file string) error { cfg.General.Editor = "vim" } } + cfg.General.Column = 40 cfg.General.SelectCmd = "fzf --ansi --layout=reverse --border --height=90% --pointer=* --cycle --prompt=Snippets:" cfg.General.Backend = "gist" @@ -165,15 +177,25 @@ func GetDefaultConfigDir() (dir string, err error) { return dir, nil } -func expandPath(s string) string { - if len(s) >= 2 && s[0] == '~' && os.IsPathSeparator(s[1]) { - if runtime.GOOS == "windows" { - s = filepath.Join(os.Getenv("USERPROFILE"), s[2:]) - } else { - s = filepath.Join(os.Getenv("HOME"), s[2:]) +// Given a path to either a file or directory, returns its absolute path format. +// ExpandPath resolves "~/" prefix in a given system path. +// Raise error if path is an empty string as it +func ExpandPath(path string) (string, error) { + if path == "" { + error := errors.New("path to file/directory is not set.") + return path, error + } + + if strings.HasPrefix(path, "~/") { + homedir, err := os.UserHomeDir() + if err != nil { + return path, err } + + return filepath.Join(homedir, path[2:]), nil } - return os.Expand(s, os.Getenv) + + return path, nil } func isCommandAvailable(name string) bool { diff --git a/snippet/snippet.go b/snippet/snippet.go index 4ed5a84..31a3a6a 100644 --- a/snippet/snippet.go +++ b/snippet/snippet.go @@ -30,12 +30,10 @@ func (snippets *Snippets) Load(includeDirs bool) error { // Create a list of snippet files to load snippets from var snippetFiles []string - // Load snippets from the main snippet file - // Raise an error if the file is not found / not configured - snippetFile := config.Conf.General.SnippetFile - if snippetFile != "" { + snippetFile, err := config.ExpandPath(config.Conf.General.SnippetFile) + if err == nil { if _, err := os.Stat(snippetFile); err == nil { - snippetFiles = append(snippetFiles, snippetFile) + snippetFiles = append(snippetFiles, config.Conf.General.SnippetFile) } else if !os.IsNotExist(err) { return fmt.Errorf("failed to load snippet file. %v", err) } else { @@ -43,32 +41,42 @@ func (snippets *Snippets) Load(includeDirs bool) error { `snippet file not found. %s Please run 'pet configure' and provide a correct file path, or remove this if you only want to provide snippetdirs instead`, - snippetFile, + config.Conf.General.SnippetFile, ) } } - // Optionally load snippets from snippet directories if includeDirs { - for _, dir := range config.Conf.General.SnippetDirs { + for _, snippetDir := range config.Conf.General.SnippetDirs { + dir, err := config.ExpandPath(snippetDir) + if err != nil { + return fmt.Errorf("snippet directory not found. %s", snippetDir) + } + if _, err := os.Stat(dir); err != nil { if os.IsNotExist(err) { - return fmt.Errorf("snippet directory not found. %s", dir) + return fmt.Errorf("snippet directory not found. %s", snippetDir) } - return fmt.Errorf("failed to load snippet directory. %v", err) + snippetFiles = append(snippetFiles, getFiles(dir)...) } + snippetFiles = append(snippetFiles, getFiles(dir)...) } } // Read files and load snippets for _, file := range snippetFiles { - tmp := Snippets{} - f, err := os.ReadFile(file) + file_path, err := config.ExpandPath(file) + if err != nil { + return fmt.Errorf("failed to load snippet file. %v", err) + } + + f, err := os.ReadFile(file_path) if err != nil { return fmt.Errorf("failed to load snippet file. %v", err) } + tmp := Snippets{} err = toml.Unmarshal(f, &tmp) if err != nil { return fmt.Errorf("failed to parse snippet file. %v", err) @@ -98,7 +106,13 @@ func (snippets *Snippets) Save() error { newSnippets.Snippets = append(newSnippets.Snippets, snippet) } } - f, err := os.Create(snippetFile) + + file_path, err := config.ExpandPath(snippetFile) + if err != nil { + return fmt.Errorf("failed to save snippet file. err: %s", err) + } + + f, err := os.Create(file_path) if err != nil { return fmt.Errorf("failed to save snippet file. err: %s", err) } diff --git a/sync/sync.go b/sync/sync.go index 6c28344..829b641 100644 --- a/sync/sync.go +++ b/sync/sync.go @@ -100,16 +100,16 @@ func upload(client Client) (err error) { // download downloads snippets from the remote repository // and saves them to the main snippet file - directories ignored func download(content string) error { - snippetFile := config.Conf.General.SnippetFile - var snippets snippet.Snippets if err := snippets.Load(false); err != nil { return err } + body, err := snippets.ToString() if err != nil { return err } + if content == body { // no need to download fmt.Println("Already up-to-date") @@ -117,5 +117,11 @@ func download(content string) error { } fmt.Println("Download success") - return os.WriteFile(snippetFile, []byte(content), os.ModePerm) + + file_path, err := config.ExpandPath(config.Conf.General.SnippetFile) + if err != nil { + return err + } + + return os.WriteFile(file_path, []byte(content), os.ModePerm) }