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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/bin/todo.rb +49 -45
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89f9cb1d9f24fe4077faebac43c8fe85041021f560a9cd812e67acace53441cc
4
- data.tar.gz: cddf8951cc9afbdea4ee6831f3c86fc5419a4f00582a2b1292007bba15b9cf13
3
+ metadata.gz: fc4e0e129e6dae5b09b233027e88344b5439b805a732a97c9162ea0cd57159d4
4
+ data.tar.gz: 3d521e8f11ccc2295bc32bc7bfdea49aca23c7b55023b19b8d90a8a0f002229a
5
5
  SHA512:
6
- metadata.gz: 9e90bb2be2db37e6bfdcee15f7953112bba1db7804562dd4ab697a033a7d38ec4cd495abb394320263ff2a76fb5ff23c0886eb8ae381959a170828a0d7d83d9f
7
- data.tar.gz: ab376c488d6a86676ee134154ef62e7c63f801d3002ef1df28ec2aee521f535730739ff4a13847dd0d77ad19bab0b6b36d5ce7732d6b317696e125293fa95d28
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 = "#{ENV['HOME']}/todo.jsonl"
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 exactly one parameter' if args.length != 1
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> delete all notes from task
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 regex patterns can be also used:
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 do |day| @today + day end
177
- @due_date_days = next_7_days.map do |day| day.strftime('%A').downcase end
178
- due_dates_for_queries = next_7_days.map do |day| day.strftime(DATE_FORMAT) end
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 do |task| /(new|started|blocked)/.match(task[:state]) end,
181
- ':done' => lambda do |task| 'done' == task[:state] end,
182
- ':blocked' => lambda do |task| 'blocked' == task[:state] end,
183
- ':started' => lambda do |task| 'started' == task[:state] end,
184
- ':new' => lambda do |task| 'new' == task[:state] end,
185
- ':all' => lambda do |task| /\w+/.match(task[:state]) end,
186
- ':today' => lambda do |task| due_dates_for_queries[0] == task[:due] end,
187
- ':tomorrow' => lambda do |task| due_dates_for_queries[1] == task[:due] end,
188
- ':next7days' => lambda do |task| /(#{due_dates_for_queries.join('|')})/.match(task[:due]) end
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 do |key|
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') do |file|
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
- [task[:priority] && task[:state] != 'done' ? 0 : 1, ORDER[task[:state] || 'default'], task[:due] || 'n/a', num]
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 |key, value|
346
- val = value.kind_of?(Array) ? "\n" + value.join("\n") : value
347
- puts "#{colorize(key.to_s.rjust(10, ' ') + ':', :cyan)} #{val}"
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 do |num| tasks.delete(num) end
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
- items = {}
375
- tasks.each do |num, task|
376
- match = patterns.uniq.all? do |pattern|
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 do |day| day[0..2] end.index(date.to_s.downcase)
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.1.33
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-18 00:00:00.000000000 Z
11
+ date: 2021-03-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: