diff --git a/README.md b/README.md index 644c86a..41374fd 100644 --- a/README.md +++ b/README.md @@ -40,9 +40,9 @@ editor_binary: "absolute path to editor you want to use" # default is $EDITOR en - pipet search : search through current snippets (only titles and tags for now) - pipet edit id : edit a snippet by id - pipet show id : show a snippet - - pipet echo id : like show, but only prints the snippet data. - pipet list : list all snippets - - pipet configure: TBD + - pipet init: inital config. + - pipet delete: delete snippets. ## TODO - [x] finish configure command @@ -53,6 +53,7 @@ editor_binary: "absolute path to editor you want to use" # default is $EDITOR en - [ ] Search full text, with a flag to search command - [ ] Try to abstract snippet id from operations. - [ ] Tests, would like more tests. + - [ ] Add an archive flag for search, the data is not deleted, but is not exposed unless user turns on another flag. ## Hacking 0. Uses [dep](https://golang.github.io/dep/) for dependency management. diff --git a/cmd/delete.go b/cmd/delete.go new file mode 100644 index 0000000..ea3eba6 --- /dev/null +++ b/cmd/delete.go @@ -0,0 +1,62 @@ +// Copyright © 2018 Dhananjay Balan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +// deleteCmd represents the delete command +var deleteCmd = &cobra.Command{ + Use: "delete uid", + Short: "Remove snippet from storage (this is irreversible!)", + Args: cobra.ExactArgs(1), + PreRunE: ensureConfig, + Run: func(cmd *cobra.Command, args []string) { + dataStore := getDataStore() + snip, err := dataStore.Read(args[0]) + errorGuard(err, "querying snippet failed") + + fmt.Printf("Are your you want to %s '%s' [y/n]: ", Red("DELETE"), Green(snip.Meta.Title)) + confirm := readLine() + if confirm == "y" || confirm == "yes" { + errorGuard(dataStore.Delete(args[0]), "program failed to delete") + fmt.Println("deleted!") + } + }, +} + +func init() { + rootCmd.AddCommand(deleteCmd) + + // FIXME: add an archive +} diff --git a/cmd/init.go b/cmd/init.go index 3051cbc..0107dc3 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -31,12 +31,11 @@ package cmd import ( "fmt" + "io/ioutil" + "os" - "github.com/fatih/color" "github.com/spf13/cobra" "gopkg.in/yaml.v2" - "io/ioutil" - "os" ) // initCmd represents the init command @@ -45,8 +44,6 @@ var initCmd = &cobra.Command{ Short: "Configure pipet", Long: `Creates the config files for pipet if not present, usually you only need at the first use`, Run: func(cmd *cobra.Command, args []string) { - green := color.New(color.FgGreen).SprintFunc() - configFile := expandHome("~/.pipet.yaml") _, err := os.Stat(configFile) if err == nil { @@ -89,7 +86,7 @@ var initCmd = &cobra.Command{ // expanded path if path != eBin { - fmt.Printf("Using %s as the absoulte path to editor\n", green(path)) + fmt.Printf("Using %s as the absoulte path to editor\n", Green(path)) } config.EBin = path } else { @@ -111,7 +108,7 @@ var initCmd = &cobra.Command{ fmt.Printf(`pipet is now ready to use snippets are stored in: %s config is stored in %s -`, green(snipDir), green(configFile)) +`, Green(snipDir), Green(configFile)) }, } diff --git a/cmd/list.go b/cmd/list.go index 4c3a677..998ad7b 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -31,11 +31,10 @@ package cmd import ( "fmt" + "strings" - "github.com/fatih/color" "github.com/ryanuber/columnize" "github.com/spf13/cobra" - "strings" ) var ( @@ -55,14 +54,11 @@ var listCmd = &cobra.Command{ sns, err := dataStore.List() errorGuard(err, "listing store failed") - blue := color.New(color.FgBlue).SprintFunc() - green := color.New(color.FgGreen).SprintFunc() - output := []string{"UID | Title | Tags"} for _, snip := range sns { tags := strings.Join(snip.Meta.Tags, " ") - out := fmt.Sprintf("%s | %s | %s", green(snip.Meta.UID), - snip.Meta.Title, blue(tags)) + out := fmt.Sprintf("%s | %s | %s", Green(snip.Meta.UID), + snip.Meta.Title, Blue(tags)) output = append(output, out) } diff --git a/cmd/show.go b/cmd/show.go index b8bfab5..965ce5f 100644 --- a/cmd/show.go +++ b/cmd/show.go @@ -32,10 +32,9 @@ package cmd import ( "fmt" - "github.com/dbalan/pipet/pipetdata" - - "github.com/fatih/color" "github.com/spf13/cobra" + + "github.com/dbalan/pipet/pipetdata" ) var body bool @@ -64,13 +63,11 @@ func init() { } func fancySnippet(s *pipetdata.Snippet) string { - green := color.New(color.FgGreen).SprintFunc() - blue := color.New(color.FgBlue).SprintFunc() - sep := green("---\n") + sep := Green("---\n") - text := sep + green("Title: ") + fmt.Sprint(s.Meta.Title) + green("\nTags:\n") + text := sep + Green("Title: ") + fmt.Sprint(s.Meta.Title) + Green("\nTags:\n") for _, t := range s.Meta.Tags { - text += green("- ") + blue(t) + "\n" + text += Green("- ") + Blue(t) + "\n" } text += sep text += s.Data diff --git a/cmd/utils.go b/cmd/utils.go index 73de4f5..6698882 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -30,27 +30,26 @@ package cmd import ( + "bufio" "bytes" "fmt" - "github.com/spf13/cobra" "os" "os/exec" "path/filepath" "strings" + "github.com/fatih/color" homedir "github.com/mitchellh/go-homedir" "github.com/pkg/errors" + "github.com/spf13/cobra" "github.com/spf13/viper" - "bufio" "github.com/dbalan/pipet/pipetdata" - "github.com/fatih/color" ) func errorGuard(err error, msg string) { - red := color.New(color.FgRed).SprintFunc() if err != nil { - fmt.Fprintf(os.Stderr, "%s: %v\n", red(msg), err) + fmt.Fprintf(os.Stderr, "%s: %v\n", Red(msg), err) os.Exit(-1) } } @@ -184,3 +183,8 @@ func readLine() string { return strings.TrimSuffix(text, "\n") } + +// console colors +var Red = color.New(color.FgRed).SprintFunc() +var Green = color.New(color.FgGreen).SprintFunc() +var Blue = color.New(color.FgBlue).SprintFunc() diff --git a/pipetdata/pipetdata.go b/pipetdata/pipetdata.go index c651d79..adaa7cc 100644 --- a/pipetdata/pipetdata.go +++ b/pipetdata/pipetdata.go @@ -188,3 +188,18 @@ func (d *DataStore) List() (sns []*Snippet, err error) { } return } + +func (d *DataStore) Delete(id string) error { + if !d.Exist(id) { + return errors.New("no such document") + } + + filename := d.Fullpath(id) + + err := os.Remove(filename) + if err != nil { + return errors.Wrap(err, "delete failed") + } + + return nil +} diff --git a/pipetdata/pipetdata_test.go b/pipetdata/pipetdata_test.go index ed57b5e..4f30bd7 100644 --- a/pipetdata/pipetdata_test.go +++ b/pipetdata/pipetdata_test.go @@ -72,6 +72,18 @@ func TestDataStore(t *testing.T) { } assert.Equal(t, expected.Meta, sn.Meta, "snippet metadata should match") + + // test delete + err = ds.Delete(uid) + assert.Nil(t, err, "should have deleted properly") + + // try random file + err = ds.Delete("probably.txt") + assert.NotNil(t, err, "should return no file") + + _, err = ds.Read(uid) + assert.NotNil(t, err, "no such snippet should exist.") + } func TestDataStoreList(t *testing.T) {