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  }