From 1252bbeae47957b0ecc18d7feeaa60503b88ff5d Mon Sep 17 00:00:00 2001 From: Thang Do Date: Wed, 16 Oct 2024 19:20:59 +1030 Subject: [PATCH] Rewrite ExpandPath to utilise builtin os.UserHomeDir() validate string, raise err and other minor typos --- cmd/edit.go | 2 +- cmd/new.go | 10 ++++++---- config/config.go | 37 +++++++++++++++++++++++++++++-------- snippet/snippet.go | 36 ++++++++++++++++++++++++++---------- sync/sync.go | 12 +++++++++--- 5 files changed, 71 insertions(+), 26 deletions(-) diff --git a/cmd/edit.go b/cmd/edit.go index 3b5ef70..84f15ce 100644 --- a/cmd/edit.go +++ b/cmd/edit.go @@ -37,7 +37,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 7b059f0..91c3ed6 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -166,12 +166,12 @@ func createAndEditSnippet(newSnippet snippet.SnippetInfo, snippets snippet.Snipp } func countSnippetLines() int { - // Count lines in snippet file - if config.Conf.General.SnippetFile == "" { + filepath, err := config.ExpandPath(config.Conf.General.SnippetFile) + if err != nil { return 0 } - f, err := os.Open(config.ExpandPath(config.Conf.General.SnippetFile)) + f, err := os.Open(filepath) if err != nil { panic("Error reading snippet file") } @@ -216,14 +216,15 @@ func new(cmd *cobra.Command, args []string) (err error) { } return createAndEditSnippet(newSnippet, snippets, lineCount+3) - } else { command, err = scan(color.HiYellowString("Command> "), os.Stdout, os.Stdin, false) } + if err != nil { return err } } + description, err = scan(color.HiGreenString("Description> "), os.Stdout, os.Stdin, false) if err != nil { return err @@ -256,6 +257,7 @@ func new(cmd *cobra.Command, 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 b0df2b9..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" @@ -99,6 +100,10 @@ func (cfg *Config) Load(file string) error { } var snippetdirs []string for _, dir := range cfg.General.SnippetDirs { + if !strings.HasSuffix(dir, "/") { + dir = dir + "/" + } + snippetdirs = append(snippetdirs, dir) // note the = instead of := } cfg.General.SnippetDirs = snippetdirs @@ -118,9 +123,14 @@ 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") + file_path, err := ExpandPath(cfg.General.SnippetFile) + if err != nil { + return errors.Wrap(err, "SnippetFile path is invalid: %v") + } - _, err = os.Create(ExpandPath(cfg.General.SnippetFile)) + _, err = os.Create(file_path) if err != nil { return errors.Wrap(err, "Failed to create a snippet file") } @@ -133,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" @@ -166,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 3b45d24..0065b95 100644 --- a/snippet/snippet.go +++ b/snippet/snippet.go @@ -28,9 +28,8 @@ type SnippetInfo struct { func (snippets *Snippets) Load() error { var snippetFiles []string - if config.Conf.General.SnippetFile != "" { - snippetFile := config.ExpandPath(config.Conf.General.SnippetFile) - + snippetFile, err := config.ExpandPath(config.Conf.General.SnippetFile) + if err == nil { if _, err := os.Stat(snippetFile); err == nil { snippetFiles = append(snippetFiles, config.Conf.General.SnippetFile) } else if !os.IsNotExist(err) { @@ -45,24 +44,35 @@ if you only want to provide snippetdirs instead`, } } - for _, dir := range config.Conf.General.SnippetDirs { - if _, err := os.Stat(config.ExpandPath(dir)); err != nil { + 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(config.ExpandPath(dir))...) + + snippetFiles = append(snippetFiles, getFiles(dir)...) } // Read files and load snippets for _, file := range snippetFiles { - tmp := Snippets{} - f, err := os.ReadFile(config.ExpandPath(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) @@ -82,6 +92,7 @@ if you only want to provide snippetdirs instead`, func (snippets *Snippets) Save() error { var snippetFile string var newSnippets Snippets + for _, snippet := range snippets.Snippets { if snippet.Filename == "" { snippetFile = config.Conf.General.SnippetDirs[0] + fmt.Sprintf("%s.toml", strings.ToLower(sanitize.BaseName(snippet.Description))) @@ -92,7 +103,12 @@ func (snippets *Snippets) Save() error { } } - f, err := os.Create(config.ExpandPath(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 90b607c..0ec7125 100644 --- a/sync/sync.go +++ b/sync/sync.go @@ -96,16 +96,16 @@ func upload(client Client) (err error) { } func download(content string) error { - snippetFile := config.ExpandPath(config.Conf.General.SnippetFile) - var snippets snippet.Snippets if err := snippets.Load(); 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") @@ -113,5 +113,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) }