todo-jsonl 0.1.10 → 0.1.16
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 +59 -26
- 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: 6d359c12e487b44bf92a6406c044944c6aac14f4e1e45850b021c7184feb274d
|
4
|
+
data.tar.gz: 84b3b6d64e208e96cb81afbad8f6b07ca2f685a13178854fbd7792c5fde9062a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2eb6fb53e9ab1abd698a55995f7497de9e26f65787402d79afaaf62ca3c58a84cd79d363167d3001e02df0c0eb9a7e024fdd7be37c19d159833041686d6c85fc
|
7
|
+
data.tar.gz: 0edda1d28b4f76aa17bbf0b6c44e11025d433022bb9fef6d1ef1671de360ba841c77dd0c47400afe9f372a0a38c3c13b1a8b85a39de813e7c68fcd146b40ce5f
|
data/bin/todo.rb
CHANGED
@@ -69,6 +69,9 @@ DUE_DATE_DAYS = NEXT_7_DAYS.map do |day| day.strftime('%A').downcase end
|
|
69
69
|
DUE_DATES_FOR_QUERIES = NEXT_7_DAYS.map do |day| day.strftime(DATE_FORMAT) end
|
70
70
|
DUE_DATE_DAYS_SIMPLE = ['today', 'tomorrow']
|
71
71
|
|
72
|
+
DUE_DATE_TAG_PATTERN = /(^| )due:([a-zA-Z0-9-]+)/
|
73
|
+
CONTEXT_TAG_PATTERN = /(^| )[@+][\w-]+/
|
74
|
+
|
72
75
|
QUERIES = {
|
73
76
|
':active' => 'state=(new|started|blocked)',
|
74
77
|
':done' => 'state=done',
|
@@ -91,12 +94,12 @@ def usage
|
|
91
94
|
|
92
95
|
Commands:
|
93
96
|
* add <text> add new task
|
94
|
-
* start <tasknumber>
|
95
|
-
* done <tasknumber>
|
96
|
-
* block <tasknumber>
|
97
|
-
* reset <tasknumber>
|
98
|
-
* prio <tasknumber>
|
99
|
-
* due <tasknumber>
|
97
|
+
* start <tasknumber> [text] mark task as started, with optional note
|
98
|
+
* done <tasknumber> [text] mark task as completed, with optional note
|
99
|
+
* block <tasknumber> [text] mark task as blocked, with optional note
|
100
|
+
* reset <tasknumber> [text] reset task to new state, with optional note
|
101
|
+
* prio <tasknumber> [text] toggle high priority flag, with optional note
|
102
|
+
* due <tasknumber> [date] set/unset due date (in YYYY-MM-DD format)
|
100
103
|
|
101
104
|
* append <tasknumber> <text> append text to task title
|
102
105
|
* rename <tasknumber> <text> rename task
|
@@ -112,8 +115,12 @@ def usage
|
|
112
115
|
With list command the following pre-defined regex patterns can be also used:
|
113
116
|
#{QUERIES.keys.join(', ')}
|
114
117
|
|
118
|
+
Due dates can be also added via tags in task title: "due:YYYY-MM-DD"
|
119
|
+
|
115
120
|
Legend:
|
116
121
|
#{STATES.select { |k, v| k != 'default' }.map { |k, v| "#{k} #{v}" }.join(', ') }, priority #{PRIORITY_FLAG}
|
122
|
+
|
123
|
+
Todo file: #{TODO_FILE}
|
117
124
|
USAGE
|
118
125
|
end
|
119
126
|
|
@@ -143,12 +150,22 @@ def write_tasks(tasks)
|
|
143
150
|
end
|
144
151
|
end
|
145
152
|
|
153
|
+
def postprocess_tags(task)
|
154
|
+
match_data = task[:title].match(DUE_DATE_TAG_PATTERN)
|
155
|
+
if match_data
|
156
|
+
task[:title] = task[:title].gsub(DUE_DATE_TAG_PATTERN, '')
|
157
|
+
task[:due] = convert_due_date(match_data[2])
|
158
|
+
end
|
159
|
+
raise 'title must not be empty' if task[:title].empty?
|
160
|
+
end
|
161
|
+
|
146
162
|
def add(text)
|
147
163
|
task = {
|
148
164
|
state: 'new',
|
149
165
|
title: text,
|
150
166
|
modified: Time.now.strftime(DATE_FORMAT)
|
151
167
|
}
|
168
|
+
postprocess_tags(task)
|
152
169
|
File.open(TODO_FILE, 'a:UTF-8') do |file|
|
153
170
|
file.write(JSON.generate(task) + "\n")
|
154
171
|
end
|
@@ -159,6 +176,7 @@ def append(item, text = '')
|
|
159
176
|
tasks = load_tasks(item)
|
160
177
|
tasks[item][:title] = [tasks[item][:title], text].join(' ')
|
161
178
|
tasks[item][:modified] = Time.now.strftime(DATE_FORMAT)
|
179
|
+
postprocess_tags(tasks[item])
|
162
180
|
write_tasks(tasks)
|
163
181
|
list(tasks)
|
164
182
|
end
|
@@ -167,6 +185,7 @@ def rename(item, text)
|
|
167
185
|
tasks = load_tasks(item)
|
168
186
|
tasks[item][:title] = text
|
169
187
|
tasks[item][:modified] = Time.now.strftime(DATE_FORMAT)
|
188
|
+
postprocess_tags(tasks[item])
|
170
189
|
write_tasks(tasks)
|
171
190
|
list(tasks)
|
172
191
|
end
|
@@ -178,30 +197,33 @@ def delete(item)
|
|
178
197
|
list
|
179
198
|
end
|
180
199
|
|
181
|
-
def change_state(item, state)
|
200
|
+
def change_state(item, state, note = nil)
|
182
201
|
tasks = load_tasks(item)
|
183
202
|
tasks[item][:state] = state
|
184
203
|
tasks[item][:modified] = Time.now.strftime(DATE_FORMAT)
|
204
|
+
if !note.nil? && !note.empty?
|
205
|
+
tasks[item][:note] ||= []
|
206
|
+
tasks[item][:note].push(note)
|
207
|
+
end
|
185
208
|
write_tasks(tasks)
|
186
209
|
list(tasks)
|
187
210
|
end
|
188
211
|
|
189
|
-
def set_priority(item)
|
212
|
+
def set_priority(item, note = nil)
|
190
213
|
tasks = load_tasks(item)
|
191
214
|
tasks[item][:priority] = !tasks[item][:priority]
|
192
215
|
tasks[item][:modified] = Time.now.strftime(DATE_FORMAT)
|
216
|
+
if !note.nil? && !note.empty?
|
217
|
+
tasks[item][:note] ||= []
|
218
|
+
tasks[item][:note].push(note)
|
219
|
+
end
|
193
220
|
write_tasks(tasks)
|
194
221
|
list(tasks)
|
195
222
|
end
|
196
223
|
|
197
|
-
def due_date(item, date = '')
|
224
|
+
def due_date(item, date = '', task = nil)
|
198
225
|
tasks = load_tasks(item)
|
199
|
-
|
200
|
-
if day_index
|
201
|
-
tasks[item][:due] = (TODAY.to_date + day_index).strftime(DATE_FORMAT)
|
202
|
-
else
|
203
|
-
tasks[item][:due] = date.nil? || date.empty? ? nil : Date.parse(date).strftime(DATE_FORMAT)
|
204
|
-
end
|
226
|
+
tasks[item][:due] = convert_due_date(date)
|
205
227
|
tasks[item][:modified] = Time.now.strftime(DATE_FORMAT)
|
206
228
|
write_tasks(tasks)
|
207
229
|
list(tasks)
|
@@ -227,7 +249,9 @@ def list(tasks = nil, patterns = nil)
|
|
227
249
|
state = task[:state] || 'default'
|
228
250
|
color = COLORS[state]
|
229
251
|
display_state = colorize(STATES[state], color)
|
230
|
-
title = task[:title].gsub(
|
252
|
+
title = task[:title].gsub(CONTEXT_TAG_PATTERN) do |tag|
|
253
|
+
(tag.start_with?(' ') ? ' ' : '') + colorize(tag.strip, :cyan)
|
254
|
+
end
|
231
255
|
priority_flag = task[:priority] ? colorize(PRIORITY_FLAG, :red) : ' '
|
232
256
|
due_date = ''
|
233
257
|
if task[:due] && state != 'done'
|
@@ -288,6 +312,19 @@ def colorize(text, color)
|
|
288
312
|
"\e[#{COLOR_CODES[color]}m#{text}\e[0m"
|
289
313
|
end
|
290
314
|
|
315
|
+
def convert_due_date(date = '')
|
316
|
+
due = nil
|
317
|
+
day_index = DUE_DATE_DAYS.index(date.to_s.downcase) ||
|
318
|
+
DUE_DATE_DAYS_SIMPLE.index(date.to_s.downcase) ||
|
319
|
+
DUE_DATE_DAYS.map do |day| day[0..2] end.index(date.to_s.downcase)
|
320
|
+
if day_index
|
321
|
+
due = (TODAY.to_date + day_index).strftime(DATE_FORMAT)
|
322
|
+
else
|
323
|
+
due = date.nil? || date.empty? ? nil : Date.parse(date).strftime(DATE_FORMAT)
|
324
|
+
end
|
325
|
+
return due
|
326
|
+
end
|
327
|
+
|
291
328
|
def read(arguments)
|
292
329
|
begin
|
293
330
|
action = arguments.first
|
@@ -297,20 +334,16 @@ def read(arguments)
|
|
297
334
|
raise action + ' command requires at least one parameter' if args.nil? || args.empty?
|
298
335
|
add(args.join(' '))
|
299
336
|
when 'start'
|
300
|
-
|
301
|
-
args.length == 1 ? change_state(args.first.to_i, 'started') : list(nil, [':started'])
|
337
|
+
args.length > 0 ? change_state(args.first.to_i, 'started', (args[1..-1] || []).join(' ')) : list(nil, [':started'])
|
302
338
|
when 'done'
|
303
|
-
|
304
|
-
args.length == 1 ? change_state(args.first.to_i, 'done') : list(nil, [':done'])
|
339
|
+
args.length > 0 ? change_state(args.first.to_i, 'done', (args[1..-1] || []).join(' ')) : list(nil, [':done'])
|
305
340
|
when 'block'
|
306
|
-
|
307
|
-
args.length == 1 ? change_state(args.first.to_i, 'blocked') : list(nil, [':blocked'])
|
341
|
+
args.length > 0 ? change_state(args.first.to_i, 'blocked', (args[1..-1] || []).join(' ')) : list(nil, [':blocked'])
|
308
342
|
when 'reset'
|
309
|
-
|
310
|
-
args.length == 1 ? change_state(args.first.to_i, 'new') : list(nil, [':new'])
|
343
|
+
args.length > 0 ? change_state(args.first.to_i, 'new', (args[1..-1] || []).join(' ')) : list(nil, [':new'])
|
311
344
|
when 'prio'
|
312
|
-
raise action + ' command requires
|
313
|
-
set_priority(args.first.to_i)
|
345
|
+
raise action + ' command requires at least one parameter' if args.length < 1
|
346
|
+
set_priority(args.first.to_i, (args[1..-1] || []).join(' '))
|
314
347
|
when 'due'
|
315
348
|
raise action + ' command requires at least one parameter' if args.length < 1
|
316
349
|
due_date(args.first.to_i, (args[1..-1] || []).join(' '))
|
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.
|
4
|
+
version: 0.1.16
|
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-
|
11
|
+
date: 2021-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|