-
Notifications
You must be signed in to change notification settings - Fork 1
/
mb.go
289 lines (241 loc) · 6.83 KB
/
mb.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
package main
import (
"fmt"
//"flag"
"os"
"time"
"path"
//"bufio"
"regexp"
"strconv"
"strings"
)
func baseExists() bool {
ok, err := os.UserHomeDir()
if err != nil {
return false
}
pathName := path.Join(ok, ".mubu")
if _, err := os.Stat(pathName); os.IsNotExist(err) {
return false
}
return true
}
func curExists() bool {
ok, err := os.Getwd()
if err != nil {
return false
}
pathName := path.Join(ok, ".mubu")
if _, err := os.Stat(pathName); os.IsNotExist(err) {
return false
}
return true
}
func makeBase() bool {
ok, err := os.UserHomeDir()
if err != nil {
return false
}
pathName := path.Join(ok, ".mubu")
if _, err := os.Stat(pathName); os.IsNotExist(err) {
if err := os.Mkdir(pathName, 0700); err != nil {
return false
}
return true
}
return true
}
func todayExists(useCur bool) bool {
pathName, err := getBasePath(useCur)
if err != nil {
return false
}
if _, err := os.Stat(pathName); os.IsNotExist(err) {
return false
}
return true
}
func makeToday(useCur bool) bool {
pathName, err := getBasePath(useCur)
if err != nil {
return false
}
if _, err := os.Stat(pathName); os.IsNotExist(err) {
// this is technically a vulnerability, because
// MkDirAll doesn't actually check each member
// of the path for existence, and it just returns
// nil if the path exists. I'm _roughly_ ok with
// this for our purposes here, but we may want to
// change this going forward
if err := os.MkdirAll(pathName, 0700); err != nil {
return false
}
return true
}
return true
}
func getBasePath(useCur bool) (string, error) {
var ok string
if useCur {
lok, err := os.Getwd()
if err != nil {
return lok, err
}
ok = lok
} else {
lok, err := os.UserHomeDir()
if err != nil {
return lok, err
}
ok = lok
}
t := time.Now()
// would be nice to make this work for other cases,
// like when we want to check if a specific day in
// the future exists
year := fmt.Sprintf("%d", t.Year())
month := fmt.Sprintf("%02d", t.Month())
day := fmt.Sprintf("%02d", t.Day())
pathName := path.Join(ok, ".mubu", year, month, day)
return pathName, nil
}
func getLatest(path string) (int, error) {
fd, err := os.Open(path)
if err != nil {
return -1, err
}
defer fd.Close()
files, err := fd.Readdir(-1)
if err != nil {
return -1, err
}
// sort the names, and return the latest one
res := -1
for _, file := range(files) {
if _, err := regexp.MatchString("^[0-9]+$", file.Name()); err == nil {
// the *one* time that strconv.Atoi isn't a problem
// because I actually want to compare on arch-non-specific
// integers
cur, err := strconv.Atoi(file.Name())
if err == nil && cur > res {
res = cur
}
}
}
return res + 1, nil
}
// there's no real reason why this can't be used
// for any type of addition; we just need to tell
// it what we're using it for...
func addNote(args []string, useCur bool) bool {
var msg string
pathName, err := getBasePath(useCur)
if err != nil {
return false
}
latestID, err := getLatest(pathName)
if err != nil {
return false
}
latest := path.Join(pathName, fmt.Sprintf("%d", latestID))
// if we have args, use those as the note
// otherwise, read the args from the console
if len(args) > 0 {
msg = fmt.Sprintf("- %s\n", strings.Join(args, " "))
} else {
// I meant to add this note to the initial commit
// but we really should use a scanner here...
buf := make([]byte, 8192)
fmt.Printf("- ")
_, err := os.Stdin.Read(buf)
if err != nil {
return false
}
msg = fmt.Sprintf("- %s\n", string(buf))
}
fd, err := os.Create(latest)
if err != nil {
return false
}
ret, err := fd.WriteString(msg)
if err != nil || ret != len(msg) {
return false
}
fd.Sync()
fd.Close()
// need to append the addition to the
// day's index
// alternatively, we don't use a single
// index file (which is probably better)
// and just read out of each of the little
// files we create...
return true
}
func main() {
var useCur bool
/*
* I could see the case for collapsing these, and just
* allowing all methods to operate off the user's specified
* directory, or some sort of defaults...
* Currently, we operate:
* - if there is a `.mubu` in `.`, use that
* - else, check if there is a `$HOME/.mubu`
* - make a base
*/
if curExists() {
fmt.Println("using local notes repository")
// operate out of the current directory first...
useCur = true
} else if baseExists() {
// operate out of base if none exist...
useCur = false
} else {
fmt.Println("no microbullet repository found")
useCur = false
}
if len(os.Args) < 2 {
if todayExists(useCur) {
fmt.Println("today does exist...")
} else {
fmt.Println("No tasks for notes for today...")
}
os.Exit(0)
}
switch os.Args[1] {
case "note", "n":
if makeToday(useCur) {
addNote(os.Args[2:], useCur)
} else {
fmt.Println("an error occurred adding today's repo...")
os.Exit(1)
}
case "entry", "e":
fmt.Println("adding a full entry...")
case "task", "t":
fmt.Println("adding a task...")
case "todo", "d":
fmt.Println("adding a todo...")
case "init", "i":
/*
* I'm definitely thinking some thoughts here...
* for one, I'd like it if we could organize multiple
* user's notes, like say in a github repo for an assessment.
* $PATH/.mubu/sedwards/...
* so, thoughts:
* - `-u` for single user, in $HOME/.mubu by default
* - `-m` for multi-user, in the specified path (defaults to ".")
*/
fmt.Println("initializing the repo")
case "header", "h":
fmt.Println("adding a header")
case "help", "H", "?":
fmt.Println("printing some help...")
case "code", "c":
fmt.Println("adding some code...")
case "view", "v":
fmt.Println("viewing some notes...")
default:
fmt.Println("invalid command...")
}
}