From 2465fdff9c878413a7668ff1bc3e68cbe028c36c Mon Sep 17 00:00:00 2001 From: Alice Zhao Date: Sun, 3 Apr 2022 14:13:31 -0700 Subject: [PATCH 1/2] feat: add custom select prompt to delete, update commands --- cmd/brag/delete/delete.go | 17 ++------ cmd/brag/update/update.go | 16 +------ cmd/daily/delete/delete.go | 17 ++------ cmd/daily/update/update.go | 18 ++------ cmd/todo/complete/complete.go | 16 +------ cmd/todo/delete/delete.go | 17 +------- cmd/todo/update/update.go | 18 ++------ go.mod | 3 +- go.sum | 4 ++ ui/constants/constants.go | 4 ++ utils/brag/brag.go | 30 ++++++++++++++ utils/daily/daily.go | 30 ++++++++++++++ utils/entries/entries.go | 40 ++++++++++++++++++ utils/file.go | 19 ++++----- utils/prompts/prompts.go | 78 +++++++++++++++++++++++++++++++++++ utils/todo/todo.go | 72 +++++++++++++++++++++++++------- utils/types/types.go | 24 +++++++++++ utils/utils.go | 18 ++++++++ 18 files changed, 314 insertions(+), 127 deletions(-) create mode 100644 utils/brag/brag.go create mode 100644 utils/daily/daily.go create mode 100644 utils/prompts/prompts.go create mode 100644 utils/types/types.go diff --git a/cmd/brag/delete/delete.go b/cmd/brag/delete/delete.go index ee3ab53..785239c 100644 --- a/cmd/brag/delete/delete.go +++ b/cmd/brag/delete/delete.go @@ -1,16 +1,14 @@ package delete import ( - "cronicle/utils" - "fmt" - "strconv" + "cronicle/utils/brag" "github.com/spf13/cobra" ) func New() *cobra.Command { cmd := &cobra.Command{ - Use: "delete [ID!]", + Use: "delete ", Short: "delete a brag entry", Long: "delete a brag entry", Run: run, @@ -20,14 +18,5 @@ func New() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - files := utils.GetAllFiles("brag") - - n, err := strconv.Atoi(args[0]) - if err != nil || n == 0 || n > len(files) { - fmt.Printf("Invalid argument") - return - } - - utils.DeleteFile(files[n-1].Name(), "brag") - utils.ListFiles("brag") + brag.DeleteBrag() } diff --git a/cmd/brag/update/update.go b/cmd/brag/update/update.go index 008abf9..594b43a 100644 --- a/cmd/brag/update/update.go +++ b/cmd/brag/update/update.go @@ -1,9 +1,7 @@ package update import ( - "cronicle/utils" - "fmt" - "strconv" + "cronicle/utils/brag" "github.com/spf13/cobra" ) @@ -20,15 +18,5 @@ func New() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - files := utils.GetAllFiles("brag") - - n, err := strconv.Atoi(args[0]) - if err != nil || n == 0 || n > len(files) { - fmt.Printf("Invalid argument") - return - } - - path := utils.GetPath([]string{"brag", files[n-1].Name()}) - - utils.EditFile(path) + brag.EditBrag() } diff --git a/cmd/daily/delete/delete.go b/cmd/daily/delete/delete.go index 8127111..5c2f302 100644 --- a/cmd/daily/delete/delete.go +++ b/cmd/daily/delete/delete.go @@ -1,16 +1,14 @@ package delete import ( - "cronicle/utils" - "fmt" - "strconv" + "cronicle/utils/daily" "github.com/spf13/cobra" ) func New() *cobra.Command { cmd := &cobra.Command{ - Use: "delete [ID!]", + Use: "delete ", Short: "delete a daily file", Long: "delete a daily file", Run: run, @@ -20,14 +18,5 @@ func New() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - files := utils.GetAllFiles("daily") - - n, err := strconv.Atoi(args[0]) - if err != nil || n == 0 || n > len(files) { - fmt.Printf("Invalid argument") - return - } - - utils.DeleteFile(files[n-1].Name(), "daily") - utils.ListFiles("daily") + daily.DeleteDaily() } diff --git a/cmd/daily/update/update.go b/cmd/daily/update/update.go index b60687c..3af2b2f 100644 --- a/cmd/daily/update/update.go +++ b/cmd/daily/update/update.go @@ -1,16 +1,14 @@ package update import ( - "cronicle/utils" - "fmt" - "strconv" + "cronicle/utils/daily" "github.com/spf13/cobra" ) func New() *cobra.Command { cmd := &cobra.Command{ - Use: "update [ID!]", + Use: "update ", Short: "update a daily entry", Long: "update a daily entry", Run: run, @@ -20,15 +18,5 @@ func New() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - files := utils.GetAllFiles("daily") - - n, err := strconv.Atoi(args[0]) - if err != nil || n == 0 || n > len(files) { - fmt.Printf("Invalid argument") - return - } - - path := utils.GetPath([]string{"daily", files[n-1].Name()}) - - utils.EditFile(path) + daily.EditDaily() } diff --git a/cmd/todo/complete/complete.go b/cmd/todo/complete/complete.go index cb7d1c1..6954f52 100644 --- a/cmd/todo/complete/complete.go +++ b/cmd/todo/complete/complete.go @@ -1,17 +1,14 @@ package complete import ( - "cronicle/utils" "cronicle/utils/todo" - "fmt" - "strconv" "github.com/spf13/cobra" ) func New() *cobra.Command { cmd := &cobra.Command{ - Use: "complete [ID!]", + Use: "complete ", Short: "complete a todo entry", Long: "complete a todo entry", Run: run, @@ -21,14 +18,5 @@ func New() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - files := utils.GetAllFiles("todo") - - n, err := strconv.Atoi(args[0]) - if err != nil || n == 0 || n > len(files) { - fmt.Printf("Invalid argument") - return - } - - todo.MarkCompleted(files[n-1]) - todo.ListTodos() + todo.CompleteTodo() } diff --git a/cmd/todo/delete/delete.go b/cmd/todo/delete/delete.go index 47be9eb..f0e4cc2 100644 --- a/cmd/todo/delete/delete.go +++ b/cmd/todo/delete/delete.go @@ -1,17 +1,14 @@ package delete import ( - "cronicle/utils" "cronicle/utils/todo" - "fmt" - "strconv" "github.com/spf13/cobra" ) func New() *cobra.Command { cmd := &cobra.Command{ - Use: "delete [ID!]", + Use: "delete ", Short: "delete a todo entry", Long: "delete a todo entry", Run: run, @@ -21,15 +18,5 @@ func New() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - - files := utils.GetAllFiles("todo") - - n, err := strconv.Atoi(args[0]) - if err != nil || n == 0 || n > len(files) { - fmt.Printf("Invalid argument") - return - } - - utils.DeleteFile(files[n-1].Name(), "todo") - todo.ListTodos() + todo.DeleteTodo() } diff --git a/cmd/todo/update/update.go b/cmd/todo/update/update.go index e4502ca..e519fdd 100644 --- a/cmd/todo/update/update.go +++ b/cmd/todo/update/update.go @@ -1,16 +1,14 @@ package update import ( - "cronicle/utils" - "fmt" - "strconv" + "cronicle/utils/todo" "github.com/spf13/cobra" ) func New() *cobra.Command { cmd := &cobra.Command{ - Use: "update [ID!]", + Use: "update ", Short: "update a todo entry", Long: "update a todo entry", Run: run, @@ -20,15 +18,5 @@ func New() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - files := utils.GetAllFiles("todo") - - n, err := strconv.Atoi(args[0]) - if err != nil || n == 0 || n > len(files) { - fmt.Printf("Invalid argument") - return - } - - path := utils.GetPath([]string{"todo", files[n-1].Name()}) - - utils.EditFile(path) + todo.EditTodo() } diff --git a/go.mod b/go.mod index 0a857a6..41a4405 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,8 @@ require ( github.com/charmbracelet/lipgloss v0.5.0 github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f // indirect - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.3.0 // indirect + github.com/manifoldco/promptui v0.9.0 // indirect github.com/pkg/term v0.0.0-20200520122047-c3ffed290a03 // indirect github.com/sergi/go-diff v1.0.0 // indirect github.com/spf13/cobra v1.3.0 diff --git a/go.sum b/go.sum index 4cd87f0..c3a1e08 100644 --- a/go.sum +++ b/go.sum @@ -94,6 +94,7 @@ github.com/charmbracelet/lipgloss v0.4.0/go.mod h1:vmdkHvce7UzX6xkyf4cca8WlwdQ5R github.com/charmbracelet/lipgloss v0.5.0 h1:lulQHuVeodSgDez+3rGiuxlPVXSnhth442DATR2/8t8= github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= @@ -284,6 +285,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= +github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -541,6 +544,7 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/ui/constants/constants.go b/ui/constants/constants.go index a9cd875..2867182 100644 --- a/ui/constants/constants.go +++ b/ui/constants/constants.go @@ -20,4 +20,8 @@ const ( ERROR_CLOSE_FILE = "Darn, error closing file: %w" ERROR_LIST_FILE = "Darn, error listing files: %w" ERROR_DELETE_FILE = "Darn, error deleting file: %w" + ERROR_PROMPT = "Darn, error with prompt: %w" ) + +const MaxLengthDisplayOption = 20 +const MaxLengthDetails = 50 diff --git a/utils/brag/brag.go b/utils/brag/brag.go new file mode 100644 index 0000000..9759903 --- /dev/null +++ b/utils/brag/brag.go @@ -0,0 +1,30 @@ +package brag + +import ( + "cronicle/ui/constants" + "cronicle/utils/entries" + "cronicle/utils/prompts" + "log" +) + +func EditBrag() { + bragOptions := entries.GetEntryDisplayOptions("brag") + id, err := prompts.SelectEntry(bragOptions, "update") + + if err != nil { + log.Fatal(constants.ERROR_PROMPT, err) + } + + entries.EditEntry("brag", id) +} + +func DeleteBrag() { + bragOptions := entries.GetEntryDisplayOptions("brag") + id, err := prompts.SelectEntry(bragOptions, "delete") + + if err != nil { + log.Fatal(constants.ERROR_PROMPT, err) + } + + entries.DeleteEntry("brag", id) +} diff --git a/utils/daily/daily.go b/utils/daily/daily.go new file mode 100644 index 0000000..ec73b4f --- /dev/null +++ b/utils/daily/daily.go @@ -0,0 +1,30 @@ +package daily + +import ( + "cronicle/ui/constants" + "cronicle/utils/entries" + "cronicle/utils/prompts" + "log" +) + +func EditDaily() { + dailyOptions := entries.GetEntryDisplayOptions("daily") + id, err := prompts.SelectEntry(dailyOptions, "update") + + if err != nil { + log.Fatal(constants.ERROR_PROMPT, err) + } + + entries.EditEntry("daily", id) +} + +func DeleteDaily() { + dailyOptions := entries.GetEntryDisplayOptions("daily") + id, err := prompts.SelectEntry(dailyOptions, "delete") + + if err != nil { + log.Fatal(constants.ERROR_PROMPT, err) + } + + entries.DeleteEntry("daily", id) +} diff --git a/utils/entries/entries.go b/utils/entries/entries.go index 8d3426c..f11a68b 100644 --- a/utils/entries/entries.go +++ b/utils/entries/entries.go @@ -3,12 +3,15 @@ package entries import ( "cronicle/ui/constants" "cronicle/utils" + "cronicle/utils/types" "errors" "fmt" "log" "os" "strings" "time" + + "github.com/adrg/frontmatter" ) func getDate() string { @@ -85,3 +88,40 @@ func composeEntry(w utils.WriteParams, t string) string { return output.String() } + +func DeleteEntry(t string, id int) { + files := utils.GetAllFiles(t) + + utils.DeleteFile(files[id].Name(), t) +} + +func EditEntry(t string, id int) { + files := utils.GetAllFiles(t) + + path := utils.GetPath([]string{t, files[id].Name()}) + + utils.EditFile(path) +} + +func GetEntryDisplayOptions(t string) []types.EntryProperties { + var matter types.EntryProperties + var options []types.EntryProperties + files := utils.GetAllFiles(t) + + for _, f := range files { + path := utils.GetPath([]string{t, f.Name()}) + content := utils.GetDataFromFile(path) + rest, err := frontmatter.Parse(strings.NewReader(content), &matter) + if err != nil { + log.Println(err) + } + a := strings.Split(string(rest), "\n") + b := strings.Join(a, ",") + matter.Entry = utils.TruncateText(string(rest)[6:], constants.MaxLengthDisplayOption) + matter.EntryDetails = utils.TruncateText(b, constants.MaxLengthDetails) + matter.FileName = f.Name() + options = append(options, matter) + } + + return options +} diff --git a/utils/file.go b/utils/file.go index d244d29..7baa4b1 100644 --- a/utils/file.go +++ b/utils/file.go @@ -2,6 +2,7 @@ package utils import ( "cronicle/ui/constants" + "cronicle/utils/types" "fmt" "io/fs" "io/ioutil" @@ -25,7 +26,10 @@ func GetDataFromFile(path string) string { func GetAllFiles(d string) []fs.FileInfo { p := GetPath([]string{d}) - f, _ := ioutil.ReadDir(p) + f, err := ioutil.ReadDir(p) + if err != nil { + log.Fatal(constants.ERROR_LIST_FILE, err) + } return f } @@ -73,7 +77,7 @@ func ListFiles(t string) { } for i, f := range files { - fmt.Printf("%v. %s", i+1, f.Name()) + fmt.Printf("%v. %s\n", i+1, f.Name()) } } @@ -94,15 +98,8 @@ func ParseContent(content string) string { return c } -type Header struct { - Date string `yaml:"date"` - Due string `yaml:"due"` - Type string `yaml:"type"` - Tags []string `yaml:"tags"` -} - -func ParseHeader(content string) Header { - var matter Header +func ParseHeader(content string) types.Header { + var matter types.Header _, err := frontmatter.Parse(strings.NewReader(content), &matter) if err != nil { diff --git a/utils/prompts/prompts.go b/utils/prompts/prompts.go new file mode 100644 index 0000000..ab417f0 --- /dev/null +++ b/utils/prompts/prompts.go @@ -0,0 +1,78 @@ +package prompts + +import ( + "cronicle/utils/types" + "fmt" + "strings" + + "github.com/manifoldco/promptui" +) + +func SelectTodo(todoOptions []types.TodoProperties, action string) (int, error) { + + templates := &promptui.SelectTemplates{ + Label: "{{ . | bold }}", + Active: "\U00002705 {{ .Todo | cyan }}", + Inactive: "{{ .Todo | cyan }}", + Selected: "\U00002714 {{ .Todo | green | cyan }}", + Details: ` + --------- Properties ---------- + {{ "Date:" | faint }} {{ .Date }} + {{ "Tags:" | faint }} {{ .Tags }} + {{ "Due:" | faint }} {{ .Due }} + {{ "Todo:" | faint }} {{ .TodoDetails }}`, + } + + searcher := func(input string, index int) bool { + todo := todoOptions[index] + name := strings.Replace(strings.ToLower(todo.Todo), " ", "", -1) + input = strings.Replace(strings.ToLower(input), " ", "", -1) + + return strings.Contains(name, input) + } + + prompt := promptui.Select{ + Label: fmt.Sprintf("Select todo to %s:", action), + Items: todoOptions, + Templates: templates, + Searcher: searcher, + } + + id, _, err := prompt.Run() + + return id, err +} + +func SelectEntry(options []types.EntryProperties, action string) (int, error) { + + templates := &promptui.SelectTemplates{ + Label: "{{ . | bold }}", + Active: "\U00002705 {{ .FileName | cyan }}", + Inactive: "{{ .FileName | cyan }}", + Selected: "\U00002714 {{ .FileName | green | cyan }}", + Details: ` + --------- Properties ---------- + {{ "Date:" | faint }} {{ .Date }} + {{ "Tags:" | faint }} {{ .Tags }} + {{ "Entry:" | faint }} {{ .EntryDetails }}`, + } + + searcher := func(input string, index int) bool { + entry := options[index] + name := strings.Replace(strings.ToLower(entry.Entry), " ", "", -1) + input = strings.Replace(strings.ToLower(input), " ", "", -1) + + return strings.Contains(name, input) + } + + prompt := promptui.Select{ + Label: fmt.Sprintf("Select entry to %s:", action), + Items: options, + Templates: templates, + Searcher: searcher, + } + + id, _, err := prompt.Run() + + return id, err +} diff --git a/utils/todo/todo.go b/utils/todo/todo.go index 6416750..736b427 100644 --- a/utils/todo/todo.go +++ b/utils/todo/todo.go @@ -4,12 +4,15 @@ import ( "cronicle/ui/constants" "cronicle/utils" "cronicle/utils/entries" + "cronicle/utils/prompts" + "cronicle/utils/types" "fmt" "io/fs" - "io/ioutil" "log" "strings" "time" + + "github.com/adrg/frontmatter" ) func ComposeTodo(w utils.WriteParams) string { @@ -73,17 +76,6 @@ func CheckTodo(todo string) string { return c.String() } -func GetTodoFilePaths() []fs.FileInfo { - p := utils.GetPath([]string{"todo"}) - - f, err := ioutil.ReadDir(p) - if err != nil { - log.Fatal(constants.ERROR_LIST_FILE, err) - } - - return f -} - func GetTodoFromFile(fileName string) string { path := utils.GetPath([]string{"todo", fileName}) todo := utils.GetDataFromFile(path) @@ -93,7 +85,7 @@ func GetTodoFromFile(fileName string) string { func GetAllTodos() []string { var todos []string - files := GetTodoFilePaths() + files := utils.GetAllFiles("todo") for _, f := range files { todo := GetTodoFromFile(f.Name()) @@ -104,7 +96,7 @@ func GetAllTodos() []string { } func ListTodos() { - files := GetTodoFilePaths() + files := utils.GetAllFiles("todo") for i, f := range files { todo := GetTodoFromFile(f.Name()) @@ -113,3 +105,55 @@ func ListTodos() { fmt.Printf("%v. %s", i+1, task[6:]) } } + +func GetTodoDisplayOptions() []types.TodoProperties { + var matter types.TodoProperties + var options []types.TodoProperties + files := utils.GetAllFiles("todo") + + for _, f := range files { + content := GetTodoFromFile(f.Name()) + rest, err := frontmatter.Parse(strings.NewReader(content), &matter) + if err != nil { + log.Println(err) + } + matter.Todo = utils.TruncateText(string(rest)[6:], constants.MaxLengthDisplayOption) + matter.TodoDetails = utils.TruncateText(string(rest)[6:], constants.MaxLengthDetails) + options = append(options, matter) + } + + return options +} + +func EditTodo() { + todoOptions := GetTodoDisplayOptions() + id, err := prompts.SelectTodo(todoOptions, "update") + + if err != nil { + log.Fatal(constants.ERROR_PROMPT, err) + } + + entries.EditEntry("todo", id) +} + +func DeleteTodo() { + todoOptions := GetTodoDisplayOptions() + id, err := prompts.SelectTodo(todoOptions, "delete") + + if err != nil { + log.Fatal(constants.ERROR_PROMPT, err) + } + + entries.DeleteEntry("todo", id) +} + +func CompleteTodo() { + todoOptions := GetTodoDisplayOptions() + id, err := prompts.SelectTodo(todoOptions, "complete") + + if err != nil { + log.Fatal(constants.ERROR_PROMPT, err) + } + files := utils.GetAllFiles("todo") + MarkCompleted(files[id]) +} diff --git a/utils/types/types.go b/utils/types/types.go new file mode 100644 index 0000000..9d83210 --- /dev/null +++ b/utils/types/types.go @@ -0,0 +1,24 @@ +package types + +type Header struct { + Date string `yaml:"date"` + Due string `yaml:"due"` + Type string `yaml:"type"` + Tags []string `yaml:"tags"` +} + +type TodoProperties struct { + Date string `yaml:"date"` + Due string `yaml:"due"` + Tags []string `yaml:"tags"` + Todo string + TodoDetails string +} + +type EntryProperties struct { + Date string `yaml:"date"` + Tags []string `yaml:"tags"` + Entry string + EntryDetails string + FileName string +} diff --git a/utils/utils.go b/utils/utils.go index 3b64fe4..a44eb5f 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -1,5 +1,9 @@ package utils +import ( + "strings" +) + func Max(a, b int) int { if a > b { return a @@ -26,3 +30,17 @@ func Contains(s []string, e string) bool { } return false } + +func TruncateText(s string, max int) string { + t := strings.TrimSpace(s) + + if max > len(t) { + return t + } + + if strings.LastIndex(s[:max], " ") == -1 { + return s[:max] + } + + return s[:strings.LastIndex(s[:max], " ")] + "..." +} From ca8501023fbe16f546a24b55bf2cee70b829b2ad Mon Sep 17 00:00:00 2001 From: Alice Zhao Date: Sun, 3 Apr 2022 20:30:26 -0700 Subject: [PATCH 2/2] feat: allow user to input arg or view options --- cmd/brag/delete/delete.go | 4 +- cmd/brag/update/update.go | 4 +- cmd/daily/delete/delete.go | 4 +- cmd/daily/update/update.go | 4 +- cmd/todo/delete/delete.go | 4 +- cmd/todo/update/update.go | 6 ++- utils/brag/brag.go | 30 ------------- utils/daily/daily.go | 30 ------------- utils/entries/entries.go | 88 +++++++++++++++++++++++++++----------- utils/prompts/prompts.go | 50 +++++++++++++++++++++- utils/todo/todo.go | 81 ++++++++--------------------------- utils/utils.go | 10 +++++ 12 files changed, 151 insertions(+), 164 deletions(-) delete mode 100644 utils/brag/brag.go delete mode 100644 utils/daily/daily.go diff --git a/cmd/brag/delete/delete.go b/cmd/brag/delete/delete.go index 785239c..4e7ffd2 100644 --- a/cmd/brag/delete/delete.go +++ b/cmd/brag/delete/delete.go @@ -1,7 +1,7 @@ package delete import ( - "cronicle/utils/brag" + "cronicle/utils/entries" "github.com/spf13/cobra" ) @@ -18,5 +18,5 @@ func New() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - brag.DeleteBrag() + entries.DeleteEntry(args, "brag") } diff --git a/cmd/brag/update/update.go b/cmd/brag/update/update.go index 594b43a..b6f360c 100644 --- a/cmd/brag/update/update.go +++ b/cmd/brag/update/update.go @@ -1,7 +1,7 @@ package update import ( - "cronicle/utils/brag" + "cronicle/utils/entries" "github.com/spf13/cobra" ) @@ -18,5 +18,5 @@ func New() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - brag.EditBrag() + entries.EditEntry(args, "brag") } diff --git a/cmd/daily/delete/delete.go b/cmd/daily/delete/delete.go index 5c2f302..aa3c718 100644 --- a/cmd/daily/delete/delete.go +++ b/cmd/daily/delete/delete.go @@ -1,7 +1,7 @@ package delete import ( - "cronicle/utils/daily" + "cronicle/utils/entries" "github.com/spf13/cobra" ) @@ -18,5 +18,5 @@ func New() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - daily.DeleteDaily() + entries.DeleteEntry(args, "daily") } diff --git a/cmd/daily/update/update.go b/cmd/daily/update/update.go index 3af2b2f..5d8a096 100644 --- a/cmd/daily/update/update.go +++ b/cmd/daily/update/update.go @@ -1,7 +1,7 @@ package update import ( - "cronicle/utils/daily" + "cronicle/utils/entries" "github.com/spf13/cobra" ) @@ -18,5 +18,5 @@ func New() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - daily.EditDaily() + entries.EditEntry(args, "daily") } diff --git a/cmd/todo/delete/delete.go b/cmd/todo/delete/delete.go index f0e4cc2..a682acd 100644 --- a/cmd/todo/delete/delete.go +++ b/cmd/todo/delete/delete.go @@ -1,7 +1,7 @@ package delete import ( - "cronicle/utils/todo" + "cronicle/utils/entries" "github.com/spf13/cobra" ) @@ -18,5 +18,5 @@ func New() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - todo.DeleteTodo() + entries.DeleteEntry(args, "todo") } diff --git a/cmd/todo/update/update.go b/cmd/todo/update/update.go index e519fdd..a7ee0bf 100644 --- a/cmd/todo/update/update.go +++ b/cmd/todo/update/update.go @@ -1,7 +1,8 @@ package update import ( - "cronicle/utils/todo" + "cronicle/utils/entries" + "log" "github.com/spf13/cobra" ) @@ -18,5 +19,6 @@ func New() *cobra.Command { } func run(cmd *cobra.Command, args []string) { - todo.EditTodo() + log.Println(args) + entries.EditEntry(args, "todo") } diff --git a/utils/brag/brag.go b/utils/brag/brag.go deleted file mode 100644 index 9759903..0000000 --- a/utils/brag/brag.go +++ /dev/null @@ -1,30 +0,0 @@ -package brag - -import ( - "cronicle/ui/constants" - "cronicle/utils/entries" - "cronicle/utils/prompts" - "log" -) - -func EditBrag() { - bragOptions := entries.GetEntryDisplayOptions("brag") - id, err := prompts.SelectEntry(bragOptions, "update") - - if err != nil { - log.Fatal(constants.ERROR_PROMPT, err) - } - - entries.EditEntry("brag", id) -} - -func DeleteBrag() { - bragOptions := entries.GetEntryDisplayOptions("brag") - id, err := prompts.SelectEntry(bragOptions, "delete") - - if err != nil { - log.Fatal(constants.ERROR_PROMPT, err) - } - - entries.DeleteEntry("brag", id) -} diff --git a/utils/daily/daily.go b/utils/daily/daily.go deleted file mode 100644 index ec73b4f..0000000 --- a/utils/daily/daily.go +++ /dev/null @@ -1,30 +0,0 @@ -package daily - -import ( - "cronicle/ui/constants" - "cronicle/utils/entries" - "cronicle/utils/prompts" - "log" -) - -func EditDaily() { - dailyOptions := entries.GetEntryDisplayOptions("daily") - id, err := prompts.SelectEntry(dailyOptions, "update") - - if err != nil { - log.Fatal(constants.ERROR_PROMPT, err) - } - - entries.EditEntry("daily", id) -} - -func DeleteDaily() { - dailyOptions := entries.GetEntryDisplayOptions("daily") - id, err := prompts.SelectEntry(dailyOptions, "delete") - - if err != nil { - log.Fatal(constants.ERROR_PROMPT, err) - } - - entries.DeleteEntry("daily", id) -} diff --git a/utils/entries/entries.go b/utils/entries/entries.go index f11a68b..0ee890f 100644 --- a/utils/entries/entries.go +++ b/utils/entries/entries.go @@ -3,15 +3,14 @@ package entries import ( "cronicle/ui/constants" "cronicle/utils" - "cronicle/utils/types" + "cronicle/utils/prompts" "errors" "fmt" + "io/fs" "log" "os" "strings" "time" - - "github.com/adrg/frontmatter" ) func getDate() string { @@ -89,39 +88,76 @@ func composeEntry(w utils.WriteParams, t string) string { return output.String() } -func DeleteEntry(t string, id int) { +func EditEntry(args []string, t string) { files := utils.GetAllFiles(t) + var id int + + if len(args) > 0 { + // user has given an arguement + argId := utils.GetIdFromArg(args, files) + if argId == -1 { + fmt.Printf("Invalid argument") + return + } + id = argId + } else { + // user selects from options + id = GetIdFromOptions(files, t, "update") + } - utils.DeleteFile(files[id].Name(), t) + path := utils.GetPath([]string{t, files[id].Name()}) + + utils.EditFile(path) } -func EditEntry(t string, id int) { +func DeleteEntry(args []string, t string) { files := utils.GetAllFiles(t) + var id int + + if len(args) > 0 { + // user has given an arguement + argId := utils.GetIdFromArg(args, files) + if argId == -1 { + fmt.Printf("Invalid argument") + return + } + id = argId + } else { + // user selects from options + id = GetIdFromOptions(files, t, "delete") + } - path := utils.GetPath([]string{t, files[id].Name()}) + utils.DeleteFile(files[id].Name(), t) +} - utils.EditFile(path) +func GetIdFromOptions(files []fs.FileInfo, t string, action string) int { + var id int + if t == "todo" { + id = GetIdFromTodoOptions(files, t, action) + } else { + id = GetIdFromEntryOptions(files, t, action) + } + return id } -func GetEntryDisplayOptions(t string) []types.EntryProperties { - var matter types.EntryProperties - var options []types.EntryProperties - files := utils.GetAllFiles(t) +func GetIdFromEntryOptions(files []fs.FileInfo, t string, action string) int { + options := prompts.GetEntryDisplayOptions(t, files) + i, err := prompts.SelectEntry(options, action) - for _, f := range files { - path := utils.GetPath([]string{t, f.Name()}) - content := utils.GetDataFromFile(path) - rest, err := frontmatter.Parse(strings.NewReader(content), &matter) - if err != nil { - log.Println(err) - } - a := strings.Split(string(rest), "\n") - b := strings.Join(a, ",") - matter.Entry = utils.TruncateText(string(rest)[6:], constants.MaxLengthDisplayOption) - matter.EntryDetails = utils.TruncateText(b, constants.MaxLengthDetails) - matter.FileName = f.Name() - options = append(options, matter) + if err != nil { + log.Fatal(constants.ERROR_PROMPT, err) + } + + return i +} + +func GetIdFromTodoOptions(files []fs.FileInfo, t string, action string) int { + options := prompts.GetTodoDisplayOptions(files) + i, err := prompts.SelectTodo(options, action) + + if err != nil { + log.Fatal(constants.ERROR_PROMPT, err) } - return options + return i } diff --git a/utils/prompts/prompts.go b/utils/prompts/prompts.go index ab417f0..7b3ccf6 100644 --- a/utils/prompts/prompts.go +++ b/utils/prompts/prompts.go @@ -1,10 +1,15 @@ package prompts import ( + "cronicle/ui/constants" + "cronicle/utils" "cronicle/utils/types" "fmt" + "io/fs" + "log" "strings" + "github.com/adrg/frontmatter" "github.com/manifoldco/promptui" ) @@ -12,7 +17,7 @@ func SelectTodo(todoOptions []types.TodoProperties, action string) (int, error) templates := &promptui.SelectTemplates{ Label: "{{ . | bold }}", - Active: "\U00002705 {{ .Todo | cyan }}", + Active: "\U00002192 {{ .Todo | cyan }}", Inactive: "{{ .Todo | cyan }}", Selected: "\U00002714 {{ .Todo | green | cyan }}", Details: ` @@ -47,7 +52,7 @@ func SelectEntry(options []types.EntryProperties, action string) (int, error) { templates := &promptui.SelectTemplates{ Label: "{{ . | bold }}", - Active: "\U00002705 {{ .FileName | cyan }}", + Active: "\U00002192 {{ .FileName | cyan }}", Inactive: "{{ .FileName | cyan }}", Selected: "\U00002714 {{ .FileName | green | cyan }}", Details: ` @@ -76,3 +81,44 @@ func SelectEntry(options []types.EntryProperties, action string) (int, error) { return id, err } + +func GetEntryDisplayOptions(t string, files []fs.FileInfo) []types.EntryProperties { + var matter types.EntryProperties + var options []types.EntryProperties + + for _, f := range files { + path := utils.GetPath([]string{t, f.Name()}) + content := utils.GetDataFromFile(path) + rest, err := frontmatter.Parse(strings.NewReader(content), &matter) + if err != nil { + log.Println(err) + } + a := strings.Split(string(rest), "\n") + b := strings.Join(a, ",") + matter.Entry = utils.TruncateText(string(rest)[6:], constants.MaxLengthDisplayOption) + matter.EntryDetails = utils.TruncateText(b, constants.MaxLengthDetails) + matter.FileName = f.Name() + options = append(options, matter) + } + + return options +} + +func GetTodoDisplayOptions(files []fs.FileInfo) []types.TodoProperties { + var matter types.TodoProperties + var options []types.TodoProperties + + for _, f := range files { + path := utils.GetPath([]string{"todo", f.Name()}) + content := utils.GetDataFromFile(path) + rest, err := frontmatter.Parse(strings.NewReader(content), &matter) + if err != nil { + log.Println(err) + } + matter.Todo = utils.TruncateText(string(rest)[6:], constants.MaxLengthDisplayOption) + matter.TodoDetails = utils.TruncateText(string(rest)[6:], constants.MaxLengthDetails) + options = append(options, matter) + } + + return options +} diff --git a/utils/todo/todo.go b/utils/todo/todo.go index 736b427..ee1bea8 100644 --- a/utils/todo/todo.go +++ b/utils/todo/todo.go @@ -5,14 +5,11 @@ import ( "cronicle/utils" "cronicle/utils/entries" "cronicle/utils/prompts" - "cronicle/utils/types" "fmt" "io/fs" "log" "strings" "time" - - "github.com/adrg/frontmatter" ) func ComposeTodo(w utils.WriteParams) string { @@ -50,17 +47,6 @@ func ComposeTodo(w utils.WriteParams) string { return output.String() } -func MarkCompleted(f fs.FileInfo) { - //add todo list to log - path := utils.GetPath([]string{"todo", f.Name()}) - todo := utils.GetDataFromFile(path) - checkedTodo := CheckTodo(todo) - tags := utils.ParseHeader(todo).Tags - //add completed todo to log - entries.WriteOrCreateEntry(utils.WriteParams{Message: checkedTodo, Tags: strings.Join(tags, ",")}, "daily") - utils.DeleteFile(f.Name(), "todo") -} - func CheckTodo(todo string) string { m := utils.ParseContent(todo) @@ -76,19 +62,14 @@ func CheckTodo(todo string) string { return c.String() } -func GetTodoFromFile(fileName string) string { - path := utils.GetPath([]string{"todo", fileName}) - todo := utils.GetDataFromFile(path) - return todo -} - func GetAllTodos() []string { var todos []string files := utils.GetAllFiles("todo") for _, f := range files { - todo := GetTodoFromFile(f.Name()) + path := utils.GetPath([]string{"todo", f.Name()}) + todo := utils.GetDataFromFile(path) todos = append(todos, utils.ParseContent(todo)) } @@ -99,61 +80,33 @@ func ListTodos() { files := utils.GetAllFiles("todo") for i, f := range files { - todo := GetTodoFromFile(f.Name()) + path := utils.GetPath([]string{"todo", f.Name()}) + todo := utils.GetDataFromFile(path) task := utils.ParseContent(todo) fmt.Printf("%v. %s", i+1, task[6:]) } } -func GetTodoDisplayOptions() []types.TodoProperties { - var matter types.TodoProperties - var options []types.TodoProperties +func CompleteTodo() { files := utils.GetAllFiles("todo") - - for _, f := range files { - content := GetTodoFromFile(f.Name()) - rest, err := frontmatter.Parse(strings.NewReader(content), &matter) - if err != nil { - log.Println(err) - } - matter.Todo = utils.TruncateText(string(rest)[6:], constants.MaxLengthDisplayOption) - matter.TodoDetails = utils.TruncateText(string(rest)[6:], constants.MaxLengthDetails) - options = append(options, matter) - } - - return options -} - -func EditTodo() { - todoOptions := GetTodoDisplayOptions() - id, err := prompts.SelectTodo(todoOptions, "update") - - if err != nil { - log.Fatal(constants.ERROR_PROMPT, err) - } - - entries.EditEntry("todo", id) -} - -func DeleteTodo() { - todoOptions := GetTodoDisplayOptions() - id, err := prompts.SelectTodo(todoOptions, "delete") + todoOptions := prompts.GetTodoDisplayOptions(files) + id, err := prompts.SelectTodo(todoOptions, "complete") if err != nil { log.Fatal(constants.ERROR_PROMPT, err) } - entries.DeleteEntry("todo", id) + MarkCompleted(files[id]) } -func CompleteTodo() { - todoOptions := GetTodoDisplayOptions() - id, err := prompts.SelectTodo(todoOptions, "complete") - - if err != nil { - log.Fatal(constants.ERROR_PROMPT, err) - } - files := utils.GetAllFiles("todo") - MarkCompleted(files[id]) +func MarkCompleted(f fs.FileInfo) { + //add todo list to log + path := utils.GetPath([]string{"todo", f.Name()}) + todo := utils.GetDataFromFile(path) + checkedTodo := CheckTodo(todo) + tags := utils.ParseHeader(todo).Tags + //add completed todo to log + entries.WriteOrCreateEntry(utils.WriteParams{Message: checkedTodo, Tags: strings.Join(tags, ",")}, "daily") + utils.DeleteFile(f.Name(), "todo") } diff --git a/utils/utils.go b/utils/utils.go index a44eb5f..b673481 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -1,6 +1,8 @@ package utils import ( + "io/fs" + "strconv" "strings" ) @@ -44,3 +46,11 @@ func TruncateText(s string, max int) string { return s[:strings.LastIndex(s[:max], " ")] + "..." } + +func GetIdFromArg(args []string, files []fs.FileInfo) int { + n, err := strconv.Atoi(args[0]) + if err != nil || n == 0 || n > len(files) { + return -1 + } + return n - 1 +}