diff --git a/README.md b/README.md index f410b41..342becb 100644 --- a/README.md +++ b/README.md @@ -42,14 +42,13 @@ Usage: pipet [command] Available Commands: - delete Remove snippet from storage (this is irreversible!) - edit edit snippet data - help Help about any command init Configure pipet - list list all snippets new Creates a new snippet and opens editor to edit content - search Search through snippets - show display the snippet + show Show snippet + delete Remove snippet from storage (this is irreversible!) + edit Edit snippet data + help Help about any command + list List all snippets Flags: --config string config file (default is $HOME/.pipet.yaml) @@ -65,7 +64,7 @@ Flags: - [x] binary downloads - [x] make public - [ ] Ability to search full text, with a flag to search command - - [ ] Try to abstract snippet id from operations, one way to do this is to move id's optional for commands and jump to a search interface in case IDs are not specified. + - [x] Try to abstract snippet id from operations, one way to do this is to move id's optional for commands and jump to a search interface in case IDs are not specified. - [ ] Tests, would like more tests. - [ ] Add an archive flag for delete, the data is not deleted, but is not exposed unless user turns on another flag. diff --git a/cmd/delete.go b/cmd/delete.go index ea3eba6..8fc24ad 100644 --- a/cmd/delete.go +++ b/cmd/delete.go @@ -37,19 +37,28 @@ import ( // deleteCmd represents the delete command var deleteCmd = &cobra.Command{ - Use: "delete uid", + Use: "delete [uid]", Short: "Remove snippet from storage (this is irreversible!)", - Args: cobra.ExactArgs(1), + Args: cobra.MaximumNArgs(1), PreRunE: ensureConfig, Run: func(cmd *cobra.Command, args []string) { + sid := "" + if len(args) == 0 { + s, err := searchFullSnippet() + errorGuard(err, "") + sid = s + } else { + sid = args[0] + } + dataStore := getDataStore() - snip, err := dataStore.Read(args[0]) + snip, err := dataStore.Read(sid) 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") + errorGuard(dataStore.Delete(sid), "program failed to delete") fmt.Println("deleted!") } }, diff --git a/cmd/edit.go b/cmd/edit.go index dc1a6a2..ce1b1de 100644 --- a/cmd/edit.go +++ b/cmd/edit.go @@ -35,12 +35,21 @@ import ( // editCmd represents the edit command var editCmd = &cobra.Command{ - Use: "edit", + Use: "edit [uid]", Short: "edit snippet data", - Args: cobra.ExactArgs(1), + Args: cobra.MaximumNArgs(1), Run: func(cmd *cobra.Command, args []string) { + sid := "" + if len(args) == 0 { + s, err := searchFullSnippet() + errorGuard(err, "") + sid = s + } else { + sid = args[0] + } + dataStore := getDataStore() - fn := dataStore.Fullpath(args[0]) + fn := dataStore.Fullpath(sid) editSnippet(fn) }, } diff --git a/cmd/list.go b/cmd/list.go index 998ad7b..d250434 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -31,9 +31,7 @@ package cmd import ( "fmt" - "strings" - "github.com/ryanuber/columnize" "github.com/spf13/cobra" ) @@ -54,22 +52,11 @@ var listCmd = &cobra.Command{ sns, err := dataStore.List() errorGuard(err, "listing store failed") - 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)) - output = append(output, out) - } - - rendered := columnize.SimpleFormat(output) + rendered := renderSnippetList(sns, true) fmt.Println(rendered) }, } func init() { rootCmd.AddCommand(listCmd) - - // listCmd.Flags().BoolVarP(&tags, "tags", "t", false, "Enable list tags associated with the snippet.") - // listCmd.Flags().BoolVarP(&full, "full", "f", false, "Print the full snippet") } diff --git a/cmd/search.go b/cmd/search.go deleted file mode 100644 index 408271b..0000000 --- a/cmd/search.go +++ /dev/null @@ -1,80 +0,0 @@ -// 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/ryanuber/columnize" - "github.com/spf13/cobra" - "strings" -) - -// searchCmd represents the search command -var searchCmd = &cobra.Command{ - Use: "search", - Short: "Search through snippets", - PreRunE: ensureConfig, - Run: func(cmd *cobra.Command, args []string) { - dataStore := getDataStore() - - sns, err := dataStore.List() - errorGuard(err, "listing dataStore failed") - - output := []string{} - for _, snip := range sns { - tags := strings.Join(snip.Meta.Tags, ",") - out := fmt.Sprintf("%s | %s | %s", snip.Meta.UID, snip.Meta.Title, tags) - output = append(output, out) - } - - rendered := columnize.SimpleFormat(output) - sid, err := fuzzyWrapper(rendered) - errorGuard(err, "searching failed") - - snip, err := dataStore.Read(sid) - errorGuard(err, "reading snippet failed") - fmt.Printf(fancySnippet(snip)) - }, -} - -func init() { - rootCmd.AddCommand(searchCmd) - - // Here you will define your flags and configuration settings. - - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - // searchCmd.PersistentFlags().String("foo", "", "A help for foo") - - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: - // searchCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") -} diff --git a/cmd/show.go b/cmd/show.go index 965ce5f..304e831 100644 --- a/cmd/show.go +++ b/cmd/show.go @@ -41,13 +41,22 @@ var body bool // showCmd represents the show command var showCmd = &cobra.Command{ - Use: "show uid", + Use: "show [uid]", Short: "display the snippet", - Args: cobra.ExactArgs(1), + Args: cobra.MaximumNArgs(1), PreRunE: ensureConfig, Run: func(cmd *cobra.Command, args []string) { + sid := "" + if len(args) == 0 { + s, err := searchFullSnippet() + errorGuard(err, "") + sid = s + } else { + sid = args[0] + } + dataStore := getDataStore() - snip, err := dataStore.Read(args[0]) + snip, err := dataStore.Read(sid) errorGuard(err, "reading snippet failed") if body { fmt.Printf(snip.Data) diff --git a/cmd/utils.go b/cmd/utils.go index 6698882..d45934b 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -41,6 +41,7 @@ import ( "github.com/fatih/color" homedir "github.com/mitchellh/go-homedir" "github.com/pkg/errors" + "github.com/ryanuber/columnize" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -121,10 +122,18 @@ func editSnippet(fn string) error { func parseOutput(out string) (string, error) { out = strings.TrimSuffix(out, "\n") oli := strings.Split(out, " ") - if len(oli) < 2 { + + coli := []string{} + // compact the output + for _, v := range oli { + if v != "" { + coli = append(coli, v) + } + } + if len(coli) < 2 { return "", errors.New("bad data") } - return oli[0], nil + return coli[len(coli)-1], nil } func which(c string) (string, error) { @@ -184,6 +193,44 @@ func readLine() string { return strings.TrimSuffix(text, "\n") } +func renderSnippetList(sns []*pipetdata.Snippet, header bool) string { + output := []string{} + if header { + output = append(output, "Title | Tags | UID") + } + + for _, snip := range sns { + tags := strings.Join(snip.Meta.Tags, ",") + if header { + snip.Meta.Title = Green(snip.Meta.Title) + tags = Blue(tags) + } + out := fmt.Sprintf("%s | %s | %s", snip.Meta.Title, + tags, snip.Meta.UID) + output = append(output, out) + } + + return columnize.SimpleFormat(output) +} + +func searchFullSnippet() (sid string, e error) { + dataStore := getDataStore() + + sns, err := dataStore.List() + if err != nil { + e = errors.Wrap(err, "listing dataStore failed") + return + } + + rendered := renderSnippetList(sns, false) + sid, err = fuzzyWrapper(rendered) + if err != nil { + e = errors.Wrap(err, "searching failed") + return + } + return sid, err +} + // console colors var Red = color.New(color.FgRed).SprintFunc() var Green = color.New(color.FgGreen).SprintFunc()