todo-jsonl 0.1.31 → 1.0.2

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 +40 -44
  3. metadata +4 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ef8eba60ead95705dc2479f4f40fc9e25989b99b25a429de36c6703dca61196
4
- data.tar.gz: 9e161dd022343525a4d1e4fd94c214763edc9a57796f3955a510082acda95515
3
+ metadata.gz: 78bbcd37bbeabd3a2f73ebdd470bde3024755c6b3e7cddfe7fecb51290936c13
4
+ data.tar.gz: 26b2670e2d2dc589c8ecd2908e072b5df89db1673b50269a8766293f014a3a87
5
5
  SHA512:
6
- metadata.gz: ba7a785128d5f7fddac436e7d2b069f3b96f69fd8f37240e06f8b2382d113391cafaf64b9cb4a48ce0260ef305b292039a40f065c8ff0188509273cad01e79c3
7
- data.tar.gz: a7d648320d0ff43680a3f6707094749b8f2f117798aafb6c0a0b94a6e625ee48d4f747b79d531fb00fb7d701094141d6a5c4a814895f240ce9fa51a1acfa6a0a
6
+ metadata.gz: 283ea89c20cbd97f4e0684f13cf4b8d9e003209103c816079cdc31b66fad9f5600b76fe084dc8319e91156fd173120452dce9d2599724c79786ae8fb0d5fa144
7
+ data.tar.gz: '09ea2b77491b0718f7af5d89d0b219e1e45e833e7ec0c83c3cd03ee2e14bc1476bf652768e84ed6db8a6315dcf19664c18094f69009e6b4e2faa42936c25be15'
data/bin/todo.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # todo.rb - todo list manager inspired by todo.txt using the jsonl format.
3
+ # todo.rb - todo list manager on the command-line
4
+ # inspired by todo.txt using the jsonl format.
4
5
  #
5
6
  # Copyright (c) 2020-2021 Gabor Bata
6
7
  #
@@ -28,7 +29,6 @@ require 'json'
28
29
  require 'date'
29
30
 
30
31
  class Todo
31
-
32
32
  COLOR_CODES = {
33
33
  black: 30,
34
34
  red: 31,
@@ -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
@@ -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
@@ -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,20 +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
179
-
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) }
180
180
  @queries = {
181
- ':active' => lambda do |task| /(new|started|blocked)/.match(task[:state]) end,
182
- ':done' => lambda do |task| 'done' == task[:state] end,
183
- ':blocked' => lambda do |task| 'blocked' == task[:state] end,
184
- ':started' => lambda do |task| 'started' == task[:state] end,
185
- ':new' => lambda do |task| 'new' == task[:state] end,
186
- ':all' => lambda do |task| /\w+/.match(task[:state]) end,
187
- ':today' => lambda do |task| due_dates_for_queries[0] == task[:due] end,
188
- ':tomorrow' => lambda do |task| due_dates_for_queries[1] == task[:due] end,
189
- ':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] }
190
194
  }
191
195
  end
192
196
 
@@ -225,8 +229,8 @@ class Todo
225
229
 
226
230
  def add(text)
227
231
  task = {
228
- state: 'new',
229
- title: text,
232
+ state: 'new',
233
+ title: text,
230
234
  modified: @today.strftime(DATE_FORMAT)
231
235
  }
232
236
  postprocess_tags(task)
@@ -247,7 +251,7 @@ class Todo
247
251
  end
248
252
  end
249
253
 
250
- def append(item, text = '')
254
+ def append(item, text)
251
255
  update_task(item, :list, lambda do |task|
252
256
  task[:title] = [task[:title], text].join(' ')
253
257
  postprocess_tags(task)
@@ -297,9 +301,10 @@ class Todo
297
301
  end
298
302
 
299
303
  def list(tasks = nil, patterns = nil)
300
- tasks = tasks || load_tasks
304
+ tasks ||= load_tasks
301
305
  task_indent = [tasks.keys.max.to_s.size, 4].max
302
- patterns = patterns.nil? || patterns.empty? ? [':active'] : patterns
306
+ patterns ||= []
307
+ patterns += [':active'] if (patterns & [':active', ':done', ':blocked', ':started', ':new', ':all']).empty?
303
308
  items = filter_tasks(tasks, patterns).sort_by do |num, task|
304
309
  [task[:priority] && task[:state] != 'done' ? 0 : 1, ORDER[task[:state] || 'default'], task[:due] || 'n/a', num]
305
310
  end
@@ -341,7 +346,7 @@ class Todo
341
346
  end
342
347
 
343
348
  def show(item, tasks = nil)
344
- tasks = tasks || load_tasks(item)
349
+ tasks ||= load_tasks(item)
345
350
  tasks[item].each do |key, value|
346
351
  val = value.kind_of?(Array) ? "\n" + value.join("\n") : value
347
352
  puts "#{colorize(key.to_s.rjust(10, ' ') + ':', :cyan)} #{val}"
@@ -365,21 +370,18 @@ class Todo
365
370
  tasks = load_tasks
366
371
  patterns = [':done'] + patterns.to_a
367
372
  items = filter_tasks(tasks, patterns)
368
- items.keys.each do |num| tasks.delete(num) end
373
+ items.each_key { |num| tasks.delete(num) }
369
374
  write_tasks(tasks)
370
375
  puts "Deleted #{items.size} todo(s)"
371
376
  end
372
377
 
373
378
  def filter_tasks(tasks, patterns)
374
- items = {}
375
- tasks.each do |num, task|
376
- match = true
377
- patterns.each do |pattern|
378
- match = false unless @queries[pattern] ? @queries[pattern].call(task) : /#{pattern}/ix.match(task[:title])
379
+ patterns = patterns.uniq
380
+ tasks.select do |num, task|
381
+ patterns.all? do |pattern|
382
+ @queries[pattern] ? @queries[pattern].call(task) : /#{pattern}/ix.match(task[:title])
379
383
  end
380
- items[num] = task if match
381
384
  end
382
- return items
383
385
  end
384
386
 
385
387
  def colorize(text, color)
@@ -387,18 +389,12 @@ class Todo
387
389
  end
388
390
 
389
391
  def convert_due_date(date)
390
- due = nil
391
392
  day_index = @due_date_days.index(date.to_s.downcase) ||
392
393
  DUE_DATE_DAYS_SIMPLE.index(date.to_s.downcase) ||
393
- @due_date_days.map do |day| day[0..2] end.index(date.to_s.downcase)
394
- if day_index
395
- due = (@today + day_index).strftime(DATE_FORMAT)
396
- else
397
- due = date.nil? || date.empty? ? nil : Date.strptime(date, DATE_FORMAT).strftime(DATE_FORMAT)
398
- end
399
- return due
394
+ @due_date_days.map { |day| day[0..2] }.index(date.to_s.downcase)
395
+ return (@today + day_index).strftime(DATE_FORMAT) if day_index
396
+ date.nil? || date.empty? ? nil : Date.strptime(date, DATE_FORMAT).strftime(DATE_FORMAT)
400
397
  end
401
-
402
398
  end
403
399
 
404
400
  Todo.new.execute(ARGV)
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.31
4
+ version: 1.0.2
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-16 00:00:00.000000000 Z
11
+ date: 2021-03-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -42,5 +42,6 @@ requirements: []
42
42
  rubygems_version: 3.0.3
43
43
  signing_key:
44
44
  specification_version: 4
45
- summary: todo list manager inspired by todo.txt using the jsonl format
45
+ summary: todo list manager on the command-line inspired by todo.txt using the jsonl
46
+ format
46
47
  test_files: []