PatchHub
t

patchhub/tasks

A tiny to-do list for your terminal

1
Download

t Download tasks

Do you want to add some patches?

No patches yet. Create the first one.

Downloads with patches are built for you. It usually takes a minute or two.
tasks / main.go 2422 bytes · raw
1// tasks is a tiny to-do list for the terminal.
2//
3// tasks add Buy milk add a task
4// tasks list open tasks
5// tasks done 2 mark task 2 as done
6// tasks all list every task, including done ones
7// tasks clear remove done tasks
8package main
9
10import (
11 "encoding/json"
12 "fmt"
13 "os"
14 "path/filepath"
15 "strconv"
16 "strings"
17 "time"
18)
19
20type task struct {
21 Text string `json:"text"`
22 Done bool `json:"done"`
23 Created time.Time `json:"created"`
24}
25
26func file() string {
27 home, err := os.UserHomeDir()
28 if err != nil {
29 home = "."
30 }
31 return filepath.Join(home, ".tasks.json")
32}
33
34func load() []task {
35 var ts []task
36 if b, err := os.ReadFile(file()); err == nil {
37 json.Unmarshal(b, &ts)
38 }
39 return ts
40}
41
42func save(ts []task) {
43 b, _ := json.MarshalIndent(ts, "", " ")
44 if err := os.WriteFile(file(), b, 0o644); err != nil {
45 fmt.Fprintln(os.Stderr, "couldn't save tasks:", err)
46 os.Exit(1)
47 }
48}
49
50func list(ts []task, all bool) {
51 shown := 0
52 for i, t := range ts {
53 if t.Done && !all {
54 continue
55 }
56 box := "[ ]"
57 if t.Done {
58 box = "[x]"
59 }
60 fmt.Printf("%3d. %s %s\n", i+1, box, t.Text)
61 shown++
62 }
63 if shown == 0 {
64 fmt.Println("Nothing to do. Add a task with: tasks add <what to do>")
65 }
66}
67
68func main() {
69 ts := load()
70 args := os.Args[1:]
71 if len(args) == 0 {
72 list(ts, false)
73 return
74 }
75 switch args[0] {
76 case "add":
77 text := strings.TrimSpace(strings.Join(args[1:], " "))
78 if text == "" {
79 fmt.Println("What should the task say? Example: tasks add Call mom")
80 os.Exit(1)
81 }
82 ts = append(ts, task{Text: text, Created: time.Now()})
83 save(ts)
84 fmt.Printf("Added task %d: %s\n", len(ts), text)
85 case "done":
86 if len(args) < 2 {
87 fmt.Println("Which task? Example: tasks done 2")
88 os.Exit(1)
89 }
90 n, err := strconv.Atoi(args[1])
91 if err != nil || n < 1 || n > len(ts) {
92 fmt.Println("There's no task with that number.")
93 os.Exit(1)
94 }
95 ts[n-1].Done = true
96 save(ts)
97 fmt.Printf("Nice! Finished: %s\n", ts[n-1].Text)
98 case "all":
99 list(ts, true)
100 case "clear":
101 var open []task
102 for _, t := range ts {
103 if !t.Done {
104 open = append(open, t)
105 }
106 }
107 save(open)
108 fmt.Printf("Removed %d finished task(s).\n", len(ts)-len(open))
109 case "help", "-h", "--help":
110 fmt.Println("Usage: tasks [add <text> | done <number> | all | clear]")
111 default:
112 fmt.Println("Unknown command. Try: tasks help")
113 os.Exit(1)
114 }
115}