datastore/tasks/tasks.go (110 lines of code) (raw):

// Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // A simple command-line task list manager to demonstrate using the // cloud.google.com/go/datastore package. package main import ( "bufio" "fmt" "io" "log" "os" "strconv" "strings" "text/tabwriter" ) func main() { projID := os.Getenv("DATASTORE_PROJECT_ID") if projID == "" { log.Fatal(`You need to set the environment variable "DATASTORE_PROJECT_ID"`) } client, err := createClient(projID) if err != nil { log.Fatalf("Could not create datastore client: %v", err) } defer client.Close() // Print welcome message. fmt.Println("Cloud Datastore Task List") fmt.Println() usage() // Read commands from stdin. scanner := bufio.NewScanner(os.Stdin) fmt.Print("> ") for scanner.Scan() { cmd, args, n := parseCmd(scanner.Text()) switch cmd { case "new": if args == "" { log.Printf("Missing description in %q command", cmd) usage() break } key, err := AddTask(projID, args) if err != nil { log.Printf("Failed to create task: %v", err) break } fmt.Printf("Created new task with ID %d\n", key.ID) case "done": if n == 0 { log.Printf("Missing numerical task ID in %q command", cmd) usage() break } if err := MarkDone(projID, n); err != nil { log.Printf("Failed to mark task done: %v", err) break } fmt.Printf("Task %d marked done\n", n) case "list": tasks, err := ListTasks(projID) if err != nil { log.Printf("Failed to fetch task list: %v", err) break } PrintTasks(os.Stdout, tasks) case "delete": if n == 0 { log.Printf("Missing numerical task ID in %q command", cmd) usage() break } if err := DeleteTask(projID, n); err != nil { log.Printf("Failed to delete task: %v", err) break } fmt.Printf("Task %d deleted\n", n) default: log.Printf("Unknown command %q", cmd) usage() } fmt.Print("> ") } if err := scanner.Err(); err != nil { log.Fatalf("Failed reading stdin: %v", err) } } // PrintTasks prints the tasks to the given writer. func PrintTasks(w io.Writer, tasks []*Task) { // Use a tab writer to help make results pretty. tw := tabwriter.NewWriter(w, 8, 8, 1, ' ', 0) // Min cell size of 8. fmt.Fprintf(tw, "ID\tDescription\tStatus\n") for _, t := range tasks { if t.Done { fmt.Fprintf(tw, "%d\t%s\tdone\n", t.id, t.Desc) } else { fmt.Fprintf(tw, "%d\t%s\tcreated %v\n", t.id, t.Desc, t.Created) } } tw.Flush() } func usage() { fmt.Print(`Usage: new <description> Adds a task with a description <description> done <task-id> Marks a task as done list Lists all tasks by creation time delete <task-id> Deletes a task `) } // parseCmd splits a line into a command and optional extra args. // n will be set if the extra args can be parsed as an int64. func parseCmd(line string) (cmd, args string, n int64) { if f := strings.Fields(line); len(f) > 0 { cmd = f[0] args = strings.Join(f[1:], " ") } if i, err := strconv.ParseInt(args, 10, 64); err == nil { n = i } return cmd, args, n }