doing 1.0.46 → 1.0.51
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -5
- data/bin/doing +115 -123
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +78 -40
- metadata +12 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03b16107627feaf0adeafbce9ad45e96fc53df7ba379f59dc72d2970d12642ef
|
4
|
+
data.tar.gz: 5cd54e6ba005e985b6c86468831d0b83369c5801916a9e8e15e742c86fcccf53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 617cd299b816ad12dc042ec76dbd58e5f19dca7098362ad4cc465d70d5c6dfab0e5ca4e05b82cd9535a85638ae490adea4da502ce4b6f0127e25da8f08b0bc6c
|
7
|
+
data.tar.gz: c82bb894c5d457d6bde4e6396cb7badffb4db3e6d0d81b75372f98968ec79b9ebfe15548b7040ddb5cc2eb2abfda2e3faaf6ea517c0485878689b50ce1739a79
|
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
|
@@ -393,10 +393,11 @@ Note that you can include a tag with synonyms in the whitelist as well to tag it
|
|
393
393
|
|
394
394
|
#### Adding entries:
|
395
395
|
|
396
|
-
now, did
|
397
|
-
later
|
398
|
-
done
|
399
|
-
meanwhile
|
396
|
+
now, did - Add an entry
|
397
|
+
later - Add an item to the Later section
|
398
|
+
done - Add a completed item with @done(date). No argument finishes last entry.
|
399
|
+
meanwhile - Finish any @meanwhile tasks and optionally create a new one
|
400
|
+
again, resume - Duplicate the last entry as new entry (without @done tag)
|
400
401
|
|
401
402
|
The `doing now` command can accept `-s section_name` to send the new entry straight to a non-default section. It also accepts `--back=AMOUNT` to let you specify a start date in the past using "natural language." For example, `doing now --back=25m ENTRY` or `doing now --back="yesterday 3:30pm" ENTRY`.
|
402
403
|
|
@@ -419,6 +420,7 @@ See `doing help meanwhile` for more options.
|
|
419
420
|
#### Modifying entries:
|
420
421
|
|
421
422
|
finish - Mark last X entries as @done
|
423
|
+
cancel - Mark last X entries as @done without completion date
|
422
424
|
tag - Tag last entry
|
423
425
|
note - Add a note to the last entry
|
424
426
|
|
@@ -430,6 +432,16 @@ See `doing help meanwhile` for more options.
|
|
430
432
|
|
431
433
|
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.
|
432
434
|
|
435
|
+
Both `done` and `finish` accept an `--archive` switch which immediately moves the completed entries to the Archive section with a `@from(Project)` tag.
|
436
|
+
|
437
|
+
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:
|
438
|
+
|
439
|
+
doing finish --tag=work,project1
|
440
|
+
|
441
|
+
You can change the boolean using `--tag_bool=OR` (last entry containing any of the specified tags) or `--tag_bool=NOT` (last entry containing none of the tags).
|
442
|
+
|
443
|
+
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.
|
444
|
+
|
433
445
|
|
434
446
|
##### Tagging and Autotagging
|
435
447
|
|
data/bin/doing
CHANGED
@@ -44,7 +44,7 @@ default_value false
|
|
44
44
|
switch [:stdout], :default_value => false, :negatable => false
|
45
45
|
|
46
46
|
desc 'Exclude auto tags and default tags'
|
47
|
-
switch [:x
|
47
|
+
switch [:x, :noauto], :default_value => false
|
48
48
|
|
49
49
|
desc 'Use a specific configuration file'
|
50
50
|
default_value false
|
@@ -52,37 +52,34 @@ flag [:config_file]
|
|
52
52
|
|
53
53
|
|
54
54
|
# desc 'Wrap notes at X chars (0 for no wrap)'
|
55
|
-
# flag [:w
|
55
|
+
# flag [:w, :wrapwidth], :must_match => /^\d+$/, :type => Integer
|
56
56
|
|
57
57
|
desc 'Specify a different doing_file'
|
58
58
|
flag [:f, :doing_file]
|
59
59
|
|
60
60
|
desc 'Add an entry'
|
61
61
|
arg_name 'entry'
|
62
|
-
command [:now
|
62
|
+
command [:now, :next] do |c|
|
63
63
|
c.desc 'Section'
|
64
64
|
c.arg_name 'section_name'
|
65
|
-
c.default_value wwid.current_section
|
66
|
-
c.flag [:s,:section], :default_value => wwid.current_section
|
65
|
+
c.flag [:s, :section], :default_value => wwid.current_section
|
67
66
|
|
68
67
|
c.desc "Edit entry with #{ENV['EDITOR']}"
|
69
|
-
c.switch [:e
|
68
|
+
c.switch [:e, :editor]
|
70
69
|
|
71
70
|
c.desc 'Backdate start time [4pm|20m|2h|yesterday noon]'
|
72
|
-
c.flag [:back]
|
71
|
+
c.flag [:b, :back]
|
73
72
|
|
74
73
|
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
|
74
|
+
c.switch [:f, :finish_last], :negatable => false, :default_value => false
|
77
75
|
|
78
76
|
c.desc 'Note'
|
79
77
|
c.arg_name 'note_text'
|
80
|
-
c.flag [:n
|
78
|
+
c.flag [:n, :note]
|
81
79
|
|
82
80
|
# c.desc "Edit entry with specified app"
|
83
81
|
# c.arg_name 'editor_app'
|
84
|
-
# c.
|
85
|
-
# c.flag [:a,:app]
|
82
|
+
# # c.flag [:a, :app]
|
86
83
|
|
87
84
|
c.action do |global_options,options,args|
|
88
85
|
if options[:back]
|
@@ -136,7 +133,6 @@ arg_name 'note_text'
|
|
136
133
|
command :note do |c|
|
137
134
|
c.desc 'Section'
|
138
135
|
c.arg_name 'section_name'
|
139
|
-
c.default_value wwid.current_section
|
140
136
|
c.flag [:s, :section], :default_value => "All"
|
141
137
|
|
142
138
|
c.desc "Edit entry with #{ENV['EDITOR']}"
|
@@ -196,7 +192,6 @@ arg_name 'entry'
|
|
196
192
|
command :meanwhile do |c|
|
197
193
|
c.desc 'Section'
|
198
194
|
c.arg_name 'section_name'
|
199
|
-
c.default_value wwid.current_section
|
200
195
|
c.flag [:s, :section], :default_value => wwid.current_section
|
201
196
|
|
202
197
|
c.desc "Edit entry with #{ENV['EDITOR']}"
|
@@ -206,7 +201,7 @@ command :meanwhile do |c|
|
|
206
201
|
c.switch [:a, :archive], :default_value => false
|
207
202
|
|
208
203
|
c.desc 'Backdate start date for new entry to date string [4pm|20m|2h|yesterday noon]'
|
209
|
-
c.flag [:back]
|
204
|
+
c.flag [:b, :back]
|
210
205
|
|
211
206
|
c.desc 'Note'
|
212
207
|
c.arg_name 'note_text'
|
@@ -238,7 +233,7 @@ command :meanwhile do |c|
|
|
238
233
|
input = false unless input && input.length > 0
|
239
234
|
|
240
235
|
note = options[:n] ? options[:n] : false
|
241
|
-
wwid.stop_start(
|
236
|
+
wwid.stop_start('meanwhile', {:new_item => input, :back => date, :section => section, :archive => options[:a], :note => note})
|
242
237
|
wwid.write(wwid.doing_file)
|
243
238
|
end
|
244
239
|
end
|
@@ -276,11 +271,10 @@ command :later do |c|
|
|
276
271
|
|
277
272
|
c.desc "Edit entry with specified app"
|
278
273
|
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
274
|
c.flag [:a, :app]
|
281
275
|
|
282
276
|
c.desc 'Backdate start time to date string [4pm|20m|2h|yesterday noon]'
|
283
|
-
c.flag [:back]
|
277
|
+
c.flag [:b, :back]
|
284
278
|
|
285
279
|
c.desc 'Note'
|
286
280
|
c.arg_name 'note_text'
|
@@ -327,17 +321,14 @@ end
|
|
327
321
|
|
328
322
|
desc 'Add a completed item with @done(date). No argument finishes last entry.'
|
329
323
|
arg_name 'entry'
|
330
|
-
command [:done
|
324
|
+
command [:done, :did] do |c|
|
331
325
|
c.desc 'Remove @done tag'
|
332
|
-
c.default_value false
|
333
326
|
c.switch [:r, :remove], :negatable => false, :default_value => false
|
334
327
|
|
335
328
|
c.desc 'Include date'
|
336
|
-
c.default_value true
|
337
|
-
c.switch [:d, :date], :negatable => true, :default_value => true
|
329
|
+
c.switch [:date], :negatable => true, :default_value => true
|
338
330
|
|
339
331
|
c.desc 'Immediately archive the entry'
|
340
|
-
c.default_value false
|
341
332
|
c.switch [:a, :archive], :negatable => false, :default_value => false
|
342
333
|
|
343
334
|
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'
|
@@ -350,16 +341,14 @@ command [:done,:did] do |c|
|
|
350
341
|
c.flag [:t, :took]
|
351
342
|
|
352
343
|
c.desc 'Section'
|
353
|
-
c.default_value wwid.current_section
|
354
|
-
c.flag [:s,:section], :default_value => wwid.current_section
|
344
|
+
c.flag [:s, :section], :default_value => wwid.current_section
|
355
345
|
|
356
346
|
c.desc "Edit entry with #{ENV['EDITOR']}"
|
357
|
-
c.switch [:e
|
347
|
+
c.switch [:e, :editor]
|
358
348
|
|
359
349
|
# c.desc "Edit entry with specified app"
|
360
350
|
# c.arg_name 'editor_app'
|
361
|
-
# c.
|
362
|
-
# c.flag [:a,:app]
|
351
|
+
# # c.flag [:a, :app]
|
363
352
|
|
364
353
|
c.action do |global_options,options,args|
|
365
354
|
took = 0
|
@@ -390,7 +379,7 @@ command [:done,:did] do |c|
|
|
390
379
|
end
|
391
380
|
|
392
381
|
section = wwid.guess_section(options[:s]) || options[:s].cap_first
|
393
|
-
donedate = options[:
|
382
|
+
donedate = options[:date] ? "(#{finish_date.strftime('%F %R')})" : ""
|
394
383
|
|
395
384
|
if options[:e]
|
396
385
|
raise "No EDITOR variable defined in environment" if ENV['EDITOR'].nil?
|
@@ -410,7 +399,7 @@ command [:done,:did] do |c|
|
|
410
399
|
if options[:r]
|
411
400
|
wwid.tag_last({:tags => ["done"], :count => 1, :section => section, :remove => true })
|
412
401
|
else
|
413
|
-
wwid.tag_last({:tags => ["done"], :count => 1, :section => section, :archive => options[:a], :back => finish_date, :date => options[:
|
402
|
+
wwid.tag_last({:tags => ["done"], :count => 1, :section => section, :archive => options[:a], :back => finish_date, :date => options[:date]})
|
414
403
|
end
|
415
404
|
else
|
416
405
|
if args.length > 0
|
@@ -433,31 +422,58 @@ command [:done,:did] do |c|
|
|
433
422
|
end
|
434
423
|
end
|
435
424
|
|
425
|
+
desc 'End last X entries with no time tracked'
|
426
|
+
long_desc 'Adds @done tag without datestamp so no elapsed time is recorded. Alias for `doing finish --no-date`.'
|
427
|
+
arg_name 'count'
|
428
|
+
command :cancel do |c|
|
429
|
+
c.desc 'Archive entries'
|
430
|
+
c.switch [:a, :archive], :negatable => false, :default_value => false
|
431
|
+
|
432
|
+
c.desc 'Section'
|
433
|
+
c.flag [:s, :section], :default_value => wwid.current_section
|
434
|
+
|
435
|
+
c.action do |global_options,options,args|
|
436
|
+
|
437
|
+
section = wwid.guess_section(options[:s]) || options[:s].cap_first
|
438
|
+
|
439
|
+
if args.length > 1
|
440
|
+
raise "Only one argument allowed"
|
441
|
+
elsif args.length == 0 || args[0] =~ /\d+/
|
442
|
+
count = args[0] ? args[0].to_i : 1
|
443
|
+
wwid.tag_last({:tags => ["done"], :count => count, :section => section, :archive => options[:a], :sequential => false, :date => false })
|
444
|
+
else
|
445
|
+
raise "Invalid argument (specify number of recent items to mark @done)"
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
436
450
|
desc 'Mark last X entries as @done'
|
437
451
|
long_desc 'Marks the last X entries with a @done tag and current date. Does not alter already completed entries.'
|
438
452
|
arg_name 'count'
|
439
453
|
command :finish do |c|
|
440
454
|
c.desc 'Include date'
|
441
|
-
c.default_value true
|
442
|
-
c.switch [:d,:date], :default_value => true
|
455
|
+
c.switch [:date], :negatable => true, :default_value => true
|
443
456
|
|
444
457
|
c.desc 'Backdate completed date to date string [4pm|20m|2h|yesterday noon]'
|
445
|
-
c.flag [:b
|
458
|
+
c.flag [:b, :back]
|
446
459
|
|
447
460
|
c.desc 'Set the completed date to the start date plus XX[hmd]'
|
448
|
-
c.flag [:t
|
461
|
+
c.flag [:t, :took]
|
462
|
+
|
463
|
+
c.desc 'Finish the last X entries containing TAG. Separate multiple tags with comma (--tag=tag2,tag2)'
|
464
|
+
c.flag [:tag], :default_value => []
|
465
|
+
|
466
|
+
c.desc 'Boolean (AND|OR|NOT) with which to combine multiple tag filters'
|
467
|
+
c.flag [:tag_bool], default_value: 'AND'
|
449
468
|
|
450
469
|
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.'
|
451
|
-
c.default_value false
|
452
470
|
c.switch [:auto], :negatable => false, :default_value => false
|
453
471
|
|
454
472
|
c.desc 'Archive entries'
|
455
|
-
c.default_value false
|
456
|
-
c.switch [:a,:archive], :negatable => false, :default_value => false
|
473
|
+
c.switch [:a, :archive], :negatable => false, :default_value => false
|
457
474
|
|
458
475
|
c.desc 'Section'
|
459
|
-
c.default_value wwid.current_section
|
460
|
-
c.flag [:s,:section], :default_value => wwid.current_section
|
476
|
+
c.flag [:s, :section], :default_value => wwid.current_section
|
461
477
|
|
462
478
|
c.action do |global_options,options,args|
|
463
479
|
|
@@ -477,11 +493,20 @@ command :finish do |c|
|
|
477
493
|
end
|
478
494
|
end
|
479
495
|
|
496
|
+
if options[:tag]
|
497
|
+
options[:tag] = options[:tag].split(/,/).map {|tag| tag.strip.sub(/^@/, '') }
|
498
|
+
if options[:tag_bool] =~ /^(and|or|not)$/i
|
499
|
+
options[:tag_bool] = options[:tag_bool].upcase
|
500
|
+
else
|
501
|
+
options[:tag_bool] = 'AND'
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
480
505
|
if args.length > 1
|
481
506
|
raise "Only one argument allowed"
|
482
507
|
elsif args.length == 0 || args[0] =~ /\d+/
|
483
508
|
count = args[0] ? args[0].to_i : 1
|
484
|
-
wwid.tag_last({:
|
509
|
+
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[:tag_bool] })
|
485
510
|
else
|
486
511
|
raise "Invalid argument (specify number of recent items to mark @done)"
|
487
512
|
end
|
@@ -490,13 +515,13 @@ end
|
|
490
515
|
|
491
516
|
desc 'Repeat last entry as new entry'
|
492
517
|
arg_name 'section'
|
493
|
-
command [:again
|
518
|
+
command [:again, :resume] do |c|
|
494
519
|
c.desc 'Section'
|
495
520
|
c.flag [:s, :section], :default_value => "All"
|
496
521
|
|
497
522
|
c.desc 'Note'
|
498
523
|
c.arg_name 'note_text'
|
499
|
-
c.flag [:n
|
524
|
+
c.flag [:n, :note]
|
500
525
|
|
501
526
|
c.action do |global_options, options, args|
|
502
527
|
wwid.restart_last({ section: options[:s], note: options[:n] })
|
@@ -510,19 +535,15 @@ command :tag do |c|
|
|
510
535
|
c.flag [:s, :section], :default_value => "All"
|
511
536
|
|
512
537
|
c.desc 'How many recent entries to tag (0 for all)'
|
513
|
-
c.default_value 1
|
514
538
|
c.flag [:c, :count], :default_value => 1
|
515
539
|
|
516
540
|
c.desc 'Include current date/time with tag'
|
517
|
-
c.default_value false
|
518
541
|
c.switch [:d, :date], :negatable => false, :default_value => false
|
519
542
|
|
520
543
|
c.desc 'Remove given tag(s)'
|
521
|
-
c.default_value false
|
522
544
|
c.switch [:r, :remove], :negatable => false, :default_value => false
|
523
545
|
|
524
546
|
c.desc 'Autotag entries based on autotag configuration in ~/.doingrc'
|
525
|
-
c.default_value false
|
526
547
|
c.switch [:a, :autotag], :negatable => false, :default_value => false
|
527
548
|
|
528
549
|
c.action do |global_options,options,args|
|
@@ -557,27 +578,25 @@ command :tag do |c|
|
|
557
578
|
question = "Are you sure you want to add #{tags.join(" and ")} to all records#{section_q}"
|
558
579
|
end
|
559
580
|
|
560
|
-
res = wwid.yn(question,false)
|
581
|
+
res = wwid.yn(question, default_response: false)
|
561
582
|
|
562
583
|
unless res
|
563
584
|
raise "Cancelled"
|
564
585
|
end
|
565
586
|
end
|
566
587
|
|
567
|
-
wwid.tag_last({:tags => tags, :count => count, :section => section, :date => options[:
|
588
|
+
wwid.tag_last({:tags => tags, :count => count, :section => section, :date => options[:date], :remove => options[:r], :autotag => options[:a]})
|
568
589
|
end
|
569
590
|
end
|
570
591
|
end
|
571
592
|
|
572
593
|
desc 'Mark last entry as highlighted'
|
573
|
-
command [:mark
|
594
|
+
command [:mark, :flag] do |c|
|
574
595
|
c.desc 'Section'
|
575
|
-
c.default_value wwid.current_section
|
576
|
-
c.flag [:s,:section], :default_value => wwid.current_section
|
596
|
+
c.flag [:s, :section], :default_value => wwid.current_section
|
577
597
|
|
578
598
|
c.desc 'Remove mark'
|
579
|
-
c.default_value false
|
580
|
-
c.switch [:r,:remove], :negatable => false, :default_value => false
|
599
|
+
c.switch [:r, :remove], :negatable => false, :default_value => false
|
581
600
|
|
582
601
|
|
583
602
|
c.action do |global_options,options,args|
|
@@ -591,32 +610,28 @@ long_desc 'The argument can be a section name, @tag(s) or both. "pick" or "choos
|
|
591
610
|
arg_name '[section|@tags]'
|
592
611
|
command :show do |c|
|
593
612
|
c.desc 'Tag boolean (AND,OR,NONE)'
|
594
|
-
c.default_value "OR"
|
595
|
-
c.flag [:b,:bool], :default_value => "OR"
|
613
|
+
c.flag [:b, :bool], :default_value => "OR"
|
596
614
|
|
597
615
|
c.desc 'Max count to show'
|
598
|
-
c.default_value 0
|
599
|
-
c.flag [:c,:count], :default_value => 0
|
616
|
+
c.flag [:c, :count], :default_value => 0
|
600
617
|
|
601
618
|
c.desc 'Age (oldest/newest)'
|
602
|
-
c.default_value 'newest'
|
603
|
-
c.flag [:a,:age], :default_value => 'newest'
|
619
|
+
c.flag [:a, :age], :default_value => 'newest'
|
604
620
|
|
605
621
|
c.desc 'Sort order (asc/desc)'
|
606
|
-
c.default_value 'asc'
|
607
|
-
c.flag [:s,:sort], :default_value => 'asc'
|
622
|
+
c.flag [:s, :sort], :default_value => 'asc'
|
608
623
|
|
609
624
|
c.desc %{
|
610
|
-
Date range to show, or a single day to filter date on.
|
625
|
+
Date range to show, or a single day to filter date on.
|
626
|
+
Date range argument should be quoted. Date specifications can be natural language.
|
627
|
+
To specify a range, use "to" or "through": `doing show --from "monday to friday"`
|
611
628
|
}
|
612
|
-
c.flag [:f
|
629
|
+
c.flag [:f, :from]
|
613
630
|
|
614
631
|
c.desc 'Show time intervals on @done tasks'
|
615
|
-
c.default_value true
|
616
|
-
c.switch [:t,:times], :default_value => true
|
632
|
+
c.switch [:t, :times], :default_value => true
|
617
633
|
|
618
634
|
c.desc 'Show intervals with totals at the end of output'
|
619
|
-
c.default_value false
|
620
635
|
c.switch [:totals], :default_value => false, :negatable => true
|
621
636
|
|
622
637
|
c.desc 'Sort tags by (name|time)'
|
@@ -627,11 +642,10 @@ command :show do |c|
|
|
627
642
|
c.flag [:tag_sort], :default_value => default
|
628
643
|
|
629
644
|
c.desc 'Only show items with recorded time intervals'
|
630
|
-
c.default_value false
|
631
645
|
c.switch [:only_timed], :default_value => false, :negatable => false
|
632
646
|
|
633
647
|
c.desc 'Output to export format (csv|html|json)'
|
634
|
-
c.flag [:o
|
648
|
+
c.flag [:o, :output]
|
635
649
|
c.action do |global_options,options,args|
|
636
650
|
|
637
651
|
tag_filter = false
|
@@ -696,22 +710,24 @@ command :show do |c|
|
|
696
710
|
end
|
697
711
|
|
698
712
|
desc 'Search for entries'
|
699
|
-
long_desc '
|
713
|
+
long_desc <<-'EODESC'
|
714
|
+
Search all sections (or limit to a single section) for entries matching text or regular expression. Normal strings are fuzzy matched.
|
715
|
+
|
716
|
+
To search with regular expressions, single quote the string and surround with slashes: `doing search '/\bm.*?x\b/'`
|
717
|
+
EODESC
|
718
|
+
|
700
719
|
arg_name 'search_pattern'
|
701
|
-
command [:grep
|
720
|
+
command [:grep, :search] do |c|
|
702
721
|
c.desc 'Section'
|
703
|
-
c.default_value "
|
704
|
-
c.flag [:s,:section], :default_value => "All"
|
722
|
+
c.flag [:s, :section], :default_value => "All"
|
705
723
|
|
706
724
|
c.desc 'Output to export format (csv|html|json)'
|
707
|
-
c.flag [:o
|
725
|
+
c.flag [:o, :output]
|
708
726
|
|
709
727
|
c.desc 'Show time intervals on @done tasks'
|
710
|
-
c.default_value true
|
711
|
-
c.switch [:t,:times], :default_value => true
|
728
|
+
c.switch [:t, :times], :default_value => true
|
712
729
|
|
713
730
|
c.desc 'Show intervals with totals at the end of output'
|
714
|
-
c.default_value false
|
715
731
|
c.switch [:totals], :default_value => false, :negatable => true
|
716
732
|
|
717
733
|
c.desc 'Sort tags by (name|time)'
|
@@ -722,7 +738,6 @@ command [:grep,:search] do |c|
|
|
722
738
|
c.flag [:tag_sort], :default_value => default
|
723
739
|
|
724
740
|
c.desc 'Only show items with recorded time intervals'
|
725
|
-
c.default_value false
|
726
741
|
c.switch [:only_timed], :default_value => false, :negatable => false
|
727
742
|
|
728
743
|
c.action do |global_options,options,args|
|
@@ -742,15 +757,12 @@ default_value 10
|
|
742
757
|
arg_name 'count'
|
743
758
|
command :recent do |c|
|
744
759
|
c.desc 'Section'
|
745
|
-
c.default_value "All"
|
746
|
-
c.flag [:s,:section], :default_value => "All"
|
760
|
+
c.flag [:s, :section], :default_value => "All"
|
747
761
|
|
748
762
|
c.desc 'Show time intervals on @done tasks'
|
749
|
-
c.default_value true
|
750
|
-
c.switch [:t,:times], :default_value => true
|
763
|
+
c.switch [:t, :times], :default_value => true
|
751
764
|
|
752
765
|
c.desc 'Show intervals with totals at the end of output'
|
753
|
-
c.default_value false
|
754
766
|
c.switch [:totals], :default_value => false, :negatable => true
|
755
767
|
|
756
768
|
c.desc 'Sort tags by (name|time)'
|
@@ -783,15 +795,12 @@ desc 'List entries from today'
|
|
783
795
|
command :today do |c|
|
784
796
|
c.desc 'Specify a section'
|
785
797
|
c.arg_name 'section_name'
|
786
|
-
c.default_value
|
787
|
-
c.flag [:s,:section], :default_value => 'All'
|
798
|
+
c.flag [:s, :section], :default_value => 'All'
|
788
799
|
|
789
800
|
c.desc 'Show time intervals on @done tasks'
|
790
|
-
c.default_value true
|
791
|
-
c.switch [:t,:times], :default_value => true
|
801
|
+
c.switch [:t, :times], :default_value => true
|
792
802
|
|
793
803
|
c.desc 'Show time totals at the end of output'
|
794
|
-
c.default_value false
|
795
804
|
c.switch [:totals], :default_value => false, :negatable => true
|
796
805
|
|
797
806
|
c.desc 'Sort tags by (name|time)'
|
@@ -802,7 +811,7 @@ command :today do |c|
|
|
802
811
|
c.flag [:tag_sort], :default_value => default
|
803
812
|
|
804
813
|
c.desc 'Output to export format (csv|html|json)'
|
805
|
-
c.flag [:o
|
814
|
+
c.flag [:o, :output]
|
806
815
|
|
807
816
|
c.action do |global_options,options,args|
|
808
817
|
|
@@ -820,15 +829,12 @@ arg_name 'date_string'
|
|
820
829
|
command :on do |c|
|
821
830
|
c.desc 'Section'
|
822
831
|
c.arg_name 'section_name'
|
823
|
-
c.default_value 'All'
|
824
|
-
c.flag [:s,:section], :default_value => 'All'
|
832
|
+
c.flag [:s, :section], :default_value => 'All'
|
825
833
|
|
826
834
|
c.desc 'Show time intervals on @done tasks'
|
827
|
-
c.default_value true
|
828
|
-
c.switch [:t,:times], :default_value => true
|
835
|
+
c.switch [:t, :times], :default_value => true
|
829
836
|
|
830
837
|
c.desc 'Show time totals at the end of output'
|
831
|
-
c.default_value false
|
832
838
|
c.switch [:totals], :default_value => false, :negatable => true
|
833
839
|
|
834
840
|
c.desc 'Sort tags by (name|time)'
|
@@ -839,7 +845,7 @@ command :on do |c|
|
|
839
845
|
c.flag [:tag_sort], :default_value => default
|
840
846
|
|
841
847
|
c.desc 'Output to export format (csv|html|json)'
|
842
|
-
c.flag [:o
|
848
|
+
c.flag [:o, :output]
|
843
849
|
|
844
850
|
c.action do |global_options,options,args|
|
845
851
|
|
@@ -872,18 +878,15 @@ desc 'List entries from yesterday'
|
|
872
878
|
command :yesterday do |c|
|
873
879
|
c.desc 'Specify a section'
|
874
880
|
c.arg_name 'section_name'
|
875
|
-
c.default_value
|
876
|
-
c.flag [:s,:section], :default_value => 'All'
|
881
|
+
c.flag [:s, :section], :default_value => 'All'
|
877
882
|
|
878
883
|
c.desc 'Output to export format (csv|html|json)'
|
879
|
-
c.flag [:o
|
884
|
+
c.flag [:o, :output]
|
880
885
|
|
881
886
|
c.desc 'Show time intervals on @done tasks'
|
882
|
-
c.default_value true
|
883
|
-
c.switch [:t,:times], :default_value => true
|
887
|
+
c.switch [:t, :times], :default_value => true
|
884
888
|
|
885
889
|
c.desc 'Show time totals at the end of output'
|
886
|
-
c.default_value false
|
887
890
|
c.switch [:totals], :default_value => false, :negatable => true
|
888
891
|
|
889
892
|
c.desc 'Sort tags by (name|time)'
|
@@ -903,8 +906,7 @@ end
|
|
903
906
|
desc 'Show the last entry'
|
904
907
|
command :last do |c|
|
905
908
|
c.desc 'Specify a section'
|
906
|
-
c.
|
907
|
-
c.flag [:s,:section]
|
909
|
+
c.flag [:s, :section]
|
908
910
|
|
909
911
|
c.action do |global_options,options,args|
|
910
912
|
puts wwid.last(true,options[:s]).strip
|
@@ -914,8 +916,7 @@ end
|
|
914
916
|
desc 'List sections'
|
915
917
|
command :sections do |c|
|
916
918
|
c.desc 'List in single column'
|
917
|
-
c.default_value false
|
918
|
-
c.switch [:c,:column], :default_value => false
|
919
|
+
c.switch [:c, :column], :default_value => false
|
919
920
|
|
920
921
|
c.action do |global_options,options,args|
|
921
922
|
joiner = options[:c] ? "\n" : "\t"
|
@@ -966,20 +967,18 @@ desc 'Display a user-created view'
|
|
966
967
|
arg_name 'view_name'
|
967
968
|
command :view do |c|
|
968
969
|
c.desc 'Section (override view settings)'
|
969
|
-
c.flag [:s
|
970
|
+
c.flag [:s, :section]
|
970
971
|
|
971
972
|
c.desc 'Count to display (override view settings)'
|
972
|
-
c.flag [:c
|
973
|
+
c.flag [:c, :count], :must_match => /^\d+$/, :type => Integer
|
973
974
|
|
974
975
|
c.desc 'Output to export format (csv|html|json)'
|
975
|
-
c.flag [:o
|
976
|
+
c.flag [:o, :output]
|
976
977
|
|
977
978
|
c.desc 'Show time intervals on @done tasks'
|
978
|
-
c.default_value true
|
979
|
-
c.switch [:t,:times], :default_value => true
|
979
|
+
c.switch [:t, :times], :default_value => true
|
980
980
|
|
981
981
|
c.desc 'Show intervals with totals at the end of output'
|
982
|
-
c.default_value false
|
983
982
|
c.switch [:totals], :default_value => false, :negatable => true
|
984
983
|
|
985
984
|
c.desc 'Sort tags by (name|time)'
|
@@ -990,7 +989,6 @@ command :view do |c|
|
|
990
989
|
c.flag [:tag_sort], :default_value => default
|
991
990
|
|
992
991
|
c.desc 'Only show items with recorded time intervals'
|
993
|
-
c.default_value false
|
994
992
|
c.switch [:only_timed], :default_value => false, :negatable => true
|
995
993
|
|
996
994
|
c.action do |global_options,options,args|
|
@@ -1053,8 +1051,7 @@ end
|
|
1053
1051
|
desc 'List available custom views'
|
1054
1052
|
command :views do |c|
|
1055
1053
|
c.desc 'List in single column'
|
1056
|
-
c.default_value false
|
1057
|
-
c.switch [:c,:column], :default_value => false
|
1054
|
+
c.switch [:c, :column], :default_value => false
|
1058
1055
|
|
1059
1056
|
c.action do |global_options,options,args|
|
1060
1057
|
joiner = options[:c] ? "\n" : "\t"
|
@@ -1067,16 +1064,13 @@ arg_name 'section'
|
|
1067
1064
|
default_value wwid.current_section
|
1068
1065
|
command :archive do |c|
|
1069
1066
|
c.desc 'Count to keep (ignored if archiving by tag)'
|
1070
|
-
c.default_value 5
|
1071
|
-
c.flag [:k,:keep], :default_value => 5, :must_match => /^\d+$/, :type => Integer
|
1067
|
+
c.flag [:k, :keep], :default_value => 5, :must_match => /^\d+$/, :type => Integer
|
1072
1068
|
|
1073
1069
|
c.desc 'Move entries to'
|
1074
|
-
c.default_value "Archive"
|
1075
|
-
c.flag [:t,:to], :default_value => "Archive"
|
1070
|
+
c.flag [:t, :to], :default_value => "Archive"
|
1076
1071
|
|
1077
1072
|
c.desc 'Tag boolean'
|
1078
|
-
c.default_value "AND"
|
1079
|
-
c.flag [:b,:bool], :default_value => "AND"
|
1073
|
+
c.flag [:b, :bool], :default_value => "AND"
|
1080
1074
|
|
1081
1075
|
c.action do |global_options,options,args|
|
1082
1076
|
if args.length > 0
|
@@ -1144,8 +1138,7 @@ end
|
|
1144
1138
|
desc 'Edit the configuration file'
|
1145
1139
|
command :config do |c|
|
1146
1140
|
c.desc 'Editor to use'
|
1147
|
-
c.
|
1148
|
-
c.flag [:e,:editor], :default_value => nil
|
1141
|
+
c.flag [:e, :editor], :default_value => nil
|
1149
1142
|
|
1150
1143
|
if `uname` =~ /Darwins/
|
1151
1144
|
c.desc 'Application to use'
|
@@ -1183,8 +1176,7 @@ end
|
|
1183
1176
|
desc 'Undo the last change to the doing_file'
|
1184
1177
|
command :undo do |c|
|
1185
1178
|
c.desc 'Specify alternate doing file'
|
1186
|
-
c.default_value wwid.doing_file
|
1187
|
-
c.flag [:f,:file], :default_value => wwid.doing_file
|
1179
|
+
c.flag [:f, :file], :default_value => wwid.doing_file
|
1188
1180
|
|
1189
1181
|
c.action do |global_options,options,args|
|
1190
1182
|
file = options[:f] || wwid.doing_file
|
data/lib/doing/version.rb
CHANGED
data/lib/doing/wwid.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
3
|
require 'deep_merge'
|
4
|
+
require 'open3'
|
4
5
|
|
5
6
|
##
|
6
7
|
## @brief String helpers
|
@@ -644,6 +645,7 @@ class WWID
|
|
644
645
|
end
|
645
646
|
# Remove @done tag
|
646
647
|
title = last['title'].sub(/\s*@done(\(.*?\))?/, '').chomp
|
648
|
+
@auto_tag = false
|
647
649
|
add_item(title, last['section'], { note: opt[:note], back: opt[:date], timed: true })
|
648
650
|
write(@doing_file)
|
649
651
|
end
|
@@ -726,7 +728,6 @@ class WWID
|
|
726
728
|
if @content.key?(section)
|
727
729
|
|
728
730
|
items = @content[section]['items'].dup.sort_by { |item| item['date'] }.reverse
|
729
|
-
|
730
731
|
index = 0
|
731
732
|
done_date = Time.now
|
732
733
|
next_start = Time.now
|
@@ -734,44 +735,80 @@ class WWID
|
|
734
735
|
items.map! do |item|
|
735
736
|
break if index == count
|
736
737
|
|
737
|
-
if opt[:
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
738
|
+
tag_match = if opt[:tag].length.positive?
|
739
|
+
case opt[:tag_bool]
|
740
|
+
when 'AND'
|
741
|
+
result = true
|
742
|
+
opt[:tag].each do |tag|
|
743
|
+
unless item['title'] =~ /@#{tag}/
|
744
|
+
result = false
|
745
|
+
break
|
746
|
+
end
|
747
|
+
end
|
748
|
+
result
|
749
|
+
when 'NOT'
|
750
|
+
result = true
|
751
|
+
opt[:tag].each do |tag|
|
752
|
+
if item['title'] =~ /@#{tag}/
|
753
|
+
result = false
|
754
|
+
break
|
755
|
+
end
|
756
|
+
end
|
757
|
+
result
|
758
|
+
else
|
759
|
+
result = false
|
760
|
+
opt[:tag].each do |tag|
|
761
|
+
if item['title'] =~ /@#{tag}/
|
762
|
+
result = true
|
763
|
+
break
|
764
|
+
end
|
765
|
+
end
|
766
|
+
result
|
767
|
+
end
|
768
|
+
else
|
769
|
+
true
|
770
|
+
end
|
771
|
+
|
772
|
+
if tag_match
|
773
|
+
if opt[:autotag]
|
774
|
+
new_title = autotag(item['title']) if @auto_tag
|
775
|
+
if new_title == item['title']
|
776
|
+
@results.push(%(Autotag: No changes))
|
777
|
+
else
|
778
|
+
@results.push("Tags updated: #{new_title}")
|
779
|
+
item['title'] = new_title
|
780
|
+
end
|
751
781
|
else
|
752
|
-
|
753
|
-
|
782
|
+
if opt[:sequential]
|
783
|
+
done_date = next_start - 1
|
784
|
+
next_start = item['date']
|
785
|
+
elsif opt[:back]
|
786
|
+
done_date = item['date'] + (opt[:back] - item['date'])
|
787
|
+
else
|
788
|
+
done_date = Time.now
|
789
|
+
end
|
754
790
|
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
791
|
+
title = item['title']
|
792
|
+
opt[:tags].each do |tag|
|
793
|
+
tag.strip!
|
794
|
+
if opt[:remove] && title =~ /@#{tag}\b/
|
795
|
+
title.gsub!(/(^| )@#{tag}(\([^)]*\))?/, '')
|
796
|
+
@results.push(%(Removed @#{tag}: "#{title}" in #{section}))
|
797
|
+
elsif title !~ /@#{tag}/
|
798
|
+
title.chomp!
|
799
|
+
title += if opt[:date]
|
800
|
+
" @#{tag}(#{done_date.strftime('%F %R')})"
|
801
|
+
else
|
802
|
+
" @#{tag}"
|
803
|
+
end
|
804
|
+
@results.push(%(Added @#{tag}: "#{title}" in #{section}))
|
805
|
+
end
|
769
806
|
end
|
807
|
+
item['title'] = title
|
770
808
|
end
|
771
|
-
item['title'] = title
|
772
|
-
end
|
773
809
|
|
774
|
-
|
810
|
+
index += 1
|
811
|
+
end
|
775
812
|
|
776
813
|
item
|
777
814
|
end
|
@@ -781,9 +818,10 @@ class WWID
|
|
781
818
|
if opt[:archive] && section != 'Archive' && (opt[:count]).positive?
|
782
819
|
# concat [count] items from [section] and archive section
|
783
820
|
archived = @content[section]['items'][0..opt[:count] - 1].map do |i|
|
784
|
-
i['title'].sub(/(?:@from\(.*?\))?(.*)$/, "\\1 @from(#{i['section']})")
|
821
|
+
i['title'].sub!(/(?:@from\(.*?\))?(.*)$/, "\\1 @from(#{i['section']})")
|
822
|
+
i
|
785
823
|
end.concat(@content['Archive']['items'])
|
786
|
-
#
|
824
|
+
# slice [count] items off of [section] items
|
787
825
|
@content[opt[:section]]['items'] = @content[opt[:section]]['items'][opt[:count]..-1]
|
788
826
|
# overwrite archive section with concatenated array
|
789
827
|
@content['Archive']['items'] = archived
|
@@ -931,10 +969,10 @@ class WWID
|
|
931
969
|
end
|
932
970
|
|
933
971
|
if @config.key?('run_after')
|
934
|
-
|
935
|
-
if
|
936
|
-
|
937
|
-
|
972
|
+
stdout, stderr, status = Open3.capture3(@config['run_after'])
|
973
|
+
if status.exitstatus.positive?
|
974
|
+
warn "Error running #{@config['run_after']}"
|
975
|
+
warn stderr
|
938
976
|
end
|
939
977
|
end
|
940
978
|
end
|
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.51
|
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
|
@@ -72,20 +78,20 @@ dependencies:
|
|
72
78
|
requirements:
|
73
79
|
- - "~>"
|
74
80
|
- !ruby/object:Gem::Version
|
75
|
-
version: '2.
|
81
|
+
version: '2.20'
|
76
82
|
- - ">="
|
77
83
|
- !ruby/object:Gem::Version
|
78
|
-
version: 2.
|
84
|
+
version: 2.20.1
|
79
85
|
type: :runtime
|
80
86
|
prerelease: false
|
81
87
|
version_requirements: !ruby/object:Gem::Requirement
|
82
88
|
requirements:
|
83
89
|
- - "~>"
|
84
90
|
- !ruby/object:Gem::Version
|
85
|
-
version: '2.
|
91
|
+
version: '2.20'
|
86
92
|
- - ">="
|
87
93
|
- !ruby/object:Gem::Version
|
88
|
-
version: 2.
|
94
|
+
version: 2.20.1
|
89
95
|
- !ruby/object:Gem::Dependency
|
90
96
|
name: haml
|
91
97
|
requirement: !ruby/object:Gem::Requirement
|