github.com/rmachuca89/go-lab@v0.0.0-20220225232501-08364e2cef7f/cmd/todo/main.go (about) 1 package main 2 3 import ( 4 "flag" 5 "fmt" 6 "log" 7 "os" 8 "path" 9 10 "github.com/rmachuca89/go-lab/pkg/todo" 11 ) 12 13 const ( 14 errorTag string = "[ERROR]" 15 debugTag string = "[DEBUG]" 16 infoTag string = "[INFO]" 17 dryRunTag string = "[DRY-RUN]" 18 ) 19 20 type Config struct { 21 binName string 22 filename string 23 debug bool 24 taskTitle string 25 dryRun bool 26 complete bool 27 } 28 29 func (cfg *Config) RegisterFlags(fs *flag.FlagSet) { 30 fs.StringVar(&cfg.filename, "file", "tasks.json", "file containing the existing tasks in valid JSON format.") 31 fs.BoolVar(&cfg.debug, "debug", false, "debug output") 32 fs.BoolVar(&cfg.debug, "v", false, "verbose output (short)") 33 fs.BoolVar(&cfg.debug, "verbose", false, "verbose output. alias to debug") 34 fs.BoolVar(&cfg.dryRun, "dryrun", false, "perform a dry run of the task where no changes are performed") 35 fs.StringVar(&cfg.taskTitle, "title", "", "title for the task to operate on") 36 fs.BoolVar(&cfg.complete, "complete", false, "completes the provided task title") 37 38 cfg.binName = path.Base(os.Args[0]) 39 fs.Usage = func() { 40 fmt.Fprintf(flag.CommandLine.Output(), "%s tool. Developed for learning purposes.\n", cfg.binName) 41 fmt.Fprintf(flag.CommandLine.Output(), "Copyright 2022\n") 42 fmt.Fprintln(flag.CommandLine.Output(), "Usage Information:") 43 fs.PrintDefaults() 44 } 45 } 46 47 func tasksList(tL *todo.Tasks) { 48 if len(*tL) == 0 { 49 fmt.Println(infoTag, "There are no existing tasks! get to work...") 50 return 51 } 52 fmt.Print(tL) 53 } 54 55 func taskAdd(tL *todo.Tasks, title string, dry bool) { 56 if title == "" { 57 log.Fatalln(errorTag, "New task title can not be empty.") 58 } 59 60 if dry { 61 log.Default().Printf("%s Task with title %q would be attempted to be added.", debugTag, title) 62 return 63 } 64 65 _, err := tL.Add(title) 66 if err != nil { 67 log.Fatalf("%s Could not add new task (%q): %q", errorTag, title, err) 68 } 69 log.Default().Println(infoTag, "Success. New task created.") 70 } 71 72 func taskSave(tL *todo.Tasks, filename string, dry bool) { 73 if dry { 74 log.Default().Println(dryRunTag, "Tasks would be attempted to be saved to disk.") 75 return 76 } 77 78 if err := tL.Save(filename); err != nil { 79 log.Fatalf("%s Could not save tasks to file: %q", errorTag, err) 80 } 81 } 82 83 func taskComplete(tL *todo.Tasks, title string, dry bool) { 84 if title == "" { 85 log.Fatalln(errorTag, "Task title to complete required.") 86 } 87 88 if dry { 89 log.Default().Println(dryRunTag, "Tasks would be attempted to be saved to disk.") 90 return 91 } 92 93 if err := tL.Complete(title); err != nil { 94 log.Fatalf("%s Could not mark task as complete: %q", errorTag, err) 95 } 96 log.Default().Println(infoTag, "Success. Task marked as complete.") 97 } 98 99 func main() { 100 // 0. Init config and parse flags 101 cfg := new(Config) 102 fs := flag.NewFlagSet("todo flagset", flag.ExitOnError) 103 cfg.RegisterFlags(fs) 104 fs.Parse(os.Args[1:]) 105 106 if cfg.debug { 107 log.Default().Printf("%s App Config: %+v", debugTag, cfg) 108 } 109 110 tL := new(todo.Tasks) 111 // 1. Check if file exists; else create an empty 112 if _, err := os.Stat(cfg.filename); err != nil { 113 if cfg.debug { 114 log.Default().Printf("%s File %q did not exist. Creating it...\n", debugTag, cfg.filename) 115 } 116 wErr := tL.Save(cfg.filename) 117 if wErr != nil { 118 log.Fatalf("%s Could not write initial empty file: %q", errorTag, err) 119 } 120 } 121 if err := tL.Load(cfg.filename); err != nil { 122 log.Fatalf("%s Could not load tasks file: %q", errorTag, err) 123 } 124 125 // Flags parsing 126 switch { 127 128 case cfg.complete: 129 taskComplete(tL, cfg.taskTitle, cfg.dryRun) 130 131 case cfg.taskTitle != "": 132 taskAdd(tL, cfg.taskTitle, cfg.dryRun) 133 134 default: 135 tasksList(tL) 136 } 137 138 taskSave(tL, cfg.filename, cfg.dryRun) 139 if cfg.debug { 140 log.Default().Println(debugTag, "Tasks saved to disk.") 141 } 142 }