todo-jsonl 0.1.33 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/todo.rb +49 -45
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc4e0e129e6dae5b09b233027e88344b5439b805a732a97c9162ea0cd57159d4
|
4
|
+
data.tar.gz: 3d521e8f11ccc2295bc32bc7bfdea49aca23c7b55023b19b8d90a8a0f002229a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75b546efb040d46254728b62a5d27962d9a96495a1c0295bc334580ac88beeaeb611359e04e881baa846de199684486850f96390b8efff2445e506375eab0bc0
|
7
|
+
data.tar.gz: c6115760b9b524d8624ccd8491119b289a5def26910c07b1cf5d295c91ad84e07a3dbb71ae6dc44dfa7fc838a666cac67dd922aa954b1660cb1a93a79611b7ab
|
data/bin/todo.rb
CHANGED
@@ -69,7 +69,7 @@ class Todo
|
|
69
69
|
DUE_DATE_TAG_PATTERN = /(^| )due:([a-zA-Z0-9-]+)/
|
70
70
|
CONTEXT_TAG_PATTERN = /(^| )[@+][\w-]+/
|
71
71
|
PRIORITY_FLAG = '*'
|
72
|
-
TODO_FILE =
|
72
|
+
TODO_FILE = File.join(Dir.home, 'todo.jsonl')
|
73
73
|
|
74
74
|
def execute(arguments)
|
75
75
|
begin
|
@@ -107,8 +107,8 @@ class Todo
|
|
107
107
|
raise action + ' command requires at least two parameters' if args.length < 2
|
108
108
|
add_note(args.first.to_i, args[1..-1].join(' '))
|
109
109
|
when 'delnote'
|
110
|
-
raise action + ' command requires
|
111
|
-
delete_note(args.first.to_i)
|
110
|
+
raise action + ' command requires one or two parameters' if args.length < 1 || args.length > 2
|
111
|
+
delete_note(args.first.to_i, args[1])
|
112
112
|
when 'list'
|
113
113
|
list(nil, args)
|
114
114
|
when 'show'
|
@@ -126,7 +126,7 @@ class Todo
|
|
126
126
|
else
|
127
127
|
list(nil, arguments)
|
128
128
|
end
|
129
|
-
rescue => error
|
129
|
+
rescue StandardError => error
|
130
130
|
puts "#{colorize('ERROR:', :red)} #{error}"
|
131
131
|
end
|
132
132
|
self
|
@@ -151,7 +151,7 @@ class Todo
|
|
151
151
|
* rename <tasknumber> <text> rename task
|
152
152
|
* del <tasknumber> delete task
|
153
153
|
* note <tasknumber> <text> add note to task
|
154
|
-
* delnote <tasknumber>
|
154
|
+
* delnote <tasknumber> [number] delete a specific or all notes from task
|
155
155
|
|
156
156
|
* list <regex> [regex...] list tasks (only active tasks by default)
|
157
157
|
* show <tasknumber> show all task details
|
@@ -159,13 +159,14 @@ class Todo
|
|
159
159
|
* cleanup <regex> [regex...] cleanup completed tasks by regex
|
160
160
|
* help this help screen
|
161
161
|
|
162
|
-
With list command the following pre-defined
|
163
|
-
#{@queries.keys.join(', ')}
|
162
|
+
With list command the following pre-defined queries can be also used:
|
163
|
+
#{@queries.keys.each_with_index.map { |k, i| (i == 8 ? "\n" : '') + k }.join(', ')}
|
164
164
|
|
165
165
|
Due dates can be also added via tags in task title: "due:YYYY-MM-DD"
|
166
|
+
In addition to formatted dates, you can use date synonyms:
|
167
|
+
"due:today", "due:tomorrow", and day names e.g. "due:monday" or "due:tue"
|
166
168
|
|
167
|
-
Legend:
|
168
|
-
#{STATES.select { |k, v| k != 'default' }.map { |k, v| "#{k} #{v}" }.join(', ') }, priority #{PRIORITY_FLAG}
|
169
|
+
Legend: #{STATES.select { |k, v| k != 'default' }.map { |k, v| "#{k} #{v}" }.join(', ') }, priority #{PRIORITY_FLAG}
|
169
170
|
|
170
171
|
Todo file: #{TODO_FILE}
|
171
172
|
USAGE
|
@@ -173,19 +174,23 @@ class Todo
|
|
173
174
|
|
174
175
|
def setup
|
175
176
|
@today = Date.today
|
176
|
-
next_7_days = (0..6).map
|
177
|
-
@due_date_days = next_7_days.map
|
178
|
-
due_dates_for_queries = next_7_days.map
|
177
|
+
next_7_days = (0..6).map { |day| @today + day }
|
178
|
+
@due_date_days = next_7_days.map { |day| day.strftime('%A').downcase }
|
179
|
+
due_dates_for_queries = next_7_days.map { |day| day.strftime(DATE_FORMAT) }
|
179
180
|
@queries = {
|
180
|
-
':active' => lambda
|
181
|
-
':done' => lambda
|
182
|
-
':blocked' => lambda
|
183
|
-
':started' => lambda
|
184
|
-
':new' => lambda
|
185
|
-
':all' => lambda
|
186
|
-
':
|
187
|
-
':
|
188
|
-
':
|
181
|
+
':active' => lambda { |task| /(new|started|blocked)/.match(task[:state]) },
|
182
|
+
':done' => lambda { |task| 'done' == task[:state] },
|
183
|
+
':blocked' => lambda { |task| 'blocked' == task[:state] },
|
184
|
+
':started' => lambda { |task| 'started' == task[:state] },
|
185
|
+
':new' => lambda { |task| 'new' == task[:state] },
|
186
|
+
':all' => lambda { |task| /\w+/.match(task[:state]) },
|
187
|
+
':priority' => lambda { |task| task[:priority] },
|
188
|
+
':note' => lambda { |task| task[:note] && !task[:note].empty? },
|
189
|
+
':today' => lambda { |task| due_dates_for_queries[0] == task[:due] },
|
190
|
+
':tomorrow' => lambda { |task| due_dates_for_queries[1] == task[:due] },
|
191
|
+
':next7days' => lambda { |task| /(#{due_dates_for_queries.join('|')})/.match(task[:due]) },
|
192
|
+
':overdue' => lambda { |task| task[:due] && task[:due] < due_dates_for_queries[0] },
|
193
|
+
':due' => lambda { |task| task[:due] }
|
189
194
|
}
|
190
195
|
end
|
191
196
|
|
@@ -207,9 +212,7 @@ class Todo
|
|
207
212
|
|
208
213
|
def write_tasks(tasks)
|
209
214
|
File.open(TODO_FILE, 'w:UTF-8') do |file|
|
210
|
-
tasks.keys.sort.each
|
211
|
-
file.write(JSON.generate(tasks[key]) + "\n")
|
212
|
-
end
|
215
|
+
tasks.keys.sort.each { |key| file.write(JSON.generate(tasks[key]) + "\n") }
|
213
216
|
end
|
214
217
|
end
|
215
218
|
|
@@ -223,15 +226,9 @@ class Todo
|
|
223
226
|
end
|
224
227
|
|
225
228
|
def add(text)
|
226
|
-
task = {
|
227
|
-
state: 'new',
|
228
|
-
title: text,
|
229
|
-
modified: @today.strftime(DATE_FORMAT)
|
230
|
-
}
|
229
|
+
task = { state: 'new', title: text, modified: @today.strftime(DATE_FORMAT) }
|
231
230
|
postprocess_tags(task)
|
232
|
-
File.open(TODO_FILE, 'a:UTF-8')
|
233
|
-
file.write(JSON.generate(task) + "\n")
|
234
|
-
end
|
231
|
+
File.open(TODO_FILE, 'a:UTF-8') { |file| file.write(JSON.generate(task) + "\n") }
|
235
232
|
list
|
236
233
|
end
|
237
234
|
|
@@ -301,7 +298,12 @@ class Todo
|
|
301
298
|
patterns ||= []
|
302
299
|
patterns += [':active'] if (patterns & [':active', ':done', ':blocked', ':started', ':new', ':all']).empty?
|
303
300
|
items = filter_tasks(tasks, patterns).sort_by do |num, task|
|
304
|
-
[
|
301
|
+
[
|
302
|
+
task[:priority] && task[:state] != 'done' ? 0 : 1,
|
303
|
+
ORDER[task[:state] || 'default'],
|
304
|
+
task[:state] != 'done' ? task[:due] || 'n/a' : task[:modified],
|
305
|
+
num
|
306
|
+
]
|
305
307
|
end
|
306
308
|
items.each do |num, task|
|
307
309
|
state = task[:state] || 'default'
|
@@ -334,17 +336,21 @@ class Todo
|
|
334
336
|
end)
|
335
337
|
end
|
336
338
|
|
337
|
-
def delete_note(item)
|
339
|
+
def delete_note(item, num = nil)
|
338
340
|
update_task(item, :show, lambda do |task|
|
339
|
-
task.delete(:note)
|
341
|
+
return task.delete(:note) if num.to_s.empty?
|
342
|
+
raise "#{num.to_i}: Note does not exist" if num.to_i <= 0 || task[:note].to_a.size < num.to_i
|
343
|
+
task[:note].delete_at(num.to_i - 1)
|
344
|
+
task.delete(:note) if task[:note].empty?
|
340
345
|
end)
|
341
346
|
end
|
342
347
|
|
343
348
|
def show(item, tasks = nil)
|
344
349
|
tasks ||= load_tasks(item)
|
345
|
-
tasks[item].each do |
|
346
|
-
|
347
|
-
|
350
|
+
tasks[item].each do |k, v|
|
351
|
+
v = "\n" + v.each_with_index.map { |n, i| "#{(i + 1).to_s.rjust(v.size.to_s.size, ' ')}: #{n}" }.
|
352
|
+
join("\n") if v.is_a?(Array)
|
353
|
+
puts "#{colorize(k.to_s.rjust(10, ' ') + ':', :cyan)} #{v}"
|
348
354
|
end
|
349
355
|
end
|
350
356
|
|
@@ -365,20 +371,18 @@ class Todo
|
|
365
371
|
tasks = load_tasks
|
366
372
|
patterns = [':done'] + patterns.to_a
|
367
373
|
items = filter_tasks(tasks, patterns)
|
368
|
-
items.each_key
|
374
|
+
items.each_key { |num| tasks.delete(num) }
|
369
375
|
write_tasks(tasks)
|
370
376
|
puts "Deleted #{items.size} todo(s)"
|
371
377
|
end
|
372
378
|
|
373
379
|
def filter_tasks(tasks, patterns)
|
374
|
-
|
375
|
-
tasks.
|
376
|
-
|
380
|
+
patterns = patterns.uniq
|
381
|
+
tasks.select do |num, task|
|
382
|
+
patterns.all? do |pattern|
|
377
383
|
@queries[pattern] ? @queries[pattern].call(task) : /#{pattern}/ix.match(task[:title])
|
378
384
|
end
|
379
|
-
items[num] = task if match
|
380
385
|
end
|
381
|
-
items
|
382
386
|
end
|
383
387
|
|
384
388
|
def colorize(text, color)
|
@@ -388,7 +392,7 @@ class Todo
|
|
388
392
|
def convert_due_date(date)
|
389
393
|
day_index = @due_date_days.index(date.to_s.downcase) ||
|
390
394
|
DUE_DATE_DAYS_SIMPLE.index(date.to_s.downcase) ||
|
391
|
-
@due_date_days.map
|
395
|
+
@due_date_days.map { |day| day[0..2] }.index(date.to_s.downcase)
|
392
396
|
return (@today + day_index).strftime(DATE_FORMAT) if day_index
|
393
397
|
date.nil? || date.empty? ? nil : Date.strptime(date, DATE_FORMAT).strftime(DATE_FORMAT)
|
394
398
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: todo-jsonl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabor Bata
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-03-
|
11
|
+
date: 2021-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|