doing 1.0.49 → 1.0.54
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -3
- data/bin/doing +180 -160
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +87 -37
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f1fda3219bcf3e27c6816ff77efe53b168d4c2ecf5d8c17653fd4dc6f95a1dd
|
4
|
+
data.tar.gz: 17a4dc1ea548c201e22335d0055fd383f6ceac611c2f0d71f1ae5900e7cd1087
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2fb4ddc3f092a01134e157e84ea86ce44b5be6714c074b17bed647b8b1341fa43a5514311cfd387e662a744d307a624a57ec242caa3e651d57dc6875e572b08
|
7
|
+
data.tar.gz: f7e2eb609ce0eda0e2ca51205609b77cc44bf7c3d6dc12f25eb5bb8f06c50322d8d89d789998509d542dd7a90b3b29e1d3c82f5e021cf501850666ccc45243d0
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
**A command line tool for remembering what you were doing and tracking what you've done.**
|
4
4
|
|
5
|
-
_If you're one of the rare people like me who find this useful, feel free to [buy me some coffee](http://brettterpstra.com/donate)._
|
5
|
+
_If you're one of the rare people like me who find this useful, feel free to [buy me some coffee](http://brettterpstra.com/donate/)._
|
6
6
|
|
7
7
|
|
8
8
|
## Contents
|
@@ -17,6 +17,7 @@ _If you're one of the rare people like me who find this useful, feel free to [bu
|
|
17
17
|
- [Changelog](#changelog)
|
18
18
|
|
19
19
|
<!-- end toc -->
|
20
|
+
<!--README-->
|
20
21
|
|
21
22
|
## What and why
|
22
23
|
|
@@ -413,6 +414,8 @@ When used with `doing done`, `--back` and `--took` allow time intervals to be ac
|
|
413
414
|
|
414
415
|
All of these commands accept a `-e` argument. This opens your command line editor (as defined in the environment variable `$EDITOR`). Add your entry, save the temp file, and close it. The new entry is added. Anything after the first line is included as a note on the entry.
|
415
416
|
|
417
|
+
`doing again` (or `doing resume`) will duplicate the last @done entry (most recently completed) with a new start date (and without the @done tag). To resume the last entry matching specific tags, use `--tag=TAG`. You can specify multiple tags by separating with a comma. Multiple tags are combined with 'AND' by default (all tags must exist on the entry to match), but you can use `--bool=` to set it to 'OR' or 'NOT'. By default the new entry will be added to the same section as the matching entry, but you can specify a section with `--in=SECTION`.
|
418
|
+
|
416
419
|
`doing meanwhile` is a special command for creating and finishing tasks that may have other entries come before they're complete. When you create an entry with `doing meanwhile [entry text]`, it will automatically complete the last _@meanwhile_ item (dated _@done_ tag) and add the _@meanwhile_ tag to the new item. This allows time tracking on a more general basis, and still lets you keep track of the smaller things you do while working on an overarching project. The `meanwhile` command accepts `--back [time]` and will backdate the _@done_ tag and start date of the new task at the same time. Running `meanwhile` with no arguments will simply complete the last _@meanwhile_ task.
|
417
420
|
|
418
421
|
See `doing help meanwhile` for more options.
|
@@ -420,6 +423,7 @@ See `doing help meanwhile` for more options.
|
|
420
423
|
#### Modifying entries:
|
421
424
|
|
422
425
|
finish - Mark last X entries as @done
|
426
|
+
cancel - Mark last X entries as @done without completion date
|
423
427
|
tag - Tag last entry
|
424
428
|
note - Add a note to the last entry
|
425
429
|
|
@@ -431,6 +435,16 @@ See `doing help meanwhile` for more options.
|
|
431
435
|
|
432
436
|
As mentioned above, `finish` also accepts `--back "2 hours"` (sets the finish date from time now minus interval) or `--took 30m` (sets the finish date to time started plus interval) so you can accurately add times to completed tasks, even if you don't do it in the moment.
|
433
437
|
|
438
|
+
Both `done` and `finish` accept an `--archive` switch which immediately moves the completed entries to the Archive section with a `@from(Project)` tag.
|
439
|
+
|
440
|
+
You can finish the last entry containing a specific tag or combination of tags using the `--tag` flag. Multiple tags are separated by commas. By default tags are combined with an AND boolean, meaning the entry must contain all specified tags to be considered. For example, to finish the last entry containing both "@work" and "@project1", you would use:
|
441
|
+
|
442
|
+
doing finish --tag=work,project1
|
443
|
+
|
444
|
+
You can change the boolean using `--bool=OR` (last entry containing any of the specified tags) or `--bool=NOT` (last entry containing none of the tags).
|
445
|
+
|
446
|
+
You can also include a `--no-date` switch to add `@done` without a finish date, meaning no time is tracked for the task. `doing cancel` is an alias for this. Like `finish`, `cancel` accepts a count to act on the last X entries, as well as `--archive` and `--section` options. `cancel` also accepts the `--tag` and `--bool` flags for tag filtering.
|
447
|
+
|
434
448
|
|
435
449
|
##### Tagging and Autotagging
|
436
450
|
|
@@ -565,11 +579,16 @@ __Fish:__ See the file [`doing.fish`](https://github.com/ttscoff/doing/blob/mast
|
|
565
579
|
|
566
580
|
The LaunchBar action requires that `doing` be available in `/usr/local/bin/doing`. If it's not (because you're using RVM or similar), you'll need to symlink it there. Running the action with Return will show the latest 9 items from Currently, along with any time intervals recorded, and includes a submenu of Timers for each tag.
|
567
581
|
|
568
|
-
Pressing Spacebar and typing allows you to add a new entry to currently. You an also trigger a custom show command by typing "show [section/tag]" and hitting return.
|
582
|
+
Pressing Spacebar and typing allows you to add a new entry to currently. You an also trigger a custom show command by typing "show [section/tag]" and hitting return. Include any command line flags at the end of the string, and if you add text in parenthesis, it will be processed as a note on the entry.
|
569
583
|
|
570
584
|
Point of interest, the LaunchBar Action makes use of the `-o json` flag for outputting JSON to the action's script for parsing.
|
571
585
|
|
586
|
+
<!--GITHUB-->
|
572
587
|
See <https://brettterpstra.com/projects/doing/> for the download.
|
588
|
+
<!--JEKYLL
|
589
|
+
{% download 117 %}
|
590
|
+
-->
|
591
|
+
<!--END GITHUB-->
|
573
592
|
|
574
593
|
Evan Lovely has [created an Alfred workflow as well](http://www.evanlovely.com/blog/technology/alfred-for-terpstras-doing/).
|
575
594
|
|
@@ -610,7 +629,9 @@ Please try not to email me directly about GitHub projects.
|
|
610
629
|
|
611
630
|
Feel free to [poke around](http://github.com/ttscoff/doing/), I'll try to add more comments in the future (and retroactively).
|
612
631
|
|
613
|
-
|
632
|
+
<!--END README-->
|
633
|
+
|
634
|
+
PayPal link: [paypal.me/ttscoff](https://paypal.me/ttscoff)
|
614
635
|
|
615
636
|
## Changelog
|
616
637
|
|
data/bin/doing
CHANGED
@@ -36,23 +36,20 @@ default_command :recent
|
|
36
36
|
# sort_help :manually
|
37
37
|
|
38
38
|
desc 'Output notes if included in the template'
|
39
|
-
default_value true
|
40
|
-
switch [:notes], :default_value => true, :negatable => true
|
39
|
+
switch [:notes], default_value: true, negatable: true
|
41
40
|
|
42
41
|
desc 'Send results report to STDOUT instead of STDERR'
|
43
|
-
default_value false
|
44
|
-
switch [:stdout], :default_value => false, :negatable => false
|
42
|
+
switch [:stdout], default_value: false, negatable: false
|
45
43
|
|
46
44
|
desc 'Exclude auto tags and default tags'
|
47
|
-
switch [:x, :noauto], :
|
45
|
+
switch [:x, :noauto], default_value: false
|
48
46
|
|
49
47
|
desc 'Use a specific configuration file'
|
50
|
-
default_value false
|
51
48
|
flag [:config_file]
|
52
49
|
|
53
50
|
|
54
51
|
# desc 'Wrap notes at X chars (0 for no wrap)'
|
55
|
-
# flag [:w, :wrapwidth], :
|
52
|
+
# flag [:w, :wrapwidth], must_match: /^\d+$/, type: Integer
|
56
53
|
|
57
54
|
desc 'Specify a different doing_file'
|
58
55
|
flag [:f, :doing_file]
|
@@ -62,8 +59,7 @@ arg_name 'entry'
|
|
62
59
|
command [:now, :next] do |c|
|
63
60
|
c.desc 'Section'
|
64
61
|
c.arg_name 'section_name'
|
65
|
-
c.default_value wwid.current_section
|
66
|
-
c.flag [:s, :section], :default_value => wwid.current_section
|
62
|
+
c.flag [:s, :section], default_value: wwid.current_section
|
67
63
|
|
68
64
|
c.desc "Edit entry with #{ENV['EDITOR']}"
|
69
65
|
c.switch [:e, :editor]
|
@@ -72,8 +68,7 @@ command [:now, :next] do |c|
|
|
72
68
|
c.flag [:b, :back]
|
73
69
|
|
74
70
|
c.desc 'Timed entry, marks last entry in section as @done'
|
75
|
-
c.default_value false
|
76
|
-
c.switch [:f, :finish_last], :negatable => false, :default_value => false
|
71
|
+
c.switch [:f, :finish_last], negatable: false, default_value: false
|
77
72
|
|
78
73
|
c.desc 'Note'
|
79
74
|
c.arg_name 'note_text'
|
@@ -81,8 +76,7 @@ command [:now, :next] do |c|
|
|
81
76
|
|
82
77
|
# c.desc "Edit entry with specified app"
|
83
78
|
# c.arg_name 'editor_app'
|
84
|
-
# c.
|
85
|
-
# c.flag [:a, :app]
|
79
|
+
# # c.flag [:a, :app]
|
86
80
|
|
87
81
|
c.action do |global_options,options,args|
|
88
82
|
if options[:back]
|
@@ -103,7 +97,7 @@ command [:now, :next] do |c|
|
|
103
97
|
if input
|
104
98
|
title, note = wwid.format_input(input)
|
105
99
|
note.push(options[:n]) if options[:n]
|
106
|
-
wwid.add_item(title.cap_first, section, {:
|
100
|
+
wwid.add_item(title.cap_first, section, {note: note, back: date, timed: options[:f]})
|
107
101
|
wwid.write(wwid.doing_file)
|
108
102
|
else
|
109
103
|
raise "No content"
|
@@ -112,12 +106,12 @@ command [:now, :next] do |c|
|
|
112
106
|
if args.length > 0
|
113
107
|
title, note = wwid.format_input(args.join(" "))
|
114
108
|
note.push(options[:n]) if options[:n]
|
115
|
-
wwid.add_item(title.cap_first, section, {:
|
109
|
+
wwid.add_item(title.cap_first, section, {note: note, back: date, timed: options[:f]})
|
116
110
|
wwid.write(wwid.doing_file)
|
117
111
|
elsif STDIN.stat.size > 0
|
118
112
|
title, note = wwid.format_input(STDIN.read)
|
119
113
|
note.push(options[:n]) if options[:n]
|
120
|
-
wwid.add_item(title.cap_first, section, {:
|
114
|
+
wwid.add_item(title.cap_first, section, {note: note, back: date, timed: options[:f]})
|
121
115
|
wwid.write(wwid.doing_file)
|
122
116
|
else
|
123
117
|
raise "You must provide content when creating a new entry"
|
@@ -136,14 +130,13 @@ arg_name 'note_text'
|
|
136
130
|
command :note do |c|
|
137
131
|
c.desc 'Section'
|
138
132
|
c.arg_name 'section_name'
|
139
|
-
c.default_value
|
140
|
-
c.flag [:s, :section], :default_value => "All"
|
133
|
+
c.flag [:s, :section], default_value: "All"
|
141
134
|
|
142
135
|
c.desc "Edit entry with #{ENV['EDITOR']}"
|
143
|
-
c.switch [:e, :editor], :
|
136
|
+
c.switch [:e, :editor], negatable: false, default_value: false
|
144
137
|
|
145
138
|
c.desc "Replace/Remove last entry's note (default append)"
|
146
|
-
c.switch [:r, :remove], :
|
139
|
+
c.switch [:r, :remove], negatable: false, default_value: false
|
147
140
|
|
148
141
|
c.action do |global_options,options,args|
|
149
142
|
section = wwid.guess_section(options[:s]) || options[:s].cap_first
|
@@ -196,14 +189,13 @@ arg_name 'entry'
|
|
196
189
|
command :meanwhile do |c|
|
197
190
|
c.desc 'Section'
|
198
191
|
c.arg_name 'section_name'
|
199
|
-
c.default_value wwid.current_section
|
200
|
-
c.flag [:s, :section], :default_value => wwid.current_section
|
192
|
+
c.flag [:s, :section], default_value: wwid.current_section
|
201
193
|
|
202
194
|
c.desc "Edit entry with #{ENV['EDITOR']}"
|
203
195
|
c.switch [:e, :editor]
|
204
196
|
|
205
197
|
c.desc "Archive previous @meanwhile entry"
|
206
|
-
c.switch [:a, :archive], :
|
198
|
+
c.switch [:a, :archive], default_value: false
|
207
199
|
|
208
200
|
c.desc 'Backdate start date for new entry to date string [4pm|20m|2h|yesterday noon]'
|
209
201
|
c.flag [:b, :back]
|
@@ -238,7 +230,7 @@ command :meanwhile do |c|
|
|
238
230
|
input = false unless input && input.length > 0
|
239
231
|
|
240
232
|
note = options[:n] ? options[:n] : false
|
241
|
-
wwid.stop_start(
|
233
|
+
wwid.stop_start('meanwhile', {new_item: input, back: date, section: section, archive: options[:a], note: note})
|
242
234
|
wwid.write(wwid.doing_file)
|
243
235
|
end
|
244
236
|
end
|
@@ -276,7 +268,6 @@ command :later do |c|
|
|
276
268
|
|
277
269
|
c.desc "Edit entry with specified app"
|
278
270
|
c.arg_name 'editor_app'
|
279
|
-
c.default_value wwid.config.has_key?('editor_app') && wwid.config['editor_app'] ? wwid.config['editor_app'] : false
|
280
271
|
c.flag [:a, :app]
|
281
272
|
|
282
273
|
c.desc 'Backdate start time to date string [4pm|20m|2h|yesterday noon]'
|
@@ -302,7 +293,7 @@ command :later do |c|
|
|
302
293
|
if input
|
303
294
|
title, note = wwid.format_input(input)
|
304
295
|
note.push(options[:n]) if options[:n]
|
305
|
-
wwid.add_item(title.cap_first, "Later", {:
|
296
|
+
wwid.add_item(title.cap_first, "Later", {note: note, back: date})
|
306
297
|
wwid.write(wwid.doing_file)
|
307
298
|
else
|
308
299
|
raise "No content"
|
@@ -311,12 +302,12 @@ command :later do |c|
|
|
311
302
|
if args.length > 0
|
312
303
|
title, note = wwid.format_input(args.join(" "))
|
313
304
|
note.push(options[:n]) if options[:n]
|
314
|
-
wwid.add_item(title.cap_first, "Later", {:
|
305
|
+
wwid.add_item(title.cap_first, "Later", {note: note, back: date})
|
315
306
|
wwid.write(wwid.doing_file)
|
316
307
|
elsif STDIN.stat.size > 0
|
317
308
|
title, note = wwid.format_input(STDIN.read)
|
318
309
|
note.push(options[:n]) if options[:n]
|
319
|
-
wwid.add_item(title.cap_first, "Later", {:
|
310
|
+
wwid.add_item(title.cap_first, "Later", {note: note, back: date})
|
320
311
|
wwid.write(wwid.doing_file)
|
321
312
|
else
|
322
313
|
raise "You must provide content when creating a new entry"
|
@@ -329,16 +320,13 @@ desc 'Add a completed item with @done(date). No argument finishes last entry.'
|
|
329
320
|
arg_name 'entry'
|
330
321
|
command [:done, :did] do |c|
|
331
322
|
c.desc 'Remove @done tag'
|
332
|
-
c.default_value false
|
333
|
-
c.switch [:r, :remove], :negatable => false, :default_value => false
|
323
|
+
c.switch [:r, :remove], negatable: false, default_value: false
|
334
324
|
|
335
325
|
c.desc 'Include date'
|
336
|
-
c.default_value true
|
337
|
-
c.switch [:date], :negatable => true, :default_value => true
|
326
|
+
c.switch [:date], negatable: true, default_value: true
|
338
327
|
|
339
328
|
c.desc 'Immediately archive the entry'
|
340
|
-
c.default_value false
|
341
|
-
c.switch [:a, :archive], :negatable => false, :default_value => false
|
329
|
+
c.switch [:a, :archive], negatable: false, default_value: false
|
342
330
|
|
343
331
|
c.desc 'Set finish date to specific date/time (natural langauge parsed, e.g. --at=1:30pm). If used, ignores --back. Used with --took, backdates start date'
|
344
332
|
c.flag [:at]
|
@@ -350,16 +338,14 @@ command [:done, :did] do |c|
|
|
350
338
|
c.flag [:t, :took]
|
351
339
|
|
352
340
|
c.desc 'Section'
|
353
|
-
c.default_value wwid.current_section
|
354
|
-
c.flag [:s, :section], :default_value => wwid.current_section
|
341
|
+
c.flag [:s, :section], default_value: wwid.current_section
|
355
342
|
|
356
343
|
c.desc "Edit entry with #{ENV['EDITOR']}"
|
357
344
|
c.switch [:e, :editor]
|
358
345
|
|
359
346
|
# c.desc "Edit entry with specified app"
|
360
347
|
# c.arg_name 'editor_app'
|
361
|
-
# c.
|
362
|
-
# c.flag [:a, :app]
|
348
|
+
# # c.flag [:a, :app]
|
363
349
|
|
364
350
|
c.action do |global_options,options,args|
|
365
351
|
took = 0
|
@@ -390,7 +376,7 @@ command [:done, :did] do |c|
|
|
390
376
|
end
|
391
377
|
|
392
378
|
section = wwid.guess_section(options[:s]) || options[:s].cap_first
|
393
|
-
donedate = options[:
|
379
|
+
donedate = options[:date] ? "(#{finish_date.strftime('%F %R')})" : ""
|
394
380
|
|
395
381
|
if options[:e]
|
396
382
|
raise "No EDITOR variable defined in environment" if ENV['EDITOR'].nil?
|
@@ -401,16 +387,16 @@ command [:done, :did] do |c|
|
|
401
387
|
title, note = wwid.format_input(input)
|
402
388
|
title += " @done#{donedate}"
|
403
389
|
section = "Archive" if options[:a]
|
404
|
-
wwid.add_item(title.cap_first, section.cap_first, {:
|
390
|
+
wwid.add_item(title.cap_first, section.cap_first, {note: note, back: date})
|
405
391
|
wwid.write(wwid.doing_file)
|
406
392
|
else
|
407
393
|
raise "No content"
|
408
394
|
end
|
409
395
|
elsif args.length == 0 && STDIN.stat.size == 0
|
410
396
|
if options[:r]
|
411
|
-
wwid.tag_last({:
|
397
|
+
wwid.tag_last({tags: ["done"], count: 1, section: section, remove: true })
|
412
398
|
else
|
413
|
-
wwid.tag_last({:
|
399
|
+
wwid.tag_last({tags: ["done"], count: 1, section: section, archive: options[:a], back: finish_date, date: options[:date]})
|
414
400
|
end
|
415
401
|
else
|
416
402
|
if args.length > 0
|
@@ -418,13 +404,13 @@ command [:done, :did] do |c|
|
|
418
404
|
title.chomp!
|
419
405
|
title += " @done#{donedate}"
|
420
406
|
section = "Archive" if options[:a]
|
421
|
-
wwid.add_item(title.cap_first, section.cap_first, {:
|
407
|
+
wwid.add_item(title.cap_first, section.cap_first, {note: note, back: date})
|
422
408
|
wwid.write(wwid.doing_file)
|
423
409
|
elsif STDIN.stat.size > 0
|
424
410
|
title, note = wwid.format_input(STDIN.read)
|
425
411
|
title += " @done#{donedate}"
|
426
412
|
section = options[:a] ? "Archive" : section
|
427
|
-
wwid.add_item(title.cap_first, section.cap_first, {:
|
413
|
+
wwid.add_item(title.cap_first, section.cap_first, {note: note, back: date})
|
428
414
|
wwid.write(wwid.doing_file)
|
429
415
|
else
|
430
416
|
raise "You must provide content when creating a new entry"
|
@@ -433,12 +419,51 @@ command [:done, :did] do |c|
|
|
433
419
|
end
|
434
420
|
end
|
435
421
|
|
422
|
+
desc 'End last X entries with no time tracked'
|
423
|
+
long_desc 'Adds @done tag without datestamp so no elapsed time is recorded. Alias for `doing finish --no-date`.'
|
424
|
+
arg_name 'count'
|
425
|
+
command :cancel do |c|
|
426
|
+
c.desc 'Archive entries'
|
427
|
+
c.switch [:a, :archive], negatable: false, default_value: false
|
428
|
+
|
429
|
+
c.desc 'Section'
|
430
|
+
c.flag [:s, :section], default_value: wwid.current_section
|
431
|
+
|
432
|
+
c.desc 'Cancel the last X entries containing TAG. Separate multiple tags with comma (--tag=tag2,tag2)'
|
433
|
+
c.flag [:tag]
|
434
|
+
|
435
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
436
|
+
c.flag [:bool], must_match: /^(and|or|not)$/i, default_value: 'AND'
|
437
|
+
|
438
|
+
|
439
|
+
c.action do |global_options,options,args|
|
440
|
+
|
441
|
+
section = wwid.guess_section(options[:s]) || options[:s].cap_first
|
442
|
+
|
443
|
+
if options[:tag].nil?
|
444
|
+
tags = []
|
445
|
+
else
|
446
|
+
tags = options[:tag].split(/ *, */).map {|t| t.strip.sub(/^@/, '') }
|
447
|
+
options[:bool] = options[:bool] =~ /^(and|or|not)$/i ? options[:bool].upcase : 'AND'
|
448
|
+
end
|
449
|
+
|
450
|
+
if args.length > 1
|
451
|
+
raise "Only one argument allowed"
|
452
|
+
elsif args.length == 0 || args[0] =~ /\d+/
|
453
|
+
count = args[0] ? args[0].to_i : 1
|
454
|
+
wwid.tag_last({tags: ["done"], count: count, section: section, archive: options[:a], sequential: false, date: false, tag: tags, tag_bool: options[:bool] })
|
455
|
+
else
|
456
|
+
raise "Invalid argument (specify number of recent items to mark @done)"
|
457
|
+
end
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
436
461
|
desc 'Mark last X entries as @done'
|
437
462
|
long_desc 'Marks the last X entries with a @done tag and current date. Does not alter already completed entries.'
|
438
463
|
arg_name 'count'
|
439
464
|
command :finish do |c|
|
440
465
|
c.desc 'Include date'
|
441
|
-
c.switch [:date], :
|
466
|
+
c.switch [:date], negatable: true, default_value: true
|
442
467
|
|
443
468
|
c.desc 'Backdate completed date to date string [4pm|20m|2h|yesterday noon]'
|
444
469
|
c.flag [:b, :back]
|
@@ -446,17 +471,20 @@ command :finish do |c|
|
|
446
471
|
c.desc 'Set the completed date to the start date plus XX[hmd]'
|
447
472
|
c.flag [:t, :took]
|
448
473
|
|
474
|
+
c.desc 'Finish the last X entries containing TAG. Separate multiple tags with comma (--tag=tag2,tag2)'
|
475
|
+
c.flag [:tag]
|
476
|
+
|
477
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
478
|
+
c.flag [:bool], must_match: /^(and|or|not)$/i, default_value: 'AND'
|
479
|
+
|
449
480
|
c.desc 'Auto-generate finish dates from next entry\'s start time. Automatically generate completion dates 1 minute before next start date. --auto overrides the --date and --back parameters.'
|
450
|
-
c.default_value false
|
451
|
-
c.switch [:auto], :negatable => false, :default_value => false
|
481
|
+
c.switch [:auto], negatable: false, default_value: false
|
452
482
|
|
453
483
|
c.desc 'Archive entries'
|
454
|
-
c.default_value false
|
455
|
-
c.switch [:a, :archive], :negatable => false, :default_value => false
|
484
|
+
c.switch [:a, :archive], negatable: false, default_value: false
|
456
485
|
|
457
486
|
c.desc 'Section'
|
458
|
-
c.default_value wwid.current_section
|
459
|
-
c.flag [:s, :section], :default_value => wwid.current_section
|
487
|
+
c.flag [:s, :section], default_value: wwid.current_section
|
460
488
|
|
461
489
|
c.action do |global_options,options,args|
|
462
490
|
|
@@ -476,11 +504,18 @@ command :finish do |c|
|
|
476
504
|
end
|
477
505
|
end
|
478
506
|
|
507
|
+
if options[:tag].nil?
|
508
|
+
tags = []
|
509
|
+
else
|
510
|
+
tags = options[:tag].split(/ *, */).map {|t| t.strip.sub(/^@/, '') }
|
511
|
+
options[:bool] = options[:bool] =~ /^(and|or|not)$/i ? options[:bool].upcase : 'AND'
|
512
|
+
end
|
513
|
+
|
479
514
|
if args.length > 1
|
480
515
|
raise "Only one argument allowed"
|
481
516
|
elsif args.length == 0 || args[0] =~ /\d+/
|
482
517
|
count = args[0] ? args[0].to_i : 1
|
483
|
-
wwid.tag_last({:
|
518
|
+
wwid.tag_last({ tags: ["done"],count: count,section: section,archive: options[:a],sequential: options[:auto],date: options[:date], back: date, tag: options[:tag], tag_bool: options[:bool] })
|
484
519
|
else
|
485
520
|
raise "Invalid argument (specify number of recent items to mark @done)"
|
486
521
|
end
|
@@ -491,14 +526,24 @@ desc 'Repeat last entry as new entry'
|
|
491
526
|
arg_name 'section'
|
492
527
|
command [:again, :resume] do |c|
|
493
528
|
c.desc 'Section'
|
494
|
-
c.flag [:s, :section], :
|
529
|
+
c.flag [:s, :section], default_value: "All"
|
530
|
+
|
531
|
+
c.desc 'Add new entry to section (default: same section as repeated entry)'
|
532
|
+
c.flag [:in]
|
533
|
+
|
534
|
+
c.desc 'Repeat last entry matching tags. Combine multiple tags with a comma.'
|
535
|
+
c.flag [:tag]
|
536
|
+
|
537
|
+
c.desc 'Boolean used to combine multiple tags'
|
538
|
+
c.flag [:bool], must_match: /^(and|or|not)$/i, default_value: 'ALL'
|
495
539
|
|
496
540
|
c.desc 'Note'
|
497
541
|
c.arg_name 'note_text'
|
498
542
|
c.flag [:n, :note]
|
499
543
|
|
500
544
|
c.action do |global_options, options, args|
|
501
|
-
|
545
|
+
tags = options[:tag].nil? ? [] : options[:tag].split(/ *, */).map {|t| t.sub(/^@/, '').strip }
|
546
|
+
wwid.restart_last({ section: options[:s], note: options[:n], tag: tags, tag_bool: options[:bool], in: options[:in] })
|
502
547
|
end
|
503
548
|
end
|
504
549
|
|
@@ -506,23 +551,19 @@ desc 'Tag last entry'
|
|
506
551
|
arg_name 'tag1 [tag2...]'
|
507
552
|
command :tag do |c|
|
508
553
|
c.desc 'Section'
|
509
|
-
c.flag [:s, :section], :
|
554
|
+
c.flag [:s, :section], default_value: 'All'
|
510
555
|
|
511
556
|
c.desc 'How many recent entries to tag (0 for all)'
|
512
|
-
c.default_value 1
|
513
|
-
c.flag [:c, :count], :default_value => 1
|
557
|
+
c.flag [:c, :count], default_value: 1
|
514
558
|
|
515
559
|
c.desc 'Include current date/time with tag'
|
516
|
-
c.default_value false
|
517
|
-
c.switch [:d, :date], :negatable => false, :default_value => false
|
560
|
+
c.switch [:d, :date], negatable: false, default_value: false
|
518
561
|
|
519
562
|
c.desc 'Remove given tag(s)'
|
520
|
-
c.default_value false
|
521
|
-
c.switch [:r, :remove], :negatable => false, :default_value => false
|
563
|
+
c.switch [:r, :remove], negatable: false, default_value: false
|
522
564
|
|
523
565
|
c.desc 'Autotag entries based on autotag configuration in ~/.doingrc'
|
524
|
-
c.default_value false
|
525
|
-
c.switch [:a, :autotag], :negatable => false, :default_value => false
|
566
|
+
c.switch [:a, :autotag], negatable: false, default_value: false
|
526
567
|
|
527
568
|
c.action do |global_options,options,args|
|
528
569
|
if args.length == 0 && !options[:a]
|
@@ -563,7 +604,7 @@ command :tag do |c|
|
|
563
604
|
end
|
564
605
|
end
|
565
606
|
|
566
|
-
wwid.tag_last({:
|
607
|
+
wwid.tag_last({tags: tags, count: count, section: section, date: options[:date], remove: options[:r], autotag: options[:a]})
|
567
608
|
end
|
568
609
|
end
|
569
610
|
end
|
@@ -571,17 +612,15 @@ end
|
|
571
612
|
desc 'Mark last entry as highlighted'
|
572
613
|
command [:mark, :flag] do |c|
|
573
614
|
c.desc 'Section'
|
574
|
-
c.default_value wwid.current_section
|
575
|
-
c.flag [:s, :section], :default_value => wwid.current_section
|
615
|
+
c.flag [:s, :section], default_value: wwid.current_section
|
576
616
|
|
577
617
|
c.desc 'Remove mark'
|
578
|
-
c.default_value false
|
579
|
-
c.switch [:r, :remove], :negatable => false, :default_value => false
|
618
|
+
c.switch [:r, :remove], negatable: false, default_value: false
|
580
619
|
|
581
620
|
|
582
621
|
c.action do |global_options,options,args|
|
583
622
|
mark = wwid.config['marker_tag'] || "flagged"
|
584
|
-
wwid.tag_last({:
|
623
|
+
wwid.tag_last({tags: [mark], section: options[:s], remove: options[:r]})
|
585
624
|
end
|
586
625
|
end
|
587
626
|
|
@@ -589,21 +628,20 @@ desc 'List all entries'
|
|
589
628
|
long_desc 'The argument can be a section name, @tag(s) or both. "pick" or "choose" as an argument will offer a section menu.'
|
590
629
|
arg_name '[section|@tags]'
|
591
630
|
command :show do |c|
|
631
|
+
c.desc 'Tag filter, combine multiple tags with a comma. Added for compatibility with other commands.'
|
632
|
+
c.flag [:tag]
|
633
|
+
|
592
634
|
c.desc 'Tag boolean (AND,OR,NONE)'
|
593
|
-
c.default_value
|
594
|
-
c.flag [:b, :bool], :default_value => "OR"
|
635
|
+
c.flag [:b, :bool], must_match: /^(and|or|not)$/i, default_value: 'OR'
|
595
636
|
|
596
637
|
c.desc 'Max count to show'
|
597
|
-
c.default_value 0
|
598
|
-
c.flag [:c, :count], :default_value => 0
|
638
|
+
c.flag [:c, :count], default_value: 0
|
599
639
|
|
600
640
|
c.desc 'Age (oldest/newest)'
|
601
|
-
c.default_value 'newest'
|
602
|
-
c.flag [:a, :age], :default_value => 'newest'
|
641
|
+
c.flag [:a, :age], default_value: 'newest'
|
603
642
|
|
604
643
|
c.desc 'Sort order (asc/desc)'
|
605
|
-
c.default_value 'asc'
|
606
|
-
c.flag [:s, :sort], :default_value => 'asc'
|
644
|
+
c.flag [:s, :sort], default_value: 'asc'
|
607
645
|
|
608
646
|
c.desc %{
|
609
647
|
Date range to show, or a single day to filter date on.
|
@@ -613,23 +651,20 @@ command :show do |c|
|
|
613
651
|
c.flag [:f, :from]
|
614
652
|
|
615
653
|
c.desc 'Show time intervals on @done tasks'
|
616
|
-
c.default_value true
|
617
|
-
c.switch [:t, :times], :default_value => true
|
654
|
+
c.switch [:t, :times], default_value: true
|
618
655
|
|
619
656
|
c.desc 'Show intervals with totals at the end of output'
|
620
|
-
c.default_value false
|
621
|
-
c.switch [:totals], :default_value => false, :negatable => true
|
657
|
+
c.switch [:totals], default_value: false, negatable: true
|
622
658
|
|
623
659
|
c.desc 'Sort tags by (name|time)'
|
624
660
|
default = 'time'
|
625
661
|
if wwid.config.has_key?('tag_sort')
|
626
662
|
default = wwid.config['tag_sort']
|
627
663
|
end
|
628
|
-
c.flag [:tag_sort], :
|
664
|
+
c.flag [:tag_sort], default_value: default
|
629
665
|
|
630
666
|
c.desc 'Only show items with recorded time intervals'
|
631
|
-
c.default_value false
|
632
|
-
c.switch [:only_timed], :default_value => false, :negatable => false
|
667
|
+
c.switch [:only_timed], default_value: false, negatable: false
|
633
668
|
|
634
669
|
c.desc 'Output to export format (csv|html|json)'
|
635
670
|
c.flag [:o, :output]
|
@@ -666,6 +701,8 @@ command :show do |c|
|
|
666
701
|
section = wwid.current_section
|
667
702
|
end
|
668
703
|
|
704
|
+
tags.concat(options[:tag].split(/ *, */).map {|t| t.sub(/^@/, '').strip }) if options[:tag]
|
705
|
+
|
669
706
|
unless tags.empty?
|
670
707
|
tag_filter = {
|
671
708
|
'tags' => tags,
|
@@ -684,14 +721,14 @@ command :show do |c|
|
|
684
721
|
finish = false
|
685
722
|
end
|
686
723
|
exit_now! "Unrecognized date string" unless start
|
687
|
-
dates = [start,finish]
|
724
|
+
dates = [start, finish]
|
688
725
|
end
|
689
726
|
|
690
727
|
options[:t] = true if options[:totals]
|
691
728
|
|
692
729
|
options[:sort_tags] = options[:tag_sort] =~ /^n/i
|
693
730
|
|
694
|
-
puts wwid.list_section({:
|
731
|
+
puts wwid.list_section({section: section, date_filter: dates, count: options[:c].to_i, tag_filter: tag_filter, age: options[:a], order: options[:s], output: options[:output], times: options[:t], totals: options[:totals], sort_tags: options[:sort_tags], highlight: true, only_timed: options[:only_timed]})
|
695
732
|
|
696
733
|
end
|
697
734
|
end
|
@@ -706,30 +743,26 @@ EODESC
|
|
706
743
|
arg_name 'search_pattern'
|
707
744
|
command [:grep, :search] do |c|
|
708
745
|
c.desc 'Section'
|
709
|
-
c.default_value "
|
710
|
-
c.flag [:s, :section], :default_value => "All"
|
746
|
+
c.flag [:s, :section], default_value: "All"
|
711
747
|
|
712
748
|
c.desc 'Output to export format (csv|html|json)'
|
713
749
|
c.flag [:o, :output]
|
714
750
|
|
715
751
|
c.desc 'Show time intervals on @done tasks'
|
716
|
-
c.default_value true
|
717
|
-
c.switch [:t, :times], :default_value => true
|
752
|
+
c.switch [:t, :times], default_value: true
|
718
753
|
|
719
754
|
c.desc 'Show intervals with totals at the end of output'
|
720
|
-
c.default_value false
|
721
|
-
c.switch [:totals], :default_value => false, :negatable => true
|
755
|
+
c.switch [:totals], default_value: false, negatable: true
|
722
756
|
|
723
757
|
c.desc 'Sort tags by (name|time)'
|
724
758
|
default = 'time'
|
725
759
|
if wwid.config.has_key?('tag_sort')
|
726
760
|
default = wwid.config['tag_sort']
|
727
761
|
end
|
728
|
-
c.flag [:tag_sort], :
|
762
|
+
c.flag [:tag_sort], default_value: default
|
729
763
|
|
730
764
|
c.desc 'Only show items with recorded time intervals'
|
731
|
-
c.default_value false
|
732
|
-
c.switch [:only_timed], :default_value => false, :negatable => false
|
765
|
+
c.switch [:only_timed], default_value: false, negatable: false
|
733
766
|
|
734
767
|
c.action do |global_options,options,args|
|
735
768
|
|
@@ -738,7 +771,7 @@ command [:grep, :search] do |c|
|
|
738
771
|
options[:t] = true if options[:totals]
|
739
772
|
options[:sort_tags] = options[:tag_sort] =~ /^n/i
|
740
773
|
|
741
|
-
puts wwid.list_section({:
|
774
|
+
puts wwid.list_section({search: args.join(' '), section: section, output: options[:output], times: options[:t], highlight: true, totals: options[:totals], only_timed: options[:only_timed], sort_tags: options[:sort_tags]})
|
742
775
|
|
743
776
|
end
|
744
777
|
end
|
@@ -748,23 +781,20 @@ default_value 10
|
|
748
781
|
arg_name 'count'
|
749
782
|
command :recent do |c|
|
750
783
|
c.desc 'Section'
|
751
|
-
c.default_value "All"
|
752
|
-
c.flag [:s, :section], :default_value => "All"
|
784
|
+
c.flag [:s, :section], default_value: "All"
|
753
785
|
|
754
786
|
c.desc 'Show time intervals on @done tasks'
|
755
|
-
c.default_value true
|
756
|
-
c.switch [:t, :times], :default_value => true
|
787
|
+
c.switch [:t, :times], default_value: true
|
757
788
|
|
758
789
|
c.desc 'Show intervals with totals at the end of output'
|
759
|
-
c.default_value false
|
760
|
-
c.switch [:totals], :default_value => false, :negatable => true
|
790
|
+
c.switch [:totals], default_value: false, negatable: true
|
761
791
|
|
762
792
|
c.desc 'Sort tags by (name|time)'
|
763
793
|
default = 'time'
|
764
794
|
if wwid.config.has_key?('tag_sort')
|
765
795
|
default = wwid.config['tag_sort']
|
766
796
|
end
|
767
|
-
c.flag [:tag_sort], :
|
797
|
+
c.flag [:tag_sort], default_value: default
|
768
798
|
|
769
799
|
c.action do |global_options,options,args|
|
770
800
|
|
@@ -779,7 +809,7 @@ command :recent do |c|
|
|
779
809
|
options[:t] = true if options[:totals]
|
780
810
|
options[:sort_tags] = options[:tag_sort] =~ /^n/i
|
781
811
|
|
782
|
-
puts wwid.recent(count,section.cap_first,{ :
|
812
|
+
puts wwid.recent(count,section.cap_first,{ times: options[:t], totals: options[:totals], sort_tags: options[:sort_tags] })
|
783
813
|
|
784
814
|
end
|
785
815
|
end
|
@@ -789,23 +819,20 @@ desc 'List entries from today'
|
|
789
819
|
command :today do |c|
|
790
820
|
c.desc 'Specify a section'
|
791
821
|
c.arg_name 'section_name'
|
792
|
-
c.default_value
|
793
|
-
c.flag [:s, :section], :default_value => 'All'
|
822
|
+
c.flag [:s, :section], default_value: 'All'
|
794
823
|
|
795
824
|
c.desc 'Show time intervals on @done tasks'
|
796
|
-
c.default_value true
|
797
|
-
c.switch [:t, :times], :default_value => true
|
825
|
+
c.switch [:t, :times], default_value: true
|
798
826
|
|
799
827
|
c.desc 'Show time totals at the end of output'
|
800
|
-
c.default_value false
|
801
|
-
c.switch [:totals], :default_value => false, :negatable => true
|
828
|
+
c.switch [:totals], default_value: false, negatable: true
|
802
829
|
|
803
830
|
c.desc 'Sort tags by (name|time)'
|
804
831
|
default = 'time'
|
805
832
|
if wwid.config.has_key?('tag_sort')
|
806
833
|
default = wwid.config['tag_sort']
|
807
834
|
end
|
808
|
-
c.flag [:tag_sort], :
|
835
|
+
c.flag [:tag_sort], default_value: default
|
809
836
|
|
810
837
|
c.desc 'Output to export format (csv|html|json)'
|
811
838
|
c.flag [:o, :output]
|
@@ -815,7 +842,7 @@ command :today do |c|
|
|
815
842
|
options[:t] = true if options[:totals]
|
816
843
|
options[:sort_tags] = options[:tag_sort] =~ /^n/i
|
817
844
|
|
818
|
-
puts wwid.today(options[:t],options[:output],{:
|
845
|
+
puts wwid.today(options[:t], options[:output], {totals: options[:totals], section: options[:s], sort_tags: options[:sort_tags]}).chomp
|
819
846
|
|
820
847
|
end
|
821
848
|
end
|
@@ -826,28 +853,26 @@ arg_name 'date_string'
|
|
826
853
|
command :on do |c|
|
827
854
|
c.desc 'Section'
|
828
855
|
c.arg_name 'section_name'
|
829
|
-
c.default_value 'All'
|
830
|
-
c.flag [:s, :section], :default_value => 'All'
|
856
|
+
c.flag [:s, :section], default_value: 'All'
|
831
857
|
|
832
858
|
c.desc 'Show time intervals on @done tasks'
|
833
|
-
c.default_value true
|
834
|
-
c.switch [:t, :times], :default_value => true
|
859
|
+
c.switch [:t, :times], default_value: true
|
835
860
|
|
836
861
|
c.desc 'Show time totals at the end of output'
|
837
|
-
c.default_value false
|
838
|
-
c.switch [:totals], :default_value => false, :negatable => true
|
862
|
+
c.switch [:totals], default_value: false, negatable: true
|
839
863
|
|
840
864
|
c.desc 'Sort tags by (name|time)'
|
841
865
|
default = 'time'
|
842
866
|
if wwid.config.has_key?('tag_sort')
|
843
867
|
default = wwid.config['tag_sort']
|
844
868
|
end
|
845
|
-
c.flag [:tag_sort], :
|
869
|
+
c.flag [:tag_sort], default_value: default
|
846
870
|
|
847
871
|
c.desc 'Output to export format (csv|html|json)'
|
848
872
|
c.flag [:o, :output]
|
849
873
|
|
850
874
|
c.action do |global_options,options,args|
|
875
|
+
exit_now! "Missing date argument" if args.empty?
|
851
876
|
|
852
877
|
date_string = args.join(" ")
|
853
878
|
|
@@ -869,7 +894,7 @@ command :on do |c|
|
|
869
894
|
options[:t] = true if options[:totals]
|
870
895
|
options[:sort_tags] = options[:tag_sort] =~ /^n/i
|
871
896
|
|
872
|
-
puts wwid.list_date([start, finish], options[:s], options[:t], options[:output], {:
|
897
|
+
puts wwid.list_date([start, finish], options[:s], options[:t], options[:output], {totals: options[:totals], sort_tags: options[:sort_tags]}).chomp
|
873
898
|
|
874
899
|
end
|
875
900
|
end
|
@@ -878,30 +903,27 @@ desc 'List entries from yesterday'
|
|
878
903
|
command :yesterday do |c|
|
879
904
|
c.desc 'Specify a section'
|
880
905
|
c.arg_name 'section_name'
|
881
|
-
c.default_value
|
882
|
-
c.flag [:s, :section], :default_value => 'All'
|
906
|
+
c.flag [:s, :section], default_value: 'All'
|
883
907
|
|
884
908
|
c.desc 'Output to export format (csv|html|json)'
|
885
909
|
c.flag [:o, :output]
|
886
910
|
|
887
911
|
c.desc 'Show time intervals on @done tasks'
|
888
|
-
c.default_value true
|
889
|
-
c.switch [:t, :times], :default_value => true
|
912
|
+
c.switch [:t, :times], default_value: true
|
890
913
|
|
891
914
|
c.desc 'Show time totals at the end of output'
|
892
|
-
c.default_value false
|
893
|
-
c.switch [:totals], :default_value => false, :negatable => true
|
915
|
+
c.switch [:totals], default_value: false, negatable: true
|
894
916
|
|
895
917
|
c.desc 'Sort tags by (name|time)'
|
896
918
|
default = 'time'
|
897
919
|
if wwid.config.has_key?('tag_sort')
|
898
920
|
default = wwid.config['tag_sort']
|
899
921
|
end
|
900
|
-
c.flag [:tag_sort], :
|
922
|
+
c.flag [:tag_sort], default_value: default
|
901
923
|
|
902
924
|
c.action do |global_options, options,args|
|
903
925
|
options[:sort_tags] = options[:tag_sort] =~ /^n/i
|
904
|
-
puts wwid.yesterday(options[:s],options[:t],options[:o],{:
|
926
|
+
puts wwid.yesterday(options[:s], options[:t], options[:o],{ totals: options[:totals], sort_tags: options[:sort_tags] }).chomp
|
905
927
|
|
906
928
|
end
|
907
929
|
end
|
@@ -909,7 +931,6 @@ end
|
|
909
931
|
desc 'Show the last entry'
|
910
932
|
command :last do |c|
|
911
933
|
c.desc 'Specify a section'
|
912
|
-
c.default_value "All"
|
913
934
|
c.flag [:s, :section]
|
914
935
|
|
915
936
|
c.action do |global_options,options,args|
|
@@ -920,8 +941,7 @@ end
|
|
920
941
|
desc 'List sections'
|
921
942
|
command :sections do |c|
|
922
943
|
c.desc 'List in single column'
|
923
|
-
c.default_value false
|
924
|
-
c.switch [:c, :column], :default_value => false
|
944
|
+
c.switch [:c, :column], default_value: false
|
925
945
|
|
926
946
|
c.action do |global_options,options,args|
|
927
947
|
joiner = options[:c] ? "\n" : "\t"
|
@@ -933,7 +953,7 @@ desc 'Select a section to display from a menu'
|
|
933
953
|
command :choose do |c|
|
934
954
|
c.action do |global_options,options,args|
|
935
955
|
section = wwid.choose_section
|
936
|
-
puts wwid.list_section({:
|
956
|
+
puts wwid.list_section({ section: section.cap_first, count: 0 })
|
937
957
|
end
|
938
958
|
end
|
939
959
|
|
@@ -975,29 +995,29 @@ command :view do |c|
|
|
975
995
|
c.flag [:s, :section]
|
976
996
|
|
977
997
|
c.desc 'Count to display (override view settings)'
|
978
|
-
c.flag [:c, :count], :
|
998
|
+
c.flag [:c, :count], must_match: /^\d+$/, type: Integer
|
979
999
|
|
980
1000
|
c.desc 'Output to export format (csv|html|json)'
|
981
1001
|
c.flag [:o, :output]
|
982
1002
|
|
983
1003
|
c.desc 'Show time intervals on @done tasks'
|
984
|
-
c.default_value true
|
985
|
-
c.switch [:t, :times], :default_value => true
|
1004
|
+
c.switch [:t, :times], default_value: true
|
986
1005
|
|
987
1006
|
c.desc 'Show intervals with totals at the end of output'
|
988
|
-
c.default_value false
|
989
|
-
|
1007
|
+
c.switch [:totals], default_value: false, negatable: true
|
1008
|
+
|
1009
|
+
c.desc 'Include colors in output'
|
1010
|
+
c.switch [:color], default_value: true, negatable: true
|
990
1011
|
|
991
1012
|
c.desc 'Sort tags by (name|time)'
|
992
1013
|
default = 'time'
|
993
1014
|
if wwid.config.has_key?('tag_sort')
|
994
1015
|
default = wwid.config['tag_sort']
|
995
1016
|
end
|
996
|
-
c.flag [:tag_sort], :
|
1017
|
+
c.flag [:tag_sort], default_value: default
|
997
1018
|
|
998
1019
|
c.desc 'Only show items with recorded time intervals'
|
999
|
-
c.default_value false
|
1000
|
-
c.switch [:only_timed], :default_value => false, :negatable => true
|
1020
|
+
c.switch [:only_timed], default_value: false, negatable: true
|
1001
1021
|
|
1002
1022
|
c.action do |global_options,options,args|
|
1003
1023
|
if args.empty?
|
@@ -1024,7 +1044,7 @@ command :view do |c|
|
|
1024
1044
|
tag_filter = false
|
1025
1045
|
if view.has_key?('tags')
|
1026
1046
|
unless view['tags'].nil? || view['tags'].empty?
|
1027
|
-
tag_filter = {'tags' => [], 'bool' =>
|
1047
|
+
tag_filter = {'tags' => [], 'bool' => 'OR'}
|
1028
1048
|
if view['tags'].class == Array
|
1029
1049
|
tag_filter['tags'] = view['tags'].map{|tag| tag.strip }
|
1030
1050
|
else
|
@@ -1045,7 +1065,7 @@ command :view do |c|
|
|
1045
1065
|
options[:output].downcase! if options[:output]
|
1046
1066
|
options[:sort_tags] = options[:tag_sort] =~ /^n/i
|
1047
1067
|
|
1048
|
-
puts wwid.list_section({:
|
1068
|
+
puts wwid.list_section({section: section, count: count, template: template, format: format, order: order, tag_filter: tag_filter, output: options[:o], tags_color: tags_color, times: options[:t], highlight: options[:color], totals: options[:totals], only_timed: only_timed, sort_tags: options[:sort_tags] })
|
1049
1069
|
else
|
1050
1070
|
if title.class == FalseClass
|
1051
1071
|
exit_now! "Cancelled"
|
@@ -1059,8 +1079,7 @@ end
|
|
1059
1079
|
desc 'List available custom views'
|
1060
1080
|
command :views do |c|
|
1061
1081
|
c.desc 'List in single column'
|
1062
|
-
c.default_value false
|
1063
|
-
c.switch [:c, :column], :default_value => false
|
1082
|
+
c.switch [:c, :column], default_value: false
|
1064
1083
|
|
1065
1084
|
c.action do |global_options,options,args|
|
1066
1085
|
joiner = options[:c] ? "\n" : "\t"
|
@@ -1068,21 +1087,21 @@ command :views do |c|
|
|
1068
1087
|
end
|
1069
1088
|
end
|
1070
1089
|
|
1071
|
-
desc 'Move entries
|
1090
|
+
desc 'Move entries between sections'
|
1072
1091
|
arg_name 'section'
|
1073
1092
|
default_value wwid.current_section
|
1074
1093
|
command :archive do |c|
|
1075
1094
|
c.desc 'Count to keep (ignored if archiving by tag)'
|
1076
|
-
c.default_value 5
|
1077
|
-
c.flag [:k, :keep], :default_value => 5, :must_match => /^\d+$/, :type => Integer
|
1095
|
+
c.flag [:k, :keep], default_value: 5, must_match: /^\d+$/, type: Integer
|
1078
1096
|
|
1079
1097
|
c.desc 'Move entries to'
|
1080
|
-
c.default_value
|
1081
|
-
|
1098
|
+
c.flag [:t, :to], default_value: 'Archive'
|
1099
|
+
|
1100
|
+
c.desc 'Tag filter, combine multiple tags with a comma. Added for compatibility with other commands.'
|
1101
|
+
c.flag [:tag]
|
1082
1102
|
|
1083
1103
|
c.desc 'Tag boolean'
|
1084
|
-
c.default_value
|
1085
|
-
c.flag [:b, :bool], :default_value => "AND"
|
1104
|
+
c.flag [:b, :bool], must_match: /(and|or|not)/i, default_value: 'AND'
|
1086
1105
|
|
1087
1106
|
c.action do |global_options,options,args|
|
1088
1107
|
if args.length > 0
|
@@ -1091,13 +1110,16 @@ command :archive do |c|
|
|
1091
1110
|
tags = args.map {|t| t.sub(/^@/,'').strip }
|
1092
1111
|
else
|
1093
1112
|
section = args[0].cap_first
|
1094
|
-
tags = args.length > 1 ? args[1..-1].map {|t| t.sub(/^@/,'').strip } : nil
|
1113
|
+
tags = args.length > 1 ? args[1..-1].map {|t| t.sub(/^@/, '').strip } : nil
|
1095
1114
|
end
|
1096
1115
|
else
|
1097
1116
|
section = wwid.current_section
|
1098
|
-
tags =
|
1117
|
+
tags = []
|
1099
1118
|
end
|
1100
|
-
|
1119
|
+
|
1120
|
+
tags.concat(options[:tag].split(/ *, */).map {|t| t.sub(/^@/, '').strip }) if options[:tag]
|
1121
|
+
|
1122
|
+
wwid.archive(section, options[:k], options[:t], tags, options[:b])
|
1101
1123
|
end
|
1102
1124
|
end
|
1103
1125
|
|
@@ -1113,7 +1135,7 @@ if `uname` =~ /Darwin/
|
|
1113
1135
|
c.flag [:b]
|
1114
1136
|
end
|
1115
1137
|
c.desc 'open with $EDITOR'
|
1116
|
-
c.switch [:e], :
|
1138
|
+
c.switch [:e], negatable: false
|
1117
1139
|
|
1118
1140
|
c.action do |global_options,options,args|
|
1119
1141
|
params = options.dup
|
@@ -1150,8 +1172,7 @@ end
|
|
1150
1172
|
desc 'Edit the configuration file'
|
1151
1173
|
command :config do |c|
|
1152
1174
|
c.desc 'Editor to use'
|
1153
|
-
c.
|
1154
|
-
c.flag [:e, :editor], :default_value => nil
|
1175
|
+
c.flag [:e, :editor], default_value: nil
|
1155
1176
|
|
1156
1177
|
if `uname` =~ /Darwins/
|
1157
1178
|
c.desc 'Application to use'
|
@@ -1189,8 +1210,7 @@ end
|
|
1189
1210
|
desc 'Undo the last change to the doing_file'
|
1190
1211
|
command :undo do |c|
|
1191
1212
|
c.desc 'Specify alternate doing file'
|
1192
|
-
c.default_value wwid.doing_file
|
1193
|
-
c.flag [:f, :file], :default_value => wwid.doing_file
|
1213
|
+
c.flag [:f, :file], default_value: wwid.doing_file
|
1194
1214
|
|
1195
1215
|
c.action do |global_options,options,args|
|
1196
1216
|
file = options[:f] || wwid.doing_file
|
@@ -1202,7 +1222,7 @@ end
|
|
1202
1222
|
pre do |global,command,options,args|
|
1203
1223
|
if global[:config_file]
|
1204
1224
|
wwid.config_file = global[:config_file]
|
1205
|
-
wwid.configure({:
|
1225
|
+
wwid.configure({ignore_local: true})
|
1206
1226
|
# wwid.results.push("Override config file #{wwid.config_file}")
|
1207
1227
|
end
|
1208
1228
|
|
data/lib/doing/version.rb
CHANGED
data/lib/doing/wwid.rb
CHANGED
@@ -3,6 +3,45 @@
|
|
3
3
|
require 'deep_merge'
|
4
4
|
require 'open3'
|
5
5
|
|
6
|
+
##
|
7
|
+
## @brief Hash helpers
|
8
|
+
##
|
9
|
+
class Hash
|
10
|
+
def has_tags?(tags, bool = 'AND')
|
11
|
+
tags = tags.split(/ *, */) if tags.is_a? String
|
12
|
+
item = self
|
13
|
+
case bool
|
14
|
+
when 'AND'
|
15
|
+
result = true
|
16
|
+
tags.each do |tag|
|
17
|
+
unless item['title'] =~ /@#{tag}/
|
18
|
+
result = false
|
19
|
+
break
|
20
|
+
end
|
21
|
+
end
|
22
|
+
result
|
23
|
+
when 'NOT'
|
24
|
+
result = true
|
25
|
+
tags.each do |tag|
|
26
|
+
if item['title'] =~ /@#{tag}/
|
27
|
+
result = false
|
28
|
+
break
|
29
|
+
end
|
30
|
+
end
|
31
|
+
result
|
32
|
+
else
|
33
|
+
result = false
|
34
|
+
tags.each do |tag|
|
35
|
+
if item['title'] =~ /@#{tag}/
|
36
|
+
result = true
|
37
|
+
break
|
38
|
+
end
|
39
|
+
end
|
40
|
+
result
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
6
45
|
##
|
7
46
|
## @brief String helpers
|
8
47
|
##
|
@@ -637,6 +676,8 @@ class WWID
|
|
637
676
|
def restart_last(opt = {})
|
638
677
|
opt[:section] ||= 'all'
|
639
678
|
opt[:note] ||= []
|
679
|
+
opt[:tag] ||= []
|
680
|
+
opt[:tag_bool] ||= 'AND'
|
640
681
|
|
641
682
|
last = last_entry(opt)
|
642
683
|
if last.nil?
|
@@ -645,8 +686,9 @@ class WWID
|
|
645
686
|
end
|
646
687
|
# Remove @done tag
|
647
688
|
title = last['title'].sub(/\s*@done(\(.*?\))?/, '').chomp
|
689
|
+
section = opt[:in].nil? ? last['section'] : guess_section(opt[:in])
|
648
690
|
@auto_tag = false
|
649
|
-
add_item(title,
|
691
|
+
add_item(title, section, { note: opt[:note], back: opt[:date], timed: true })
|
650
692
|
write(@doing_file)
|
651
693
|
end
|
652
694
|
|
@@ -656,6 +698,8 @@ class WWID
|
|
656
698
|
## @param opt (Hash) Additional Options
|
657
699
|
##
|
658
700
|
def last_entry(opt = {})
|
701
|
+
opt[:tag] ||= []
|
702
|
+
opt[:tag_bool] ||= 'AND'
|
659
703
|
opt[:section] ||= @current_section
|
660
704
|
|
661
705
|
sec_arr = []
|
@@ -682,6 +726,8 @@ class WWID
|
|
682
726
|
all_items.concat(@content[section]['items'].dup) if @content.key?(section)
|
683
727
|
end
|
684
728
|
|
729
|
+
all_items.select! { |item| item.has_tags?(opt[:tag], opt[:tag_bool]) } if !opt[:tag].nil? && opt[:tag].length.positive?
|
730
|
+
|
685
731
|
all_items.max_by { |item| item['date'] }
|
686
732
|
end
|
687
733
|
|
@@ -728,7 +774,6 @@ class WWID
|
|
728
774
|
if @content.key?(section)
|
729
775
|
|
730
776
|
items = @content[section]['items'].dup.sort_by { |item| item['date'] }.reverse
|
731
|
-
|
732
777
|
index = 0
|
733
778
|
done_date = Time.now
|
734
779
|
next_start = Time.now
|
@@ -736,44 +781,48 @@ class WWID
|
|
736
781
|
items.map! do |item|
|
737
782
|
break if index == count
|
738
783
|
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
next_start = item['date']
|
751
|
-
elsif opt[:back]
|
752
|
-
done_date = item['date'] + (opt[:back] - item['date'])
|
784
|
+
tag_match = !opt[:tag].nil? && opt[:tag].length.positive? ? item.has_tags?(opt[:tag], opt[:tag_bool]) : true
|
785
|
+
|
786
|
+
if tag_match
|
787
|
+
if opt[:autotag]
|
788
|
+
new_title = autotag(item['title']) if @auto_tag
|
789
|
+
if new_title == item['title']
|
790
|
+
@results.push(%(Autotag: No changes))
|
791
|
+
else
|
792
|
+
@results.push("Tags updated: #{new_title}")
|
793
|
+
item['title'] = new_title
|
794
|
+
end
|
753
795
|
else
|
754
|
-
|
755
|
-
|
796
|
+
if opt[:sequential]
|
797
|
+
done_date = next_start - 1
|
798
|
+
next_start = item['date']
|
799
|
+
elsif opt[:back]
|
800
|
+
done_date = item['date'] + (opt[:back] - item['date'])
|
801
|
+
else
|
802
|
+
done_date = Time.now
|
803
|
+
end
|
756
804
|
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
805
|
+
title = item['title']
|
806
|
+
opt[:tags].each do |tag|
|
807
|
+
tag.strip!
|
808
|
+
if opt[:remove] && title =~ /@#{tag}\b/
|
809
|
+
title.gsub!(/(^| )@#{tag}(\([^)]*\))?/, '')
|
810
|
+
@results.push(%(Removed @#{tag}: "#{title}" in #{section}))
|
811
|
+
elsif title !~ /@#{tag}/
|
812
|
+
title.chomp!
|
813
|
+
title += if opt[:date]
|
814
|
+
" @#{tag}(#{done_date.strftime('%F %R')})"
|
815
|
+
else
|
816
|
+
" @#{tag}"
|
817
|
+
end
|
818
|
+
@results.push(%(Added @#{tag}: "#{title}" in #{section}))
|
819
|
+
end
|
771
820
|
end
|
821
|
+
item['title'] = title
|
772
822
|
end
|
773
|
-
item['title'] = title
|
774
|
-
end
|
775
823
|
|
776
|
-
|
824
|
+
index += 1
|
825
|
+
end
|
777
826
|
|
778
827
|
item
|
779
828
|
end
|
@@ -783,9 +832,10 @@ class WWID
|
|
783
832
|
if opt[:archive] && section != 'Archive' && (opt[:count]).positive?
|
784
833
|
# concat [count] items from [section] and archive section
|
785
834
|
archived = @content[section]['items'][0..opt[:count] - 1].map do |i|
|
786
|
-
i['title'].sub(/(?:@from\(.*?\))?(.*)$/, "\\1 @from(#{i['section']})")
|
835
|
+
i['title'].sub!(/(?:@from\(.*?\))?(.*)$/, "\\1 @from(#{i['section']})")
|
836
|
+
i
|
787
837
|
end.concat(@content['Archive']['items'])
|
788
|
-
#
|
838
|
+
# slice [count] items off of [section] items
|
789
839
|
@content[opt[:section]]['items'] = @content[opt[:section]]['items'][opt[:count]..-1]
|
790
840
|
# overwrite archive section with concatenated array
|
791
841
|
@content['Archive']['items'] = archived
|
metadata
CHANGED
@@ -1,19 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: doing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.54
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-07-
|
11
|
+
date: 2021-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '13.0'
|
17
20
|
- - ">="
|
18
21
|
- !ruby/object:Gem::Version
|
19
22
|
version: 13.0.1
|
@@ -21,6 +24,9 @@ dependencies:
|
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '13.0'
|
24
30
|
- - ">="
|
25
31
|
- !ruby/object:Gem::Version
|
26
32
|
version: 13.0.1
|