diff --git a/go.mod b/go.mod index 3622b60..75bde85 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,10 @@ module todo-app go 1.20 + +require ( + github.com/fatih/color v1.15.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + golang.org/x/sys v0.6.0 // indirect +) diff --git a/main.go b/main.go index c2030c1..f5c1378 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "bufio" "fmt" "os" + "strings" ) func PrintMenu() { @@ -11,17 +12,26 @@ func PrintMenu() { fmt.Printf("1: List Todo\n") fmt.Printf("2: Add Todo\n") fmt.Printf("3: Remove Todo (via index)\n") + fmt.Printf("4: Save to file\n") - fmt.Printf("\n\n0: List menu again\n") - fmt.Printf("4: Quit\n\n> ") + fmt.Printf("\n\n0: Quit\n> ") } +const ( + QUIT = 0 + LIST = 1 + ADD = 2 + REMOVE = 3 + SAVE = 4 +) + func main() { fmt.Print("\033[H\033[2J") //clear PrintMenu() list := Todos{} for { + var input int n, err := fmt.Scanln(&input) if n < 1 || err != nil { @@ -29,12 +39,15 @@ func main() { } switch input { - case 0: - PrintMenu() - case 1: - list.ListTodo() + case QUIT: + fmt.Print("Quitting, goodbye!\n") + os.Exit(0) + case LIST: + if err := list.ListTodo(); err != nil { + fmt.Print(err) + } PrintMenu() - case 2: + case ADD: in := bufio.NewReader(os.Stdin) fmt.Print("Add Title:\n> ") @@ -46,7 +59,7 @@ func main() { list.AddTodo(Todo{Title: title, Content: content}) fmt.Printf("Added %s to the list!\n", title) PrintMenu() - case 3: + case REMOVE: var index int fmt.Printf("Which TODO to remove?\n> ") @@ -58,9 +71,18 @@ func main() { fmt.Print(err) } PrintMenu() - case 4: - fmt.Print("Quitting, goodbye!\n") - os.Exit(0) + case SAVE: + in := bufio.NewReader(os.Stdin) + fmt.Print("Save to file:\n> ") + filename, _ := in.ReadString('\n') + filename = strings.TrimSuffix(filename, "\n") + + if err := list.SaveToFile(filename); err != nil { + fmt.Print(err) + } else { + fmt.Printf("%s saved!\n", filename) + } + PrintMenu() default: PrintMenu() } diff --git a/todo b/todo index e270749..8b3caed 100755 Binary files a/todo and b/todo differ diff --git a/todo.go b/todo.go index 244d7d0..ab5f183 100644 --- a/todo.go +++ b/todo.go @@ -3,8 +3,19 @@ package main import ( "errors" "fmt" + "os" + "strconv" + "strings" + + "github.com/fatih/color" ) +func check(err error) { + if err != nil { + fmt.Fprintf(os.Stderr, "[ERR] %s", err) + } +} + type Todo struct { Title string Content string @@ -32,12 +43,56 @@ func (todo *Todos) RemoveTodo(index int) (err error) { return nil } -func (todo *Todos) ListTodo() int { +func (todo *Todos) ListTodo() (err error) { + // Create a custom print function for convenience + id := color.New(color.Bold, color.FgGreen).PrintfFunc() + title := color.New(color.Bold, color.FgBlue).PrintfFunc() + content := color.New(color.Bold, color.FgWhite).PrintfFunc() + if len(todo.Items) == 0 { - return 0 + return errors.New("[ERR] Todo list is empty!\n") + } + for k, v := range todo.Items { + id("[%d]", k) + title("%s", v.Title) + content("%s\n", v.Content) } + return nil +} + +func (todo *Todos) SaveToFile(filename string) error { + var sb strings.Builder + var FILE *os.File + + filename = filename + ".txt" for k, v := range todo.Items { - fmt.Printf("%d:%s\n", k, v) + fmt.Printf("#%d,%s,%s;\n", k, strings.ReplaceAll(v.Title, "\n", ""), strings.ReplaceAll(v.Content, "\n", "")) + sb.WriteString(strconv.Itoa(k)) + sb.WriteString(",") + sb.WriteString(strings.ReplaceAll(v.Title, "\n", "")) + sb.WriteString(",") + sb.WriteString(strings.ReplaceAll(v.Content, "\n", "")) + sb.WriteString(";\n") + } + + content := sb.String() + + fmt.Println(content) + + if _, err := os.Stat(filename); err != nil { + if FILE, err = os.Create(filename); err != nil { + return errors.New("[ERR] could not create file \n") + } + return errors.New("[ERR] file does not exist, creating one...\n") + } + FILE, _ = os.Create(filename) //errors already handled + + if _, err := FILE.WriteString(content); err != nil { + return err + //return errors.New("[ERR] could not write to file\n") } - return 1 + + sb.Reset() //reset the string builder + FILE.Close() //close the file + return nil }